зеркало из https://github.com/mozilla/gecko-dev.git
Bug 804852: Support for the hwc implementation of Composer2D. r=mattwoodrow,mwu,roc sr=roc a=blocking-basecamp
This is a rollup of the following patches part 0: Add a dynamic cast to ColorLayer* part 1: Add a Composer2D interface to enable implementations to more efficiently compose layer trees part 2: Let widgets expose Composer2Ds, if they have them part 3: Expose a layers ogl "friend" API that Composer2D will consume part 4: Hook Composer2D into the LayerManagerOGL rendering pipeline part 5: Implement all the goop to let widget/gonk use a Composer2D (HwcComposer2D)
This commit is contained in:
Родитель
450c02e0f3
Коммит
0b4ee49f4e
|
@ -19,7 +19,7 @@
|
|||
#define GET_NATIVE_WINDOW(aWidget) (EGLNativeWindowType)static_cast<QWidget*>(aWidget->GetNativeData(NS_NATIVE_SHELLWIDGET))->winId()
|
||||
#elif defined(MOZ_WIDGET_GONK)
|
||||
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
|
||||
#include "HWComposer.h"
|
||||
#include "HwcComposer2D.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
|
@ -270,12 +270,14 @@ public:
|
|||
printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
|
||||
#endif
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
if (!aIsOffscreen)
|
||||
mHwc = new HWComposer();
|
||||
if (!aIsOffscreen) {
|
||||
mHwc = HwcComposer2D::GetInstance();
|
||||
MOZ_ASSERT(!mHwc->Initialized());
|
||||
|
||||
if (mHwc && mHwc->init()) {
|
||||
NS_WARNING("HWComposer initialization failed!");
|
||||
mHwc = nullptr;
|
||||
if (mHwc->Init(EGL_DISPLAY(), mSurface)) {
|
||||
NS_WARNING("HWComposer initialization failed!");
|
||||
mHwc = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -696,7 +698,7 @@ protected:
|
|||
bool mCanBindToTexture;
|
||||
bool mShareWithEGLImage;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
nsAutoPtr<HWComposer> mHwc;
|
||||
nsRefPtr<HwcComposer2D> mHwc;
|
||||
#endif
|
||||
|
||||
// A dummy texture ID that can be used when we need a texture object whose
|
||||
|
|
|
@ -900,6 +900,12 @@ public:
|
|||
*/
|
||||
virtual RefLayer* AsRefLayer() { return nullptr; }
|
||||
|
||||
/**
|
||||
* Dynamic cast to a Color. Returns null if this is not a
|
||||
* ColorLayer.
|
||||
*/
|
||||
virtual ColorLayer* AsColorLayer() { return nullptr; }
|
||||
|
||||
/**
|
||||
* Dynamic cast to a ShadowLayer. Return null if this is not a
|
||||
* ShadowLayer. Can be used anytime.
|
||||
|
@ -1363,6 +1369,8 @@ protected:
|
|||
*/
|
||||
class THEBES_API ColorLayer : public Layer {
|
||||
public:
|
||||
virtual ColorLayer* AsColorLayer() { return this; }
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Set the color of the layer.
|
||||
|
|
|
@ -31,6 +31,7 @@ EXPORTS = \
|
|||
BasicLayers.h \
|
||||
BasicTiledThebesLayer.h \
|
||||
BasicImplData.h \
|
||||
Composer2D.h \
|
||||
GonkIOSurfaceImage.h \
|
||||
FrameMetrics.h \
|
||||
CompositorChild.h \
|
||||
|
|
|
@ -475,6 +475,16 @@ ShadowCanvasLayerOGL::GetLayer()
|
|||
return this;
|
||||
}
|
||||
|
||||
LayerRenderState
|
||||
ShadowCanvasLayerOGL::GetRenderState()
|
||||
{
|
||||
if (mDestroyed) {
|
||||
return LayerRenderState();
|
||||
}
|
||||
return LayerRenderState(&mFrontBufferDescriptor,
|
||||
mNeedsYFlip ? LAYER_RENDER_STATE_Y_FLIPPED : 0);
|
||||
}
|
||||
|
||||
void
|
||||
ShadowCanvasLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset)
|
||||
|
|
|
@ -126,6 +126,7 @@ public:
|
|||
// LayerOGL impl
|
||||
void Destroy();
|
||||
Layer* GetLayer();
|
||||
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
virtual void CleanupResources();
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/* -*- 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_layers_Composer2D_h
|
||||
#define mozilla_layers_Composer2D_h
|
||||
|
||||
#include "gfxTypes.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
/**
|
||||
* Many platforms have dedicated hardware for simple composition.
|
||||
* This hardware is usually faster or more power efficient than the
|
||||
* GPU. However, in exchange for this better performance, generality
|
||||
* has to be sacrificed: no 3d transforms, no intermediate surfaces,
|
||||
* no special shader effects, loss of other goodies depending on the
|
||||
* platform.
|
||||
*
|
||||
* Composer2D is a very simple interface to this class of hardware
|
||||
* that allows an implementation to "try rendering" with the fast
|
||||
* path. If the given layer tree requires more generality than the
|
||||
* hardware provides, the implementation should bail and have the
|
||||
* layer manager fall back on full GPU composition.
|
||||
*/
|
||||
|
||||
class gfxMatrix;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Layer;
|
||||
|
||||
class THEBES_API Composer2D {
|
||||
NS_INLINE_DECL_REFCOUNTING(Composer2D)
|
||||
|
||||
public:
|
||||
virtual ~Composer2D() {}
|
||||
|
||||
/**
|
||||
* Return true if |aRoot| met the implementation's criteria for fast
|
||||
* composition and the render was successful. Return false to fall
|
||||
* back on the GPU.
|
||||
*
|
||||
* |aWorldTransform| must be applied to |aRoot|'s subtree when
|
||||
* rendering to the framebuffer. This is a global transform on the
|
||||
* entire scene, defined in GL space. If the Composer2D
|
||||
* implementation is unable to honor the transform, it should return
|
||||
* false.
|
||||
*
|
||||
* Currently, when TryRender() returns true, the entire framebuffer
|
||||
* must have been rendered.
|
||||
*/
|
||||
virtual bool TryRender(Layer* aRoot, const gfxMatrix& aWorldTransform) = 0;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_layers_Composer2D_h
|
|
@ -817,6 +817,28 @@ ShadowImageLayerOGL::GetLayer()
|
|||
return this;
|
||||
}
|
||||
|
||||
LayerRenderState
|
||||
ShadowImageLayerOGL::GetRenderState()
|
||||
{
|
||||
if (!mImageContainerID) {
|
||||
return LayerRenderState();
|
||||
}
|
||||
|
||||
// Update the associated compositor ID in case Composer2D succeeds,
|
||||
// because we won't enter RenderLayer() if so ...
|
||||
ImageContainerParent::SetCompositorIDForImage(
|
||||
mImageContainerID, mOGLManager->GetCompositorID());
|
||||
// ... but do *not* try to update the local image version. We need
|
||||
// to retain that information in case we fall back on GL, so that we
|
||||
// can upload / attach buffers properly.
|
||||
|
||||
SharedImage* img = ImageContainerParent::GetSharedImage(mImageContainerID);
|
||||
if (img && img->type() == SharedImage::TSurfaceDescriptor) {
|
||||
return LayerRenderState(&img->get_SurfaceDescriptor());
|
||||
}
|
||||
return LayerRenderState();
|
||||
}
|
||||
|
||||
void ShadowImageLayerOGL::UploadSharedYUVToTexture(const YUVImage& yuv)
|
||||
{
|
||||
AutoOpenSurface asurfY(OPEN_READ_ONLY, yuv.Ydata());
|
||||
|
@ -927,6 +949,8 @@ ShadowImageLayerOGL::RenderLayer(int aPreviousFrameBuffer,
|
|||
ShmemYCbCrImage shmemImage(img->get_YCbCrImage().data(),
|
||||
img->get_YCbCrImage().offset());
|
||||
UploadSharedYCbCrToTexture(shmemImage, img->get_YCbCrImage().picture());
|
||||
|
||||
mImageVersion = imgVersion;
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
} else if (img
|
||||
&& (img->type() == SharedImage::TSurfaceDescriptor)
|
||||
|
|
|
@ -173,6 +173,7 @@ public:
|
|||
virtual bool LoadAsTexture(GLuint aTextureUnit, gfxIntSize* aSize);
|
||||
|
||||
virtual Layer* GetLayer();
|
||||
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
/* This must occur *after* layers/PLayers.h to avoid typedefs conflicts. */
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "Composer2D.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "ThebesLayerOGL.h"
|
||||
#include "ContainerLayerOGL.h"
|
||||
|
@ -583,6 +584,8 @@ LayerManagerOGL::Initialize(nsRefPtr<GLContext> aContext, bool force)
|
|||
NS_DispatchToMainThread(new ReadDrawFPSPref());
|
||||
}
|
||||
|
||||
mComposer2D = mWidget->GetComposer2D();
|
||||
|
||||
reporter.SetSuccessful();
|
||||
return true;
|
||||
}
|
||||
|
@ -671,7 +674,31 @@ LayerManagerOGL::EndTransaction(DrawThebesLayerCallback aCallback,
|
|||
mThebesLayerCallbackData = aCallbackData;
|
||||
SetCompositingDisabled(aFlags & END_NO_COMPOSITE);
|
||||
|
||||
Render();
|
||||
bool needGLRender = true;
|
||||
if (mComposer2D && mComposer2D->TryRender(mRoot, mWorldMatrix)) {
|
||||
needGLRender = false;
|
||||
|
||||
if (sDrawFPS) {
|
||||
if (!mFPS) {
|
||||
mFPS = new FPSState();
|
||||
}
|
||||
double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now());
|
||||
printf_stderr("HWComposer: FPS is %g\n", fps);
|
||||
}
|
||||
|
||||
// This lets us reftest and screenshot content rendered by the
|
||||
// 2d composer.
|
||||
if (mTarget) {
|
||||
MakeCurrent();
|
||||
CopyToTarget(mTarget);
|
||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
MOZ_ASSERT(!needGLRender);
|
||||
}
|
||||
|
||||
if (needGLRender) {
|
||||
Render();
|
||||
}
|
||||
|
||||
mThebesLayerCallback = nullptr;
|
||||
mThebesLayerCallbackData = nullptr;
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef int GLsizei;
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class Composer2D;
|
||||
class LayerOGL;
|
||||
class ShadowThebesLayer;
|
||||
class ShadowContainerLayer;
|
||||
|
@ -378,6 +379,9 @@ private:
|
|||
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
|
||||
/** Our more efficient but less powerful alter ego, if one is available. */
|
||||
nsRefPtr<Composer2D> mComposer2D;
|
||||
|
||||
already_AddRefed<mozilla::gl::GLContext> CreateContext();
|
||||
|
||||
/** Backbuffer */
|
||||
|
@ -460,6 +464,30 @@ private:
|
|||
static bool sFrameCounter;
|
||||
};
|
||||
|
||||
enum LayerRenderStateFlags {
|
||||
LAYER_RENDER_STATE_Y_FLIPPED = 1 << 0,
|
||||
LAYER_RENDER_STATE_BUFFER_ROTATION = 1 << 1
|
||||
};
|
||||
|
||||
struct LayerRenderState {
|
||||
LayerRenderState() : mSurface(nullptr), mFlags(0)
|
||||
{}
|
||||
|
||||
LayerRenderState(SurfaceDescriptor* aSurface, uint32_t aFlags = 0)
|
||||
: mSurface(aSurface)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
bool YFlipped() const
|
||||
{ return mFlags & LAYER_RENDER_STATE_Y_FLIPPED; }
|
||||
|
||||
bool BufferRotated() const
|
||||
{ return mFlags & LAYER_RENDER_STATE_BUFFER_ROTATION; }
|
||||
|
||||
SurfaceDescriptor* mSurface;
|
||||
uint32_t mFlags;
|
||||
};
|
||||
|
||||
/**
|
||||
* General information and tree management for OGL layers.
|
||||
*/
|
||||
|
@ -483,6 +511,8 @@ public:
|
|||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
|
||||
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset) = 0;
|
||||
|
||||
|
|
|
@ -903,6 +903,10 @@ public:
|
|||
const nsIntRect& aRect, const nsIntPoint& aRotation,
|
||||
nsIntRect* aPrevRect, nsIntPoint* aPrevRotation);
|
||||
|
||||
nsIntPoint Rotation() {
|
||||
return mBufferRotation;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual nsIntPoint GetOriginOffset() {
|
||||
return mBufferRect.TopLeft() - mBufferRotation;
|
||||
|
@ -1104,6 +1108,17 @@ ShadowThebesLayerOGL::GetLayer()
|
|||
return this;
|
||||
}
|
||||
|
||||
LayerRenderState
|
||||
ShadowThebesLayerOGL::GetRenderState()
|
||||
{
|
||||
if (!mBuffer || mDestroyed) {
|
||||
return LayerRenderState();
|
||||
}
|
||||
uint32_t flags = (mBuffer->Rotation() != nsIntPoint()) ?
|
||||
LAYER_RENDER_STATE_BUFFER_ROTATION : 0;
|
||||
return LayerRenderState(&mBufferDescriptor, flags);
|
||||
}
|
||||
|
||||
bool
|
||||
ShadowThebesLayerOGL::IsEmpty()
|
||||
{
|
||||
|
|
|
@ -131,6 +131,7 @@ public:
|
|||
// LayerOGL impl
|
||||
void Destroy();
|
||||
Layer* GetLayer();
|
||||
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE;
|
||||
virtual bool IsEmpty();
|
||||
virtual void RenderLayer(int aPreviousFrameBuffer,
|
||||
const nsIntPoint& aOffset);
|
||||
|
|
|
@ -3652,6 +3652,9 @@ pref("layers.offmainthreadcomposition.animate-opacity", false);
|
|||
pref("layers.offmainthreadcomposition.animate-transform", false);
|
||||
pref("layers.offmainthreadcomposition.log-animations", false);
|
||||
|
||||
// Whether to (try) to use a Composer2D if available on this platform.
|
||||
pref("layers.composer2d.enabled", false);
|
||||
|
||||
#ifdef MOZ_X11
|
||||
#ifdef MOZ_WIDGET_GTK2
|
||||
pref("gfx.xrender.enabled",true);
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
// swap buffers using vendor specific implementation
|
||||
status_t swapBuffers(hwc_display_t dpy, hwc_surface_t surf) const;
|
||||
|
||||
private:
|
||||
protected:
|
||||
struct cb_context {
|
||||
hwc_procs_t procs;
|
||||
HWComposer* hwc;
|
||||
|
|
|
@ -35,6 +35,7 @@ LIBXUL_LIBRARY = 1
|
|||
CPPSRCS = \
|
||||
Framebuffer.cpp \
|
||||
HWComposer.cpp \
|
||||
HwcComposer2D.cpp \
|
||||
nsAppShell.cpp \
|
||||
nsWidgetFactory.cpp \
|
||||
nsWindow.cpp \
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "GLContextProvider.h"
|
||||
#include "HwcComposer2D.h"
|
||||
#include "LayerManagerOGL.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsAppShell.h"
|
||||
|
@ -66,6 +67,7 @@ static nsWindow *gFocusedWindow = nullptr;
|
|||
static android::FramebufferNativeWindow *gNativeWindow = nullptr;
|
||||
static bool sFramebufferOpen;
|
||||
static bool sUsingOMTC;
|
||||
static bool sUsingHwc;
|
||||
static bool sScreenInitialized;
|
||||
static nsRefPtr<gfxASurface> sOMTCSurface;
|
||||
static pthread_t sFramebufferWatchThread;
|
||||
|
@ -215,6 +217,7 @@ nsWindow::nsWindow()
|
|||
// This has to happen after other init has finished.
|
||||
gfxPlatform::GetPlatform();
|
||||
sUsingOMTC = UseOffMainThreadCompositing();
|
||||
sUsingHwc = Preferences::GetBool("layers.composer2d.enabled", false);
|
||||
|
||||
if (sUsingOMTC) {
|
||||
sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
|
||||
|
@ -693,6 +696,18 @@ nsWindow::NeedsPaint()
|
|||
return nsIWidget::NeedsPaint();
|
||||
}
|
||||
|
||||
Composer2D*
|
||||
nsWindow::GetComposer2D()
|
||||
{
|
||||
if (!sUsingHwc) {
|
||||
return nullptr;
|
||||
}
|
||||
if (HwcComposer2D* hwc = HwcComposer2D::GetInstance()) {
|
||||
return hwc->Initialized() ? hwc : nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// nsScreenGonk.cpp
|
||||
|
||||
nsScreenGonk::nsScreenGonk(void *nativeScreen)
|
||||
|
|
|
@ -110,6 +110,8 @@ public:
|
|||
virtual nsIntRect GetNaturalBounds() MOZ_OVERRIDE;
|
||||
virtual bool NeedsPaint();
|
||||
|
||||
virtual Composer2D* GetComposer2D() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
nsWindow* mParent;
|
||||
bool mVisible;
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace dom {
|
|||
class TabChild;
|
||||
}
|
||||
namespace layers {
|
||||
class Composer2D;
|
||||
class CompositorChild;
|
||||
class LayerManager;
|
||||
class PLayersChild;
|
||||
|
@ -90,8 +91,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
|
|||
#endif
|
||||
|
||||
#define NS_IWIDGET_IID \
|
||||
{ 0x46409199, 0x4190, 0x4619, \
|
||||
{0xba, 0xd0, 0x01, 0x31, 0x24, 0x94, 0xa9, 0x2c} }
|
||||
{ 0xdb9b0931, 0xebf9, 0x4e0d, \
|
||||
{ 0xb2, 0x0a, 0xf7, 0x5f, 0xcb, 0x17, 0xe6, 0xe1 } }
|
||||
|
||||
/*
|
||||
* Window shadow styles
|
||||
|
@ -382,6 +383,7 @@ class nsIWidget : public nsISupports {
|
|||
typedef mozilla::dom::TabChild TabChild;
|
||||
|
||||
public:
|
||||
typedef mozilla::layers::Composer2D Composer2D;
|
||||
typedef mozilla::layers::CompositorChild CompositorChild;
|
||||
typedef mozilla::layers::LayerManager LayerManager;
|
||||
typedef mozilla::layers::LayersBackend LayersBackend;
|
||||
|
@ -1643,6 +1645,16 @@ class nsIWidget : public nsISupports {
|
|||
virtual CompositorChild* GetRemoteRenderer()
|
||||
{ return nullptr; }
|
||||
|
||||
/**
|
||||
* If this widget has a more efficient composer available for its
|
||||
* native framebuffer, return it.
|
||||
*
|
||||
* This can be called from a non-main thread, but that thread must
|
||||
* hold a strong reference to this.
|
||||
*/
|
||||
virtual Composer2D* GetComposer2D()
|
||||
{ return nullptr; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Like GetDefaultScale, but taking into account only the system settings
|
||||
|
|
Загрузка…
Ссылка в новой задаче