Bug 711959 - Add RenderTask and the necessary mechanisms to use it. r=kats
This commit is contained in:
@@ -204,6 +204,7 @@ FENNEC_JAVA_FILES = \
|
|||||||
gfx/PointUtils.java \
|
gfx/PointUtils.java \
|
||||||
gfx/ProgressiveUpdateData.java \
|
gfx/ProgressiveUpdateData.java \
|
||||||
gfx/RectUtils.java \
|
gfx/RectUtils.java \
|
||||||
|
gfx/RenderTask.java \
|
||||||
gfx/ScrollbarLayer.java \
|
gfx/ScrollbarLayer.java \
|
||||||
gfx/SimpleScaleGestureDetector.java \
|
gfx/SimpleScaleGestureDetector.java \
|
||||||
gfx/SingleTileLayer.java \
|
gfx/SingleTileLayer.java \
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.mozilla.gecko.R;
|
|||||||
import org.mozilla.gecko.Tab;
|
import org.mozilla.gecko.Tab;
|
||||||
import org.mozilla.gecko.Tabs;
|
import org.mozilla.gecko.Tabs;
|
||||||
import org.mozilla.gecko.gfx.Layer.RenderContext;
|
import org.mozilla.gecko.gfx.Layer.RenderContext;
|
||||||
|
import org.mozilla.gecko.gfx.RenderTask;
|
||||||
import org.mozilla.gecko.mozglue.DirectBufferAllocator;
|
import org.mozilla.gecko.mozglue.DirectBufferAllocator;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -50,6 +51,9 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
private static final int FRAME_RATE_METER_WIDTH = 128;
|
private static final int FRAME_RATE_METER_WIDTH = 128;
|
||||||
private static final int FRAME_RATE_METER_HEIGHT = 32;
|
private static final int FRAME_RATE_METER_HEIGHT = 32;
|
||||||
|
|
||||||
|
private static final long NANOS_PER_MS = 1000000;
|
||||||
|
private static final int NANOS_PER_SECOND = 1000000000;
|
||||||
|
|
||||||
private final LayerView mView;
|
private final LayerView mView;
|
||||||
private final NinePatchTileLayer mShadowLayer;
|
private final NinePatchTileLayer mShadowLayer;
|
||||||
private TextLayer mFrameRateLayer;
|
private TextLayer mFrameRateLayer;
|
||||||
@@ -63,6 +67,9 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
private int mBackgroundColor;
|
private int mBackgroundColor;
|
||||||
private int mOverscrollColor;
|
private int mOverscrollColor;
|
||||||
|
|
||||||
|
private long mLastFrameTime;
|
||||||
|
private final CopyOnWriteArrayList<RenderTask> mTasks;
|
||||||
|
|
||||||
private CopyOnWriteArrayList<Layer> mExtraLayers = new CopyOnWriteArrayList<Layer>();
|
private CopyOnWriteArrayList<Layer> mExtraLayers = new CopyOnWriteArrayList<Layer>();
|
||||||
|
|
||||||
// Dropped frames display
|
// Dropped frames display
|
||||||
@@ -138,6 +145,10 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
Bitmap scrollbarImage = view.getScrollbarImage();
|
Bitmap scrollbarImage = view.getScrollbarImage();
|
||||||
IntSize size = new IntSize(scrollbarImage.getWidth(), scrollbarImage.getHeight());
|
IntSize size = new IntSize(scrollbarImage.getWidth(), scrollbarImage.getHeight());
|
||||||
scrollbarImage = expandCanvasToPowerOfTwo(scrollbarImage, size);
|
scrollbarImage = expandCanvasToPowerOfTwo(scrollbarImage, size);
|
||||||
|
|
||||||
|
mTasks = new CopyOnWriteArrayList<RenderTask>();
|
||||||
|
mLastFrameTime = System.nanoTime();
|
||||||
|
|
||||||
mVertScrollLayer = new ScrollbarLayer(this, scrollbarImage, size, true);
|
mVertScrollLayer = new ScrollbarLayer(this, scrollbarImage, size, true);
|
||||||
mHorizScrollLayer = new ScrollbarLayer(this, diagonalFlip(scrollbarImage), new IntSize(size.height, size.width), false);
|
mHorizScrollLayer = new ScrollbarLayer(this, diagonalFlip(scrollbarImage), new IntSize(size.height, size.width), false);
|
||||||
mFadeRunnable = new FadeRunnable();
|
mFadeRunnable = new FadeRunnable();
|
||||||
@@ -241,6 +252,30 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
return mMaxTextureSize;
|
return mMaxTextureSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void postRenderTask(RenderTask aTask) {
|
||||||
|
mTasks.add(aTask);
|
||||||
|
mView.requestRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRenderTask(RenderTask aTask) {
|
||||||
|
mTasks.remove(aTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runRenderTasks(CopyOnWriteArrayList<RenderTask> tasks, boolean after, long frameStartTime) {
|
||||||
|
for (RenderTask task : tasks) {
|
||||||
|
if (task.runAfter != after) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean stillRunning = task.run(frameStartTime - mLastFrameTime, frameStartTime);
|
||||||
|
|
||||||
|
// Remove the task from the list if its finished
|
||||||
|
if (!stillRunning) {
|
||||||
|
tasks.remove(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addLayer(Layer layer) {
|
public void addLayer(Layer layer) {
|
||||||
synchronized (mExtraLayers) {
|
synchronized (mExtraLayers) {
|
||||||
if (mExtraLayers.contains(layer)) {
|
if (mExtraLayers.contains(layer)) {
|
||||||
@@ -299,7 +334,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateDroppedFrames(long frameStartTime) {
|
private void updateDroppedFrames(long frameStartTime) {
|
||||||
int frameElapsedTime = (int)(SystemClock.uptimeMillis() - frameStartTime);
|
int frameElapsedTime = (int)((System.nanoTime() - frameStartTime) / NANOS_PER_MS);
|
||||||
|
|
||||||
/* Update the running statistics. */
|
/* Update the running statistics. */
|
||||||
mFrameTimingsSum -= mFrameTimings[mCurrentFrame];
|
mFrameTimingsSum -= mFrameTimings[mCurrentFrame];
|
||||||
@@ -456,7 +491,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
|
|
||||||
/** This function is invoked via JNI; be careful when modifying signature. */
|
/** This function is invoked via JNI; be careful when modifying signature. */
|
||||||
public void beginDrawing() {
|
public void beginDrawing() {
|
||||||
mFrameStartTime = SystemClock.uptimeMillis();
|
mFrameStartTime = System.nanoTime();
|
||||||
|
|
||||||
TextureReaper.get().reap();
|
TextureReaper.get().reap();
|
||||||
TextureGenerator.get().fill();
|
TextureGenerator.get().fill();
|
||||||
@@ -465,6 +500,9 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
|
|
||||||
Layer rootLayer = mView.getLayerClient().getRoot();
|
Layer rootLayer = mView.getLayerClient().getRoot();
|
||||||
|
|
||||||
|
// Run through pre-render tasks
|
||||||
|
runRenderTasks(mTasks, false, mFrameStartTime);
|
||||||
|
|
||||||
if (!mPageContext.fuzzyEquals(mLastPageContext) && !mView.isFullScreen()) {
|
if (!mPageContext.fuzzyEquals(mLastPageContext) && !mView.isFullScreen()) {
|
||||||
// The viewport or page changed, so show the scrollbars again
|
// The viewport or page changed, so show the scrollbars again
|
||||||
// as per UX decision. Don't do this if we're in full-screen mode though.
|
// as per UX decision. Don't do this if we're in full-screen mode though.
|
||||||
@@ -604,12 +642,14 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
mCompleteFramesRendered += 1.0f - checkerboard;
|
mCompleteFramesRendered += 1.0f - checkerboard;
|
||||||
mFramesRendered ++;
|
mFramesRendered ++;
|
||||||
|
|
||||||
if (mFrameStartTime - mProfileOutputTime > 1000) {
|
if (mFrameStartTime - mProfileOutputTime > NANOS_PER_SECOND) {
|
||||||
mProfileOutputTime = mFrameStartTime;
|
mProfileOutputTime = mFrameStartTime;
|
||||||
printCheckerboardStats();
|
printCheckerboardStats();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runRenderTasks(mTasks, true, mFrameStartTime);
|
||||||
|
|
||||||
/* Draw the FPS. */
|
/* Draw the FPS. */
|
||||||
if (mFrameRateLayer != null) {
|
if (mFrameRateLayer != null) {
|
||||||
updateDroppedFrames(mFrameStartTime);
|
updateDroppedFrames(mFrameStartTime);
|
||||||
@@ -652,6 +692,7 @@ public class LayerRenderer implements Tabs.OnTabsChangedListener {
|
|||||||
});
|
});
|
||||||
mView.setPaintState(LayerView.PAINT_AFTER_FIRST);
|
mView.setPaintState(LayerView.PAINT_AFTER_FIRST);
|
||||||
}
|
}
|
||||||
|
mLastFrameTime = mFrameStartTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -401,6 +401,14 @@ public class LayerView extends FrameLayout {
|
|||||||
mRenderer.removeLayer(layer);
|
mRenderer.removeLayer(layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void postRenderTask(RenderTask task) {
|
||||||
|
mRenderer.postRenderTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeRenderTask(RenderTask task) {
|
||||||
|
mRenderer.removeRenderTask(task);
|
||||||
|
}
|
||||||
|
|
||||||
public int getMaxTextureSize() {
|
public int getMaxTextureSize() {
|
||||||
return mRenderer.getMaxTextureSize();
|
return mRenderer.getMaxTextureSize();
|
||||||
}
|
}
|
||||||
|
|||||||
80
mobile/android/base/gfx/RenderTask.java
Normal file
80
mobile/android/base/gfx/RenderTask.java
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.gecko.gfx;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class used to schedule a callback to occur when the next frame is drawn.
|
||||||
|
* Subclasses must redefine the internalRun method, not the run method.
|
||||||
|
*/
|
||||||
|
public abstract class RenderTask {
|
||||||
|
/**
|
||||||
|
* Whether to run the task after the render, or before.
|
||||||
|
*/
|
||||||
|
public final boolean runAfter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Time when this task has first run, in ns. Useful for tasks which run for a specific duration.
|
||||||
|
*/
|
||||||
|
private long mStartTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether we should initialise mStartTime on the next frame run.
|
||||||
|
*/
|
||||||
|
private boolean mResetStartTime = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The callback to run on each frame. timeDelta is the time elapsed since
|
||||||
|
* the last call, in nanoseconds. Returns true if it should continue
|
||||||
|
* running, or false if it should be removed from the task queue. Returning
|
||||||
|
* true implicitly schedules a redraw.
|
||||||
|
*
|
||||||
|
* This method first initializes the start time if resetStartTime has been invoked,
|
||||||
|
* then calls internalRun.
|
||||||
|
*
|
||||||
|
* Note : subclasses should override internalRun.
|
||||||
|
*
|
||||||
|
* @param timeDelta the time between the beginning of last frame and the beginning of this frame, in ns.
|
||||||
|
* @param currentFrameStartTime the startTime of the current frame, in ns.
|
||||||
|
* @return true if animation should be run at the next frame, false otherwise
|
||||||
|
* @see RenderTask#internalRun(long, long)
|
||||||
|
*/
|
||||||
|
public final boolean run(long timeDelta, long currentFrameStartTime) {
|
||||||
|
if (mResetStartTime) {
|
||||||
|
mStartTime = currentFrameStartTime;
|
||||||
|
mResetStartTime = false;
|
||||||
|
}
|
||||||
|
return internalRun(timeDelta, currentFrameStartTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract method to be overridden by subclasses.
|
||||||
|
* @param timeDelta the time between the beginning of last frame and the beginning of this frame, in ns
|
||||||
|
* @param currentFrameStartTime the startTime of the current frame, in ns.
|
||||||
|
* @return true if animation should be run at the next frame, false otherwise
|
||||||
|
*/
|
||||||
|
protected abstract boolean internalRun(long timeDelta, long currentFrameStartTime);
|
||||||
|
|
||||||
|
public RenderTask(boolean aRunAfter) {
|
||||||
|
runAfter = aRunAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the start time of this task.
|
||||||
|
* It is the start time of the first frame this task was run on.
|
||||||
|
* @return the start time in ns
|
||||||
|
*/
|
||||||
|
public long getStartTime() {
|
||||||
|
return mStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a reset of the recorded start time next time {@link RenderTask#run(long, long)} is run.
|
||||||
|
* @see RenderTask#getStartTime()
|
||||||
|
*/
|
||||||
|
public void resetStartTime() {
|
||||||
|
mResetStartTime = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user