mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1186000 - Support screen mirroring to HDMI display on gonk r=mwu,mattwoodrow
This commit is contained in:
parent
be1f9cecbe
commit
def035db89
@ -996,6 +996,9 @@ pref("gfx.canvas.max-size-for-skia-gl", -1);
|
|||||||
// enable fence with readpixels for SurfaceStream
|
// enable fence with readpixels for SurfaceStream
|
||||||
pref("gfx.gralloc.fence-with-readpixels", true);
|
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.
|
// The url of the page used to display network error details.
|
||||||
pref("b2g.neterror.url", "net_error.html");
|
pref("b2g.neterror.url", "net_error.html");
|
||||||
|
|
||||||
|
@ -55,11 +55,17 @@
|
|||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include "AndroidBridge.h"
|
#include "AndroidBridge.h"
|
||||||
|
#endif
|
||||||
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||||
#include "opengl/CompositorOGL.h"
|
#include "opengl/CompositorOGL.h"
|
||||||
#include "GLContextEGL.h"
|
#include "GLContextEGL.h"
|
||||||
#include "GLContextProvider.h"
|
#include "GLContextProvider.h"
|
||||||
#include "ScopedGLHelpers.h"
|
#include "ScopedGLHelpers.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
#include "nsScreenManagerGonk.h"
|
||||||
|
#include "nsWindow.h"
|
||||||
|
#endif
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
#include "TextRenderer.h" // for TextRenderer
|
#include "TextRenderer.h" // for TextRenderer
|
||||||
|
|
||||||
@ -302,7 +308,7 @@ LayerManagerComposite::EndTransaction(const TimeStamp& aTimeStamp,
|
|||||||
ApplyOcclusionCulling(mRoot, opaque);
|
ApplyOcclusionCulling(mRoot, opaque);
|
||||||
|
|
||||||
Render();
|
Render();
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||||
RenderToPresentationSurface();
|
RenderToPresentationSurface();
|
||||||
#endif
|
#endif
|
||||||
mGeometryChanged = false;
|
mGeometryChanged = false;
|
||||||
@ -780,7 +786,7 @@ LayerManagerComposite::Render()
|
|||||||
RecordFrame();
|
RecordFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||||
class ScopedCompositorProjMatrix {
|
class ScopedCompositorProjMatrix {
|
||||||
public:
|
public:
|
||||||
ScopedCompositorProjMatrix(CompositorOGL* aCompositor, const Matrix4x4& aProjMatrix):
|
ScopedCompositorProjMatrix(CompositorOGL* aCompositor, const Matrix4x4& aProjMatrix):
|
||||||
@ -854,6 +860,7 @@ private:
|
|||||||
void
|
void
|
||||||
LayerManagerComposite::RenderToPresentationSurface()
|
LayerManagerComposite::RenderToPresentationSurface()
|
||||||
{
|
{
|
||||||
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
if (!AndroidBridge::Bridge()) {
|
if (!AndroidBridge::Bridge()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -886,17 +893,60 @@ LayerManagerComposite::RenderToPresentationSurface()
|
|||||||
|
|
||||||
const IntSize windowSize = AndroidBridge::Bridge()->GetNativeWindowSize(window);
|
const IntSize windowSize = AndroidBridge::Bridge()->GetNativeWindowSize(window);
|
||||||
|
|
||||||
|
#elif defined(MOZ_WIDGET_GONK)
|
||||||
|
CompositorOGL* compositor = static_cast<CompositorOGL*>(mCompositor.get());
|
||||||
|
nsScreenGonk* screen = static_cast<nsWindow*>(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<GLContext> gl = gl::GLContextProvider::CreateForWindow(mirrorScreenWidget);
|
||||||
|
mirrorScreenWidget->SetNativeData(NS_NATIVE_OPENGL_CONTEXT,
|
||||||
|
reinterpret_cast<uintptr_t>(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)) {
|
if ((windowSize.width <= 0) || (windowSize.height <= 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScreenRotation rotation = compositor->GetScreenRotation();
|
||||||
|
|
||||||
const int actualWidth = windowSize.width;
|
const int actualWidth = windowSize.width;
|
||||||
const int actualHeight = windowSize.height;
|
const int actualHeight = windowSize.height;
|
||||||
|
|
||||||
const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
|
const gfx::IntSize originalSize = compositor->GetDestinationSurfaceSize();
|
||||||
|
const nsIntRect originalRect = nsIntRect(0, 0, originalSize.width, originalSize.height);
|
||||||
|
|
||||||
const int pageWidth = originalSize.width;
|
int pageWidth = originalSize.width;
|
||||||
const int pageHeight = originalSize.height;
|
int pageHeight = originalSize.height;
|
||||||
|
if (rotation == ROTATION_90 || rotation == ROTATION_270) {
|
||||||
|
pageWidth = originalSize.height;
|
||||||
|
pageHeight = originalSize.width;
|
||||||
|
}
|
||||||
|
|
||||||
float scale = 1.0;
|
float scale = 1.0;
|
||||||
|
|
||||||
@ -910,42 +960,47 @@ LayerManagerComposite::RenderToPresentationSurface()
|
|||||||
ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);
|
ScopedCompostitorSurfaceSize overrideSurfaceSize(compositor, actualSize);
|
||||||
|
|
||||||
const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
|
const ScreenPoint offset((actualWidth - (int)(scale * pageWidth)) / 2, 0);
|
||||||
ScopedCompositorRenderOffset overrideRenderOffset(compositor, offset);
|
|
||||||
ScopedContextSurfaceOverride overrideSurface(egl, surface);
|
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;
|
nsIntRegion invalid;
|
||||||
Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight);
|
Rect bounds(0.0f, 0.0f, scale * pageWidth, (float)actualHeight);
|
||||||
Rect rect, actualBounds;
|
Rect rect, actualBounds;
|
||||||
|
|
||||||
mCompositor->BeginFrame(invalid, nullptr, bounds, &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
|
// 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
|
// chrome such as the URL bar. Override that so that the entire frame buffer
|
||||||
// is cleared.
|
// 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->fClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
egl->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
|
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()->Prepare(RenderTargetPixel::FromUntyped(clipRect));
|
||||||
RootLayer()->RenderLayer(clipRect);
|
RootLayer()->RenderLayer(clipRect);
|
||||||
|
|
||||||
mCompositor->EndFrame();
|
mCompositor->EndFrame();
|
||||||
mCompositor->SetDispAcquireFence(mRoot);
|
mCompositor->SetDispAcquireFence(mRoot); // Call after EndFrame()
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
nsRefPtr<Composer2D> composer2D;
|
||||||
|
composer2D = mCompositor->GetWidget()->GetComposer2D();
|
||||||
|
if (composer2D) {
|
||||||
|
composer2D->Render(mirrorScreenWidget);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ private:
|
|||||||
* Render the current layer tree to the active target.
|
* Render the current layer tree to the active target.
|
||||||
*/
|
*/
|
||||||
void Render();
|
void Render();
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||||
void RenderToPresentationSurface();
|
void RenderToPresentationSurface();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -263,6 +263,7 @@ private:
|
|||||||
DECL_GFX_PREF(Once, "gfx.vsync.hw-vsync.enabled", HardwareVsyncEnabled, bool, false);
|
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.vsync.refreshdriver", VsyncAlignedRefreshDriver, bool, false);
|
||||||
DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true);
|
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.msaa-level", MSAALevel, uint32_t, 2);
|
||||||
DECL_GFX_PREF(Live, "gl.require-hardware", RequireHardwareGL, bool, false);
|
DECL_GFX_PREF(Live, "gl.require-hardware", RequireHardwareGL, bool, false);
|
||||||
|
@ -751,6 +751,9 @@ HwcComposer2D::Render(nsIWidget* aWidget)
|
|||||||
mList->hwLayers[mList->numHwLayers - 1].handle = dispSurface->lastHandle;
|
mList->hwLayers[mList->numHwLayers - 1].handle = dispSurface->lastHandle;
|
||||||
mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
|
mList->hwLayers[mList->numHwLayers - 1].acquireFenceFd = dispSurface->GetPrevDispAcquireFd();
|
||||||
} else {
|
} else {
|
||||||
|
// Update screen rect to handle a case that TryRenderWithHwc() is not called.
|
||||||
|
mScreenRect = screen->GetNaturalBounds();
|
||||||
|
|
||||||
mList->flags = HWC_GEOMETRY_CHANGED;
|
mList->flags = HWC_GEOMETRY_CHANGED;
|
||||||
mList->numHwLayers = 2;
|
mList->numHwLayers = 2;
|
||||||
mList->hwLayers[0].hints = 0;
|
mList->hwLayers[0].hints = 0;
|
||||||
@ -773,7 +776,8 @@ HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* scre
|
|||||||
if (mPrepared) {
|
if (mPrepared) {
|
||||||
LOGE("Multiple hwc prepare calls!");
|
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;
|
mPrepared = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,6 @@ HwcHAL::HwcHAL()
|
|||||||
printf_stderr("HwcHAL Error: Cannot load hwcomposer");
|
printf_stderr("HwcHAL Error: Cannot load hwcomposer");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetHwcAttributes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HwcHAL::~HwcHAL()
|
HwcHAL::~HwcHAL()
|
||||||
@ -79,6 +77,7 @@ HwcHAL::ResetHwc()
|
|||||||
int
|
int
|
||||||
HwcHAL::Prepare(HwcList *aList,
|
HwcHAL::Prepare(HwcList *aList,
|
||||||
uint32_t aDisp,
|
uint32_t aDisp,
|
||||||
|
hwc_rect_t aDispRect,
|
||||||
buffer_handle_t aHandle,
|
buffer_handle_t aHandle,
|
||||||
int aFenceFd)
|
int aFenceFd)
|
||||||
{
|
{
|
||||||
@ -103,8 +102,8 @@ HwcHAL::Prepare(HwcList *aList,
|
|||||||
aList->hwLayers[idx].handle = aHandle;
|
aList->hwLayers[idx].handle = aHandle;
|
||||||
aList->hwLayers[idx].blending = HWC_BLENDING_PREMULT;
|
aList->hwLayers[idx].blending = HWC_BLENDING_PREMULT;
|
||||||
aList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET;
|
aList->hwLayers[idx].compositionType = HWC_FRAMEBUFFER_TARGET;
|
||||||
SetCrop(aList->hwLayers[idx], mHwcRect);
|
SetCrop(aList->hwLayers[idx], aDispRect);
|
||||||
aList->hwLayers[idx].displayFrame = mHwcRect;
|
aList->hwLayers[idx].displayFrame = aDispRect;
|
||||||
aList->hwLayers[idx].visibleRegionScreen.numRects = 1;
|
aList->hwLayers[idx].visibleRegionScreen.numRects = 1;
|
||||||
aList->hwLayers[idx].visibleRegionScreen.rects = &aList->hwLayers[idx].displayFrame;
|
aList->hwLayers[idx].visibleRegionScreen.rects = &aList->hwLayers[idx].displayFrame;
|
||||||
aList->hwLayers[idx].acquireFenceFd = aFenceFd;
|
aList->hwLayers[idx].acquireFenceFd = aFenceFd;
|
||||||
@ -195,20 +194,6 @@ HwcHAL::RegisterHwcEventCallback(const HwcHALProcs_t &aProcs)
|
|||||||
#endif
|
#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
|
uint32_t
|
||||||
HwcHAL::GetAPIVersion() const
|
HwcHAL::GetAPIVersion() const
|
||||||
{
|
{
|
||||||
|
@ -31,8 +31,6 @@ public:
|
|||||||
|
|
||||||
virtual bool HasHwc() const override { return static_cast<bool>(mHwc); }
|
virtual bool HasHwc() const override { return static_cast<bool>(mHwc); }
|
||||||
|
|
||||||
virtual const hwc_rect_t GetHwcRect() const override { return mHwcRect; }
|
|
||||||
|
|
||||||
virtual void SetEGLInfo(hwc_display_t aDpy,
|
virtual void SetEGLInfo(hwc_display_t aDpy,
|
||||||
hwc_surface_t aSur) override { }
|
hwc_surface_t aSur) override { }
|
||||||
|
|
||||||
@ -45,6 +43,7 @@ public:
|
|||||||
|
|
||||||
virtual int Prepare(HwcList *aList,
|
virtual int Prepare(HwcList *aList,
|
||||||
uint32_t aDisp,
|
uint32_t aDisp,
|
||||||
|
hwc_rect_t aDispRect,
|
||||||
buffer_handle_t aHandle,
|
buffer_handle_t aHandle,
|
||||||
int aFenceFd) override;
|
int aFenceFd) override;
|
||||||
|
|
||||||
@ -60,13 +59,10 @@ public:
|
|||||||
virtual bool RegisterHwcEventCallback(const HwcHALProcs_t &aProcs) override;
|
virtual bool RegisterHwcEventCallback(const HwcHALProcs_t &aProcs) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GetHwcAttributes();
|
|
||||||
|
|
||||||
uint32_t GetAPIVersion() const;
|
uint32_t GetAPIVersion() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HwcDevice *mHwc = nullptr;
|
HwcDevice *mHwc = nullptr;
|
||||||
hwc_rect_t mHwcRect = {0};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -85,9 +85,6 @@ public:
|
|||||||
// Check if mHwc exists
|
// Check if mHwc exists
|
||||||
virtual bool HasHwc() const = 0;
|
virtual bool HasHwc() const = 0;
|
||||||
|
|
||||||
// Get HwcRect
|
|
||||||
virtual const hwc_rect_t GetHwcRect() const = 0;
|
|
||||||
|
|
||||||
// Set EGL info (only ICS need this info)
|
// Set EGL info (only ICS need this info)
|
||||||
virtual void SetEGLInfo(hwc_display_t aEGLDisplay,
|
virtual void SetEGLInfo(hwc_display_t aEGLDisplay,
|
||||||
hwc_surface_t aEGLSurface) = 0;
|
hwc_surface_t aEGLSurface) = 0;
|
||||||
@ -105,6 +102,7 @@ public:
|
|||||||
// HwcDevice prepare
|
// HwcDevice prepare
|
||||||
virtual int Prepare(HwcList *aList,
|
virtual int Prepare(HwcList *aList,
|
||||||
uint32_t aDisp,
|
uint32_t aDisp,
|
||||||
|
hwc_rect_t aDispRect,
|
||||||
buffer_handle_t aHandle,
|
buffer_handle_t aHandle,
|
||||||
int aFenceFd) = 0;
|
int aFenceFd) = 0;
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ HwcICS::ResetHwc()
|
|||||||
int
|
int
|
||||||
HwcICS::Prepare(HwcList *aList,
|
HwcICS::Prepare(HwcList *aList,
|
||||||
uint32_t aDisp,
|
uint32_t aDisp,
|
||||||
|
hwc_rect_t aDispRect,
|
||||||
buffer_handle_t aHandle,
|
buffer_handle_t aHandle,
|
||||||
int aFenceFd)
|
int aFenceFd)
|
||||||
{
|
{
|
||||||
|
@ -31,8 +31,6 @@ public:
|
|||||||
|
|
||||||
virtual bool HasHwc() const override { return static_cast<bool>(mHwc); }
|
virtual bool HasHwc() const override { return static_cast<bool>(mHwc); }
|
||||||
|
|
||||||
virtual const hwc_rect_t GetHwcRect() const override { return {0}; }
|
|
||||||
|
|
||||||
virtual void SetEGLInfo(hwc_display_t aEGLDisplay,
|
virtual void SetEGLInfo(hwc_display_t aEGLDisplay,
|
||||||
hwc_surface_t aEGLSurface) override;
|
hwc_surface_t aEGLSurface) override;
|
||||||
|
|
||||||
@ -45,6 +43,7 @@ public:
|
|||||||
|
|
||||||
virtual int Prepare(HwcList *aList,
|
virtual int Prepare(HwcList *aList,
|
||||||
uint32_t aDisp,
|
uint32_t aDisp,
|
||||||
|
hwc_rect_t aDispRect,
|
||||||
buffer_handle_t aHandle,
|
buffer_handle_t aHandle,
|
||||||
int aFenceFd) override;
|
int aFenceFd) override;
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ nsScreenGonk::nsScreenGonk(uint32_t aId,
|
|||||||
#if ANDROID_VERSION >= 17
|
#if ANDROID_VERSION >= 17
|
||||||
, mDisplaySurface(aNativeData.mDisplaySurface)
|
, mDisplaySurface(aNativeData.mDisplaySurface)
|
||||||
#endif
|
#endif
|
||||||
|
, mIsMirroring(false)
|
||||||
, mDisplayType(aDisplayType)
|
, mDisplayType(aDisplayType)
|
||||||
, mEGLDisplay(EGL_NO_DISPLAY)
|
, mEGLDisplay(EGL_NO_DISPLAY)
|
||||||
, mEGLSurface(EGL_NO_SURFACE)
|
, mEGLSurface(EGL_NO_SURFACE)
|
||||||
@ -143,8 +144,22 @@ nsScreenGonk::nsScreenGonk(uint32_t aId,
|
|||||||
mColorDepth = SurfaceFormatToColorDepth(mSurfaceFormat);
|
mColorDepth = SurfaceFormatToColorDepth(mSurfaceFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ReleaseGLContextSync(mozilla::gl::GLContext* aGLContext) {
|
||||||
|
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||||
|
aGLContext->Release();
|
||||||
|
}
|
||||||
|
|
||||||
nsScreenGonk::~nsScreenGonk()
|
nsScreenGonk::~nsScreenGonk()
|
||||||
{
|
{
|
||||||
|
// Release GLContext on compositor thread
|
||||||
|
if (mGLContext) {
|
||||||
|
CompositorParent::CompositorLoop()->PostTask(
|
||||||
|
FROM_HERE,
|
||||||
|
NewRunnableFunction(&ReleaseGLContextSync,
|
||||||
|
mGLContext.forget().take()));
|
||||||
|
mGLContext = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -359,7 +374,8 @@ nsScreenGonk::GetDisplayType()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
|
nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay,
|
||||||
|
hwc_surface_t aSurface,
|
||||||
gl::GLContext* aGLContext)
|
gl::GLContext* aGLContext)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||||
@ -378,10 +394,116 @@ nsScreenGonk::GetEGLDisplay()
|
|||||||
hwc_surface_t
|
hwc_surface_t
|
||||||
nsScreenGonk::GetEGLSurface()
|
nsScreenGonk::GetEGLSurface()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
|
||||||
return mEGLSurface;
|
return mEGLSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
UpdateMirroringWidgetSync(nsScreenGonk* aScreen, nsWindow* aWindow) {
|
||||||
|
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||||
|
already_AddRefed<nsWindow> window(aWindow);
|
||||||
|
aScreen->UpdateMirroringWidget(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsScreenGonk::EnableMirroring()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
MOZ_ASSERT(!IsPrimaryScreen());
|
||||||
|
|
||||||
|
nsRefPtr<nsScreenGonk> 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<nsWindow> window = new nsWindow();
|
||||||
|
window->Create(nullptr, nullptr, mNaturalBounds, &initData);
|
||||||
|
MOZ_ASSERT(static_cast<nsWindow*>(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<nsScreenGonk> 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<nsWindow>& aWindow)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(CompositorParent::IsInCompositorThread());
|
||||||
|
MOZ_ASSERT(IsPrimaryScreen());
|
||||||
|
|
||||||
|
if (mMirroringWidget) {
|
||||||
|
nsCOMPtr<nsIWidget> 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)
|
NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager)
|
||||||
|
|
||||||
nsScreenManagerGonk::nsScreenManagerGonk()
|
nsScreenManagerGonk::nsScreenManagerGonk()
|
||||||
@ -611,7 +733,7 @@ NotifyDisplayChange(uint32_t aId, bool aConnected)
|
|||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType,
|
nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType,
|
||||||
android::IGraphicBufferProducer* aProducer)
|
android::IGraphicBufferProducer* aSink)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
@ -622,13 +744,19 @@ nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType,
|
|||||||
NS_ENSURE_TRUE(!IsScreenConnected(id), NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(!IsScreenConnected(id), NS_ERROR_FAILURE);
|
||||||
|
|
||||||
GonkDisplay::NativeData nativeData =
|
GonkDisplay::NativeData nativeData =
|
||||||
GetGonkDisplay()->GetNativeData(aDisplayType, aProducer);
|
GetGonkDisplay()->GetNativeData(aDisplayType, aSink);
|
||||||
nsScreenGonk* screen = new nsScreenGonk(id, aDisplayType, nativeData);
|
nsScreenGonk* screen = new nsScreenGonk(id, aDisplayType, nativeData);
|
||||||
|
|
||||||
mScreens.AppendElement(screen);
|
mScreens.AppendElement(screen);
|
||||||
|
|
||||||
NotifyDisplayChange(id, true);
|
NotifyDisplayChange(id, true);
|
||||||
|
|
||||||
|
// By default, non primary screen does mirroring.
|
||||||
|
if (aDisplayType != GonkDisplay::DISPLAY_PRIMARY &&
|
||||||
|
gfxPrefs::ScreenMirroringEnabled()) {
|
||||||
|
screen->EnableMirroring();
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,6 +773,9 @@ nsScreenManagerGonk::RemoveScreen(GonkDisplay::DisplayType aDisplayType)
|
|||||||
|
|
||||||
for (size_t i = 0; i < mScreens.Length(); i++) {
|
for (size_t i = 0; i < mScreens.Length(); i++) {
|
||||||
if (mScreens[i]->GetId() == screenId) {
|
if (mScreens[i]->GetId() == screenId) {
|
||||||
|
if (mScreens[i]->IsMirroring()) {
|
||||||
|
mScreens[i]->DisableMirroring();
|
||||||
|
}
|
||||||
mScreens.RemoveElementAt(i);
|
mScreens.RemoveElementAt(i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,16 @@
|
|||||||
#ifndef nsScreenManagerGonk_h___
|
#ifndef nsScreenManagerGonk_h___
|
||||||
#define nsScreenManagerGonk_h___
|
#define nsScreenManagerGonk_h___
|
||||||
|
|
||||||
#include "mozilla/Hal.h"
|
|
||||||
|
|
||||||
#include "cutils/properties.h"
|
#include "cutils/properties.h"
|
||||||
#include "hardware/hwcomposer.h"
|
#include "hardware/hwcomposer.h"
|
||||||
|
|
||||||
#include "libdisplay/GonkDisplay.h"
|
#include "libdisplay/GonkDisplay.h"
|
||||||
|
#include "mozilla/Hal.h"
|
||||||
|
#include "mozilla/Mutex.h"
|
||||||
#include "nsBaseScreen.h"
|
#include "nsBaseScreen.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIScreenManager.h"
|
#include "nsIScreenManager.h"
|
||||||
|
#include "nsProxyRelease.h"
|
||||||
|
|
||||||
#include <android/native_window.h>
|
#include <android/native_window.h>
|
||||||
|
|
||||||
@ -87,11 +89,25 @@ public:
|
|||||||
return mTopWindows;
|
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,
|
void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
|
||||||
mozilla::gl::GLContext* aGLContext);
|
mozilla::gl::GLContext* aGLContext);
|
||||||
hwc_display_t GetEGLDisplay();
|
hwc_display_t GetEGLDisplay();
|
||||||
hwc_surface_t GetEGLSurface();
|
hwc_surface_t GetEGLSurface();
|
||||||
|
void UpdateMirroringWidget(already_AddRefed<nsWindow>& aWindow); // Primary screen only
|
||||||
|
nsWindow* GetMirroringWidget(); // Primary screen only
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint32_t mId;
|
uint32_t mId;
|
||||||
@ -107,12 +123,15 @@ protected:
|
|||||||
#if ANDROID_VERSION >= 17
|
#if ANDROID_VERSION >= 17
|
||||||
android::sp<android::DisplaySurface> mDisplaySurface;
|
android::sp<android::DisplaySurface> mDisplaySurface;
|
||||||
#endif
|
#endif
|
||||||
|
bool mIsMirroring; // Non-primary screen only
|
||||||
|
nsRefPtr<nsScreenGonk> mMirroringScreen; // Primary screen only
|
||||||
|
|
||||||
// Accessed and updated only on compositor thread
|
// Accessed and updated only on compositor thread
|
||||||
GonkDisplay::DisplayType mDisplayType;
|
GonkDisplay::DisplayType mDisplayType;
|
||||||
hwc_display_t mEGLDisplay;
|
hwc_display_t mEGLDisplay;
|
||||||
hwc_surface_t mEGLSurface;
|
hwc_surface_t mEGLSurface;
|
||||||
mozilla::gl::GLContext* mGLContext;
|
nsRefPtr<mozilla::gl::GLContext> mGLContext;
|
||||||
|
nsRefPtr<nsWindow> mMirroringWidget; // Primary screen only
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsScreenManagerGonk final : public nsIScreenManager
|
class nsScreenManagerGonk final : public nsIScreenManager
|
||||||
@ -133,7 +152,7 @@ public:
|
|||||||
void DisplayEnabled(bool aEnabled);
|
void DisplayEnabled(bool aEnabled);
|
||||||
|
|
||||||
nsresult AddScreen(GonkDisplay::DisplayType aDisplayType,
|
nsresult AddScreen(GonkDisplay::DisplayType aDisplayType,
|
||||||
android::IGraphicBufferProducer* aProducer = nullptr);
|
android::IGraphicBufferProducer* aSink = nullptr);
|
||||||
|
|
||||||
nsresult RemoveScreen(GonkDisplay::DisplayType aDisplayType);
|
nsresult RemoveScreen(GonkDisplay::DisplayType aDisplayType);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user