Bug 1138287 - Part 2: Support multi-screen on Gonk platform. r=mwu, r=sotaro, r=jgilbert, r=mattwoodrow

This commit is contained in:
Shelly Lin 2015-06-05 11:29:30 +08:00
parent 8c9a101347
commit 0c646b32d4
17 changed files with 480 additions and 186 deletions

View File

@ -19,6 +19,8 @@
#define GET_NATIVE_WINDOW(aWidget) ((EGLNativeWindowType)aWidget->GetNativeData(NS_NATIVE_WINDOW))
#include "HwcComposer2D.h"
#include "libdisplay/GonkDisplay.h"
#include "nsWindow.h"
#include "nsScreenManagerGonk.h"
#endif
#if defined(ANDROID)
@ -128,7 +130,7 @@ namespace gl {
} while (0)
static bool
CreateConfig(EGLConfig* aConfig);
CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget);
// append three zeros at the end of attribs list to work around
// EGL implementation bugs that iterate until they find 0, instead of
@ -483,7 +485,7 @@ GLContextEGL::CreateSurfaceForWindow(nsIWidget* aWidget)
}
EGLConfig config;
if (!CreateConfig(&config)) {
if (!CreateConfig(&config, aWidget)) {
MOZ_CRASH("Failed to create EGLConfig!\n");
return nullptr;
}
@ -637,7 +639,7 @@ static const EGLint kEGLConfigAttribsRGBA32[] = {
};
static bool
CreateConfig(EGLConfig* aConfig, int32_t depth)
CreateConfig(EGLConfig* aConfig, int32_t depth, nsIWidget* aWidget)
{
EGLConfig configs[64];
const EGLint* attribs;
@ -673,12 +675,13 @@ CreateConfig(EGLConfig* aConfig, int32_t depth)
// HAL_PIXEL_FORMAT_RGBX_8888
// HAL_PIXEL_FORMAT_BGRA_8888
// HAL_PIXEL_FORMAT_RGB_565
nsWindow* window = static_cast<nsWindow*>(aWidget);
for (int j = 0; j < ncfg; ++j) {
EGLConfig config = configs[j];
EGLint format;
if (sEGLLibrary.fGetConfigAttrib(EGL_DISPLAY(), config,
LOCAL_EGL_NATIVE_VISUAL_ID, &format) &&
format == GetGonkDisplay()->surfaceformat)
format == window->GetScreen()->GetSurfaceFormat())
{
*aConfig = config;
return true;
@ -714,20 +717,20 @@ CreateConfig(EGLConfig* aConfig, int32_t depth)
// NB: It's entirely legal for the returned EGLConfig to be valid yet
// have the value null.
static bool
CreateConfig(EGLConfig* aConfig)
CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget)
{
int32_t depth = gfxPlatform::GetPlatform()->GetScreenDepth();
if (!CreateConfig(aConfig, depth)) {
if (!CreateConfig(aConfig, depth, aWidget)) {
#ifdef MOZ_WIDGET_ANDROID
// Bug 736005
// Android doesn't always support 16 bit so also try 24 bit
if (depth == 16) {
return CreateConfig(aConfig, 24);
return CreateConfig(aConfig, 24, aWidget);
}
// Bug 970096
// Some devices that have 24 bit screens only support 16 bit OpenGL?
if (depth == 24) {
return CreateConfig(aConfig, 16);
return CreateConfig(aConfig, 16, aWidget);
}
#endif
return false;
@ -772,7 +775,7 @@ GLContextProviderEGL::CreateForWindow(nsIWidget *aWidget)
bool doubleBuffered = true;
EGLConfig config;
if (!CreateConfig(&config)) {
if (!CreateConfig(&config, aWidget)) {
MOZ_CRASH("Failed to create EGLConfig!\n");
return nullptr;
}
@ -811,7 +814,7 @@ GLContextProviderEGL::CreateEGLSurface(void* aWindow)
}
EGLConfig config;
if (!CreateConfig(&config)) {
if (!CreateConfig(&config, static_cast<nsIWidget*>(aWindow))) {
MOZ_CRASH("Failed to create EGLConfig!\n");
}

View File

@ -666,7 +666,8 @@ LayerManagerComposite::Render()
// We can't use composert2D if we have layer effects
if (!mTarget && !haveLayerEffects &&
gfxPrefs::Composer2DCompositionEnabled() &&
composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot, mGeometryChanged))
composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot,
mCompositor->GetWidget(), mGeometryChanged))
{
LayerScope::SetHWComposed();
if (mFPS) {
@ -772,7 +773,7 @@ LayerManagerComposite::Render()
}
if (composer2D) {
composer2D->Render();
composer2D->Render(mCompositor->GetWidget());
}
mCompositor->GetWidget()->PostRender(this);

View File

@ -26,6 +26,8 @@
* layer manager fall back on full GPU composition.
*/
class nsIWidget;
namespace mozilla {
namespace layers {
@ -47,13 +49,14 @@ public:
* Currently, when TryRender() returns true, the entire framebuffer
* must have been rendered.
*/
virtual bool TryRenderWithHwc(Layer* aRoot, bool aGeometryChanged) = 0;
virtual bool TryRenderWithHwc(Layer* aRoot, nsIWidget* aWidget,
bool aGeometryChanged) = 0;
/**
* Return true if Composer2D does composition. Return false if Composer2D
* failed the composition.
*/
virtual bool Render() = 0;
virtual bool Render(nsIWidget* aWidget) = 0;
/**
* Return true if Composer2D has a fast composition hardware.

View File

@ -57,6 +57,8 @@
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
#include "libdisplay/GonkDisplay.h" // for GonkDisplay
#include <ui/Fence.h>
#include "nsWindow.h"
#include "nsScreenManagerGonk.h"
#endif
namespace mozilla {
@ -1401,8 +1403,9 @@ CompositorOGL::SetDispAcquireFence(Layer* aLayer)
if (!aLayer) {
return;
}
RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(GetGonkDisplay()->GetPrevDispAcquireFd());
nsWindow* window = static_cast<nsWindow*>(mWidget);
RefPtr<FenceHandle::FdObj> fence = new FenceHandle::FdObj(
window->GetScreen()->GetPrevDispAcquireFd());
mReleaseFenceHandle.Merge(FenceHandle(fence));
}

View File

@ -33,6 +33,8 @@
#include "gfx2DGlue.h"
#include "gfxPlatform.h"
#include "VsyncSource.h"
#include "nsScreenManagerGonk.h"
#include "nsWindow.h"
#if ANDROID_VERSION >= 17
#include "libdisplay/DisplaySurface.h"
@ -96,7 +98,7 @@ static void
HookHotplug(const struct hwc_procs* aProcs, int aDisplay,
int aConnected)
{
// no op
HwcComposer2D::GetInstance()->Hotplug(aDisplay, aConnected);
}
static const hwc_procs_t sHWCProcs = {
@ -111,9 +113,6 @@ static StaticRefPtr<HwcComposer2D> sInstance;
HwcComposer2D::HwcComposer2D()
: mHwc(nullptr)
, mList(nullptr)
, mDpy(EGL_NO_DISPLAY)
, mSur(EGL_NO_SURFACE)
, mGLContext(nullptr)
, mMaxLayerCount(0)
, mColorFill(false)
, mRBSwapSupport(false)
@ -133,7 +132,8 @@ HwcComposer2D::HwcComposer2D()
nsIntSize screenSize;
ANativeWindow *win = GetGonkDisplay()->GetNativeWindow();
GonkDisplay::NativeData data = GetGonkDisplay()->GetNativeData(GonkDisplay::DISPLAY_PRIMARY);
ANativeWindow *win = data.mNativeWindow.get();
win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width);
win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height);
mScreenRect = gfx::IntRect(gfx::IntPoint(0, 0), screenSize);
@ -248,6 +248,38 @@ HwcComposer2D::Invalidate()
mCompositorParent->ScheduleRenderOnCompositorThread();
}
}
namespace {
class HotplugEvent : public nsRunnable {
public:
HotplugEvent(GonkDisplay::DisplayType aType, bool aConnected)
: mType(aType)
, mConnected(aConnected)
{
}
NS_IMETHOD Run()
{
nsRefPtr<nsScreenManagerGonk> screenManager =
nsScreenManagerGonk::GetInstance();
if (mConnected) {
screenManager->AddScreen(mType);
} else {
screenManager->RemoveScreen(mType);
}
}
private:
GonkDisplay::DisplayType mType;
bool mConnected;
};
} // anonymous namespace
void
HwcComposer2D::Hotplug(int aDisplay, int aConnected)
{
NS_DispatchToMainThread(new HotplugEvent(GonkDisplay::DISPLAY_EXTERNAL,
aConnected));
}
#endif
void
@ -257,14 +289,6 @@ HwcComposer2D::SetCompositorParent(CompositorParent* aCompositorParent)
mCompositorParent = aCompositorParent;
}
void
HwcComposer2D::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext)
{
mDpy = aDisplay;
mSur = aSurface;
mGLContext = aGLContext;
}
bool
HwcComposer2D::ReallocLayerList()
{
@ -684,9 +708,9 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
#if ANDROID_VERSION >= 17
bool
HwcComposer2D::TryHwComposition()
HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
{
DisplaySurface* dispSurface = (DisplaySurface*)(GetGonkDisplay()->GetDispSurface());
DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
if (!(dispSurface && dispSurface->lastHandle)) {
LOGD("H/W Composition failed. DispSurface not initialized.");
@ -702,7 +726,7 @@ HwcComposer2D::TryHwComposition()
}
}
Prepare(dispSurface->lastHandle, -1);
Prepare(dispSurface->lastHandle, -1, aScreen);
/* Possible composition paths, after hwc prepare:
1. GPU Composition
@ -757,8 +781,8 @@ HwcComposer2D::TryHwComposition()
return false;
} else if (blitComposite) {
// BLIT Composition, flip DispSurface target
GetGonkDisplay()->UpdateDispSurface(mDpy, mSur);
DisplaySurface* dispSurface = (DisplaySurface*)(GetGonkDisplay()->GetDispSurface());
GetGonkDisplay()->UpdateDispSurface(aScreen->GetDpy(), aScreen->GetSur());
DisplaySurface* dispSurface = aScreen->GetDisplaySurface();
if (!dispSurface) {
LOGE("H/W Composition failed. NULL DispSurface.");
return false;
@ -769,22 +793,25 @@ HwcComposer2D::TryHwComposition()
}
// BLIT or full OVERLAY Composition
Commit();
Commit(aScreen);
GetGonkDisplay()->SetDispReleaseFd(mList->hwLayers[idx].releaseFenceFd);
DisplaySurface* displaySurface = aScreen->GetDisplaySurface();
displaySurface->setReleaseFenceFd(mList->hwLayers[idx].releaseFenceFd);
mList->hwLayers[idx].releaseFenceFd = -1;
return true;
}
bool
HwcComposer2D::Render()
HwcComposer2D::Render(nsIWidget* aWidget)
{
nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
// HWC module does not exist or mList is not created yet.
if (!mHwc || !mList) {
return GetGonkDisplay()->SwapBuffers(mDpy, mSur);
return GetGonkDisplay()->SwapBuffers(screen->GetDpy(), screen->GetSur());
}
DisplaySurface* dispSurface = (DisplaySurface*)(GetGonkDisplay()->GetDispSurface());
DisplaySurface* dispSurface = screen->GetDisplaySurface();
if (!dispSurface) {
LOGE("H/W Composition failed. DispSurface not initialized.");
return false;
@ -804,25 +831,26 @@ HwcComposer2D::Render()
mList->hwLayers[0].acquireFenceFd = -1;
mList->hwLayers[0].releaseFenceFd = -1;
mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height};
Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd());
Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd(), screen);
}
// GPU or partial HWC Composition
Commit();
Commit(screen);
GetGonkDisplay()->SetDispReleaseFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
dispSurface->setReleaseFenceFd(mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd);
mList->hwLayers[mList->numHwLayers - 1].releaseFenceFd = -1;
return true;
}
void
HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence)
HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen)
{
int idx = mList->numHwLayers - 1;
const hwc_rect_t r = {0, 0, mScreenRect.width, mScreenRect.height};
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
displays[HWC_DISPLAY_PRIMARY] = mList;
uint32_t displaytype = screen->GetDisplayType();
displays[displaytype] = mList;
mList->outbufAcquireFenceFd = -1;
mList->outbuf = nullptr;
mList->retireFenceFd = -1;
@ -845,15 +873,17 @@ HwcComposer2D::Prepare(buffer_handle_t dispHandle, int fence)
if (mPrepared) {
LOGE("Multiple hwc prepare calls!");
}
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
mPrepared = true;
}
bool
HwcComposer2D::Commit()
HwcComposer2D::Commit(nsScreenGonk* aScreen)
{
hwc_display_contents_1_t *displays[HWC_NUM_DISPLAY_TYPES] = { nullptr };
displays[HWC_DISPLAY_PRIMARY] = mList;
uint32_t displaytype = aScreen->GetDisplayType();
displays[displaytype] = mList;
for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) {
mList->hwLayers[j].acquireFenceFd = -1;
@ -910,15 +940,17 @@ HwcComposer2D::Reset()
}
#else
bool
HwcComposer2D::TryHwComposition()
HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
{
return !mHwc->set(mHwc, mDpy, mSur, mList);
return !mHwc->set(mHwc, aScreen->GetDpy(), aScreen->GetSur(), mList);
}
bool
HwcComposer2D::Render()
HwcComposer2D::Render(nsIWidget* aWidget)
{
return GetGonkDisplay()->SwapBuffers(mDpy, mSur);
nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
return GetGonkDisplay()->SwapBuffers(screen->GetDpy(), screen->GetSur());
}
void
@ -930,12 +962,15 @@ HwcComposer2D::Reset()
bool
HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
nsIWidget* aWidget,
bool aGeometryChanged)
{
if (!mHwc) {
return false;
}
nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen();
if (mList) {
setHwcGeometry(aGeometryChanged);
mList->numHwLayers = 0;
@ -950,6 +985,7 @@ HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
// reallocated. We may want to avoid this if possible
mVisibleRegions.clear();
mScreenRect = screen->GetNaturalBounds();
MOZ_ASSERT(mHwcLayerMap.IsEmpty());
if (!PrepareLayerList(aRoot,
mScreenRect,
@ -963,7 +999,7 @@ HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
// Send data to LayerScope for debugging
SendtoLayerScope();
if (!TryHwComposition()) {
if (!TryHwComposition(screen)) {
LOGD("Full HWC Composition failed. Fallback to GPU Composition or partial OVERLAY Composition");
LayerScope::CleanLayer();
return false;

View File

@ -31,6 +31,8 @@
#include <utils/Timers.h>
#endif
class nsScreenGonk;
namespace mozilla {
namespace gl {
@ -83,9 +85,10 @@ public:
// Returns FALSE if the container cannot be fully rendered
// by this composer so nothing was rendered at all
virtual bool TryRenderWithHwc(layers::Layer* aRoot,
nsIWidget* aWidget,
bool aGeometryChanged) override;
virtual bool Render() override;
virtual bool Render(nsIWidget* aWidget) override;
virtual bool HasHwc() override { return mHwc; }
@ -94,18 +97,15 @@ public:
bool RegisterHwcEventCallback();
void Vsync(int aDisplay, int64_t aTimestamp);
void Invalidate();
void Hotplug(int aDisplay, int aConnected);
#endif
void SetCompositorParent(layers::CompositorParent* aCompositorParent);
// Set EGL info of primary display. Used for BLIT Composition.
// XXX Add multiple displays compostion support.
void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface, gl::GLContext* aGLContext);
private:
void Reset();
void Prepare(buffer_handle_t dispHandle, int fence);
bool Commit();
bool TryHwComposition();
void Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen);
bool Commit(nsScreenGonk* aScreen);
bool TryHwComposition(nsScreenGonk* aScreen);
bool ReallocLayerList();
bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
const gfx::Matrix& aParentTransform);
@ -115,9 +115,6 @@ private:
HwcDevice* mHwc;
HwcList* mList;
hwc_display_t mDpy; // Store for BLIT Composition and GonkDisplayICS
hwc_surface_t mSur; // Store for BLIT Composition and GonkDisplayICS
gl::GLContext* mGLContext; // Store for BLIT Composition
nsIntRect mScreenRect;
int mMaxLayerCount;
bool mColorFill;

View File

@ -17,8 +17,14 @@
#define GONKDISPLAY_H
#include <system/window.h>
#include <utils/StrongPointer.h>
#include "mozilla/Types.h"
namespace android {
class DisplaySurface;
class IGraphicBufferProducer;
}
namespace mozilla {
typedef void * EGLDisplay;
@ -26,7 +32,28 @@ typedef void * EGLSurface;
class MOZ_EXPORT GonkDisplay {
public:
virtual ANativeWindow* GetNativeWindow() = 0;
/**
* This enum is for types of display. DISPLAY_PRIMARY refers to the default
* built-in display, DISPLAY_EXTERNAL refers to displays connected with
* HDMI, and DISPLAY_VIRTUAL are displays which makes composited output
* available within the system. Currently, displays of external are detected
* via the hotplug detection in HWC, and displays of virtual are connected
* via Wifi Display.
*/
enum DisplayType {
DISPLAY_PRIMARY,
DISPLAY_EXTERNAL,
DISPLAY_VIRTUAL,
NUM_DISPLAY_TYPES
};
struct NativeData {
android::sp<ANativeWindow> mNativeWindow;
#if ANDROID_VERSION >= 17
android::sp<android::DisplaySurface> mDisplaySurface;
#endif
float mXdpi;
};
virtual void SetEnabled(bool enabled) = 0;
@ -36,8 +63,6 @@ public:
virtual void* GetHWCDevice() = 0;
virtual void* GetDispSurface() = 0;
/**
* Only GonkDisplayICS uses arguments.
*/
@ -49,18 +74,9 @@ public:
virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur) = 0;
/**
* Set FramebufferSurface ReleaseFence's file descriptor.
* ReleaseFence will be signaled after the HWC has finished reading
* from a buffer.
*/
virtual void SetDispReleaseFd(int fd) = 0;
/**
* Get FramebufferSurface AcquireFence's file descriptor
* AcquireFence will be signaled when a buffer's content is available.
*/
virtual int GetPrevDispAcquireFd() = 0;
virtual NativeData GetNativeData(
GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer = nullptr) = 0;
float xdpi;
int32_t surfaceformat;

View File

@ -23,6 +23,7 @@
#include <cutils/log.h>
#include <fcntl.h>
#include "mozilla/Assertions.h"
#include "mozilla/FileUtils.h"
#include "mozilla/FileUtils.h"
@ -139,13 +140,6 @@ GonkDisplayICS::~GonkDisplayICS()
hwc_close(mHwc);
}
ANativeWindow*
GonkDisplayICS::GetNativeWindow()
{
StopBootAnimation();
return static_cast<ANativeWindow *>(mFBSurface.get());
}
void
GonkDisplayICS::SetEnabled(bool enabled)
{
@ -207,7 +201,6 @@ GonkDisplayICS::QueueBuffer(ANativeWindowBuffer *buf)
void
GonkDisplayICS::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
{
eglSwapBuffers(dpy, sur);
}
void
@ -215,6 +208,20 @@ GonkDisplayICS::SetDispReleaseFd(int fd)
{
}
GonkDisplay::NativeData
GonkDisplayICS::GetNativeData(GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer)
{
MOZ_ASSERT(aDisplayType == DISPLAY_PRIMARY, "ICS gonk supports primary display only.");
NativeData data;
StopBootAnimation();
data.mNativeWindow = static_cast<ANativeWindow *>(mFBSurface.get());
data.mXdpi = xdpi;
return data;
}
__attribute__ ((visibility ("default")))
GonkDisplay*
GetGonkDisplay()

View File

@ -23,6 +23,10 @@
#include "hardware/hwcomposer.h"
#include "utils/RefBase.h"
namespace android {
class IGraphicBufferProducer;
}
namespace mozilla {
class MOZ_EXPORT GonkDisplayICS : public GonkDisplay {
@ -30,19 +34,12 @@ public:
GonkDisplayICS();
~GonkDisplayICS();
virtual ANativeWindow* GetNativeWindow();
virtual void SetEnabled(bool enabled);
virtual void OnEnabled(OnEnabledCallbackType callback);
virtual void* GetHWCDevice();
virtual void* GetDispSurface()
{
return nullptr;
}
virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur);
virtual ANativeWindowBuffer* DequeueBuffer();
@ -58,6 +55,10 @@ public:
return -1;
}
virtual NativeData GetNativeData(
GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer = nullptr);
private:
hw_module_t const* mModule;
hwc_composer_device_t* mHwc;

View File

@ -26,11 +26,14 @@
#include <hardware/power.h>
#include <suspend/autosuspend.h>
#include "BootAnimation.h"
#include "FramebufferSurface.h"
#if ANDROID_VERSION == 17
#include "GraphicBufferAlloc.h"
#endif
#include "BootAnimation.h"
#include "mozilla/Assertions.h"
#define DEFAULT_XDPI 75.0
using namespace android;
@ -108,7 +111,7 @@ GonkDisplayJB::GonkDisplayJB()
mAlloc = new GraphicBufferAlloc();
CreateSurface(mSTClient, mDispSurface);
CreateSurface(mSTClient, mDispSurface, mWidth, mHeight);
mList = (hwc_display_contents_1_t *)calloc(1, sizeof(*mList) + (sizeof(hwc_layer_1_t)*2));
@ -118,18 +121,10 @@ GonkDisplayJB::GonkDisplayJB()
mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_BUFFER_COUNT, 2);
mSTClient->perform(mSTClient.get(), NATIVE_WINDOW_SET_USAGE, usage);
} else if (mHwc) {
#if ANDROID_VERSION >= 21
if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
mHwc->setPowerMode(mHwc, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL);
} else {
mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0);
}
#else
mHwc->blank(mHwc, HWC_DISPLAY_PRIMARY, 0);
#endif
PowerOnDisplay(HWC_DISPLAY_PRIMARY);
// For devices w/ hwc v1.0 or no hwc, this buffer can not be created,
// only create this buffer for devices w/ hwc version > 1.0.
CreateSurface(mBootAnimSTClient, mBootAnimDispSurface);
CreateSurface(mBootAnimSTClient, mBootAnimDispSurface, mWidth, mHeight);
}
ALOGI("Starting bootanimation with (%d) format framebuffer", surfaceformat);
@ -147,7 +142,8 @@ GonkDisplayJB::~GonkDisplayJB()
void
GonkDisplayJB::CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
android::sp<android::DisplaySurface>& aDisplaySurface)
android::sp<android::DisplaySurface>& aDisplaySurface,
uint32_t aWidth, uint32_t aHeight)
{
#if ANDROID_VERSION >= 21
sp<IGraphicBufferProducer> producer;
@ -163,7 +159,7 @@ GonkDisplayJB::CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
sp<BufferQueue> consumer = new BufferQueue(true, mAlloc);
#endif
aDisplaySurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, consumer);
aDisplaySurface = new FramebufferSurface(0, aWidth, aHeight, surfaceformat, consumer);
#if ANDROID_VERSION == 17
aNativeWindow = new SurfaceTextureClient(
@ -173,14 +169,6 @@ GonkDisplayJB::CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
#endif
}
ANativeWindow*
GonkDisplayJB::GetNativeWindow()
{
StopBootAnim();
return mSTClient.get();
}
void
GonkDisplayJB::SetEnabled(bool enabled)
{
@ -234,12 +222,6 @@ GonkDisplayJB::GetHWCDevice()
return mHwc;
}
void*
GonkDisplayJB::GetDispSurface()
{
return mDispSurface.get();
}
bool
GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
{
@ -363,18 +345,6 @@ GonkDisplayJB::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
eglSwapBuffers(dpy, sur);
}
void
GonkDisplayJB::SetDispReleaseFd(int fd)
{
mDispSurface->setReleaseFenceFd(fd);
}
int
GonkDisplayJB::GetPrevDispAcquireFd()
{
return mDispSurface->GetPrevDispAcquireFd();
}
void
GonkDisplayJB::StopBootAnim()
{
@ -385,6 +355,57 @@ GonkDisplayJB::StopBootAnim()
}
}
void
GonkDisplayJB::PowerOnDisplay(int aDpy)
{
MOZ_ASSERT(mHwc);;
#if ANDROID_VERSION >= 21
if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
mHwc->setPowerMode(mHwc, aDpy, HWC_POWER_MODE_NORMAL);
} else {
mHwc->blank(mHwc, aDpy, 0);
}
#else
mHwc->blank(mHwc, aDpy, 0);
#endif
}
GonkDisplay::NativeData
GonkDisplayJB::GetNativeData(GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer)
{
NativeData data;
if (aDisplayType == DISPLAY_PRIMARY) {
StopBootAnim();
data.mNativeWindow = mSTClient;
data.mDisplaySurface = mDispSurface;
data.mXdpi = xdpi;
} else if (aDisplayType == DISPLAY_EXTERNAL) {
int32_t values[3];
const uint32_t attrs[] = {
HWC_DISPLAY_WIDTH,
HWC_DISPLAY_HEIGHT,
HWC_DISPLAY_DPI_X,
HWC_DISPLAY_NO_ATTRIBUTE
};
mHwc->getDisplayAttributes(mHwc, aDisplayType, 0, attrs, values);
int width = values[0];
int height = values[1];
// FIXME!! values[2] returns 0 for external display, which doesn't
// sound right, Bug 1169176 is the follow-up bug for this issue.
data.mXdpi = values[2] ? values[2] / 1000.f : DEFAULT_XDPI;
PowerOnDisplay(HWC_DISPLAY_EXTERNAL);
CreateSurface(data.mNativeWindow, data.mDisplaySurface, width, height);
} else if (aDisplayType == DISPLAY_VIRTUAL) {
// TODO: Bug 1161874 (the support of WifiDisplay) should fill up the
// implementation of virtual display.
MOZ_CRASH("Display type of virtual is not supported yet.");
}
return data;
}
__attribute__ ((visibility ("default")))
GonkDisplay*
GetGonkDisplay()

View File

@ -30,16 +30,12 @@ public:
GonkDisplayJB();
~GonkDisplayJB();
virtual ANativeWindow* GetNativeWindow();
virtual void SetEnabled(bool enabled);
virtual void OnEnabled(OnEnabledCallbackType callback);
virtual void* GetHWCDevice();
virtual void* GetDispSurface();
virtual bool SwapBuffers(EGLDisplay dpy, EGLSurface sur);
virtual ANativeWindowBuffer* DequeueBuffer();
@ -48,16 +44,18 @@ public:
virtual void UpdateDispSurface(EGLDisplay dpy, EGLSurface sur);
virtual void SetDispReleaseFd(int fd);
virtual int GetPrevDispAcquireFd();
bool Post(buffer_handle_t buf, int fence);
virtual NativeData GetNativeData(
GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer = nullptr);
private:
void StopBootAnim();
void CreateSurface(android::sp<ANativeWindow>& aNativeWindow,
android::sp<android::DisplaySurface>& aDisplaySurface);
android::sp<android::DisplaySurface>& aDisplaySurface,
uint32_t aWidth, uint32_t aHeight);
void PowerOnDisplay(int aDpy);
hw_module_t const* mModule;
hw_module_t const* mFBModule;

View File

@ -19,7 +19,6 @@
#include "mozilla/TouchEvents.h"
#include "mozilla/Hal.h"
#include "libdisplay/GonkDisplay.h"
#include "libdisplay/DisplaySurface.h"
#include "nsScreenManagerGonk.h"
#include "nsThreadUtils.h"
#include "HwcComposer2D.h"
@ -32,7 +31,11 @@
#include "nsAppShell.h"
#include "nsTArray.h"
#include "pixelflinger/format.h"
#include "cutils/properties.h"
#include "nsIDisplayInfo.h"
#if ANDROID_VERSION >= 17
#include "libdisplay/DisplaySurface.h"
#endif
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsScreenGonk" , ## args)
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "nsScreenGonk", ## args)
@ -103,16 +106,25 @@ SurfaceFormatToColorDepth(int32_t aSurfaceFormat)
// nsScreenGonk.cpp
nsScreenGonk::nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow)
nsScreenGonk::nsScreenGonk(uint32_t aId,
GonkDisplay::DisplayType aDisplayType,
const GonkDisplay::NativeData& aNativeData)
: mId(aId)
, mNativeWindow(aNativeWindow)
, mNativeWindow(aNativeData.mNativeWindow)
, mDpi(aNativeData.mXdpi)
, mScreenRotation(nsIScreen::ROTATION_0_DEG)
, mPhysicalScreenRotation(nsIScreen::ROTATION_0_DEG)
#if ANDROID_VERSION >= 17
, mDisplaySurface(aNativeData.mDisplaySurface)
#endif
, mDisplayType(aDisplayType)
, mDpy(EGL_NO_DISPLAY)
, mSur(EGL_NO_SURFACE)
, mGLContext(nullptr)
{
int surfaceFormat;
if (mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &mVirtualBounds.width) ||
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &mVirtualBounds.height) ||
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &surfaceFormat)) {
mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_FORMAT, &mSurfaceFormat)) {
NS_RUNTIMEABORT("Failed to get native window size, aborting...");
}
@ -124,8 +136,7 @@ nsScreenGonk::nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow)
mPhysicalScreenRotation = atoi(propValue) / 90;
}
mDpi = GetGonkDisplay()->xdpi;
mColorDepth = SurfaceFormatToColorDepth(surfaceFormat);
mColorDepth = SurfaceFormatToColorDepth(mSurfaceFormat);
}
nsScreenGonk::~nsScreenGonk()
@ -135,7 +146,7 @@ nsScreenGonk::~nsScreenGonk()
bool
nsScreenGonk::IsPrimaryScreen()
{
return nsScreenManagerGonk::PRIMARY_SCREEN_ID == mId;
return mDisplayType == GonkDisplay::DISPLAY_PRIMARY;
}
NS_IMETHODIMP
@ -206,6 +217,12 @@ nsScreenGonk::GetDpi()
return mDpi;
}
int32_t
nsScreenGonk::GetSurfaceFormat()
{
return mSurfaceFormat;
}
ANativeWindow*
nsScreenGonk::GetNativeWindow()
{
@ -238,8 +255,8 @@ nsScreenGonk::SetRotation(uint32_t aRotation)
for (unsigned int i = 0; i < mTopWindows.Length(); i++) {
mTopWindows[i]->Resize(mVirtualBounds.width,
mVirtualBounds.height,
true);
mVirtualBounds.height,
true);
}
return NS_OK;
@ -314,6 +331,50 @@ nsScreenGonk::BringToTop(nsWindow* aWindow)
mTopWindows.InsertElementAt(0, aWindow);
}
#if ANDROID_VERSION >= 17
android::DisplaySurface*
nsScreenGonk::GetDisplaySurface()
{
return mDisplaySurface.get();
}
int
nsScreenGonk::GetPrevDispAcquireFd()
{
if (!mDisplaySurface.get()) {
return -1;
}
return mDisplaySurface->GetPrevDispAcquireFd();
}
#endif
GonkDisplay::DisplayType
nsScreenGonk::GetDisplayType()
{
return mDisplayType;
}
void
nsScreenGonk::SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
gl::GLContext* aGLContext)
{
mDpy = aDisplay;
mSur = aSurface;
mGLContext = aGLContext;
}
hwc_display_t
nsScreenGonk::GetDpy()
{
return mDpy;
}
hwc_surface_t
nsScreenGonk::GetSur()
{
return mSur;
}
NS_IMPL_ISUPPORTS(nsScreenManagerGonk, nsIScreenManager)
nsScreenManagerGonk::nsScreenManagerGonk()
@ -357,7 +418,7 @@ nsScreenManagerGonk::Initialize()
mScreenOffEvent = new ScreenOnOffEvent(false);
GetGonkDisplay()->OnEnabled(displayEnabledCallback);
AddScreen(PRIMARY_SCREEN_TYPE);
AddScreen(GonkDisplay::DISPLAY_PRIMARY);
nsAppShell::NotifyScreenInitialized();
mInitialized = true;
@ -458,7 +519,7 @@ nsScreenManagerGonk::VsyncControl(bool aEnabled)
}
uint32_t
nsScreenManagerGonk::GetIdFromType(uint32_t aDisplayType)
nsScreenManagerGonk::GetIdFromType(GonkDisplay::DisplayType aDisplayType)
{
// This is the only place where we make the assumption that
// display type is equivalent to screen id.
@ -467,28 +528,122 @@ nsScreenManagerGonk::GetIdFromType(uint32_t aDisplayType)
return aDisplayType;
}
void
nsScreenManagerGonk::AddScreen(uint32_t aDisplayType)
bool
nsScreenManagerGonk::IsScreenConnected(uint32_t aId)
{
// We currently only support adding primary screen.
MOZ_ASSERT(PRIMARY_SCREEN_TYPE == aDisplayType);
for (size_t i = 0; i < mScreens.Length(); ++i) {
if (mScreens[i]->GetId() == aId) {
return true;
}
}
uint32_t id = GetIdFromType(aDisplayType);
ANativeWindow* win = GetGonkDisplay()->GetNativeWindow();
nsScreenGonk* screen = new nsScreenGonk(id, win);
mScreens.AppendElement(screen);
return false;
}
namespace {
// A concrete class as a subject for 'display-changed' observer event.
class DisplayInfo : public nsIDisplayInfo {
public:
NS_DECL_ISUPPORTS
DisplayInfo(uint32_t aId, bool aConnected)
: mId(aId)
, mConnected(aConnected)
{
}
NS_IMETHODIMP GetId(int32_t *aId)
{
*aId = mId;
return NS_OK;
}
NS_IMETHODIMP GetConnected(bool *aConnected)
{
*aConnected = mConnected;
return NS_OK;
}
private:
virtual ~DisplayInfo() {}
uint32_t mId;
bool mConnected;
};
NS_IMPL_ISUPPORTS(DisplayInfo, nsIDisplayInfo, nsISupports)
class NotifyTask : public nsRunnable {
public:
NotifyTask(uint32_t aId, bool aConnected)
: mDisplayInfo(new DisplayInfo(aId, aConnected))
{
}
NS_IMETHOD Run()
{
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os) {
os->NotifyObservers(mDisplayInfo, "display-changed", nullptr);
}
return NS_OK;
}
private:
nsRefPtr<DisplayInfo> mDisplayInfo;
};
void
nsScreenManagerGonk::RemoveScreen(uint32_t aDisplayType)
NotifyDisplayChange(uint32_t aId, bool aConnected)
{
NS_DispatchToMainThread(new NotifyTask(aId, aConnected));
}
} // end of unnamed namespace.
nsresult
nsScreenManagerGonk::AddScreen(GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(aDisplayType < GonkDisplay::DisplayType::NUM_DISPLAY_TYPES,
NS_ERROR_FAILURE);
uint32_t id = GetIdFromType(aDisplayType);
NS_ENSURE_TRUE(!IsScreenConnected(id), NS_ERROR_FAILURE);
GonkDisplay::NativeData nativeData =
GetGonkDisplay()->GetNativeData(aDisplayType, aProducer);
nsScreenGonk* screen = new nsScreenGonk(id, aDisplayType, nativeData);
mScreens.AppendElement(screen);
NotifyDisplayChange(id, true);
return NS_OK;
}
nsresult
nsScreenManagerGonk::RemoveScreen(GonkDisplay::DisplayType aDisplayType)
{
MOZ_ASSERT(NS_IsMainThread());
NS_ENSURE_TRUE(aDisplayType < GonkDisplay::DisplayType::NUM_DISPLAY_TYPES,
NS_ERROR_FAILURE);
uint32_t screenId = GetIdFromType(aDisplayType);
NS_ENSURE_TRUE(IsScreenConnected(screenId), NS_ERROR_FAILURE);
for (size_t i = 0; i < mScreens.Length(); i++) {
if (mScreens[i]->GetId() == screenId) {
mScreens.RemoveElementAt(i);
break;
}
}
NotifyDisplayChange(screenId, false);
return NS_OK;
}

View File

@ -18,20 +18,37 @@
#define nsScreenManagerGonk_h___
#include "mozilla/Hal.h"
#include "nsCOMPtr.h"
#include "cutils/properties.h"
#include "hardware/hwcomposer.h"
#include "libdisplay/GonkDisplay.h"
#include "nsBaseScreen.h"
#include "nsCOMPtr.h"
#include "nsIScreenManager.h"
class nsRunnable;
class nsWindow;
namespace android {
class DisplaySurface;
class IGraphicBufferProducer;
};
namespace mozilla {
namespace gl {
class GLContext;
}
}
class nsScreenGonk : public nsBaseScreen
{
typedef mozilla::hal::ScreenConfiguration ScreenConfiguration;
typedef mozilla::GonkDisplay GonkDisplay;
public:
nsScreenGonk(uint32_t aId, ANativeWindow* aNativeWindow);
nsScreenGonk(uint32_t aId,
GonkDisplay::DisplayType aDisplayType,
const GonkDisplay::NativeData& aNativeData);
~nsScreenGonk();
@ -46,12 +63,19 @@ public:
uint32_t GetId();
nsIntRect GetRect();
float GetDpi();
int32_t GetSurfaceFormat();
ANativeWindow* GetNativeWindow();
nsIntRect GetNaturalBounds();
uint32_t EffectiveScreenRotation();
ScreenConfiguration GetConfiguration();
bool IsPrimaryScreen();
#if ANDROID_VERSION >= 17
android::DisplaySurface* GetDisplaySurface();
int GetPrevDispAcquireFd();
#endif
GonkDisplay::DisplayType GetDisplayType();
void RegisterWindow(nsWindow* aWindow);
void UnregisterWindow(nsWindow* aWindow);
void BringToTop(nsWindow* aWindow);
@ -61,28 +85,36 @@ public:
return mTopWindows;
}
// Set EGL info of primary display. Used for BLIT Composition.
void SetEGLInfo(hwc_display_t aDisplay, hwc_surface_t aSurface,
mozilla::gl::GLContext* aGLContext);
hwc_display_t GetDpy();
hwc_surface_t GetSur();
protected:
uint32_t mId;
int32_t mColorDepth;
android::sp<ANativeWindow> mNativeWindow;
float mDpi;
int32_t mSurfaceFormat;
nsIntRect mNaturalBounds; // Screen bounds w/o rotation taken into account.
nsIntRect mVirtualBounds; // Screen bounds w/ rotation taken into account.
uint32_t mScreenRotation;
uint32_t mPhysicalScreenRotation;
nsTArray<nsWindow*> mTopWindows;
#if ANDROID_VERSION >= 17
android::sp<android::DisplaySurface> mDisplaySurface;
#endif
GonkDisplay::DisplayType mDisplayType;
hwc_display_t mDpy; // Store for BLIT Composition and GonkDisplayICS
hwc_surface_t mSur; // Store for BLIT Composition and GonkDisplayICS
mozilla::gl::GLContext* mGLContext; // Store for BLIT Composition
};
class nsScreenManagerGonk final : public nsIScreenManager
{
public:
enum {
// TODO: Bug 1138287 will define more screen/display types.
PRIMARY_SCREEN_TYPE = 0,
// TODO: Maintain a mapping from type to id dynamically.
PRIMARY_SCREEN_ID = 0,
};
typedef mozilla::GonkDisplay GonkDisplay;
public:
nsScreenManagerGonk();
@ -96,13 +128,16 @@ public:
void Initialize();
void DisplayEnabled(bool aEnabled);
void AddScreen(uint32_t aDisplayType);
void RemoveScreen(uint32_t aDisplayType);
nsresult AddScreen(GonkDisplay::DisplayType aDisplayType,
android::IGraphicBufferProducer* aProducer = nullptr);
nsresult RemoveScreen(GonkDisplay::DisplayType aDisplayType);
protected:
~nsScreenManagerGonk();
void VsyncControl(bool aEnabled);
uint32_t GetIdFromType(uint32_t aDisplayType);
uint32_t GetIdFromType(GonkDisplay::DisplayType aDisplayType);
bool IsScreenConnected(uint32_t aId);
bool mInitialized;
nsTArray<nsRefPtr<nsScreenGonk>> mScreens;

View File

@ -18,7 +18,6 @@
#include <fcntl.h>
#include "android/log.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
@ -45,8 +44,6 @@
#include "mozilla/layers/APZCTreeManager.h"
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layers/CompositorParent.h"
#include "mozilla/layers/InputAPZContext.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/TouchEvents.h"
#include "HwcComposer2D.h"
@ -549,11 +546,9 @@ nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
case NS_NATIVE_OPENGL_CONTEXT:
// Called after primary display's GLContextEGL creation.
GLContext* context = reinterpret_cast<GLContext*>(aVal);
HwcComposer2D* hwc = HwcComposer2D::GetInstance();
hwc->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(),
GLContextEGL::Cast(context)->GetEGLSurface(),
context);
mScreen->SetEGLInfo(GLContextEGL::Cast(context)->GetEGLDisplay(),
GLContextEGL::Cast(context)->GetEGLSurface(),
context);
return;
}
}
@ -810,6 +805,12 @@ nsWindow::GetNaturalBounds()
return mScreen->GetNaturalBounds();
}
nsScreenGonk*
nsWindow::GetScreen()
{
return mScreen;
}
bool
nsWindow::NeedsPaint()
{
@ -822,7 +823,7 @@ nsWindow::NeedsPaint()
Composer2D*
nsWindow::GetComposer2D()
{
if (!mScreen->IsPrimaryScreen()) {
if (mScreen->GetDisplayType() == GonkDisplay::DISPLAY_VIRTUAL) {
return nullptr;
}

View File

@ -123,6 +123,8 @@ public:
void ConfigureAPZControllerThread() override;
nsScreenGonk* GetScreen();
protected:
nsWindow* mParent;
bool mVisible;

View File

@ -66,6 +66,7 @@ XPIDL_SOURCES += [
'nsIClipboardHelper.idl',
'nsIClipboardOwner.idl',
'nsIColorPicker.idl',
'nsIDisplayInfo.idl',
'nsIDragService.idl',
'nsIDragSession.idl',
'nsIFilePicker.idl',

14
widget/nsIDisplayInfo.idl Normal file
View File

@ -0,0 +1,14 @@
/* -*- Mode: IDL; 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/. */
#include "nsISupports.idl"
[scriptable, uuid(615bc23d-6346-4b15-9c10-add002f140b6)]
interface nsIDisplayInfo : nsISupports
{
readonly attribute long id;
readonly attribute boolean connected;
};