--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -17,16 +17,17 @@
#define PIXMAN_DONT_DEFINE_STDINT
#include "pixman.h"
#include "BasicTiledThebesLayer.h"
#include "BasicLayersImpl.h"
#include "BasicThebesLayer.h"
#include "BasicContainerLayer.h"
#include "mozilla/Preferences.h"
+#include "nsIWidget.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
/**
* Clips to the smallest device-pixel-aligned rectangle containing aRect
@@ -127,17 +128,18 @@ BasicLayerManager::~BasicLayerManager()
mRoot = nsnull;
MOZ_COUNT_DTOR(BasicLayerManager);
}
void
BasicLayerManager::SetDefaultTarget(gfxContext* aContext,
- BufferMode aDoubleBuffering)
+ BufferMode aDoubleBuffering,
+ ScreenRotation aRotation)
{
NS_ASSERTION(!InTransaction(),
"Must set default target outside transaction");
mDefaultTarget = aContext;
mDoubleBuffering = aDoubleBuffering;
}
void
@@ -917,17 +919,17 @@ already_AddRefed<ReadbackLayer>
BasicLayerManager::CreateReadbackLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
nsRefPtr<ReadbackLayer> layer = new BasicReadbackLayer(this);
return layer.forget();
}
BasicShadowLayerManager::BasicShadowLayerManager(nsIWidget* aWidget) :
- BasicLayerManager(aWidget)
+ BasicLayerManager(aWidget), mTargetRotation(ROTATION_0)
{
MOZ_COUNT_CTOR(BasicShadowLayerManager);
}
BasicShadowLayerManager::~BasicShadowLayerManager()
{
MOZ_COUNT_DTOR(BasicShadowLayerManager);
}
@@ -938,16 +940,28 @@ BasicShadowLayerManager::GetMaxTextureSi
if (HasShadowManager()) {
return ShadowLayerForwarder::GetMaxTextureSize();
}
return PR_INT32_MAX;
}
void
+BasicShadowLayerManager::SetDefaultTarget(gfxContext* aContext,
+ BufferMode aDoubleBuffering,
+ ScreenRotation aRotation)
+{
+ BasicLayerManager::SetDefaultTarget(aContext, aDoubleBuffering, aRotation);
+ mTargetRotation = aRotation;
+ if (mWidget) {
+ mTargetBounds = mWidget->GetNaturalBounds();
+ }
+}
+
+void
BasicShadowLayerManager::SetRoot(Layer* aLayer)
{
if (mRoot != aLayer) {
if (HasShadowManager()) {
// Have to hold the old root and its children in order to
// maintain the same view of the layer tree in this process as
// the parent sees. Otherwise layers can be destroyed
// mid-transaction and bad things can happen (v. bug 612573)
@@ -976,17 +990,17 @@ BasicShadowLayerManager::BeginTransactio
{
NS_ABORT_IF_FALSE(mKeepAlive.IsEmpty(), "uncommitted txn?");
nsRefPtr<gfxContext> targetContext = aTarget;
// If the last transaction was incomplete (a failed DoEmptyTransaction),
// don't signal a new transaction to ShadowLayerForwarder. Carry on adding
// to the previous transaction.
if (HasShadowManager()) {
- ShadowLayerForwarder::BeginTransaction();
+ ShadowLayerForwarder::BeginTransaction(mTargetBounds, mTargetRotation);
// If we have a non-default target, we need to let our shadow manager draw
// to it. This will happen at the end of the transaction.
if (aTarget && (aTarget != mDefaultTarget) &&
XRE_GetProcessType() == GeckoProcessType_Default) {
mShadowTarget = aTarget;
// Create a temporary target for ourselves, so that mShadowTarget is only
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -5,21 +5,21 @@
#ifndef GFX_BASICLAYERS_H
#define GFX_BASICLAYERS_H
#include "Layers.h"
#include "gfxContext.h"
#include "gfxCachedTempSurface.h"
+#include "mozilla/layers/ShadowLayers.h"
+#include "mozilla/WidgetUtils.h"
#include "nsAutoRef.h"
#include "nsThreadUtils.h"
-#include "mozilla/layers/ShadowLayers.h"
-
class nsIWidget;
namespace mozilla {
namespace layers {
class BasicShadowableLayer;
class ShadowThebesLayer;
class ShadowContainerLayer;
@@ -75,17 +75,18 @@ public:
* results, by using a temporary buffer when necessary. In BUFFERED
* mode we always completely overwrite the contents of aContext's
* destination surface (within the clip region) using OPERATOR_SOURCE.
*/
enum BufferMode {
BUFFER_NONE,
BUFFER_BUFFERED
};
- void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
+ virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
+ ScreenRotation aRotation);
gfxContext* GetDefaultTarget() { return mDefaultTarget; }
nsIWidget* GetRetainerWidget() { return mWidget; }
void ClearRetainerWidget() { mWidget = nsnull; }
virtual bool IsWidgetLayerManager() { return mWidget != nsnull; }
virtual void BeginTransaction();
@@ -216,16 +217,18 @@ public:
}
virtual ShadowLayerManager* AsShadowManager()
{
return this;
}
virtual PRInt32 GetMaxTextureSize() const;
+ virtual void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering,
+ ScreenRotation aRotation) MOZ_OVERRIDE;
virtual void BeginTransactionWithTarget(gfxContext* aTarget);
virtual bool EndEmptyTransaction();
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags = END_DEFAULT);
virtual void SetRoot(Layer* aLayer);
@@ -256,21 +259,30 @@ public:
void SetRepeatTransaction() { mRepeatTransaction = true; }
private:
/**
* Forward transaction results to the parent context.
*/
void ForwardTransaction();
+ // The bounds of |mTarget| in device pixels.
+ nsIntRect mTargetBounds;
+
+ LayerRefArray mKeepAlive;
+
+ // Sometimes we draw to targets that don't natively support
+ // landscape/portrait orientation. When we need to implement that
+ // ourselves, |mTargetRotation| describes the induced transform we
+ // need to apply when compositing content to our target.
+ ScreenRotation mTargetRotation;
+
// Used to repeat the transaction right away (to avoid rebuilding
// a display list) to support progressive drawing.
bool mRepeatTransaction;
-
- LayerRefArray mKeepAlive;
};
class BasicShadowableThebesLayer;
class BasicShadowableLayer : public ShadowableLayer
{
public:
BasicShadowableLayer()
{
--- a/gfx/layers/d3d10/LayerManagerD3D10.cpp
+++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp
@@ -15,16 +15,17 @@
#include "ContainerLayerD3D10.h"
#include "ThebesLayerD3D10.h"
#include "ColorLayerD3D10.h"
#include "CanvasLayerD3D10.h"
#include "ReadbackLayerD3D10.h"
#include "ImageLayerD3D10.h"
#include "mozilla/layers/PLayerChild.h"
+#include "mozilla/WidgetUtils.h"
#include "../d3d9/Nv3DVUtils.h"
#include "gfxCrashReporterUtils.h"
using namespace std;
using namespace mozilla::gfx;
@@ -724,17 +725,18 @@ LayerManagerD3D10::Render()
}
device()->RSSetScissorRects(1, &r);
static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
if (mTarget) {
PaintToTarget();
} else if (mBackBuffer) {
- ShadowLayerForwarder::BeginTransaction();
+ ShadowLayerForwarder::BeginTransaction(mWidget->GetNaturalBounds(),
+ ROTATION_0);
nsIntRect contentRect = nsIntRect(0, 0, rect.width, rect.height);
if (!mRootForShadowTree) {
mRootForShadowTree = new DummyRoot(this);
mRootForShadowTree->SetShadow(ConstructShadowFor(mRootForShadowTree));
CreatedContainerLayer(mRootForShadowTree);
ShadowLayerForwarder::SetRoot(mRootForShadowTree);
}
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -417,16 +417,23 @@ CompositorParent::Composite()
bool requestNextFrame = TransformShadowTree(mLastCompose);
if (requestNextFrame) {
ScheduleComposition();
}
RenderTraceLayers(aLayer, "0000");
+ if (LAYERS_OPENGL == mLayerManager->GetBackendType() &&
+ !mTargetConfig.naturalBounds().IsEmpty()) {
+ LayerManagerOGL* lm = static_cast<LayerManagerOGL*>(mLayerManager.get());
+ lm->SetWorldTransform(
+ ComputeGLTransformForRotation(mTargetConfig.naturalBounds(),
+ mTargetConfig.rotation()));
+ }
mLayerManager->EndEmptyTransaction();
#ifdef COMPOSITOR_PERFORMANCE_WARNING
if (mExpectedComposeTime + TimeDuration::FromMilliseconds(15) < TimeStamp::Now()) {
printf_stderr("Compositor: Composite took %i ms.\n",
15 + (int)(TimeStamp::Now() - mExpectedComposeTime).ToMilliseconds());
}
#endif
@@ -689,18 +696,20 @@ CompositorParent::SyncViewportInfo(const
#ifdef MOZ_WIDGET_ANDROID
AndroidBridge::Bridge()->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
aScrollOffset, aScaleX, aScaleY);
#endif
}
void
CompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+ const TargetConfig& aTargetConfig,
bool isFirstPaint)
{
+ mTargetConfig = aTargetConfig;
mIsFirstPaint = mIsFirstPaint || isFirstPaint;
mLayersUpdated = true;
Layer* root = aLayerTree->GetRoot();
mLayerManager->SetRoot(root);
if (root) {
SetShadowProperties(root);
}
ScheduleComposition();
@@ -893,16 +902,17 @@ public:
virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendType,
const uint64_t& aId,
LayersBackend* aBackend,
int32_t* aMaxTextureSize) MOZ_OVERRIDE;
virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+ const TargetConfig& aTargetConfig,
bool isFirstPaint) MOZ_OVERRIDE;
private:
void DeferredDestroy();
// There can be many CPCPs, and IPDL-generated code doesn't hold a
// reference to top-level actors. So we hold a reference to
// ourself. This is released (deferred) in ActorDestroy().
@@ -992,18 +1002,20 @@ CrossProcessCompositorParent::DeallocPLa
{
ShadowLayersParent* slp = static_cast<ShadowLayersParent*>(aLayers);
RemoveIndirectTree(slp->GetId());
delete aLayers;
return true;
}
void
-CrossProcessCompositorParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
- bool isFirstPaint)
+CrossProcessCompositorParent::ShadowLayersUpdated(
+ ShadowLayersParent* aLayerTree,
+ const TargetConfig& aTargetConfig,
+ bool isFirstPaint)
{
uint64_t id = aLayerTree->GetId();
MOZ_ASSERT(id != 0);
Layer* shadowRoot = aLayerTree->GetRoot();
if (shadowRoot) {
SetShadowProperties(shadowRoot);
}
UpdateIndirectTree(id, shadowRoot, isFirstPaint);
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -65,16 +65,17 @@ public:
virtual ~CompositorParent();
virtual bool RecvWillStop() MOZ_OVERRIDE;
virtual bool RecvStop() MOZ_OVERRIDE;
virtual bool RecvPause() MOZ_OVERRIDE;
virtual bool RecvResume() MOZ_OVERRIDE;
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+ const TargetConfig& aTargetConfig,
bool isFirstPaint) MOZ_OVERRIDE;
void Destroy();
LayerManager* GetLayerManager() { return mLayerManager; }
void SetTransformation(float aScale, nsIntPoint aScrollOffset);
void AsyncRender();
@@ -222,16 +223,17 @@ private:
* fixed position layers remain in the same position.
*/
void TransformFixedLayers(Layer* aLayer,
const gfxPoint& aTranslation,
const gfxPoint& aScaleDiff);
nsRefPtr<LayerManager> mLayerManager;
nsIWidget* mWidget;
+ TargetConfig mTargetConfig;
CancelableTask *mCurrentCompositeTask;
TimeStamp mLastCompose;
#ifdef COMPOSITOR_PERFORMANCE_WARNING
TimeStamp mExpectedComposeTime;
#endif
bool mPaused;
float mXScale;
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -1,34 +1,41 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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/. */
include LayersSurfaces;
+using mozilla::ScreenRotation;
include protocol PCompositor;
include protocol PGrallocBuffer;
include protocol PLayer;
include protocol PRenderFrame;
include "gfxipc/ShadowLayerUtils.h";
+include "mozilla/WidgetUtils.h";
/**
* The layers protocol is spoken between thread contexts that manage
* layer (sub)trees. The protocol comprises atomically publishing
* layer subtrees to a "shadow" thread context (which grafts the
* subtree into its own tree), and atomically updating a published
* subtree. ("Atomic" in this sense is wrt painting.)
*/
namespace mozilla {
namespace layers {
+struct TargetConfig {
+ nsIntRect naturalBounds;
+ ScreenRotation rotation;
+};
+
// Create a shadow layer for |layer|
struct OpCreateThebesLayer { PLayer layer; };
struct OpCreateContainerLayer { PLayer layer; };
struct OpCreateImageLayer { PLayer layer; };
struct OpCreateColorLayer { PLayer layer; };
struct OpCreateCanvasLayer { PLayer layer; };
struct OpCreateRefLayer { PLayer layer; };
@@ -186,24 +193,24 @@ parent:
* is returned.
*/
sync PGrallocBuffer(gfxIntSize size, gfxContentType content)
returns (MaybeMagicGrallocBufferHandle handle);
async PLayer();
// The isFirstPaint flag can be used to indicate that this is the first update
// for a particular document.
- sync Update(Edit[] cset, bool isFirstPaint)
+ sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
returns (EditReply[] reply);
// Composite the layer tree to the given surface, and return the surface.
sync DrawToSurface(SurfaceDescriptor surfaceIn)
returns (SurfaceDescriptor surfaceOut);
// We don't need to send a sync transaction if
// no transaction operate require a swap.
- async UpdateNoSwap(Edit[] cset, bool isFirstPaint);
+ async UpdateNoSwap(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint);
async __delete__();
};
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/ipc/ShadowLayerUtils.h
+++ b/gfx/layers/ipc/ShadowLayerUtils.h
@@ -6,16 +6,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef IPC_ShadowLayerUtils_h
#define IPC_ShadowLayerUtils_h
#include "IPC/IPCMessageUtils.h"
#include "Layers.h"
#include "GLContext.h"
+#include "mozilla/WidgetUtils.h"
#if defined(MOZ_ENABLE_D3D10_LAYER)
# include "mozilla/layers/ShadowLayerUtilsD3D10.h"
#endif
#if defined(MOZ_X11)
# include "mozilla/layers/ShadowLayerUtilsX11.h"
#else
@@ -102,11 +103,18 @@ struct ParamTraits<mozilla::gl::TextureI
template <>
struct ParamTraits<mozilla::layers::MagicGrallocBufferHandle> {
typedef mozilla::layers::MagicGrallocBufferHandle paramType;
static void Write(Message*, const paramType&) {}
static bool Read(const Message*, void**, paramType*) { return false; }
};
#endif // !defined(MOZ_HAVE_XSURFACEDESCRIPTORGRALLOC)
-}
+template <>
+struct ParamTraits<mozilla::ScreenRotation>
+ : public EnumSerializer<mozilla::ScreenRotation,
+ mozilla::ROTATION_0,
+ mozilla::ROTATION_COUNT>
+{};
+
+} // namespace IPC
#endif // IPC_ShadowLayerUtils_h
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -36,17 +36,22 @@ typedef std::set<ShadowableLayer*> Shado
class Transaction
{
public:
Transaction()
: mSwapRequired(false)
, mOpen(false)
{}
- void Begin() { mOpen = true; }
+ void Begin(const nsIntRect& aTargetBounds, ScreenRotation aRotation)
+ {
+ mOpen = true;
+ mTargetBounds = aTargetBounds;
+ mTargetRotation = aRotation;
+ }
void AddEdit(const Edit& aEdit)
{
NS_ABORT_IF_FALSE(!Finished(), "forgot BeginTransaction?");
mCset.push_back(aEdit);
}
void AddPaint(const Edit& aPaint)
{
@@ -87,16 +92,18 @@ public:
return mCset.empty() && mPaints.empty() && mMutants.empty();
}
bool Finished() const { return !mOpen && Empty(); }
EditVector mCset;
EditVector mPaints;
BufferArray mDyingBuffers;
ShadowableLayerSet mMutants;
+ nsIntRect mTargetBounds;
+ ScreenRotation mTargetRotation;
bool mSwapRequired;
private:
bool mOpen;
// disabled
Transaction(const Transaction&);
Transaction& operator=(const Transaction&);
@@ -118,21 +125,22 @@ ShadowLayerForwarder::ShadowLayerForward
ShadowLayerForwarder::~ShadowLayerForwarder()
{
NS_ABORT_IF_FALSE(mTxn->Finished(), "unfinished transaction?");
delete mTxn;
}
void
-ShadowLayerForwarder::BeginTransaction()
+ShadowLayerForwarder::BeginTransaction(const nsIntRect& aTargetBounds,
+ ScreenRotation aRotation)
{
NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to");
NS_ABORT_IF_FALSE(mTxn->Finished(), "uncommitted txn?");
- mTxn->Begin();
+ mTxn->Begin(aTargetBounds, aRotation);
}
static PLayerChild*
Shadow(ShadowableLayer* aLayer)
{
return aLayer->GetShadow();
}
@@ -320,32 +328,35 @@ ShadowLayerForwarder::EndTransaction(Inf
cset.AppendElements(&mTxn->mCset.front(), mTxn->mCset.size());
}
// Paints after non-paint ops, including attribute changes. See
// above.
if (!mTxn->mPaints.empty()) {
cset.AppendElements(&mTxn->mPaints.front(), mTxn->mPaints.size());
}
+ TargetConfig targetConfig(mTxn->mTargetBounds, mTxn->mTargetRotation);
+
MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send..."));
PlatformSyncBeforeUpdate();
if (mTxn->mSwapRequired) {
MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
RenderTraceScope rendertrace3("Forward Transaction", "000093");
- if (!mShadowManager->SendUpdate(cset, mIsFirstPaint, aReplies)) {
+ if (!mShadowManager->SendUpdate(cset, targetConfig, mIsFirstPaint,
+ aReplies)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
}
} else {
// If we don't require a swap we can call SendUpdateNoSwap which
// assumes that aReplies is empty (DEBUG assertion)
MOZ_LAYERS_LOG(("[LayersForwarder] sending no swap transaction..."));
RenderTraceScope rendertrace3("Forward NoSwap Transaction", "000093");
- if (!mShadowManager->SendUpdateNoSwap(cset, mIsFirstPaint)) {
+ if (!mShadowManager->SendUpdateNoSwap(cset, targetConfig, mIsFirstPaint)) {
MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
return false;
}
}
mIsFirstPaint = false;
MOZ_LAYERS_LOG(("[LayersForwarder] ... done"));
return true;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -9,16 +9,17 @@
#define mozilla_layers_ShadowLayers_h 1
#include "gfxASurface.h"
#include "GLDefs.h"
#include "ImageLayers.h"
#include "LayersBackend.h"
#include "mozilla/ipc/SharedMemory.h"
+#include "mozilla/WidgetUtils.h"
class gfxSharedImageSurface;
namespace mozilla {
namespace gl {
class GLContext;
class TextureImage;
@@ -111,17 +112,18 @@ public:
typedef gfxASurface::gfxContentType gfxContentType;
virtual ~ShadowLayerForwarder();
/**
* Begin recording a transaction to be forwarded atomically to a
* ShadowLayerManager.
*/
- void BeginTransaction();
+ void BeginTransaction(const nsIntRect& aTargetBounds,
+ ScreenRotation aRotation);
/**
* The following methods may only be called after BeginTransaction()
* but before EndTransaction(). They mirror the LayerManager
* interface in Layers.h.
*/
/**
--- a/gfx/layers/ipc/ShadowLayersManager.h
+++ b/gfx/layers/ipc/ShadowLayersManager.h
@@ -5,22 +5,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_layers_ShadowLayersManager_h
#define mozilla_layers_ShadowLayersManager_h
namespace mozilla {
namespace layers {
+class TargetConfig;
class ShadowLayersParent;
class ShadowLayersManager
{
public:
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
- // FIXME nuke this
+ const TargetConfig& aTargetConfig,
bool isFirstPaint) = 0;
};
} // layers
} // mozilla
#endif // mozilla_layers_ShadowLayersManager_h
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -114,26 +114,28 @@ ShadowLayersParent::Destroy()
static_cast<ShadowLayerParent*>(ManagedPLayerParent()[i]);
slp->Destroy();
}
}
/* virtual */
bool
ShadowLayersParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
- const bool& isFirstPaint)
+ const TargetConfig& targetConfig,
+ const bool& isFirstPaint)
{
InfallibleTArray<EditReply> noReplies;
- bool success = RecvUpdate(cset, isFirstPaint, &noReplies);
+ bool success = RecvUpdate(cset, targetConfig, isFirstPaint, &noReplies);
NS_ABORT_IF_FALSE(noReplies.Length() == 0, "RecvUpdateNoSwap requires a sync Update to carry Edits");
return success;
}
bool
ShadowLayersParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
+ const TargetConfig& targetConfig,
const bool& isFirstPaint,
InfallibleTArray<EditReply>* reply)
{
#ifdef COMPOSITOR_PERFORMANCE_WARNING
TimeStamp updateStart = TimeStamp::Now();
#endif
MOZ_LAYERS_LOG(("[ParentSide] received txn with %d edits", cset.Length()));
@@ -412,17 +414,17 @@ ShadowLayersParent::RecvUpdate(const Inf
reply->AppendElements(&replyv.front(), replyv.size());
}
// Ensure that any pending operations involving back and front
// buffers have completed, so that neither process stomps on the
// other's buffer contents.
ShadowLayerManager::PlatformSyncBeforeReplyUpdate();
- mShadowLayersManager->ShadowLayersUpdated(this, isFirstPaint);
+ mShadowLayersManager->ShadowLayersUpdated(this, targetConfig, isFirstPaint);
#ifdef COMPOSITOR_PERFORMANCE_WARNING
int compositeTime = (int)(mozilla::TimeStamp::Now() - updateStart).ToMilliseconds();
if (compositeTime > 15) {
printf_stderr("Compositor: Layers update took %i ms (blocking gecko).\n", compositeTime);
}
#endif
--- a/gfx/layers/ipc/ShadowLayersParent.h
+++ b/gfx/layers/ipc/ShadowLayersParent.h
@@ -43,23 +43,25 @@ public:
uint64_t GetId() const { return mId; }
ContainerLayer* GetRoot() const { return mRoot; }
virtual void DestroySharedSurface(gfxSharedImageSurface* aSurface);
virtual void DestroySharedSurface(SurfaceDescriptor* aSurface);
protected:
virtual bool RecvUpdate(const EditArray& cset,
+ const TargetConfig& targetConfig,
const bool& isFirstPaint,
EditReplyArray* reply) MOZ_OVERRIDE;
virtual bool RecvDrawToSurface(const SurfaceDescriptor& surfaceIn,
SurfaceDescriptor* surfaceOut) MOZ_OVERRIDE;
virtual bool RecvUpdateNoSwap(const EditArray& cset,
+ const TargetConfig& targetConfig,
const bool& isFirstPaint) MOZ_OVERRIDE;
virtual PGrallocBufferParent*
AllocPGrallocBuffer(const gfxIntSize& aSize, const gfxContentType& aContent,
MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
virtual bool
DeallocPGrallocBuffer(PGrallocBufferParent* actor) MOZ_OVERRIDE;
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -552,16 +552,17 @@ RenderFrameParent::ContentViewScaleChang
{
// Since the scale has changed for a view, it and its descendents need their
// shadow-space attributes updated. It's easiest to rebuild the view map.
BuildViewMap();
}
void
RenderFrameParent::ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+ const TargetConfig& aTargetConfig,
bool isFirstPaint)
{
// View map must only contain views that are associated with the current
// shadow layer tree. We must always update the map when shadow layers
// are updated.
BuildViewMap();
TriggerRepaint();
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -22,30 +22,32 @@ class nsSubDocumentFrame;
namespace mozilla {
class InputEvent;
namespace layers {
class AsyncPanZoomController;
class GestureEventListener;
+class TargetConfig;
class ShadowLayersParent;
}
namespace layout {
class RemoteContentController;
class RenderFrameParent : public PRenderFrameParent,
public mozilla::layers::ShadowLayersManager
{
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::ContainerLayer ContainerLayer;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
+ typedef mozilla::layers::TargetConfig TargetConfig;
typedef mozilla::layers::ShadowLayersParent ShadowLayersParent;
typedef FrameMetrics::ViewID ViewID;
public:
typedef std::map<ViewID, nsRefPtr<nsContentView> > ViewMap;
/**
* Select the desired scrolling behavior. If ASYNC_PAN_ZOOM is
@@ -65,16 +67,17 @@ public:
* Helper function for getting a non-owning reference to a scrollable.
* @param aId The ID of the frame.
*/
nsContentView* GetContentView(ViewID aId = FrameMetrics::ROOT_SCROLL_ID);
void ContentViewScaleChanged(nsContentView* aView);
virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
+ const TargetConfig& aTargetConfig,
bool isFirstPaint) MOZ_OVERRIDE;
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsSubDocumentFrame* aFrame,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
--- a/widget/Makefile.in
+++ b/widget/Makefile.in
@@ -38,26 +38,25 @@ endif
ifdef MOZ_ENABLE_GTK2
DIRS += gtk2
ifdef MOZ_X11
DIRS += gtkxtbin
endif
endif
-EXPORTS_NAMESPACES = IPC
+EXPORTS_NAMESPACES = IPC mozilla
EXPORTS_IPC = \
nsGUIEventIPC.h \
$(NULL)
-EXPORTS_NAMESPACES += mozilla
-
EXPORTS_mozilla = \
LookAndFeel.h \
+ WidgetUtils.h \
$(NULL)
ifdef MOZ_INSTRUMENT_EVENT_LOOP
EXPORTS_mozilla += \
WidgetTraceEvent.h \
$(NULL)
endif
new file mode 100644
--- /dev/null
+++ b/widget/WidgetUtils.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
+
+#ifndef mozilla_WidgetUtils_h
+#define mozilla_WidgetUtils_h
+
+#include "gfxMatrix.h"
+
+namespace mozilla {
+
+// NB: these must match up with pseudo-enum in nsIScreen.idl.
+enum ScreenRotation {
+ ROTATION_0 = 0,
+ ROTATION_90,
+ ROTATION_180,
+ ROTATION_270,
+
+ ROTATION_COUNT
+};
+
+gfxMatrix ComputeGLTransformForRotation(const nsIntRect& aBounds,
+ ScreenRotation aRotation);
+
+} // namespace mozilla
+
+#endif // mozilla_WidgetUtils_h
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -63,16 +63,22 @@ static android::FramebufferNativeWindow
static bool sFramebufferOpen;
static bool sUsingOMTC;
static bool sScreenInitialized;
static nsRefPtr<gfxASurface> sOMTCSurface;
static pthread_t sFramebufferWatchThread;
namespace {
+static PRUint32
+EffectiveScreenRotation()
+{
+ return (sScreenRotation + sPhysicalScreenRotation) % (360 / 90);
+}
+
class ScreenOnOffEvent : public nsRunnable {
public:
ScreenOnOffEvent(bool on)
: mIsOn(on)
{}
NS_IMETHOD Run() {
nsSizeModeEvent event(true, NS_SIZEMODE, NULL);
@@ -231,17 +237,18 @@ nsWindow::DoDraw(void)
{
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
gfxUtils::PathFromRegion(ctx, event.region);
ctx->Clip();
// No double-buffering needed.
AutoLayerManagerSetup setupLayerManager(
- gWindowToRedraw, ctx, BasicLayerManager::BUFFER_NONE);
+ gWindowToRedraw, ctx, BasicLayerManager::BUFFER_NONE,
+ ScreenRotation(EffectiveScreenRotation()));
gWindowToRedraw->mEventCallback(&event);
}
if (!sUsingOMTC) {
targetSurface->Flush();
Framebuffer::Present(event.region);
}
} else {
@@ -597,16 +604,22 @@ nsWindow::GetGLFrameBufferFormat()
mLayerManager->GetBackendType() == mozilla::layers::LAYERS_OPENGL) {
// We directly map the hardware fb on Gonk. The hardware fb
// has RGB format.
return LOCAL_GL_RGB;
}
return LOCAL_GL_NONE;
}
+nsIntRect
+nsWindow::GetNaturalBounds()
+{
+ return gScreenBounds;
+}
+
// nsScreenGonk.cpp
nsScreenGonk::nsScreenGonk(void *nativeScreen)
{
}
nsScreenGonk::~nsScreenGonk()
{
@@ -671,42 +684,26 @@ nsScreenGonk::SetRotation(PRUint32 aRota
{
if (!(ROTATION_0_DEG <= aRotation && aRotation <= ROTATION_270_DEG))
return NS_ERROR_ILLEGAL_VALUE;
if (sScreenRotation == aRotation)
return NS_OK;
sScreenRotation = aRotation;
- sRotationMatrix.Reset();
- switch ((aRotation + sPhysicalScreenRotation) % (360 / 90)) {
- case nsIScreen::ROTATION_0_DEG:
- sVirtualBounds = gScreenBounds;
- break;
- case nsIScreen::ROTATION_90_DEG:
- sRotationMatrix.Translate(gfxPoint(gScreenBounds.width, 0));
- sRotationMatrix.Rotate(M_PI / 2);
+ sRotationMatrix =
+ ComputeGLTransformForRotation(gScreenBounds,
+ ScreenRotation(EffectiveScreenRotation()));
+ PRUint32 rotation = EffectiveScreenRotation();
+ if (rotation == nsIScreen::ROTATION_90_DEG ||
+ rotation == nsIScreen::ROTATION_270_DEG) {
sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height,
- gScreenBounds.width);
- break;
- case nsIScreen::ROTATION_180_DEG:
- sRotationMatrix.Translate(gfxPoint(gScreenBounds.width,
- gScreenBounds.height));
- sRotationMatrix.Rotate(M_PI);
+ gScreenBounds.width);
+ } else {
sVirtualBounds = gScreenBounds;
- break;
- case nsIScreen::ROTATION_270_DEG:
- sRotationMatrix.Translate(gfxPoint(0, gScreenBounds.height));
- sRotationMatrix.Rotate(M_PI * 3 / 2);
- sVirtualBounds = nsIntRect(0, 0, gScreenBounds.height,
- gScreenBounds.width);
- break;
- default:
- MOZ_NOT_REACHED("Unknown rotation");
- break;
}
for (unsigned int i = 0; i < sTopWindows.Length(); i++)
sTopWindows[i]->Resize(sVirtualBounds.width,
sVirtualBounds.height,
!i);
nsAppShell::NotifyScreenRotation();
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -100,16 +100,18 @@ public:
gfxASurface* GetThebesSurface();
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction);
NS_IMETHOD_(InputContext) GetInputContext();
virtual PRUint32 GetGLFrameBufferFormat() MOZ_OVERRIDE;
+ virtual nsIntRect GetNaturalBounds() MOZ_OVERRIDE;
+
protected:
nsWindow* mParent;
bool mVisible;
nsIntRegion mDirtyRegion;
InputContext mInputContext;
nsCOMPtr<nsIIdleServiceInternal> mIdleService;
void BringToTop();
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -82,18 +82,18 @@ typedef nsEventStatus (* EVENT_CALLBACK)
#endif
#ifdef XP_WIN
#define NS_NATIVE_TSF_THREAD_MGR 100
#define NS_NATIVE_TSF_CATEGORY_MGR 101
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
#endif
#define NS_IWIDGET_IID \
- { 0x97afe930, 0x72d7, 0x4d95, \
- { 0x88, 0x5f, 0x37, 0x09, 0x14, 0x2a, 0xf4, 0xe2 } }
+ { 0x91aafae4, 0xd814, 0x4803, \
+ { 0x9a, 0xf5, 0xb0, 0x2f, 0x1b, 0x2c, 0xaf, 0x57 } }
/*
* Window shadow styles
* Also used for the -moz-window-shadow CSS property
*/
#define NS_STYLE_WINDOW_SHADOW_NONE 0
#define NS_STYLE_WINDOW_SHADOW_DEFAULT 1
@@ -1565,16 +1565,34 @@ class nsIWidget : public nsISupports {
/**
* Returns true to indicate that this widget paints an opaque background
* that we want to be visible under the page, so layout should not force
* a default background.
*/
virtual bool WidgetPaintsBackground() { return false; }
+ /**
+ * Get the natural bounds of this widget. This method is only
+ * meaningful for widgets for which Gecko implements screen
+ * rotation natively. When this is the case, GetBounds() returns
+ * the widget bounds taking rotation into account, and
+ * GetNaturalBounds() returns the bounds *not* taking rotation
+ * into account.
+ *
+ * No code outside of the composition pipeline should know or care
+ * about this. If you're not an agent of the compositor, you
+ * probably shouldn't call this method.
+ */
+ virtual nsIntRect GetNaturalBounds() {
+ nsIntRect bounds;
+ GetBounds(bounds);
+ return bounds;
+ }
+
protected:
// keep the list of children. We also keep track of our siblings.
// The ownership model is as follows: parent holds a strong ref to
// the first element of the list, and each element holds a strong
// ref to the next element in the list. The prevsibling and
// lastchild pointers are weak, which is fine as long as they are
// maintained properly.
--- a/widget/xpwidgets/Makefile.in
+++ b/widget/xpwidgets/Makefile.in
@@ -38,16 +38,17 @@ CPPSRCS = \
nsPrintSession.cpp \
nsIdleService.cpp \
nsClipboardPrivacyHandler.cpp \
GfxInfoWebGL.cpp \
GfxDriverInfo.cpp \
GfxInfoBase.cpp \
PuppetWidget.cpp \
nsFilePickerProxy.cpp \
+ WidgetUtils.cpp \
$(NULL)
ifdef MOZ_X11
CPPSRCS += \
GfxInfoX11.cpp
endif
ifneq (,$(filter os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT)))
new file mode 100644
--- /dev/null
+++ b/widget/xpwidgets/WidgetUtils.cpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
+
+#include "mozilla/WidgetUtils.h"
+
+namespace mozilla {
+
+gfxMatrix
+ComputeGLTransformForRotation(const nsIntRect& aBounds,
+ ScreenRotation aRotation)
+{
+ gfxMatrix transform;
+ switch (aRotation) {
+ case ROTATION_0:
+ break;
+ case ROTATION_90:
+ transform.Translate(gfxPoint(aBounds.width, 0));
+ transform.Rotate(M_PI / 2);
+ break;
+ case ROTATION_180:
+ transform.Translate(gfxPoint(aBounds.width, aBounds.height));
+ transform.Rotate(M_PI);
+ break;
+ case ROTATION_270:
+ transform.Translate(gfxPoint(0, aBounds.height));
+ transform.Rotate(M_PI * 3 / 2);
+ break;
+ default:
+ MOZ_NOT_REACHED("Unknown rotation");
+ break;
+ }
+ return transform;
+}
+
+} // namespace mozilla
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -726,36 +726,37 @@ NS_IMETHODIMP nsBaseWidget::MakeFullScre
mOriginalBounds->height, true);
}
return NS_OK;
}
nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
nsBaseWidget* aWidget, gfxContext* aTarget,
- BasicLayerManager::BufferMode aDoubleBuffering)
+ BasicLayerManager::BufferMode aDoubleBuffering, ScreenRotation aRotation)
: mWidget(aWidget)
{
BasicLayerManager* manager =
static_cast<BasicLayerManager*>(mWidget->GetLayerManager());
if (manager) {
NS_ASSERTION(manager->GetBackendType() == LAYERS_BASIC,
"AutoLayerManagerSetup instantiated for non-basic layer backend!");
- manager->SetDefaultTarget(aTarget, aDoubleBuffering);
+ manager->SetDefaultTarget(aTarget, aDoubleBuffering, aRotation);
}
}
nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup()
{
BasicLayerManager* manager =
static_cast<BasicLayerManager*>(mWidget->GetLayerManager());
if (manager) {
NS_ASSERTION(manager->GetBackendType() == LAYERS_BASIC,
"AutoLayerManagerSetup instantiated for non-basic layer backend!");
- manager->SetDefaultTarget(nsnull, BasicLayerManager::BUFFER_NONE);
+ manager->SetDefaultTarget(nsnull, BasicLayerManager::BUFFER_NONE,
+ ROTATION_0);
}
}
nsBaseWidget::AutoUseBasicLayerManager::AutoUseBasicLayerManager(nsBaseWidget* aWidget)
: mWidget(aWidget)
{
mWidget->mTemporarilyUseBasicLayerManager = true;
}
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -1,15 +1,16 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef nsBaseWidget_h__
#define nsBaseWidget_h__
+#include "mozilla/WidgetUtils.h"
#include "nsRect.h"
#include "nsIWidget.h"
#include "nsWidgetsCID.h"
#include "nsIFile.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsGUIEvent.h"
#include "nsAutoPtr.h"
@@ -41,20 +42,21 @@ class Thread;
* class, but it gives them a head start.)
*/
class nsBaseWidget : public nsIWidget
{
friend class nsAutoRollup;
protected:
+ typedef base::Thread Thread;
typedef mozilla::layers::BasicLayerManager BasicLayerManager;
typedef mozilla::layers::CompositorChild CompositorChild;
typedef mozilla::layers::CompositorParent CompositorParent;
- typedef base::Thread Thread;
+ typedef mozilla::ScreenRotation ScreenRotation;
public:
nsBaseWidget();
virtual ~nsBaseWidget();
NS_DECL_ISUPPORTS
// nsIWidget interface
@@ -177,21 +179,27 @@ public:
NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent) = 0;
virtual PRUint32 GetGLFrameBufferFormat() MOZ_OVERRIDE;
/**
* Use this when GetLayerManager() returns a BasicLayerManager
* (nsBaseWidget::GetLayerManager() does). This sets up the widget's
* layer manager to temporarily render into aTarget.
+ *
+ * |aNaturalWidgetBounds| is the un-rotated bounds of |aWidget|.
+ * |aRotation| is the "virtual rotation" to apply when rendering to
+ * the target. When |aRotation| is ROTATION_0,
+ * |aNaturalWidgetBounds| is not used.
*/
class AutoLayerManagerSetup {
public:
AutoLayerManagerSetup(nsBaseWidget* aWidget, gfxContext* aTarget,
- BasicLayerManager::BufferMode aDoubleBuffering);
+ BasicLayerManager::BufferMode aDoubleBuffering,
+ ScreenRotation aRotation = mozilla::ROTATION_0);
~AutoLayerManagerSetup();
private:
nsBaseWidget* mWidget;
};
friend class AutoLayerManagerSetup;
class AutoUseBasicLayerManager {
public: