diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 35a86b96aa3..d7f5c06ec3c 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -603,6 +603,12 @@ GLContext::IsExtensionSupported(const char *extension) return ListHasExtension(fGetString(LOCAL_GL_EXTENSIONS), extension); } +bool +GLContext::PreferPowerOfTwoTextures() +{ + return Renderer() == RendererAdreno200; +} + bool GLContext::CanUploadSubTextures() { diff --git a/gfx/gl/GLContext.h b/gfx/gl/GLContext.h index 0fa1da06e32..899884702c3 100644 --- a/gfx/gl/GLContext.h +++ b/gfx/gl/GLContext.h @@ -704,6 +704,12 @@ public: bool CanUploadSubTextures(); + // Quirks mode to force the platform to use Power of Two. + // Currently provided only as a best effort. We're not in a + // state where we can yet quarante that the platform will honor + // this. + bool PreferPowerOfTwoTextures(); + /** * If this context wraps a double-buffered target, swap the back * and front buffers. It should be assumed that after a swap, the diff --git a/gfx/layers/ipc/PLayers.ipdl b/gfx/layers/ipc/PLayers.ipdl index bd008d85276..1cde1688145 100644 --- a/gfx/layers/ipc/PLayers.ipdl +++ b/gfx/layers/ipc/PLayers.ipdl @@ -74,6 +74,14 @@ struct OpCreateImageLayer { PLayer layer; }; struct OpCreateColorLayer { PLayer layer; }; struct OpCreateCanvasLayer { PLayer layer; }; +struct LayerForwarderQuirks { + // 1 << 0 -> Use power of two Shmem for GPU that require it. + // The other alternative would be to memcpy the Shmem + // into a PoT buffer before the upload and wasting bandwidth. + // 1 << 1 -> Unused + uint32_t quirks; +}; + struct SurfaceDescriptorD3D10 { WindowsHandle handle; }; @@ -232,6 +240,11 @@ sync protocol PLayers { parent: async PLayer(); + // LayersBackend can request the quirks from the layer + // fowarder. + sync GetForwarderQuirks() + returns (LayerForwarderQuirks Quirks); + sync Update(Edit[] cset) returns (EditReply[] reply); diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 536e5cead0e..7c4d162c24f 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -392,7 +392,7 @@ ShadowLayerForwarder::AllocBuffer(const gfxIntSize& aSize, SharedMemory::SharedMemoryType shmemType = OptimalShmemType(); nsRefPtr back = - gfxSharedImageSurface::CreateUnsafe(mShadowManager, aSize, format, shmemType); + gfxSharedImageSurface::CreateUnsafe(mShadowManager, aSize, format, shmemType, mUsePoTShmem); if (!back) return false; @@ -507,6 +507,11 @@ ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer) return mShadowManager->SendPLayerConstructor(new ShadowLayerChild(aLayer)); } +LayerForwarderQuirks +ShadowLayerManager::GetForwarderQuirks() +{ + return LayerForwarderQuirks(0); +} void ShadowLayerManager::DestroySharedSurface(gfxSharedImageSurface* aSurface, @@ -583,5 +588,11 @@ IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) return SurfaceDescriptor::T__None != aSurface.type(); } +void +ShadowLayerForwarder::SetForwarderQuirks(LayerForwarderQuirks aQuirks) +{ + mUsePoTShmem = aQuirks.quirks() & (1 << 0); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/ipc/ShadowLayers.h b/gfx/layers/ipc/ShadowLayers.h index a492c53a08f..fc54c89bd96 100644 --- a/gfx/layers/ipc/ShadowLayers.h +++ b/gfx/layers/ipc/ShadowLayers.h @@ -42,7 +42,8 @@ #define mozilla_layers_ShadowLayers_h 1 #include "gfxASurface.h" - +#include "ShadowLayers.h" +#include "ShadowLayersManager.h" #include "ImageLayers.h" #include "Layers.h" @@ -51,6 +52,7 @@ class gfxSharedImageSurface; namespace mozilla { namespace layers { +class LayerForwarderQuirks; class Edit; class EditReply; class OptionalThebesBuffer; @@ -308,6 +310,8 @@ public: */ bool ShouldDoubleBuffer() { return GetParentBackendType() == LayerManager::LAYERS_BASIC; } + void SetForwarderQuirks(LayerForwarderQuirks aQuirks); + protected: ShadowLayerForwarder(); @@ -332,6 +336,7 @@ private: Transaction* mTxn; LayersBackend mParentBackend; + bool mUsePoTShmem; }; @@ -359,6 +364,8 @@ public: /** CONSTRUCTION PHASE ONLY */ virtual already_AddRefed CreateShadowCanvasLayer() = 0; + virtual LayerForwarderQuirks GetForwarderQuirks(); + static void PlatformSyncBeforeReplyUpdate(); protected: diff --git a/gfx/layers/ipc/ShadowLayersParent.cpp b/gfx/layers/ipc/ShadowLayersParent.cpp index 1f2471aa7e2..1dbbbccf282 100644 --- a/gfx/layers/ipc/ShadowLayersParent.cpp +++ b/gfx/layers/ipc/ShadowLayersParent.cpp @@ -388,6 +388,12 @@ ShadowLayersParent::RecvUpdate(const InfallibleTArray& cset, return true; } +bool +ShadowLayersParent::RecvGetForwarderQuirks(mozilla::layers::LayerForwarderQuirks* aQuirks) { + *aQuirks = layer_manager()->GetForwarderQuirks(); + return true; +} + PLayerParent* ShadowLayersParent::AllocPLayer() { diff --git a/gfx/layers/ipc/ShadowLayersParent.h b/gfx/layers/ipc/ShadowLayersParent.h index 2be5cda846c..2d2df684438 100644 --- a/gfx/layers/ipc/ShadowLayersParent.h +++ b/gfx/layers/ipc/ShadowLayersParent.h @@ -80,6 +80,8 @@ protected: NS_OVERRIDE virtual bool RecvUpdate(const EditArray& cset, EditReplyArray* reply); + NS_OVERRIDE virtual bool RecvGetForwarderQuirks(mozilla::layers::LayerForwarderQuirks* aQuirks); + NS_OVERRIDE virtual PLayerParent* AllocPLayer(); NS_OVERRIDE virtual bool DeallocPLayer(PLayerParent* actor); diff --git a/gfx/layers/opengl/LayerManagerOGL.cpp b/gfx/layers/opengl/LayerManagerOGL.cpp index 15381cbc1f7..c81e079b8d3 100644 --- a/gfx/layers/opengl/LayerManagerOGL.cpp +++ b/gfx/layers/opengl/LayerManagerOGL.cpp @@ -935,6 +935,17 @@ LayerManagerOGL::WorldTransformRect(nsIntRect& aRect) aRect.SetRect(grect.X(), grect.Y(), grect.Width(), grect.Height()); } +LayerForwarderQuirks +LayerManagerOGL::GetForwarderQuirks() +{ + uint16_t quirks = 0; + if (mGLContext->PreferPowerOfTwoTextures()) { + quirks |= 1 << 0; + } + + return LayerForwarderQuirks(quirks); +} + void LayerManagerOGL::SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy) { diff --git a/gfx/layers/opengl/LayerManagerOGL.h b/gfx/layers/opengl/LayerManagerOGL.h index 00635fc7e31..3f584bec292 100644 --- a/gfx/layers/opengl/LayerManagerOGL.h +++ b/gfx/layers/opengl/LayerManagerOGL.h @@ -400,6 +400,8 @@ public: gfxMatrix& GetWorldTransform(void); void WorldTransformRect(nsIntRect& aRect); + LayerForwarderQuirks GetForwarderQuirks(); + private: /** Widget associated with this layer manager */ nsIWidget *mWidget; diff --git a/gfx/thebes/gfxSharedImageSurface.h b/gfx/thebes/gfxSharedImageSurface.h index a7dfd103b30..a469a7fd394 100644 --- a/gfx/thebes/gfxSharedImageSurface.h +++ b/gfx/thebes/gfxSharedImageSurface.h @@ -85,9 +85,11 @@ public: CreateUnsafe(ShmemAllocator* aAllocator, const gfxIntSize& aSize, gfxImageFormat aFormat, - SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC) + SharedMemory::SharedMemoryType aShmType = SharedMemory::TYPE_BASIC, + bool aUsePoTSharedSurface = false) { - return Create(aAllocator, aSize, aFormat, aShmType); + return Create(aAllocator, aSize, aFormat, + aShmType, aUsePoTSharedSurface); } Shmem& GetShmem() { return mShmem; } @@ -106,14 +108,30 @@ private: Create(ShmemAllocator* aAllocator, const gfxIntSize& aSize, gfxImageFormat aFormat, - SharedMemory::SharedMemoryType aShmType) + SharedMemory::SharedMemoryType aShmType, + bool aUsePoTSharedSurface = false) { if (!CheckSurfaceSize(aSize)) return nsnull; Shmem shmem; - long stride = ComputeStride(aSize, aFormat); - size_t size = GetAlignedSize(aSize, stride); + long stride; + size_t size; + if (aUsePoTSharedSurface) { + printf_stderr("Buffer PoT\n"); + int potW = 1; + while( potW < aSize.width ) potW <<= 1; + int potH = 1; + while( potH < aSize.height ) potH <<= 1; + + stride = ComputeStride(gfxIntSize(potW, potH), aFormat); + size = GetAlignedSize(gfxIntSize(potW, potH), stride); + } else { + printf_stderr("Buffer NOT PoT\n"); + stride = ComputeStride(aSize, aFormat); + size = GetAlignedSize(aSize, stride); + } + if (!Unsafe) { if (!aAllocator->AllocShmem(size, aShmType, &shmem)) return nsnull; diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index c0b0c3984f0..ff29edf2a8f 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -40,6 +40,7 @@ #include "mozilla/layers/CompositorChild.h" #include "mozilla/layers/CompositorParent.h" +#include "mozilla/layers/PLayersChild.h" #include "nsBaseWidget.h" #include "nsDeviceContext.h" #include "nsCOMPtr.h" @@ -857,8 +858,12 @@ void nsBaseWidget::CreateCompositor() PLayersChild* shadowManager = mCompositorChild->SendPLayersConstructor(LayerManager::LAYERS_OPENGL); + LayerForwarderQuirks forwarderQuirk; + shadowManager->SendGetForwarderQuirks(&forwarderQuirk); + if (shadowManager) { ShadowLayerForwarder* lf = lm->AsShadowForwarder(); + lf->SetForwarderQuirks(forwarderQuirk); if (!lf) { delete lm; mCompositorChild = nsnull;