diff --git a/b2g/app/b2g.js b/b2g/app/b2g.js index b3f108129db..cf7e61c3fec 100644 --- a/b2g/app/b2g.js +++ b/b2g/app/b2g.js @@ -996,6 +996,9 @@ pref("gfx.canvas.max-size-for-skia-gl", -1); // enable fence with readpixels for SurfaceStream pref("gfx.gralloc.fence-with-readpixels", true); +// enable screen mirroring to external display +pref("gfx.screen-mirroring.enabled", true); + // The url of the page used to display network error details. pref("b2g.neterror.url", "net_error.html"); diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index ebc31e61f7d..acbf82722e9 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -55,11 +55,17 @@ #ifdef MOZ_WIDGET_ANDROID #include #include "AndroidBridge.h" +#endif +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) #include "opengl/CompositorOGL.h" #include "GLContextEGL.h" #include "GLContextProvider.h" #include "ScopedGLHelpers.h" #endif +#ifdef MOZ_WIDGET_GONK +#include "nsScreenManagerGonk.h" +#include "nsWindow.h" +#endif #include "GeckoProfiler.h" #include "TextRenderer.h" // for TextRenderer @@ -302,7 +308,7 @@ LayerManagerComposite::EndTransaction(const TimeStamp& aTimeStamp, ApplyOcclusionCulling(mRoot, opaque); Render(); -#ifdef MOZ_WIDGET_ANDROID +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) RenderToPresentationSurface(); #endif mGeometryChanged = false; @@ -780,7 +786,7 @@ LayerManagerComposite::Render() RecordFrame(); } -#ifdef MOZ_WIDGET_ANDROID +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) class ScopedCompositorProjMatrix { public: ScopedCompositorProjMatrix(CompositorOGL* aCompositor, const Matrix4x4& aProjMatrix): @@ -854,6 +860,7 @@ private: void LayerManagerComposite::RenderToPresentationSurface() { +#ifdef MOZ_WIDGET_ANDROID if (!AndroidBridge::Bridge()) { return; } @@ -886,17 +893,60 @@ LayerManagerComposite::RenderToPresentationSurface() const IntSize windowSize = AndroidBridge::Bridge()->GetNativeWindowSize(window); +#elif defined(MOZ_WIDGET_GONK) + CompositorOGL* compositor = static_cast(mCompositor.get()); + nsScreenGonk* screen = static_cast(mCompositor->GetWidget())->GetScreen(); + if (!screen->IsPrimaryScreen()) { + // Only primary screen support mirroring + return; + } + + nsWindow* mirrorScreenWidget = screen->GetMirroringWidget(); + if (!mirrorScreenWidget) { + // No mirroring + return; + } + + nsScreenGonk* mirrorScreen = mirrorScreenWidget->GetScreen(); + if (!mirrorScreen->GetTopWindows().IsEmpty()) { + return; + } + + EGLSurface surface = mirrorScreen->GetEGLSurface(); + if (surface == LOCAL_EGL_NO_SURFACE) { + // Create GLContext + nsRefPtr gl = gl::GLContextProvider::CreateForWindow(mirrorScreenWidget); + mirrorScreenWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT, + reinterpret_cast(gl.get())); + surface = mirrorScreen->GetEGLSurface(); + if (surface == LOCAL_EGL_NO_SURFACE) { + // Failed to create EGLSurface + return; + } + } + GLContext* gl = compositor->gl(); + GLContextEGL* egl = GLContextEGL::Cast(gl); + const IntSize windowSize = mirrorScreen->GetNaturalBounds().Size(); +#endif + if ((windowSize.width <= 0) || (windowSize.height <= 0)) { return; } + ScreenRotation rotation = compositor->GetScreenRotation(); + const int actualWidth = windowSize.width; const int actualHeight = windowSize.height; const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize(); + const nsIntRect originalRect = nsIntRect(0, 0, originalSize.width, originalSize.height); - const int pageWidth = originalSize.width; - const int pageHeight = originalSize.height; + int pageWidth = originalSize.width; + int pageHeight = originalSize.height; + if (rotation == ROTATION_90 || rotation == ROTATION_270) { + pageWidth = originalSize.height; + pageHeight = originalSize.width; + } float scale = 1.0; @@ -910,42 +960,47 @@ LayerManagerComposite::RenderToPresentationSurface() ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize); const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0); - ScopedCompositorRenderOffset overrideRenderOffset(compositor, offset); ScopedContextSurfaceOverride overrideSurface(egl, surface); + Matrix viewMatrix = ComputeTransformForRotation(originalRect, + rotation); + viewMatrix.Invert(); // unrotate + viewMatrix.PostScale(scale, scale); + viewMatrix.PostTranslate(offset.x, offset.y); + Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix); + + mRoot->ComputeEffectiveTransforms(matrix); + nsIntRegion opaque; + ApplyOcclusionCulling(mRoot, opaque); + nsIntRegion invalid; Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight); Rect rect, actualBounds; mCompositor->BeginFrame(invalid, nullptr, bounds, &rect, &actualBounds); - // Override the projection matrix since the presentation frame buffer - // is probably not the same size as the device frame buffer. The override - // projection matrix also scales the content to fit into the presentation - // frame buffer. - Matrix viewMatrix; - viewMatrix.PreTranslate(-1.0, 1.0); - viewMatrix.PreScale((2.0f * scale) / (float)actualWidth, (2.0f * scale) / (float)actualHeight); - viewMatrix.PreScale(1.0f, -1.0f); - viewMatrix.PreTranslate((int)((float)offset.x / scale), offset.y); - - Matrix4x4 projMatrix = Matrix4x4::From2D(viewMatrix); - - ScopedCompositorProjMatrix overrideProjMatrix(compositor, projMatrix); - // The Java side of Fennec sets a scissor rect that accounts for // chrome such as the URL bar. Override that so that the entire frame buffer // is cleared. - ScopedScissorRect screen(egl, 0, 0, actualWidth, actualHeight); + ScopedScissorRect scissorRect(egl, 0, 0, actualWidth, actualHeight); egl->fClearColor(0.0, 0.0, 0.0, 0.0); egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT); - const IntRect clipRect = IntRect(0, 0, (int)(scale * pageWidth), actualHeight); + const IntRect clipRect = IntRect(0, 0, actualWidth, actualHeight); + RootLayer()->Prepare(RenderTargetPixel::FromUntyped(clipRect)); RootLayer()->RenderLayer(clipRect); mCompositor->EndFrame(); - mCompositor->SetDispAcquireFence(mRoot); + mCompositor->SetDispAcquireFence(mRoot); // Call after EndFrame() + +#ifdef MOZ_WIDGET_GONK + nsRefPtr composer2D; + composer2D = mCompositor->GetWidget()->GetComposer2D(); + if (composer2D) { + composer2D->Render(mirrorScreenWidget); + } +#endif } #endif diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index 897a586f760..1df10906e7e 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -301,7 +301,7 @@ private: * Render the current layer tree to the active target. */ void Render(); -#ifdef MOZ_WIDGET_ANDROID +#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK) void RenderToPresentationSurface(); #endif diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 4b193175f1d..7b1b8f875ce 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -263,6 +263,7 @@ private: DECL_GFX_PREF(Once, "gfx.vsync.hw-vsync.enabled", HardwareVsyncEnabled, bool, false); DECL_GFX_PREF(Once, "gfx.vsync.refreshdriver", VsyncAlignedRefreshDriver, bool, false); DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true); + DECL_GFX_PREF(Once, "gfx.screen-mirroring.enabled", ScreenMirroringEnabled, bool, false); DECL_GFX_PREF(Live, "gl.msaa-level", MSAALevel, uint32_t, 2); DECL_GFX_PREF(Live, "gl.require-hardware", RequireHardwareGL, bool, false); diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp index afd0c4f4bc1..816f9660275 100644 --- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -751,6 +751,9 @@ HwcComposer2D::Render(nsIWidget* aWidget) mList->hwLayers[mList->numHwLayers - 1].handle = dispSurface->lastHandle; mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = dispSurface->GetPrevDispAcquireFd(); } else { + // Update screen rect to handle a case that TryRenderWithHwc() is not called. + mScreenRect = screen->GetNaturalBounds(); + mList->flags = HWC_GEOMETRY_CHANGED; mList->numHwLayers = 2; mList->hwLayers[0].hints = 0; @@ -773,7 +776,8 @@ HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* scre if (mPrepared) { LOGE("Multiple hwc prepare calls!"); } - mHal->Prepare(mList, screen->GetDisplayType(), dispHandle, fence); + hwc_rect_t dispRect = {0, 0, mScreenRect.width, mScreenRect.height}; + mHal->Prepare(mList, screen->GetDisplayType(), dispRect, dispHandle, fence); mPrepared = true; } diff --git a/widget/gonk/hwchal/HwcHAL.cpp b/widget/gonk/hwchal/HwcHAL.cpp index ecd8327de07..1793b75e658 100644 --- a/widget/gonk/hwchal/HwcHAL.cpp +++ b/widget/gonk/hwchal/HwcHAL.cpp @@ -32,8 +32,6 @@ HwcHAL::HwcHAL() printf_stderr("HwcHAL Error: Cannot load hwcomposer"); return; } - - GetHwcAttributes(); } HwcHAL::~HwcHAL() @@ -79,6 +77,7 @@ HwcHAL::ResetHwc() int HwcHAL::Prepare(HwcList *aList, uint32_t aDisp, + hwc_rect_t aDispRect, buffer_handle_t aHandle, int aFenceFd) { @@ -103,8 +102,8 @@ HwcHAL::Prepare(HwcList *aList, aList->hwLayers[idx].handle = aHandle; aList->hwLayers[idx].blending = HWC_BLENDING_PREMULT; aList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET; - SetCrop(aList->hwLayers[idx], mHwcRect); - aList->hwLayers[idx].displayFrame = mHwcRect; + SetCrop(aList->hwLayers[idx], aDispRect); + aList->hwLayers[idx].displayFrame = aDispRect; aList->hwLayers[idx].visibleRegionScreen.numRects = 1; aList->hwLayers[idx].visibleRegionScreen.rects = &aList->hwLayers[idx].displayFrame; aList->hwLayers[idx].acquireFenceFd = aFenceFd; @@ -195,20 +194,6 @@ HwcHAL::RegisterHwcEventCallback(const HwcHALProcs_t &aProcs) #endif } -void -HwcHAL::GetHwcAttributes() -{ - int32_t values[2]; - const uint32_t attrs[] = { - HWC_DISPLAY_WIDTH, - HWC_DISPLAY_HEIGHT, - HWC_DISPLAY_NO_ATTRIBUTE - }; - - mHwc->getDisplayAttributes(mHwc, 0, 0, attrs, values); - mHwcRect = {0, 0, values[0], values[1]}; -} - uint32_t HwcHAL::GetAPIVersion() const { diff --git a/widget/gonk/hwchal/HwcHAL.h b/widget/gonk/hwchal/HwcHAL.h index 0dc8b7f205d..05cb6a45f10 100644 --- a/widget/gonk/hwchal/HwcHAL.h +++ b/widget/gonk/hwchal/HwcHAL.h @@ -31,8 +31,6 @@ public: virtual bool HasHwc() const override { return static_cast(mHwc); } - virtual const hwc_rect_t GetHwcRect() const override { return mHwcRect; } - virtual void SetEGLInfo(hwc_display_t aDpy, hwc_surface_t aSur) override { } @@ -45,6 +43,7 @@ public: virtual int Prepare(HwcList *aList, uint32_t aDisp, + hwc_rect_t aDispRect, buffer_handle_t aHandle, int aFenceFd) override; @@ -60,13 +59,10 @@ public: virtual bool RegisterHwcEventCallback(const HwcHALProcs_t &aProcs) override; private: - void GetHwcAttributes(); - uint32_t GetAPIVersion() const; private: HwcDevice *mHwc = nullptr; - hwc_rect_t mHwcRect = {0}; }; } // namespace mozilla diff --git a/widget/gonk/hwchal/HwcHALBase.h b/widget/gonk/hwchal/HwcHALBase.h index 6a07ddd9157..753af5e409c 100644 --- a/widget/gonk/hwchal/HwcHALBase.h +++ b/widget/gonk/hwchal/HwcHALBase.h @@ -85,9 +85,6 @@ public: // Check if mHwc exists virtual bool HasHwc() const = 0; - // Get HwcRect - virtual const hwc_rect_t GetHwcRect() const = 0; - // Set EGL info (only ICS need this info) virtual void SetEGLInfo(hwc_display_t aEGLDisplay, hwc_surface_t aEGLSurface) = 0; @@ -105,6 +102,7 @@ public: // HwcDevice prepare virtual int Prepare(HwcList *aList, uint32_t aDisp, + hwc_rect_t aDispRect, buffer_handle_t aHandle, int aFenceFd) = 0; diff --git a/widget/gonk/hwchal/HwcICS.cpp b/widget/gonk/hwchal/HwcICS.cpp index 92e953555de..45ffa2d6b29 100644 --- a/widget/gonk/hwchal/HwcICS.cpp +++ b/widget/gonk/hwchal/HwcICS.cpp @@ -86,6 +86,7 @@ HwcICS::ResetHwc() int HwcICS::Prepare(HwcList *aList, uint32_t aDisp, + hwc_rect_t aDispRect, buffer_handle_t aHandle, int aFenceFd) { diff --git a/widget/gonk/hwchal/HwcICS.h b/widget/gonk/hwchal/HwcICS.h index 015b79a410d..5385ded98b2 100644 --- a/widget/gonk/hwchal/HwcICS.h +++ b/widget/gonk/hwchal/HwcICS.h @@ -31,8 +31,6 @@ public: virtual bool HasHwc() const override { return static_cast(mHwc); } - virtual const hwc_rect_t GetHwcRect() const override { return {0}; } - virtual void SetEGLInfo(hwc_display_t aEGLDisplay, hwc_surface_t aEGLSurface) override; @@ -45,6 +43,7 @@ public: virtual int Prepare(HwcList *aList, uint32_t aDisp, + hwc_rect_t aDispRect, buffer_handle_t aHandle, int aFenceFd) override; diff --git a/widget/gonk/nsScreenManagerGonk.cpp b/widget/gonk/nsScreenManagerGonk.cpp index 607e7c72970..2368ef22aa2 100644 --- a/widget/gonk/nsScreenManagerGonk.cpp +++ b/widget/gonk/nsScreenManagerGonk.cpp @@ -121,6 +121,7 @@ nsScreenGonk::nsScreenGonk(uint32_t aId, #if ANDROID_VERSION >= 17 , mDisplaySurface(aNativeData.mDisplaySurface) #endif + , mIsMirroring(false) , mDisplayType(aDisplayType) , mEGLDisplay(EGL_NO_DISPLAY) , mEGLSurface(EGL_NO_SURFACE) @@ -143,8 +144,22 @@ nsScreenGonk::nsScreenGonk(uint32_t aId, mColorDepth = SurfaceFormatToColorDepth(mSurfaceFormat); } +static void +ReleaseGLContextSync(mozilla::gl::GLContext* aGLContext) { + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + aGLContext->Release(); +} + nsScreenGonk::~nsScreenGonk() { + // Release GLContext on compositor thread + if (mGLContext) { + CompositorParent::CompositorLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(&ReleaseGLContextSync, + mGLContext.forget().take())); + mGLContext = nullptr; + } } bool @@ -359,7 +374,8 @@ nsScreenGonk::GetDisplayType() } void -nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, +nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay, + hwc_surface_t aSurface, gl::GLContext* aGLContext) { MOZ_ASSERT(CompositorParent::IsInCompositorThread()); @@ -378,10 +394,116 @@ nsScreenGonk::GetEGLDisplay() hwc_surface_t nsScreenGonk::GetEGLSurface() { - MOZ_ASSERT(CompositorParent::IsInCompositorThread()); return mEGLSurface; } +static void +UpdateMirroringWidgetSync(nsScreenGonk* aScreen, nsWindow* aWindow) { + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + already_AddRefed window(aWindow); + aScreen->UpdateMirroringWidget(window); +} + +bool +nsScreenGonk::EnableMirroring() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!IsPrimaryScreen()); + + nsRefPtr primaryScreen = nsScreenManagerGonk::GetPrimaryScreen(); + NS_ENSURE_TRUE(primaryScreen, false); + + bool ret = primaryScreen->SetMirroringScreen(this); + NS_ENSURE_TRUE(ret, false); + + // Create a widget for mirroring + nsWidgetInitData initData; + initData.mScreenId = mId; + nsRefPtr window = new nsWindow(); + window->Create(nullptr, nullptr, mNaturalBounds, &initData); + MOZ_ASSERT(static_cast(window)->GetScreen() == this); + + // Update mMirroringWidget on compositor thread + CompositorParent::CompositorLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(&UpdateMirroringWidgetSync, + primaryScreen, + window.forget().take())); + + mIsMirroring = true; + return true; +} + +bool +nsScreenGonk::DisableMirroring() +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(!IsPrimaryScreen()); + + mIsMirroring = false; + nsRefPtr primaryScreen = nsScreenManagerGonk::GetPrimaryScreen(); + NS_ENSURE_TRUE(primaryScreen, false); + + bool ret = primaryScreen->ClearMirroringScreen(this); + NS_ENSURE_TRUE(ret, false); + + // Update mMirroringWidget on compositor thread + CompositorParent::CompositorLoop()->PostTask( + FROM_HERE, + NewRunnableFunction(&UpdateMirroringWidgetSync, + primaryScreen, + nullptr)); + return true; +} + +bool +nsScreenGonk::SetMirroringScreen(nsScreenGonk* aScreen) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsPrimaryScreen()); + + if (mMirroringScreen) { + return false; + } + mMirroringScreen = mMirroringScreen; + return true; +} + +bool +nsScreenGonk::ClearMirroringScreen(nsScreenGonk* aScreen) +{ + MOZ_ASSERT(NS_IsMainThread()); + MOZ_ASSERT(IsPrimaryScreen()); + + if (mMirroringScreen != aScreen) { + return false; + } + mMirroringScreen = nullptr; + return true; +} + +void +nsScreenGonk::UpdateMirroringWidget(already_AddRefed& aWindow) +{ + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + MOZ_ASSERT(IsPrimaryScreen()); + + if (mMirroringWidget) { + nsCOMPtr widget = mMirroringWidget.forget(); + NS_ReleaseOnMainThread(widget); + } + mMirroringWidget = aWindow; +} + +nsWindow* +nsScreenGonk::GetMirroringWidget() +{ + MOZ_ASSERT(CompositorParent::IsInCompositorThread()); + MOZ_ASSERT(IsPrimaryScreen()); + + return mMirroringWidget; +} + NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager) nsScreenManagerGonk::nsScreenManagerGonk() @@ -611,7 +733,7 @@ NotifyDisplayChange(uint32_t aId, bool aConnected) nsresult nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType, - android::IGraphicBufferProducer* aProducer) + android::IGraphicBufferProducer* aSink) { MOZ_ASSERT(NS_IsMainThread()); @@ -622,13 +744,19 @@ nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType, NS_ENSURE_TRUE(!IsScreenConnected(id), NS_ERROR_FAILURE); GonkDisplay::NativeData nativeData = - GetGonkDisplay()->GetNativeData(aDisplayType, aProducer); + GetGonkDisplay()->GetNativeData(aDisplayType, aSink); nsScreenGonk* screen = new nsScreenGonk(id, aDisplayType, nativeData); mScreens.AppendElement(screen); NotifyDisplayChange(id, true); + // By default, non primary screen does mirroring. + if (aDisplayType != GonkDisplay::DISPLAY_PRIMARY && + gfxPrefs::ScreenMirroringEnabled()) { + screen->EnableMirroring(); + } + return NS_OK; } @@ -645,6 +773,9 @@ nsScreenManagerGonk::RemoveScreen(GonkDisplay::DisplayType aDisplayType) for (size_t i = 0; i < mScreens.Length(); i++) { if (mScreens[i]->GetId() == screenId) { + if (mScreens[i]->IsMirroring()) { + mScreens[i]->DisableMirroring(); + } mScreens.RemoveElementAt(i); break; } diff --git a/widget/gonk/nsScreenManagerGonk.h b/widget/gonk/nsScreenManagerGonk.h index 247c6874b47..7d93d3e4bb7 100644 --- a/widget/gonk/nsScreenManagerGonk.h +++ b/widget/gonk/nsScreenManagerGonk.h @@ -17,14 +17,16 @@ #ifndef nsScreenManagerGonk_h___ #define nsScreenManagerGonk_h___ -#include "mozilla/Hal.h" - #include "cutils/properties.h" #include "hardware/hwcomposer.h" + #include "libdisplay/GonkDisplay.h" +#include "mozilla/Hal.h" +#include "mozilla/Mutex.h" #include "nsBaseScreen.h" #include "nsCOMPtr.h" #include "nsIScreenManager.h" +#include "nsProxyRelease.h" #include @@ -87,11 +89,25 @@ public: return mTopWindows; } - // Set EGL info of primary display. Used for BLIT Composition. + // Non-primary screen only + bool EnableMirroring(); + bool DisableMirroring(); + bool IsMirroring() + { + return mIsMirroring; + } + + // Primary screen only + bool SetMirroringScreen(nsScreenGonk* aScreen); + bool ClearMirroringScreen(nsScreenGonk* aScreen); + + // Called only on compositor thread void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, mozilla::gl::GLContext* aGLContext); hwc_display_t GetEGLDisplay(); hwc_surface_t GetEGLSurface(); + void UpdateMirroringWidget(already_AddRefed& aWindow); // Primary screen only + nsWindow* GetMirroringWidget(); // Primary screen only protected: uint32_t mId; @@ -107,12 +123,15 @@ protected: #if ANDROID_VERSION >= 17 android::sp mDisplaySurface; #endif + bool mIsMirroring; // Non-primary screen only + nsRefPtr mMirroringScreen; // Primary screen only // Accessed and updated only on compositor thread GonkDisplay::DisplayType mDisplayType; hwc_display_t mEGLDisplay; hwc_surface_t mEGLSurface; - mozilla::gl::GLContext* mGLContext; + nsRefPtr mGLContext; + nsRefPtr mMirroringWidget; // Primary screen only }; class nsScreenManagerGonk final : public nsIScreenManager @@ -133,7 +152,7 @@ public: void DisplayEnabled(bool aEnabled); nsresult AddScreen(GonkDisplay::DisplayType aDisplayType, - android::IGraphicBufferProducer* aProducer = nullptr); + android::IGraphicBufferProducer* aSink = nullptr); nsresult RemoveScreen(GonkDisplay::DisplayType aDisplayType);