Bug 694706 - Get rid of checkerboard for remote viewport. r=cjones

This commit is contained in:
Oleg Romashin 2011-10-20 15:17:09 -07:00
Родитель 6aa0d23e8b
Коммит 1bf4a5f86f
12 изменённых файлов: 74 добавлений и 120 удалений

Просмотреть файл

@ -63,6 +63,7 @@ using nsMouseScrollEvent;
using nsKeyEvent;
using RemoteDOMEvent;
using mozilla::WindowsHandle;
using nscolor;
namespace mozilla {
namespace dom {
@ -190,6 +191,7 @@ parent:
sync GetWidgetNativeData() returns (WindowsHandle value);
SetCursor(PRUint32 value);
SetBackgroundColor(nscolor color);
PContentPermissionRequest(nsCString aType, URI uri);

Просмотреть файл

@ -123,6 +123,7 @@ TabChild::TabChild(PRUint32 aChromeFlags)
, mTabChildGlobal(nsnull)
, mChromeFlags(aChromeFlags)
, mOuterRect(0, 0, 0, 0)
, mLastBackgroundColor(NS_RGB(255, 255, 255))
{
printf("creating %d!\n", NS_IsMainThread());
}
@ -1000,6 +1001,15 @@ TabChild::InitWidget(const nsIntSize& size)
return true;
}
void
TabChild::SetBackgroundColor(const nscolor& aColor)
{
if (mLastBackgroundColor != aColor) {
mLastBackgroundColor = aColor;
SendSetBackgroundColor(mLastBackgroundColor);
}
}
static bool
SendSyncMessageToParent(void* aCallbackData,
const nsAString& aMessage,
@ -1121,4 +1131,3 @@ TabChildGlobal::GetPrincipal()
return nsnull;
return mTabChild->GetPrincipal();
}

Просмотреть файл

@ -255,6 +255,7 @@ public:
nsIPrincipal* GetPrincipal() { return mPrincipal; }
void SetBackgroundColor(const nscolor& aColor);
protected:
NS_OVERRIDE
virtual PRenderFrameChild* AllocPRenderFrame();
@ -278,6 +279,7 @@ private:
nsRefPtr<TabChildGlobal> mTabChildGlobal;
PRUint32 mChromeFlags;
nsIntRect mOuterRect;
nscolor mLastBackgroundColor;
DISALLOW_EVIL_CONSTRUCTORS(TabChild);
};

Просмотреть файл

@ -341,6 +341,17 @@ TabParent::RecvSetCursor(const PRUint32& aCursor)
return true;
}
bool
TabParent::RecvSetBackgroundColor(const nscolor& aColor)
{
if (nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader()) {
if (RenderFrameParent* frame = frameLoader->GetCurrentRemoteFrame()) {
frame->SetBackgroundColor(aColor);
}
}
return true;
}
bool
TabParent::RecvNotifyIMEFocus(const bool& aFocus,
nsIMEUpdatePreference* aPreference,

Просмотреть файл

@ -108,6 +108,7 @@ public:
virtual bool RecvGetIMEOpenState(bool* aValue);
virtual bool RecvSetIMEOpenState(const bool& aValue);
virtual bool RecvSetCursor(const PRUint32& aValue);
virtual bool RecvSetBackgroundColor(const nscolor& aValue);
virtual bool RecvGetDPI(float* aValue);
virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue);
virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType,

Просмотреть файл

@ -56,6 +56,8 @@
/* a presentation of a document, part 2 */
#include "mozilla/dom/PBrowserChild.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/Util.h"
#include "nsPresShell.h"
@ -5092,6 +5094,11 @@ void PresShell::UpdateCanvasBackground()
if (!FrameConstructor()->GetRootElementFrame()) {
mCanvasBackgroundColor = GetDefaultBackgroundColorToDraw();
}
if (XRE_GetProcessType() == GeckoProcessType_Content) {
if (TabChild* tabChild = GetTabChildFrom(this)) {
tabChild->SetBackgroundColor(mCanvasBackgroundColor);
}
}
}
nscolor PresShell::ComputeBackstopColor(nsIView* aDisplayRoot)

Просмотреть файл

@ -62,28 +62,6 @@ namespace layout {
typedef FrameMetrics::ViewID ViewID;
typedef RenderFrameParent::ViewMap ViewMap;
nsRefPtr<ImageContainer> sCheckerboard = nsnull;
class CheckerBoardPatternDeleter : public nsIObserver
{
public:
NS_DECL_NSIOBSERVER
NS_DECL_ISUPPORTS
};
NS_IMPL_ISUPPORTS1(CheckerBoardPatternDeleter, nsIObserver)
NS_IMETHODIMP
CheckerBoardPatternDeleter::Observe(nsISupports* aSubject,
const char* aTopic,
const PRUnichar* aData)
{
if (!strcmp(aTopic, "xpcom-shutdown")) {
sCheckerboard = nsnull;
}
return NS_OK;
}
// Represents (affine) transforms that are calculated from a content view.
struct ViewTransform {
ViewTransform(nsIntPoint aTranslation = nsIntPoint(0, 0), float aXScale = 1, float aYScale = 1)
@ -424,61 +402,14 @@ BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
}
}
#define BOARDSIZE 32
#define CHECKERSIZE 16
already_AddRefed<gfxASurface>
GetBackgroundImage()
{
static unsigned int data[BOARDSIZE * BOARDSIZE];
static bool initialized = false;
if (!initialized) {
initialized = true;
for (unsigned int y = 0; y < BOARDSIZE; y++) {
for (unsigned int x = 0; x < BOARDSIZE; x++) {
bool col_odd = (x / CHECKERSIZE) & 1;
bool row_odd = (y / CHECKERSIZE) & 1;
if (col_odd ^ row_odd) { // xor
data[y * BOARDSIZE + x] = 0xFFFFFFFF;
}
else {
data[y * BOARDSIZE + x] = 0xFFDDDDDD;
}
}
}
}
nsRefPtr<gfxASurface> s =
new gfxImageSurface((unsigned char*) data,
gfxIntSize(BOARDSIZE, BOARDSIZE),
BOARDSIZE * sizeof(unsigned int),
gfxASurface::ImageFormatARGB32);
return s.forget();
}
static void
BuildBackgroundPatternFor(ContainerLayer* aContainer,
ContainerLayer* aShadowRoot,
const FrameMetrics& aMetrics,
const ViewConfig& aConfig,
const gfxRGBA& aColor,
LayerManager* aManager,
nsIFrame* aFrame,
nsDisplayListBuilder* aBuilder)
nsIFrame* aFrame)
{
// We tile a visible region that is the frame's area \setminus the
// rect in our frame onto which valid pixels from remote content
// will be drawn. It's just a waste of CPU cycles to draw a
// checkerboard behind that content.
//
// We want to give the background the illusion of moving while the
// user pans, so we nudge the tiling area a bit based on the
// "desired" scroll offset.
//
// The background-image layer is added to the layer tree "behind"
// the shadow tree. It doesn't matter in theory which is behind/in
// front, except that having the background in front of content
// means we have to be more careful about snapping boundaries,
// whereas having it behind allows us to trade off simplicity for
// "wasted" drawing of a few extra pixels.
ShadowLayer* shadowRoot = aShadowRoot->AsShadowLayer();
gfxMatrix t;
if (!shadowRoot->GetShadowTransform().Is2D(&t)) {
@ -505,57 +436,14 @@ BuildBackgroundPatternFor(ContainerLayer* aContainer,
if (localIntContentVis.Contains(frameRect)) {
return;
}
nsRefPtr<gfxASurface> bgImage = GetBackgroundImage();
gfxIntSize bgImageSize = bgImage->GetSize();
// Set up goop needed to get a cairo image into its own layer
if (!sCheckerboard) {
sCheckerboard = aManager->CreateImageContainer().get();
const Image::Format fmts[] = { Image::CAIRO_SURFACE };
nsRefPtr<Image> img = sCheckerboard->CreateImage(fmts, 1);
CairoImage::Data data = { bgImage.get(), bgImageSize };
static_cast<CairoImage*>(img.get())->SetData(data);
sCheckerboard->SetCurrentImage(img);
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (!observerService) {
return;
}
nsresult rv = observerService->AddObserver(new CheckerBoardPatternDeleter, "xpcom-shutdown", false);
if (NS_FAILED(rv)) {
return;
}
}
nsRefPtr<ImageLayer> layer = aManager->CreateImageLayer();
layer->SetContainer(sCheckerboard);
// The tile source is the entire background image
nsIntRect tileSource(0, 0, bgImageSize.width, bgImageSize.height);
layer->SetTileSourceRect(&tileSource);
// The origin of the tiling plane, top-left of the tile source rect,
// is at layer-space point <0,0>. Set up a translation from that
// origin to the frame top-left, with the little nudge included.
nsIntPoint translation = frameRect.TopLeft();
nsIntPoint panNudge = aConfig.mScrollOffset.ToNearestPixels(auPerDevPixel);
// This offset must be positive to ensure that the tiling rect
// contains the frame's visible rect. The "desired" scroll offset
// is allowed to be negative, however, so we fix that up here.
panNudge.x = (panNudge.x % bgImageSize.width);
if (panNudge.x < 0) panNudge.x += bgImageSize.width;
panNudge.y = (panNudge.y % bgImageSize.height);
if (panNudge.y < 0) panNudge.y += bgImageSize.height;
translation -= panNudge;
layer->SetTransform(gfx3DMatrix::Translation(translation.x, translation.y, 0));
nsRefPtr<ColorLayer> layer = aManager->CreateColorLayer();
layer->SetColor(aColor);
// The visible area of the background is the frame's area minus the
// content area
nsIntRegion bgRgn(frameRect);
bgRgn.Sub(bgRgn, localIntContentVis);
bgRgn.MoveBy(-translation);
bgRgn.MoveBy(-frameRect.TopLeft());
layer->SetVisibleRegion(bgRgn);
aContainer->InsertAfter(layer, nsnull);
@ -564,6 +452,7 @@ BuildBackgroundPatternFor(ContainerLayer* aContainer,
RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader)
: mFrameLoader(aFrameLoader)
, mFrameLoaderDestroyed(false)
, mBackgroundColor(gfxRGBA(1, 1, 1))
{
if (aFrameLoader) {
mContentViews[FrameMetrics::ROOT_SCROLL_ID] =
@ -691,9 +580,9 @@ RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder,
const nsContentView* view = GetContentView(FrameMetrics::ROOT_SCROLL_ID);
BuildBackgroundPatternFor(mContainer,
shadowRoot,
shadowRoot->GetFrameMetrics(),
view->GetViewConfig(),
aManager, aFrame, aBuilder);
mBackgroundColor,
aManager, aFrame);
}
mContainer->SetVisibleRegion(aVisibleRect);

Просмотреть файл

@ -98,6 +98,8 @@ public:
void OwnerContentChanged(nsIContent* aContent);
void SetBackgroundColor(nscolor aColor) { mBackgroundColor = gfxRGBA(aColor); };
protected:
NS_OVERRIDE void ActorDestroy(ActorDestroyReason why);
@ -133,6 +135,8 @@ private:
// It's possible for mFrameLoader==null and
// mFrameLoaderDestroyed==false.
bool mFrameLoaderDestroyed;
// this is gfxRGBA because that's what ColorLayer wants.
gfxRGBA mBackgroundColor;
};
} // namespace layout

Просмотреть файл

@ -91,6 +91,7 @@ fails-if(!browserIsRemote) == test-displayport.html test-displayport-ref.html #
skip-if(!browserIsRemote) != test-displayport-2.html test-displayport-ref.html # bug 593168
skip-if(!browserIsRemote) == 647192-1.html 647192-1-ref.html
skip-if(!browserIsRemote) == 656041-1.html 656041-1-ref.html
skip-if(!browserIsRemote) == test-displayport-bg.html test-displayport-ref.html # bug 694706
# IPC Position-fixed frames/layers test
# Fixed layers are temporarily disabled (bug 656167).

Просмотреть файл

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html reftest-viewport-w="100" reftest-viewport-h="100"
reftest-displayport-w="400" reftest-displayport-h="500"
reftest-async-scroll=true>
<body bgcolor=green style="position: absolute; left:0px; top:0px;width:800px; height:1000px;"></body>
</html>

Просмотреть файл

@ -257,6 +257,10 @@ function setupDisplayport(contentRootElement) {
LogInfo("Setting displayport to <x="+ dpx +", y="+ dpy +", w="+ dpw +", h="+ dph +">");
windowUtils().setDisplayPortForElement(dpx, dpy, dpw, dph, content.document.documentElement);
}
var asyncScroll = attrOrDefault("reftest-async-scroll", false);
if (asyncScroll) {
SendEnableAsyncScroll();
}
// XXX support resolution when needed
@ -751,6 +755,11 @@ function SendFailedLoad(why)
sendAsyncMessage("reftest:FailedLoad", { why: why });
}
function SendEnableAsyncScroll()
{
sendAsyncMessage("reftest:EnableAsyncScroll");
}
// Return true if a snapshot was taken.
function SendInitCanvasWithSnapshot()
{

Просмотреть файл

@ -1346,6 +1346,7 @@ function FinishTestItem()
gDumpLog("REFTEST INFO | Loading a blank page\n");
// After clearing, content will notify us of the assertion count
// and tests will continue.
SetAsyncScroll(false);
SendClear();
}
@ -1442,10 +1443,21 @@ function RegisterMessageListenersAndLoadContentScript()
"reftest:ExpectProcessCrash",
function (m) { RecvExpectProcessCrash(); }
);
gBrowserMessageManager.addMessageListener(
"reftest:EnableAsyncScroll",
function (m) { SetAsyncScroll(true); }
);
gBrowserMessageManager.loadFrameScript("chrome://reftest/content/reftest-content.js", true);
}
function SetAsyncScroll(enabled)
{
gBrowser.QueryInterface(CI.nsIFrameLoaderOwner).frameLoader.renderMode =
enabled ? CI.nsIFrameLoader.RENDER_MODE_ASYNC_SCROLL :
CI.nsIFrameLoader.RENDER_MODE_DEFAULT;
}
function RecvAssertionCount(count)
{
DoAssertionCheck(count);