Merge viewport with tip

This commit is contained in:
Benoit Girard 2012-02-08 20:42:17 -05:00
commit beb2ae7df8
9 changed files with 101 additions and 87 deletions

View File

@ -52,9 +52,9 @@ namespace mozilla {
namespace layers {
CompositorParent::CompositorParent(nsIWidget* aWidget)
: mPaused(false)
, mWidget(aWidget)
: mWidget(aWidget)
, mCurrentCompositeTask(NULL)
, mPaused(false)
{
MOZ_COUNT_CTOR(CompositorParent);
}
@ -104,13 +104,11 @@ CompositorParent::PauseComposition()
void
CompositorParent::ResumeComposition()
{
if (mPaused) {
mPaused = false;
mPaused = false;
#ifdef MOZ_WIDGET_ANDROID
static_cast<LayerManagerOGL*>(mLayerManager.get())->gl()->RenewSurface();
static_cast<LayerManagerOGL*>(mLayerManager.get())->gl()->RenewSurface();
#endif
}
}
void
@ -184,13 +182,49 @@ CompositorParent::Composite()
printf_stderr("Correcting for position fixed %i, %i\n", -mScrollOffset.x, -mScrollOffset.y);
worldTransform.Translate(offset);
worldTransform.Scale(mXScale, mYScale, 1.0f);
Layer* root = mLayerManager->GetRoot();
root->AsShadowLayer()->SetShadowTransform(worldTransform);
#ifdef MOZ_WIDGET_ANDROID
Layer* layer = GetPrimaryScrollableLayer();
#else
Layer* layer = mLayerManager->GetRoot();
#endif
layer->AsShadowLayer()->SetShadowTransform(worldTransform);
mLayerManager->EndEmptyTransaction();
mLastCompose = mozilla::TimeStamp::Now();
}
#ifdef MOZ_WIDGET_ANDROID
// Do a breadth-first search to find the first layer in the tree with a
// displayport set.
Layer*
CompositorParent::GetPrimaryScrollableLayer()
{
Layer* root = mLayerManager->GetRoot();
nsTArray<Layer*> queue;
queue.AppendElement(root);
for (int i = 0; i < queue.Length(); i++) {
ContainerLayer* containerLayer = queue[i]->AsContainerLayer();
if (!containerLayer) {
continue;
}
const FrameMetrics& frameMetrics = containerLayer->GetFrameMetrics();
if (!frameMetrics.mDisplayPort.IsEmpty()) {
return containerLayer;
}
Layer* child = containerLayer->GetFirstChild();
while (child) {
queue.AppendElement(child);
child = child->GetNextSibling();
}
}
return root;
}
#endif
// Go down shadow layer tree, setting properties to match their non-shadow
// counterparts.
static void
@ -383,12 +417,6 @@ CompositorParent::TestScroll()
PLayersParent*
CompositorParent::AllocPLayers(const LayersBackend &backendType)
{
#ifdef MOZ_WIDGET_ANDROID
// Registering with the compositor will create the surface view that
// the layer manager expects to attach to.
//RegisterCompositorWithJava();
#endif
if (backendType == LayerManager::LAYERS_OPENGL) {
nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(mWidget);
mWidget = NULL;
@ -417,14 +445,6 @@ CompositorParent::DeallocPLayers(PLayersParent* actor)
return true;
}
#ifdef MOZ_WIDGET_ANDROID
void
CompositorParent::RegisterCompositorWithJava()
{
mozilla::AndroidBridge::Bridge()->RegisterCompositor();
}
#endif
} // namespace layers
} // namespace mozilla

View File

@ -114,18 +114,17 @@ private:
// Platform specific functions
#ifdef MOZ_WIDGET_ANDROID
/**
* Register the compositor thread with the Java native thread.
* This will replace the temporary compositor with the real
* Gecko compositor thread.
**/
void RegisterCompositorWithJava();
/**
* Asks Java for the viewport position and updates the world transform
* accordingly.
*/
void RequestViewTransform();
/**
* Does a breadth-first search to find the first layer in the tree with a
* displayport set.
*/
Layer* GetPrimaryScrollableLayer();
#endif
nsRefPtr<LayerManager> mLayerManager;

View File

@ -782,18 +782,7 @@ LayerManagerOGL::Render()
mGLContext->fEnable(LOCAL_GL_SCISSOR_TEST);
static int i = 0;
i++;
i=i%3;
if( i == 0 ) {
mGLContext->fClearColor(1.0, 0.0, 0.0, 0.0);
} else if( i == 1 ) {
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
} else if( i == 2 ) {
mGLContext->fClearColor(1.0, 1.0, 0.0, 0.0);
} else {
mGLContext->fClearColor(0.0, 1.0, 0.0, 0.0);
}
mGLContext->fClearColor(1.0, 1.0, 1.0, 0.0);
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
// Render our layers.

View File

@ -871,6 +871,8 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
matrix.Translate(gfxPoint(pixOffset.x, pixOffset.y));
layer->SetTransform(gfx3DMatrix::From2D(matrix));
// FIXME: Temporary workaround for bug 681192 and bug 724786. Uncomment this code before review!
#if 0
// Calculate exact position of the top-left of the active scrolled root.
// This might not be 0,0 due to the snapping in ScaleToNearestPixels.
gfxPoint activeScrolledRootTopLeft = scaledOffset - matrix.GetTranslation();
@ -882,6 +884,7 @@ ContainerState::CreateOrRecycleThebesLayer(nsIFrame* aActiveScrolledRoot)
nsIntRect invalidate = layer->GetValidRegion().GetBounds();
layer->InvalidateRegion(invalidate);
}
#endif
return layer.forget();
}

View File

@ -2043,16 +2043,18 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
NS_ENSURE_SUCCESS(rv, rv);
// Since making new layers is expensive, only use nsDisplayScrollLayer
// if the area is scrollable.
// if the area is scrollable and there's a displayport (or we're the content
// process).
nsRect scrollRange = GetScrollRange();
ScrollbarStyles styles = GetScrollbarStylesFromFrame();
mShouldBuildLayer =
(XRE_GetProcessType() == GeckoProcessType_Content &&
((XRE_GetProcessType() == GeckoProcessType_Content || usingDisplayport) &&
(styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN ||
styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN) &&
(scrollRange.width > 0 ||
scrollRange.height > 0) &&
(!mIsRoot || !mOuter->PresContext()->IsRootContentDocument()));
(usingDisplayport || !mIsRoot ||
!mOuter->PresContext()->IsRootContentDocument()));
if (ShouldBuildLayer()) {
// ScrollLayerWrapper must always be created because it initializes the

View File

@ -157,8 +157,7 @@ public class FlexibleGLSurfaceView extends SurfaceView implements SurfaceHolder.
}
if (mListener != null) {
mListener.compositionResumeRequested();
mListener.renderRequested();
mListener.surfaceChanged(width, height);
}
}
@ -203,6 +202,7 @@ public class FlexibleGLSurfaceView extends SurfaceView implements SurfaceHolder.
void renderRequested();
void compositionPauseRequested();
void compositionResumeRequested();
void surfaceChanged(int width, int height);
}
public static class FlexibleGLSurfaceViewException extends RuntimeException {

View File

@ -203,5 +203,13 @@ public class GeckoGLLayerClient extends GeckoLayerClient
Log.e(LOGTAG, "### Scheduling ResumeComposition");
GeckoAppShell.scheduleResumeComposition();
}
public void surfaceChanged(int width, int height) {
compositionPauseRequested();
LayerController layerController = getLayerController();
layerController.setViewportSize(new FloatSize(width, height));
compositionResumeRequested();
renderRequested();
}
}

View File

@ -74,7 +74,7 @@ public abstract class GeckoLayerClient extends LayerClient implements GeckoEvent
/* The viewport that Gecko will display when drawing is finished */
protected ViewportMetrics mNewGeckoViewport;
private static final long MIN_VIEWPORT_CHANGE_DELAY = 200L;
private static final long MIN_VIEWPORT_CHANGE_DELAY = 25L;
private long mLastViewportChangeTime;
private boolean mPendingViewportAdjust;
private boolean mViewportSizeChanged;
@ -265,8 +265,10 @@ public abstract class GeckoLayerClient extends LayerClient implements GeckoEvent
}
private void adjustViewportWithThrottling() {
if (!getLayerController().getRedrawHint())
return;
// FIXME: Allow redraw while a finger is down, but only if we're about to checkerboard.
// This requires fixing aboutToCheckerboard() to know about the new buffer size.
/*if (!getLayerController().getRedrawHint())
return;*/
if (mPendingViewportAdjust)
return;

View File

@ -102,6 +102,12 @@ const kElementsReceivingInput = {
video: true
};
// How many pixels on each side to buffer.
const kBufferAmount = 300;
// Whether we're using GL layers.
const kUsingGLLayers = true;
function dump(a) {
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a);
}
@ -863,27 +869,20 @@ var BrowserApp = {
top: focusedRect.top - tab.viewportExcess.y,
bottom: focusedRect.bottom - tab.viewportExcess.y
};
let transformChanged = false;
if (focusedRect.right >= visibleContentWidth && focusedRect.left > 0) {
// the element is too far off the right side, so we need to scroll to the right more
tab.viewportExcess.x += Math.min(focusedRect.left, focusedRect.right - visibleContentWidth);
transformChanged = true;
} else if (focusedRect.left < 0) {
// the element is too far off the left side, so we need to scroll to the left more
tab.viewportExcess.x += focusedRect.left;
transformChanged = true;
}
if (focusedRect.bottom >= visibleContentHeight && focusedRect.top > 0) {
// the element is too far down, so we need to scroll down more
tab.viewportExcess.y += Math.min(focusedRect.top, focusedRect.bottom - visibleContentHeight);
transformChanged = true;
} else if (focusedRect.top < 0) {
// the element is too far up, so we need to scroll up more
tab.viewportExcess.y += focusedRect.top;
transformChanged = true;
}
if (transformChanged)
tab.updateTransform();
// finally, let java know where we ended up
tab.sendViewportUpdate();
}
@ -1409,6 +1408,8 @@ let gTabIDFactory = 0;
let gScreenWidth = 1;
let gScreenHeight = 1;
let gBrowserWidth = null;
function Tab(aURL, aParams) {
this.browser = null;
this.vbox = null;
@ -1438,14 +1439,19 @@ Tab.prototype = {
this.browser = document.createElement("browser");
this.browser.setAttribute("type", "content-targetable");
this.setBrowserSize(980, 480);
this.browser.style.MozTransformOrigin = "0 0";
this.browser.style.width = gScreenWidth + "px";
this.browser.style.height = gScreenHeight + "px";
this.vbox.appendChild(this.browser);
this.browser.stop();
// Turn off clipping so we can buffer areas outside of the browser element.
let frameLoader = this.browser.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader;
frameLoader.clipSubdocument = false;
if (kUsingGLLayers) {
frameLoader.renderMode = Ci.nsIFrameLoader.RENDER_MODE_ASYNC_SCROLL;
} else {
// Turn off clipping so we can buffer areas outside of the browser element.
frameLoader.clipSubdocument = false;
}
this.id = ++gTabIDFactory;
@ -1568,27 +1574,19 @@ Tab.prototype = {
this._viewport.height = gScreenHeight = aViewport.height;
dump("### gScreenWidth = " + gScreenWidth + "\n");
let transformChanged = false;
if ((aViewport.offsetX != this._viewport.offsetX) ||
(excessX != this.viewportExcess.x)) {
this._viewport.offsetX = aViewport.offsetX;
this.viewportExcess.x = excessX;
transformChanged = true;
}
if ((aViewport.offsetY != this._viewport.offsetY) ||
(excessY != this.viewportExcess.y)) {
this._viewport.offsetY = aViewport.offsetY;
this.viewportExcess.y = excessY;
transformChanged = true;
}
if (Math.abs(aViewport.zoom - this._viewport.zoom) >= 1e-6) {
this._viewport.zoom = aViewport.zoom;
transformChanged = true;
}
if (transformChanged)
this.updateTransform();
},
screenshot: function(aSrc, aDst) {
@ -1619,20 +1617,6 @@ Tab.prototype = {
}, Ci.nsIThread.DISPATCH_NORMAL);
},
updateTransform: function() {
let hasZoom = (Math.abs(this._viewport.zoom - 1.0) >= 1e-6);
let x = this._viewport.offsetX + Math.round(-this.viewportExcess.x * this._viewport.zoom);
let y = this._viewport.offsetY + Math.round(-this.viewportExcess.y * this._viewport.zoom);
let transform =
"translate(" + x + "px, " +
y + "px)";
if (hasZoom)
transform += " scale(" + this._viewport.zoom + ")";
this.browser.style.MozTransform = transform;
},
get viewport() {
// Update the viewport to current dimensions
this._viewport.x = (this.browser.contentWindow.scrollX +
@ -1747,6 +1731,14 @@ Tab.prototype = {
if (this._pluginCount && !this._pluginOverlayShowing)
PluginHelper.showDoorHanger(this);
// FIXME: This should not be in DOMContentLoaded; it should happen earlier.
let cwu = this.browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
cwu.setDisplayPortForElement(-kBufferAmount, -kBufferAmount,
gScreenWidth + kBufferAmount * 2,
gScreenHeight + kBufferAmount * 2,
this.browser.contentDocument.documentElement);
break;
}
@ -2068,7 +2060,7 @@ Tab.prototype = {
let minScale = this.getPageZoomLevel(screenW);
viewportH = Math.max(viewportH, screenH / minScale);
let oldBrowserWidth = parseInt(this.browser.style.width);
let oldBrowserWidth = gBrowserWidth;
this.setBrowserSize(viewportW, viewportH);
// Avoid having the scroll position jump around after device rotation.
@ -2079,7 +2071,7 @@ Tab.prototype = {
// If the browser width changes, we change the zoom proportionally. This ensures sensible
// behavior when rotating the device on pages with automatically-resizing viewports.
if (viewportW == oldBrowserWidth)
if (oldBrowserWidth == null || viewportW == oldBrowserWidth)
return;
let viewport = this.viewport;
@ -2092,9 +2084,8 @@ Tab.prototype = {
if ("defaultZoom" in md && md.defaultZoom)
return md.defaultZoom;
let browserWidth = parseInt(this.browser.style.width);
dump("### getDefaultZoomLevel gScreenWidth=" + gScreenWidth);
return gScreenWidth / browserWidth;
return gScreenWidth / gBrowserWidth;
},
getPageZoomLevel: function getPageZoomLevel() {
@ -2107,8 +2098,8 @@ Tab.prototype = {
},
setBrowserSize: function(aWidth, aHeight) {
this.browser.style.width = aWidth + "px";
this.browser.style.height = aHeight + "px";
// TODO: Use nsIDOMWindowUtils::SetCSSViewport() here.
gBrowserWidth = aWidth;
},
getRequestLoadContext: function(aRequest) {