Bug 748384 - Propagate page bounds and CSS page bounds in via compositor. r=Cwiiis,ajuma,mats

This commit is contained in:
Kartikaya Gupta 2012-05-23 10:51:39 -04:00
parent cd7997a23d
commit 8a9a864a95
13 changed files with 100 additions and 84 deletions

View File

@ -77,10 +77,10 @@ public:
FrameMetrics()
: mViewport(0, 0, 0, 0)
, mContentSize(0, 0)
, mContentRect(0, 0, 0, 0)
, mViewportScrollOffset(0, 0)
, mScrollId(NULL_SCROLL_ID)
, mCSSContentSize(0, 0)
, mCSSContentRect(0, 0, 0, 0)
, mResolution(1, 1)
{}
@ -115,14 +115,14 @@ public:
// These are all in layer coordinate space.
nsIntRect mViewport;
nsIntSize mContentSize;
nsIntRect mContentRect;
nsIntPoint mViewportScrollOffset;
nsIntRect mDisplayPort;
ViewID mScrollId;
// Consumers often want to know the size before scaling to pixels
// so we record this size as well.
gfx::Size mCSSContentSize;
// Consumers often want to know the origin/size before scaling to pixels
// so we record this as well.
gfx::Rect mCSSContentRect;
// This represents the resolution at which the associated layer
// will been rendered.

View File

@ -355,21 +355,15 @@ CompositorParent::TransformShadowTree()
float rootScaleY = rootTransform.GetYScale();
if (mIsFirstPaint && metrics) {
nsIntPoint scrollOffset = metrics->mViewportScrollOffset;
mContentSize = metrics->mContentSize;
SetFirstPaintViewport(scrollOffset.x, scrollOffset.y,
mContentRect = metrics->mContentRect;
SetFirstPaintViewport(metrics->mViewportScrollOffset,
1/rootScaleX,
mContentSize.width,
mContentSize.height,
metrics->mCSSContentSize.width,
metrics->mCSSContentSize.height);
mContentRect,
metrics->mCSSContentRect);
mIsFirstPaint = false;
} else if (metrics && (metrics->mContentSize != mContentSize)) {
mContentSize = metrics->mContentSize;
SetPageSize(1/rootScaleX, mContentSize.width,
mContentSize.height,
metrics->mCSSContentSize.width,
metrics->mCSSContentSize.height);
} else if (metrics && !metrics->mContentRect.IsEqualEdges(mContentRect)) {
mContentRect = metrics->mContentRect;
SetPageRect(1/rootScaleX, mContentRect, metrics->mCSSContentRect);
}
// We synchronise the viewport information with Java after sending the above
@ -408,8 +402,8 @@ CompositorParent::TransformShadowTree()
// Alter the scroll offset so that fixed position layers remain within
// the page area.
int offsetX = NS_MAX(0, NS_MIN(mScrollOffset.x, mContentSize.width - mWidgetSize.width));
int offsetY = NS_MAX(0, NS_MIN(mScrollOffset.y, mContentSize.height - mWidgetSize.height));
int offsetX = NS_MAX(0, NS_MIN(mScrollOffset.x, mContentRect.width - mWidgetSize.width));
int offsetY = NS_MAX(0, NS_MIN(mScrollOffset.y, mContentRect.height - mWidgetSize.height));
gfxPoint reverseViewTranslation(offsetX / tempScaleDiffX - metricsScrollOffset.x,
offsetY / tempScaleDiffY - metricsScrollOffset.y);
@ -421,24 +415,19 @@ CompositorParent::TransformShadowTree()
}
void
CompositorParent::SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom,
float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight)
CompositorParent::SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom,
const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
{
#ifdef MOZ_WIDGET_ANDROID
mozilla::AndroidBridge::Bridge()->SetFirstPaintViewport(aOffsetX, aOffsetY,
aZoom, aPageWidth, aPageHeight,
aCssPageWidth, aCssPageHeight);
mozilla::AndroidBridge::Bridge()->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
#endif
}
void
CompositorParent::SetPageSize(float aZoom, float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight)
CompositorParent::SetPageRect(float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
{
#ifdef MOZ_WIDGET_ANDROID
mozilla::AndroidBridge::Bridge()->SetPageSize(aZoom, aPageWidth, aPageHeight,
aCssPageWidth, aCssPageHeight);
mozilla::AndroidBridge::Bridge()->SetPageRect(aZoom, aPageRect, aCssPageRect);
#endif
}

View File

@ -83,9 +83,8 @@ protected:
virtual void ScheduleTask(CancelableTask*, int);
virtual void Composite();
virtual void ScheduleComposition();
virtual void SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight);
virtual void SetPageSize(float aZoom, float aPageWidth, float aPageHeight, float aCssPageWidth, float aCssPageHeight);
virtual void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
virtual void SetPageRect(float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
virtual void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
void SetEGLSurfaceSize(int width, int height);
@ -125,7 +124,7 @@ private:
float mXScale;
float mYScale;
nsIntPoint mScrollOffset;
nsIntSize mContentSize;
nsIntRect mContentRect;
nsIntSize mWidgetSize;
// When this flag is set, the next composition will be the first for a

View File

@ -34,9 +34,9 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
static void Write(Message* aMsg, const paramType& aParam)
{
WriteParam(aMsg, aParam.mCSSContentSize);
WriteParam(aMsg, aParam.mCSSContentRect);
WriteParam(aMsg, aParam.mViewport);
WriteParam(aMsg, aParam.mContentSize);
WriteParam(aMsg, aParam.mContentRect);
WriteParam(aMsg, aParam.mViewportScrollOffset);
WriteParam(aMsg, aParam.mDisplayPort);
WriteParam(aMsg, aParam.mScrollId);
@ -45,9 +45,9 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
{
return (ReadParam(aMsg, aIter, &aResult->mCSSContentSize) &&
return (ReadParam(aMsg, aIter, &aResult->mCSSContentRect) &&
ReadParam(aMsg, aIter, &aResult->mViewport) &&
ReadParam(aMsg, aIter, &aResult->mContentSize) &&
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
ReadParam(aMsg, aIter, &aResult->mViewportScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mScrollId) &&

View File

@ -219,9 +219,9 @@ ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
displayPort = parent->GetEffectiveTransform().
TransformBounds(gfxRect(parentMetrics.mDisplayPort));
const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics();
const nsIntSize& contentSize = metrics.mContentSize;
const nsIntPoint& contentOrigin = metrics.mViewportScrollOffset;
gfxRect contentRect = gfxRect(-contentOrigin.x, -contentOrigin.y,
const nsIntSize& contentSize = metrics.mContentRect.Size();
const nsIntPoint& contentOrigin = metrics.mContentRect.TopLeft() - metrics.mViewportScrollOffset;
gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y,
contentSize.width, contentSize.height);
contentBounds = scrollableLayer->GetEffectiveTransform().TransformBounds(contentRect);
break;

View File

@ -760,6 +760,27 @@ struct ParamTraits<mozilla::gfx::Size>
}
};
template<>
struct ParamTraits<mozilla::gfx::Rect>
{
typedef mozilla::gfx::Rect paramType;
static void Write(Message* msg, const paramType& param)
{
WriteParam(msg, param.x);
WriteParam(msg, param.y);
WriteParam(msg, param.width);
WriteParam(msg, param.height);
}
static bool Read(const Message* msg, void** iter, paramType* result)
{
return (ReadParam(msg, iter, &result->x) &&
ReadParam(msg, iter, &result->y) &&
ReadParam(msg, iter, &result->width) &&
ReadParam(msg, iter, &result->height));
}
};
template<>
struct ParamTraits<nsRect>

View File

@ -199,21 +199,25 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
scrollableFrame = aScrollFrame->GetScrollTargetFrame();
if (scrollableFrame) {
nsSize contentSize =
scrollableFrame->GetScrollRange().Size() +
scrollableFrame->GetScrollPortRect().Size();
metrics.mCSSContentSize = gfx::Size(nsPresContext::AppUnitsToFloatCSSPixels(contentSize.width),
nsPresContext::AppUnitsToFloatCSSPixels(contentSize.height));
metrics.mContentSize = contentSize.ScaleToNearestPixels(
nsRect contentBounds = scrollableFrame->GetScrollRange();
contentBounds.width += scrollableFrame->GetScrollPortRect().width;
contentBounds.height += scrollableFrame->GetScrollPortRect().height;
metrics.mCSSContentRect = gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
metrics.mContentRect = contentBounds.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
metrics.mViewportScrollOffset = scrollableFrame->GetScrollPosition().ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
}
else {
nsSize contentSize = aForFrame->GetSize();
metrics.mCSSContentSize = gfx::Size(nsPresContext::AppUnitsToFloatCSSPixels(contentSize.width),
nsPresContext::AppUnitsToFloatCSSPixels(contentSize.height));
metrics.mContentSize = contentSize.ScaleToNearestPixels(
nsRect contentBounds = aForFrame->GetRect();
metrics.mCSSContentRect = gfx::Rect(nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.x),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.y),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.width),
nsPresContext::AppUnitsToFloatCSSPixels(contentBounds.height));
metrics.mContentRect = contentBounds.ScaleToNearestPixels(
aContainerParameters.mXScale, aContainerParameters.mYScale, auPerDevPixel);
}

View File

@ -384,8 +384,8 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
NSIntPixelsToAppUnits(metrics.mViewport.width, auPerDevPixel) * aXScale,
NSIntPixelsToAppUnits(metrics.mViewport.height, auPerDevPixel) * aYScale);
view->mContentSize = nsSize(
nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentSize.width) * aXScale,
nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentSize.height) * aYScale);
nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentRect.width) * aXScale,
nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentRect.height) * aYScale);
newContentViews[scrollId] = view;
}

View File

@ -298,16 +298,18 @@ public class GeckoLayerClient implements GeckoEventResponder,
* The compositor invokes this function just before compositing a frame where the document
* is different from the document composited on the last frame. In these cases, the viewport
* information we have in Java is no longer valid and needs to be replaced with the new
* viewport information provided. setPageSize will never be invoked on the same frame that
* viewport information provided. setPageRect will never be invoked on the same frame that
* this function is invoked on; and this function will always be called prior to syncViewportInfo.
*/
public void setFirstPaintViewport(float offsetX, float offsetY, float zoom, float pageWidth, float pageHeight, float cssPageWidth, float cssPageHeight) {
public void setFirstPaintViewport(float offsetX, float offsetY, float zoom,
float pageLeft, float pageTop, float pageRight, float pageBottom,
float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
synchronized (mLayerController) {
final ViewportMetrics currentMetrics = new ViewportMetrics(mLayerController.getViewportMetrics());
currentMetrics.setOrigin(new PointF(offsetX, offsetY));
currentMetrics.setZoomFactor(zoom);
currentMetrics.setPageRect(new RectF(0.0f, 0.0f, pageWidth, pageHeight),
new RectF(0.0f, 0.0f, cssPageWidth, cssPageHeight));
currentMetrics.setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom),
new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom));
// Since we have switched to displaying a different document, we need to update any
// viewport-related state we have lying around. This includes mGeckoViewport and the
// viewport in mLayerController. Usually this information is updated via handleViewportMessage
@ -341,18 +343,19 @@ public class GeckoLayerClient implements GeckoEventResponder,
}
/** This function is invoked by Gecko via JNI; be careful when modifying signature.
* The compositor invokes this function whenever it determines that the page size
* The compositor invokes this function whenever it determines that the page rect
* has changed (based on the information it gets from layout). If setFirstPaintViewport
* is invoked on a frame, then this function will not be. For any given frame, this
* function will be invoked before syncViewportInfo.
*/
public void setPageSize(float zoom, float pageWidth, float pageHeight, float cssPageWidth, float cssPageHeight) {
public void setPageRect(float zoom, float pageLeft, float pageTop, float pageRight, float pageBottom,
float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
synchronized (mLayerController) {
// adjust the page dimensions to account for differences in zoom
// between the rendered content (which is what the compositor tells us)
// and our zoom level (which may have diverged).
RectF pageRect = new RectF(0.0f, 0.0f, pageWidth, pageHeight);
RectF cssPageRect = new RectF(0.0f, 0.0f, cssPageWidth, cssPageHeight);
RectF pageRect = new RectF(pageLeft, pageTop, pageRight, pageBottom);
RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
float ourZoom = mLayerController.getZoomFactor();
mLayerController.setPageRect(RectUtils.scale(pageRect, ourZoom / zoom), cssPageRect);
// Here the page size of the document has changed, but the document being displayed

View File

@ -2032,24 +2032,23 @@ AndroidBridge::IsTablet()
}
void
AndroidBridge::SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight)
AndroidBridge::SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
{
AndroidGeckoLayerClient *client = mLayerClient;
if (!client)
return;
client->SetFirstPaintViewport(aOffsetX, aOffsetY, aZoom, aPageWidth, aPageHeight, aCssPageWidth, aCssPageHeight);
client->SetFirstPaintViewport(aOffset, aZoom, aPageRect, aCssPageRect);
}
void
AndroidBridge::SetPageSize(float aZoom, float aPageWidth, float aPageHeight, float aCssPageWidth, float aCssPageHeight)
AndroidBridge::SetPageRect(float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
{
AndroidGeckoLayerClient *client = mLayerClient;
if (!client)
return;
client->SetPageSize(aZoom, aPageWidth, aPageHeight, aCssPageWidth, aCssPageHeight);
client->SetPageRect(aZoom, aPageRect, aCssPageRect);
}
void

View File

@ -330,9 +330,8 @@ public:
void EnableNetworkNotifications();
void DisableNetworkNotifications();
void SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight);
void SetPageSize(float aZoom, float aPageWidth, float aPageHeight, float aCssPageWidth, float aCssPageHeight);
void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
void SetPageRect(float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);

View File

@ -64,7 +64,7 @@ jmethodID AndroidLocation::jGetTimeMethod = 0;
jclass AndroidGeckoLayerClient::jGeckoLayerClientClass = 0;
jmethodID AndroidGeckoLayerClient::jSetFirstPaintViewport = 0;
jmethodID AndroidGeckoLayerClient::jSetPageSize = 0;
jmethodID AndroidGeckoLayerClient::jSetPageRect = 0;
jmethodID AndroidGeckoLayerClient::jSyncViewportInfoMethod = 0;
jmethodID AndroidGeckoLayerClient::jCreateFrameMethod = 0;
jmethodID AndroidGeckoLayerClient::jActivateProgramMethod = 0;
@ -248,8 +248,8 @@ AndroidGeckoLayerClient::InitGeckoLayerClientClass(JNIEnv *jEnv)
jGeckoLayerClientClass = getClassGlobalRef("org/mozilla/gecko/gfx/GeckoLayerClient");
jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFF)V");
jSetPageSize = getMethod("setPageSize", "(FFFFF)V");
jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFFFFFF)V");
jSetPageRect = getMethod("setPageRect", "(FFFFFFFFF)V");
jSyncViewportInfoMethod = getMethod("syncViewportInfo",
"(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
jCreateFrameMethod = getMethod("createFrame", "()Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;");
@ -651,8 +651,7 @@ AndroidGeckoSurfaceView::Draw2D(jobject buffer, int stride)
}
void
AndroidGeckoLayerClient::SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight)
AndroidGeckoLayerClient::SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
{
NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread
@ -660,20 +659,23 @@ AndroidGeckoLayerClient::SetFirstPaintViewport(float aOffsetX, float aOffsetY, f
return;
AutoLocalJNIFrame jniFrame(env, 0);
return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, aOffsetX, aOffsetY, aZoom, aPageWidth, aPageHeight,
aCssPageWidth, aCssPageHeight);
return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom,
(float)aPageRect.x, (float)aPageRect.y, (float)aPageRect.XMost(), (float)aPageRect.YMost(),
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
void
AndroidGeckoLayerClient::SetPageSize(float aZoom, float aPageWidth, float aPageHeight, float aCssPageWidth, float aCssPageHeight)
AndroidGeckoLayerClient::SetPageRect(float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect)
{
NS_ASSERTION(!isNull(), "SetPageSize called on null layer client!");
NS_ASSERTION(!isNull(), "SetPageRect called on null layer client!");
JNIEnv *env = GetJNIForThread(); // this is called on the compositor thread
if (!env)
return;
AutoLocalJNIFrame jniFrame(env, 0);
return env->CallVoidMethod(wrapped_obj, jSetPageSize, aZoom, aPageWidth, aPageHeight, aCssPageWidth, aCssPageHeight);
return env->CallVoidMethod(wrapped_obj, jSetPageRect, aZoom,
(float)aPageRect.x, (float)aPageRect.y, (float)aPageRect.XMost(), (float)aPageRect.YMost(),
aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
}
void

View File

@ -13,6 +13,7 @@
#include "nsPoint.h"
#include "nsRect.h"
#include "nsString.h"
#include "mozilla/gfx/Rect.h"
//#define FORCE_ALOG 1
@ -171,9 +172,8 @@ public:
AndroidGeckoLayerClient() {}
AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
void SetFirstPaintViewport(float aOffsetX, float aOffsetY, float aZoom, float aPageWidth, float aPageHeight,
float aCssPageWidth, float aCssPageHeight);
void SetPageSize(float aZoom, float aPageWidth, float aPageHeight, float aCssPageWidth, float aCssPageHeight);
void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
void SetPageRect(float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
bool CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame);
@ -183,7 +183,7 @@ public:
protected:
static jclass jGeckoLayerClientClass;
static jmethodID jSetFirstPaintViewport;
static jmethodID jSetPageSize;
static jmethodID jSetPageRect;
static jmethodID jSyncViewportInfoMethod;
static jmethodID jCreateFrameMethod;
static jmethodID jActivateProgramMethod;