Bug 783368 - Add critical display port content property. r=roc

Add a property to represent a sub-rectangle of the display port that is
considered 'critical' to render correctly.
This commit is contained in:
Chris Lord 2012-11-21 19:16:51 +00:00
parent 308de53b5b
commit 9a58cff763
8 changed files with 115 additions and 6 deletions

View File

@ -1945,6 +1945,7 @@ GK_ATOM(DeleteTxnName, "Deleting")
GK_ATOM(Remote, "remote")
GK_ATOM(RemoteId, "_remote_id")
GK_ATOM(DisplayPort, "_displayport")
GK_ATOM(CriticalDisplayPort, "_critical_displayport")
// Names for system metrics
GK_ATOM(scrollbar_start_backward, "scrollbar-start-backward")

View File

@ -402,6 +402,54 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetCriticalDisplayPortForElement(float aXPx, float aYPx,
float aWidthPx, float aHeightPx,
nsIDOMElement* aElement)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
nsIPresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
if (!aElement) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
if (!content) {
return NS_ERROR_INVALID_ARG;
}
if (content->GetCurrentDoc() != presShell->GetDocument()) {
return NS_ERROR_INVALID_ARG;
}
nsRect displayport;
if (!nsLayoutUtils::GetDisplayPort(content, &displayport)) {
return NS_ERROR_INVALID_ARG;
}
nsRect criticalDisplayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
nsPresContext::CSSPixelsToAppUnits(aYPx),
nsPresContext::CSSPixelsToAppUnits(aWidthPx),
nsPresContext::CSSPixelsToAppUnits(aHeightPx));
content->SetProperty(nsGkAtoms::CriticalDisplayPort, new nsRect(criticalDisplayport),
DestroyNsRect);
nsIFrame* rootFrame = presShell->GetRootFrame();
if (rootFrame) {
rootFrame->InvalidateFrame();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetResolution(float aXResolution, float aYResolution)
{

View File

@ -148,6 +148,18 @@ interface nsIDOMWindowUtils : nsISupports {
in float aWidthPx, in float aHeightPx,
in nsIDOMElement aElement);
/**
* When a display port is set, this allows a sub-section of that
* display port to be marked as 'critical'. In this scenario, the
* area outside of this rectangle may be rendered at a lower
* detail (for example, by reducing its resolution), or not rendered
* at all under some circumstances.
* This call will have no effect if a display port has not been set.
*/
void setCriticalDisplayPortForElement(in float aXPx, in float aYPx,
in float aWidthPx, in float aHeightPx,
in nsIDOMElement aElement);
/**
* Get/set the resolution at which rescalable web content is drawn.
* Currently this is only (some) thebes content.

View File

@ -33,6 +33,7 @@ public:
: mCompositionBounds(0, 0, 0, 0)
, mContentRect(0, 0, 0, 0)
, mDisplayPort(0, 0, 0, 0)
, mCriticalDisplayPort(0, 0, 0, 0)
, mViewport(0, 0, 0, 0)
, mScrollOffset(0, 0)
, mScrollId(NULL_SCROLL_ID)
@ -50,6 +51,7 @@ public:
return mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
mContentRect.IsEqualEdges(aOther.mContentRect) &&
mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
mViewport.IsEqualEdges(aOther.mViewport) &&
mScrollOffset == aOther.mScrollOffset &&
mScrollId == aOther.mScrollId &&
@ -149,6 +151,14 @@ public:
// displayport set on them. See bug 775452.
gfx::Rect mDisplayPort;
// If non-empty, the area of a frame's contents that is considered critical
// to paint. Area outside of this area (i.e. area inside mDisplayPort, but
// outside of mCriticalDisplayPort) is considered low-priority, and may be
// painted with lower precision, or not painted at all.
//
// The same restrictions for mDisplayPort apply here.
gfx::Rect mCriticalDisplayPort;
// The CSS viewport, which is the dimensions we're using to constrain the
// <html> element of this frame, relative to the top-left of the layer. Note
// that its offset is structured in such a way that it doesn't depend on the

View File

@ -965,6 +965,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
WriteParam(aMsg, aParam.mContentRect);
WriteParam(aMsg, aParam.mScrollOffset);
WriteParam(aMsg, aParam.mDisplayPort);
WriteParam(aMsg, aParam.mCriticalDisplayPort);
WriteParam(aMsg, aParam.mCompositionBounds);
WriteParam(aMsg, aParam.mScrollId);
WriteParam(aMsg, aParam.mResolution);
@ -980,6 +981,7 @@ struct ParamTraits<mozilla::layers::FrameMetrics>
ReadParam(aMsg, aIter, &aResult->mContentRect) &&
ReadParam(aMsg, aIter, &aResult->mScrollOffset) &&
ReadParam(aMsg, aIter, &aResult->mDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mCriticalDisplayPort) &&
ReadParam(aMsg, aIter, &aResult->mCompositionBounds) &&
ReadParam(aMsg, aIter, &aResult->mScrollId) &&
ReadParam(aMsg, aIter, &aResult->mResolution) &&

View File

@ -574,6 +574,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
const nsRect& aVisibleRect,
const nsRect& aViewport,
nsRect* aDisplayPort,
nsRect* aCriticalDisplayPort,
ViewID aScrollId,
const nsDisplayItem::ContainerParameters& aContainerParameters,
bool aMayHaveTouchListeners) {
@ -599,6 +600,14 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
NSAppUnitsToDoublePixels(aDisplayPort->y, auPerDevPixel),
NSAppUnitsToDoublePixels(aDisplayPort->width, auPerDevPixel),
NSAppUnitsToDoublePixels(aDisplayPort->height, auPerDevPixel));
if (aCriticalDisplayPort) {
metrics.mCriticalDisplayPort = mozilla::gfx::Rect(
NSAppUnitsToDoublePixels(aCriticalDisplayPort->x, auPerDevPixel),
NSAppUnitsToDoublePixels(aCriticalDisplayPort->y, auPerDevPixel),
NSAppUnitsToDoublePixels(aCriticalDisplayPort->width, auPerDevPixel),
NSAppUnitsToDoublePixels(aCriticalDisplayPort->height, auPerDevPixel));
}
}
nsIScrollableFrame* scrollableFrame = nullptr;
@ -1090,12 +1099,15 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
: FrameMetrics::NULL_SCROLL_ID;
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
nsRect displayport;
nsRect displayport, criticalDisplayport;
bool usingDisplayport = false;
bool usingCriticalDisplayport = false;
if (rootScrollFrame) {
nsIContent* content = rootScrollFrame->GetContent();
if (content) {
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
usingCriticalDisplayport =
nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
}
}
@ -1114,8 +1126,9 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
RecordFrameMetrics(aForFrame, rootScrollFrame,
root, mVisibleRect, viewport,
(usingDisplayport ? &displayport : nullptr), id,
containerParameters, mayHaveTouchListeners);
(usingDisplayport ? &displayport : nullptr),
(usingCriticalDisplayport ? &criticalDisplayport : nullptr),
id, containerParameters, mayHaveTouchListeners);
if (usingDisplayport &&
!(root->GetContentFlags() & Layer::CONTENT_OPAQUE)) {
// See bug 693938, attachment 567017
@ -2947,13 +2960,17 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
bool usingDisplayport = false;
nsRect displayport;
bool usingCriticalDisplayport = false;
nsRect displayport, criticalDisplayport;
if (content) {
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
usingCriticalDisplayport =
nsLayoutUtils::GetCriticalDisplayPort(content, &criticalDisplayport);
}
RecordFrameMetrics(mScrolledFrame, mScrollFrame, layer, mVisibleRect, viewport,
(usingDisplayport ? &displayport : nullptr), scrollId,
aContainerParameters, false);
(usingDisplayport ? &displayport : nullptr),
(usingCriticalDisplayport ? &criticalDisplayport : nullptr),
scrollId, aContainerParameters, false);
return layer.forget();
}

View File

@ -378,6 +378,20 @@ nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult)
return true;
}
bool
nsLayoutUtils::GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult)
{
void* property = aContent->GetProperty(nsGkAtoms::CriticalDisplayPort);
if (!property) {
return false;
}
if (aResult) {
*aResult = *static_cast<nsRect*>(property);
}
return true;
}
nsIFrame*
nsLayoutUtils::GetLastContinuationWithChild(nsIFrame* aFrame)
{

View File

@ -78,6 +78,11 @@ public:
*/
static bool GetDisplayPort(nsIContent* aContent, nsRect *aResult);
/**
* Get the critical display port for the given element.
*/
static bool GetCriticalDisplayPort(nsIContent* aContent, nsRect* aResult);
/**
* Use heuristics to figure out the child list that
* aChildFrame is currently in.