HWComposer now has its own concept of display IDs
HWComposer can now create IDs representing a display it can deal with. IDs MAIN and HDMI are reserved. SurfaceFlinger associate HWComposer IDs with a DisplayDevice and uses that when it talks to HWComposer. A DisplayDevice doesn't have to have a HWComposer ID, in that case it just can't use h/w composer composition. Change-Id: Iec3d7ac92e0c22bf975052ae2847402f58bade71
This commit is contained in:
parent
7c9e82633c
commit
e60b0687c8
|
@ -68,12 +68,12 @@ void checkGLErrors()
|
||||||
|
|
||||||
DisplayDevice::DisplayDevice(
|
DisplayDevice::DisplayDevice(
|
||||||
const sp<SurfaceFlinger>& flinger,
|
const sp<SurfaceFlinger>& flinger,
|
||||||
int display,
|
int32_t display, int32_t hwcDisplayId,
|
||||||
const sp<ANativeWindow>& nativeWindow,
|
const sp<ANativeWindow>& nativeWindow,
|
||||||
const sp<FramebufferSurface>& framebufferSurface,
|
const sp<FramebufferSurface>& framebufferSurface,
|
||||||
EGLConfig config)
|
EGLConfig config)
|
||||||
: mFlinger(flinger),
|
: mFlinger(flinger),
|
||||||
mId(display),
|
mId(display), mHwcDisplayId(hwcDisplayId),
|
||||||
mNativeWindow(nativeWindow),
|
mNativeWindow(nativeWindow),
|
||||||
mFramebufferSurface(framebufferSurface),
|
mFramebufferSurface(framebufferSurface),
|
||||||
mDisplay(EGL_NO_DISPLAY),
|
mDisplay(EGL_NO_DISPLAY),
|
||||||
|
|
|
@ -62,7 +62,7 @@ public:
|
||||||
|
|
||||||
DisplayDevice(
|
DisplayDevice(
|
||||||
const sp<SurfaceFlinger>& flinger,
|
const sp<SurfaceFlinger>& flinger,
|
||||||
int dpy,
|
int32_t dpy, int32_t hwcDisplayId,
|
||||||
const sp<ANativeWindow>& nativeWindow,
|
const sp<ANativeWindow>& nativeWindow,
|
||||||
const sp<FramebufferSurface>& framebufferSurface,
|
const sp<FramebufferSurface>& framebufferSurface,
|
||||||
EGLConfig config);
|
EGLConfig config);
|
||||||
|
@ -96,6 +96,7 @@ public:
|
||||||
const Transform& getTransform() const { return mGlobalTransform; }
|
const Transform& getTransform() const { return mGlobalTransform; }
|
||||||
uint32_t getLayerStack() const { return mLayerStack; }
|
uint32_t getLayerStack() const { return mLayerStack; }
|
||||||
int32_t getDisplayId() const { return mId; }
|
int32_t getDisplayId() const { return mId; }
|
||||||
|
int32_t getHwcDisplayId() const { return mHwcDisplayId; }
|
||||||
|
|
||||||
status_t compositionComplete() const;
|
status_t compositionComplete() const;
|
||||||
|
|
||||||
|
@ -132,6 +133,7 @@ private:
|
||||||
*/
|
*/
|
||||||
sp<SurfaceFlinger> mFlinger;
|
sp<SurfaceFlinger> mFlinger;
|
||||||
int32_t mId;
|
int32_t mId;
|
||||||
|
int32_t mHwcDisplayId;
|
||||||
|
|
||||||
// ANativeWindow this display is rendering into
|
// ANativeWindow this display is rendering into
|
||||||
sp<ANativeWindow> mNativeWindow;
|
sp<ANativeWindow> mNativeWindow;
|
||||||
|
|
|
@ -194,13 +194,13 @@ HWComposer::HWComposer(
|
||||||
framebuffer_device_t const* fbDev)
|
framebuffer_device_t const* fbDev)
|
||||||
: mFlinger(flinger),
|
: mFlinger(flinger),
|
||||||
mModule(0), mHwc(0), mNumDisplays(1), mCapacity(0),
|
mModule(0), mHwc(0), mNumDisplays(1), mCapacity(0),
|
||||||
mNumOVLayers(0), mNumFBLayers(0),
|
|
||||||
mCBContext(new cb_context),
|
mCBContext(new cb_context),
|
||||||
mEventHandler(handler), mRefreshPeriod(0),
|
mEventHandler(handler),
|
||||||
mVSyncCount(0), mDebugForceFakeVSync(false)
|
mVSyncCount(0), mDebugForceFakeVSync(false)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < MAX_DISPLAYS; i++)
|
for (size_t i =0 ; i<MAX_DISPLAYS ; i++) {
|
||||||
mLists[i] = NULL;
|
mLists[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
char value[PROPERTY_VALUE_MAX];
|
char value[PROPERTY_VALUE_MAX];
|
||||||
property_get("debug.sf.no_hw_vsync", value, "0");
|
property_get("debug.sf.no_hw_vsync", value, "0");
|
||||||
|
@ -232,6 +232,10 @@ HWComposer::HWComposer(
|
||||||
mHwc->registerProcs(mHwc, &mCBContext->procs);
|
mHwc->registerProcs(mHwc, &mCBContext->procs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// these IDs are always reserved
|
||||||
|
mTokens.markBit(HWC_DISPLAY_PRIMARY);
|
||||||
|
mTokens.markBit(HWC_DISPLAY_EXTERNAL);
|
||||||
|
|
||||||
// always turn vsync off when we start
|
// always turn vsync off when we start
|
||||||
needVSyncThread = false;
|
needVSyncThread = false;
|
||||||
if (hwcHasVsyncEvent(mHwc)) {
|
if (hwcHasVsyncEvent(mHwc)) {
|
||||||
|
@ -239,7 +243,7 @@ HWComposer::HWComposer(
|
||||||
|
|
||||||
int period;
|
int period;
|
||||||
if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) {
|
if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) {
|
||||||
mRefreshPeriod = nsecs_t(period);
|
mDisplayData[0].refresh = nsecs_t(period);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
needVSyncThread = true;
|
needVSyncThread = true;
|
||||||
|
@ -255,17 +259,17 @@ HWComposer::HWComposer(
|
||||||
|
|
||||||
|
|
||||||
if (fbDev) {
|
if (fbDev) {
|
||||||
if (mRefreshPeriod == 0) {
|
if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
|
||||||
mRefreshPeriod = nsecs_t(1e9 / fbDev->fps);
|
mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / fbDev->fps);
|
||||||
ALOGW("getting VSYNC period from fb HAL: %lld", mRefreshPeriod);
|
ALOGW("getting VSYNC period from fb HAL: %lld", mDisplayData[0].refresh);
|
||||||
}
|
}
|
||||||
mDpiX = fbDev->xdpi;
|
mDisplayData[HWC_DISPLAY_PRIMARY].xdpi = fbDev->xdpi;
|
||||||
mDpiY = fbDev->ydpi;
|
mDisplayData[HWC_DISPLAY_PRIMARY].ydpi = fbDev->ydpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mRefreshPeriod == 0) {
|
if (mDisplayData[HWC_DISPLAY_PRIMARY].refresh == 0) {
|
||||||
mRefreshPeriod = nsecs_t(1e9 / 60.0);
|
mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(1e9 / 60.0);
|
||||||
ALOGW("getting VSYNC period thin air: %lld", mRefreshPeriod);
|
ALOGW("getting VSYNC period thin air: %lld", mDisplayData[0].refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needVSyncThread) {
|
if (needVSyncThread) {
|
||||||
|
@ -276,8 +280,9 @@ HWComposer::HWComposer(
|
||||||
|
|
||||||
HWComposer::~HWComposer() {
|
HWComposer::~HWComposer() {
|
||||||
hwcEventControl(mHwc, 0, EVENT_VSYNC, 0);
|
hwcEventControl(mHwc, 0, EVENT_VSYNC, 0);
|
||||||
for (size_t i = 0; i < MAX_DISPLAYS; i++)
|
for (size_t i = 0; i < MAX_DISPLAYS; i++) {
|
||||||
free(mLists[i]);
|
free(mLists[i]);
|
||||||
|
}
|
||||||
if (mVSyncThread != NULL) {
|
if (mVSyncThread != NULL) {
|
||||||
mVSyncThread->requestExitAndWait();
|
mVSyncThread->requestExitAndWait();
|
||||||
}
|
}
|
||||||
|
@ -315,8 +320,32 @@ void HWComposer::vsync(int dpy, int64_t timestamp) {
|
||||||
mLastHwVSync = timestamp;
|
mLastHwVSync = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t HWComposer::allocateDisplayId() {
|
||||||
|
if (mTokens.isFull()) {
|
||||||
|
return NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: for now we don't support h/w composition wifi displays
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int32_t id = mTokens.firstUnmarkedBit();
|
||||||
|
mTokens.markBit(id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t HWComposer::freeDisplayId(int32_t id) {
|
||||||
|
if (id < MAX_DISPLAYS) {
|
||||||
|
return BAD_VALUE;
|
||||||
|
}
|
||||||
|
if (!mTokens.hasBit(id)) {
|
||||||
|
return BAD_INDEX;
|
||||||
|
}
|
||||||
|
mTokens.clearBit(id);
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
nsecs_t HWComposer::getRefreshPeriod() const {
|
nsecs_t HWComposer::getRefreshPeriod() const {
|
||||||
return mRefreshPeriod;
|
return mDisplayData[0].refresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsecs_t HWComposer::getRefreshTimestamp() const {
|
nsecs_t HWComposer::getRefreshTimestamp() const {
|
||||||
|
@ -325,15 +354,15 @@ nsecs_t HWComposer::getRefreshTimestamp() const {
|
||||||
// the refresh period and whatever closest timestamp we have.
|
// the refresh period and whatever closest timestamp we have.
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
nsecs_t now = systemTime(CLOCK_MONOTONIC);
|
nsecs_t now = systemTime(CLOCK_MONOTONIC);
|
||||||
return now - ((now - mLastHwVSync) % mRefreshPeriod);
|
return now - ((now - mLastHwVSync) % mDisplayData[0].refresh);
|
||||||
}
|
}
|
||||||
|
|
||||||
float HWComposer::getDpiX() const {
|
float HWComposer::getDpiX() const {
|
||||||
return mDpiX;
|
return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
float HWComposer::getDpiY() const {
|
float HWComposer::getDpiY() const {
|
||||||
return mDpiY;
|
return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HWComposer::eventControl(int event, int enabled) {
|
void HWComposer::eventControl(int event, int enabled) {
|
||||||
|
@ -354,10 +383,11 @@ void HWComposer::eventControl(int event, int enabled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
||||||
// FIXME: handle multiple displays
|
if (!mTokens.hasBit(id)) {
|
||||||
if (uint32_t(id) >= MAX_DISPLAYS)
|
|
||||||
return BAD_INDEX;
|
return BAD_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: handle multiple displays
|
||||||
if (mHwc) {
|
if (mHwc) {
|
||||||
// TODO: must handle multiple displays here
|
// TODO: must handle multiple displays here
|
||||||
// mLists[0] is NULL only when this is called from the constructor
|
// mLists[0] is NULL only when this is called from the constructor
|
||||||
|
@ -376,9 +406,10 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t HWComposer::prepare() const {
|
status_t HWComposer::prepare() {
|
||||||
int err = hwcPrepare(mHwc, mNumDisplays,
|
int err = hwcPrepare(mHwc, mNumDisplays,
|
||||||
const_cast<hwc_display_contents_1_t**>(mLists));
|
const_cast<hwc_display_contents_1_t**>(mLists));
|
||||||
|
|
||||||
if (err == NO_ERROR) {
|
if (err == NO_ERROR) {
|
||||||
|
|
||||||
// here we're just making sure that "skip" layers are set
|
// here we're just making sure that "skip" layers are set
|
||||||
|
@ -388,65 +419,58 @@ status_t HWComposer::prepare() const {
|
||||||
// think is almost possible.
|
// think is almost possible.
|
||||||
|
|
||||||
// TODO: must handle multiple displays here
|
// TODO: must handle multiple displays here
|
||||||
|
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
||||||
size_t numOVLayers = 0;
|
size_t count = getNumLayers(0);
|
||||||
size_t numFBLayers = 0;
|
struct hwc_display_contents_1* disp = mLists[0];
|
||||||
size_t count = getNumLayers(0);
|
mDisplayData[0].hasFbComp = false;
|
||||||
|
mDisplayData[0].hasOvComp = false;
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
int compositionType;
|
hwc_layer_1_t* l = &disp->hwLayers[i];
|
||||||
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
|
||||||
hwc_layer_1_t* l = &mLists[0]->hwLayers[i];
|
|
||||||
if (l->flags & HWC_SKIP_LAYER) {
|
if (l->flags & HWC_SKIP_LAYER) {
|
||||||
l->compositionType = HWC_FRAMEBUFFER;
|
l->compositionType = HWC_FRAMEBUFFER;
|
||||||
}
|
}
|
||||||
compositionType = l->compositionType;
|
if (l->compositionType == HWC_FRAMEBUFFER)
|
||||||
} else {
|
mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
|
||||||
// mList really has hwc_layer_list_t memory layout
|
if (l->compositionType == HWC_OVERLAY)
|
||||||
hwc_layer_list_t* list0 = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
|
mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
|
||||||
hwc_layer_t* l = &list0->hwLayers[i];
|
|
||||||
if (l->flags & HWC_SKIP_LAYER) {
|
|
||||||
l->compositionType = HWC_FRAMEBUFFER;
|
|
||||||
}
|
|
||||||
compositionType = l->compositionType;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
switch (compositionType) {
|
size_t count = getNumLayers(0);
|
||||||
case HWC_OVERLAY:
|
hwc_layer_list_t* disp = reinterpret_cast<hwc_layer_list_t*>(mLists[0]);
|
||||||
numOVLayers++;
|
mDisplayData[0].hasFbComp = false;
|
||||||
break;
|
mDisplayData[0].hasOvComp = false;
|
||||||
case HWC_FRAMEBUFFER:
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
numFBLayers++;
|
hwc_layer_t* l = &disp->hwLayers[i];
|
||||||
break;
|
if (l->flags & HWC_SKIP_LAYER) {
|
||||||
|
l->compositionType = HWC_FRAMEBUFFER;
|
||||||
|
}
|
||||||
|
if (l->compositionType == HWC_FRAMEBUFFER)
|
||||||
|
mDisplayData[HWC_DISPLAY_PRIMARY].hasFbComp = true;
|
||||||
|
if (l->compositionType == HWC_OVERLAY)
|
||||||
|
mDisplayData[HWC_DISPLAY_PRIMARY].hasOvComp = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mNumOVLayers = numOVLayers;
|
|
||||||
mNumFBLayers = numFBLayers;
|
|
||||||
}
|
}
|
||||||
return (status_t)err;
|
return (status_t)err;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t HWComposer::getLayerCount(int32_t id, int type) const {
|
bool HWComposer::hasHwcComposition(int32_t id) const {
|
||||||
// FIXME: handle multiple displays
|
if (!mTokens.hasBit(id))
|
||||||
if (uint32_t(id) >= MAX_DISPLAYS) {
|
return false;
|
||||||
// FIXME: in practice this is only use to know
|
return mDisplayData[id].hasOvComp;
|
||||||
// if we have at least one layer of type.
|
|
||||||
return (type == HWC_FRAMEBUFFER) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case HWC_OVERLAY:
|
|
||||||
return mNumOVLayers;
|
|
||||||
case HWC_FRAMEBUFFER:
|
|
||||||
return mNumFBLayers;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t HWComposer::commit(void* fbDisplay, void* fbSurface) const {
|
bool HWComposer::hasGlesComposition(int32_t id) const {
|
||||||
|
if (!mTokens.hasBit(id))
|
||||||
|
return false;
|
||||||
|
return mDisplayData[id].hasFbComp;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t HWComposer::commit() const {
|
||||||
int err = NO_ERROR;
|
int err = NO_ERROR;
|
||||||
if (mHwc) {
|
if (mHwc) {
|
||||||
|
void* fbDisplay = eglGetCurrentDisplay();
|
||||||
|
void* fbSurface = eglGetCurrentSurface(EGL_DRAW);
|
||||||
err = hwcSet(mHwc, fbDisplay, fbSurface, mNumDisplays,
|
err = hwcSet(mHwc, fbDisplay, fbSurface, mNumDisplays,
|
||||||
const_cast<hwc_display_contents_1_t**>(mLists));
|
const_cast<hwc_display_contents_1_t**>(mLists));
|
||||||
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
||||||
|
@ -661,10 +685,10 @@ public:
|
||||||
* returns an iterator initialized at a given index in the layer list
|
* returns an iterator initialized at a given index in the layer list
|
||||||
*/
|
*/
|
||||||
HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
|
HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
|
||||||
// FIXME: handle multiple displays
|
if (!mTokens.hasBit(id))
|
||||||
if (uint32_t(id) >= MAX_DISPLAYS)
|
|
||||||
return LayerListIterator();
|
return LayerListIterator();
|
||||||
|
|
||||||
|
// FIXME: handle multiple displays
|
||||||
if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
|
if (!mHwc || index > hwcNumHwLayers(mHwc, mLists[0]))
|
||||||
return LayerListIterator();
|
return LayerListIterator();
|
||||||
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
if (hwcHasVersion(mHwc, HWC_DEVICE_API_VERSION_1_0)) {
|
||||||
|
@ -741,7 +765,7 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
|
||||||
HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
|
HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
|
||||||
: mHwc(hwc), mEnabled(false),
|
: mHwc(hwc), mEnabled(false),
|
||||||
mNextFakeVSync(0),
|
mNextFakeVSync(0),
|
||||||
mRefreshPeriod(hwc.mRefreshPeriod)
|
mRefreshPeriod(hwc.getRefreshPeriod())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <utils/Thread.h>
|
#include <utils/Thread.h>
|
||||||
#include <utils/Timers.h>
|
#include <utils/Timers.h>
|
||||||
#include <utils/Vector.h>
|
#include <utils/Vector.h>
|
||||||
|
#include <utils/BitSet.h>
|
||||||
|
|
||||||
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
|
extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
|
||||||
const struct timespec *request,
|
const struct timespec *request,
|
||||||
|
@ -70,14 +71,26 @@ public:
|
||||||
|
|
||||||
status_t initCheck() const;
|
status_t initCheck() const;
|
||||||
|
|
||||||
|
// returns a display ID starting at MAX_DISPLAYS, this ID
|
||||||
|
// is to be used with createWorkList (and all other
|
||||||
|
// methods requiring an ID below).
|
||||||
|
// IDs below MAX_DISPLAY are pre-defined and therefore are always valid.
|
||||||
|
// returns a negative error code if an ID cannot be allocated
|
||||||
|
int32_t allocateDisplayId();
|
||||||
|
|
||||||
|
// recycles the given ID and frees the associated worklist.
|
||||||
|
// IDs below MAX_DISPLAYS are not recycled
|
||||||
|
status_t freeDisplayId(int32_t id);
|
||||||
|
|
||||||
|
|
||||||
// Asks the HAL what it can do
|
// Asks the HAL what it can do
|
||||||
status_t prepare() const;
|
status_t prepare();
|
||||||
|
|
||||||
// disable hwc until next createWorkList
|
// disable hwc until next createWorkList
|
||||||
status_t disable();
|
status_t disable();
|
||||||
|
|
||||||
// commits the list
|
// commits the list
|
||||||
status_t commit(void* fbDisplay, void* fbSurface) const;
|
status_t commit() const;
|
||||||
|
|
||||||
// release hardware resources and blank screen
|
// release hardware resources and blank screen
|
||||||
status_t release() const;
|
status_t release() const;
|
||||||
|
@ -88,9 +101,11 @@ public:
|
||||||
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
|
// create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
|
||||||
status_t createWorkList(int32_t id, size_t numLayers);
|
status_t createWorkList(int32_t id, size_t numLayers);
|
||||||
|
|
||||||
// get number of layers of the given type as updated in prepare().
|
// does this display have layers handled by HWC
|
||||||
// type is HWC_OVERLAY or HWC_FRAMEBUFFER
|
bool hasHwcComposition(int32_t id) const;
|
||||||
size_t getLayerCount(int32_t id, int type) const;
|
|
||||||
|
// does this display have layers handled by GLES
|
||||||
|
bool hasGlesComposition(int32_t id) const;
|
||||||
|
|
||||||
// needed forward declarations
|
// needed forward declarations
|
||||||
class LayerListIterator;
|
class LayerListIterator;
|
||||||
|
@ -237,26 +252,32 @@ private:
|
||||||
inline void vsync(int dpy, int64_t timestamp);
|
inline void vsync(int dpy, int64_t timestamp);
|
||||||
|
|
||||||
|
|
||||||
|
struct DisplayData {
|
||||||
|
DisplayData() : xdpi(0), ydpi(0), refresh(0),
|
||||||
|
hasFbComp(false), hasOvComp(false) { }
|
||||||
|
float xdpi;
|
||||||
|
float ydpi;
|
||||||
|
nsecs_t refresh;
|
||||||
|
bool hasFbComp;
|
||||||
|
bool hasOvComp;
|
||||||
|
};
|
||||||
|
|
||||||
sp<SurfaceFlinger> mFlinger;
|
sp<SurfaceFlinger> mFlinger;
|
||||||
hw_module_t const* mModule;
|
hw_module_t const* mModule;
|
||||||
struct hwc_composer_device_1* mHwc;
|
struct hwc_composer_device_1* mHwc;
|
||||||
// invariant: mLists[0] != NULL iff mHwc != NULL
|
// invariant: mLists[0] != NULL iff mHwc != NULL
|
||||||
// TODO: decide whether mLists[i>0] should be non-NULL when display i is
|
// mLists[i>0] can be NULL. that display is to be ignored
|
||||||
// not attached/enabled.
|
|
||||||
struct hwc_display_contents_1* mLists[MAX_DISPLAYS];
|
struct hwc_display_contents_1* mLists[MAX_DISPLAYS];
|
||||||
|
DisplayData mDisplayData[MAX_DISPLAYS];
|
||||||
size_t mNumDisplays;
|
size_t mNumDisplays;
|
||||||
|
|
||||||
size_t mCapacity;
|
size_t mCapacity;
|
||||||
mutable size_t mNumOVLayers;
|
|
||||||
mutable size_t mNumFBLayers;
|
|
||||||
cb_context* mCBContext;
|
cb_context* mCBContext;
|
||||||
EventHandler& mEventHandler;
|
EventHandler& mEventHandler;
|
||||||
nsecs_t mRefreshPeriod;
|
|
||||||
float mDpiX;
|
|
||||||
float mDpiY;
|
|
||||||
size_t mVSyncCount;
|
size_t mVSyncCount;
|
||||||
sp<VSyncThread> mVSyncThread;
|
sp<VSyncThread> mVSyncThread;
|
||||||
bool mDebugForceFakeVSync;
|
bool mDebugForceFakeVSync;
|
||||||
|
BitSet32 mTokens;
|
||||||
|
|
||||||
// protected by mLock
|
// protected by mLock
|
||||||
mutable Mutex mLock;
|
mutable Mutex mLock;
|
||||||
|
|
|
@ -409,7 +409,8 @@ status_t SurfaceFlinger::readyToRun()
|
||||||
mCurrentState.displays.add(mDefaultDisplays[i], DisplayDeviceState(i));
|
mCurrentState.displays.add(mDefaultDisplays[i], DisplayDeviceState(i));
|
||||||
}
|
}
|
||||||
sp<DisplayDevice> hw = new DisplayDevice(this,
|
sp<DisplayDevice> hw = new DisplayDevice(this,
|
||||||
DisplayDevice::DISPLAY_ID_MAIN, anw, fbs, mEGLConfig);
|
DisplayDevice::DISPLAY_ID_MAIN, HWC_DISPLAY_PRIMARY,
|
||||||
|
anw, fbs, mEGLConfig);
|
||||||
mDisplays.add(hw->getDisplayId(), hw);
|
mDisplays.add(hw->getDisplayId(), hw);
|
||||||
|
|
||||||
// initialize OpenGL ES
|
// initialize OpenGL ES
|
||||||
|
@ -779,29 +780,30 @@ void SurfaceFlinger::setUpHWComposer() {
|
||||||
mHwWorkListDirty = false;
|
mHwWorkListDirty = false;
|
||||||
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
||||||
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
||||||
const Vector< sp<LayerBase> >& currentLayers(
|
const int32_t id = hw->getHwcDisplayId();
|
||||||
|
if (id >= 0) {
|
||||||
|
const Vector< sp<LayerBase> >& currentLayers(
|
||||||
hw->getVisibleLayersSortedByZ());
|
hw->getVisibleLayersSortedByZ());
|
||||||
const size_t count = currentLayers.size();
|
const size_t count = currentLayers.size();
|
||||||
|
if (hwc.createWorkList(id, count) >= 0) {
|
||||||
|
HWComposer::LayerListIterator cur = hwc.begin(id);
|
||||||
|
const HWComposer::LayerListIterator end = hwc.end(id);
|
||||||
|
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
|
||||||
|
const sp<LayerBase>& layer(currentLayers[i]);
|
||||||
|
|
||||||
const int32_t id = hw->getDisplayId();
|
if (CC_UNLIKELY(workListsDirty)) {
|
||||||
if (hwc.createWorkList(id, count) >= 0) {
|
layer->setGeometry(hw, *cur);
|
||||||
HWComposer::LayerListIterator cur = hwc.begin(id);
|
if (mDebugDisableHWC || mDebugRegion) {
|
||||||
const HWComposer::LayerListIterator end = hwc.end(id);
|
cur->setSkip(true);
|
||||||
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
|
}
|
||||||
const sp<LayerBase>& layer(currentLayers[i]);
|
|
||||||
|
|
||||||
if (CC_UNLIKELY(workListsDirty)) {
|
|
||||||
layer->setGeometry(hw, *cur);
|
|
||||||
if (mDebugDisableHWC || mDebugRegion) {
|
|
||||||
cur->setSkip(true);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* update the per-frame h/w composer data for each layer
|
* update the per-frame h/w composer data for each layer
|
||||||
* and build the transparent region of the FB
|
* and build the transparent region of the FB
|
||||||
*/
|
*/
|
||||||
layer->setPerFrameData(hw, *cur);
|
layer->setPerFrameData(hw, *cur);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,21 +843,20 @@ void SurfaceFlinger::postFramebuffer()
|
||||||
|
|
||||||
HWComposer& hwc(getHwComposer());
|
HWComposer& hwc(getHwComposer());
|
||||||
if (hwc.initCheck() == NO_ERROR) {
|
if (hwc.initCheck() == NO_ERROR) {
|
||||||
// FIXME: eventually commit() won't take arguments
|
|
||||||
// FIXME: EGL spec says:
|
// FIXME: EGL spec says:
|
||||||
// "surface must be bound to the calling thread's current context,
|
// "surface must be bound to the calling thread's current context,
|
||||||
// for the current rendering API."
|
// for the current rendering API."
|
||||||
DisplayDevice::makeCurrent(
|
DisplayDevice::makeCurrent(
|
||||||
getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext);
|
getDisplayDevice(DisplayDevice::DISPLAY_ID_MAIN), mEGLContext);
|
||||||
hwc.commit(mEGLDisplay, getDefaultDisplayDevice()->getEGLSurface());
|
hwc.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
|
||||||
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
sp<const DisplayDevice> hw(mDisplays[dpy]);
|
||||||
const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
|
const Vector< sp<LayerBase> >& currentLayers(hw->getVisibleLayersSortedByZ());
|
||||||
const size_t count = currentLayers.size();
|
const size_t count = currentLayers.size();
|
||||||
if (hwc.initCheck() == NO_ERROR) {
|
int32_t id = hw->getHwcDisplayId();
|
||||||
int32_t id = hw->getDisplayId();
|
if (id >=0 && hwc.initCheck() == NO_ERROR) {
|
||||||
HWComposer::LayerListIterator cur = hwc.begin(id);
|
HWComposer::LayerListIterator cur = hwc.begin(id);
|
||||||
const HWComposer::LayerListIterator end = hwc.end(id);
|
const HWComposer::LayerListIterator end = hwc.end(id);
|
||||||
for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
|
for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
|
||||||
|
@ -951,12 +952,15 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||||
if (state.surface->asBinder() != draw[i].surface->asBinder()) {
|
if (state.surface->asBinder() != draw[i].surface->asBinder()) {
|
||||||
// changing the surface is like destroying and
|
// changing the surface is like destroying and
|
||||||
// recreating the DisplayDevice
|
// recreating the DisplayDevice
|
||||||
|
const int32_t hwcDisplayId =
|
||||||
|
(uint32_t(state.id) < DisplayDevice::DISPLAY_ID_COUNT) ?
|
||||||
|
state.id : getHwComposer().allocateDisplayId();
|
||||||
|
|
||||||
sp<SurfaceTextureClient> stc(
|
sp<SurfaceTextureClient> stc(
|
||||||
new SurfaceTextureClient(state.surface));
|
new SurfaceTextureClient(state.surface));
|
||||||
|
|
||||||
sp<DisplayDevice> disp = new DisplayDevice(this,
|
sp<DisplayDevice> disp = new DisplayDevice(this,
|
||||||
state.id, stc, 0, mEGLConfig);
|
state.id, hwcDisplayId, stc, 0, mEGLConfig);
|
||||||
|
|
||||||
disp->setLayerStack(state.layerStack);
|
disp->setLayerStack(state.layerStack);
|
||||||
disp->setOrientation(state.orientation);
|
disp->setOrientation(state.orientation);
|
||||||
|
@ -982,10 +986,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
|
||||||
for (size_t i=0 ; i<cc ; i++) {
|
for (size_t i=0 ; i<cc ; i++) {
|
||||||
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
|
if (draw.indexOfKey(curr.keyAt(i)) < 0) {
|
||||||
const DisplayDeviceState& state(curr[i]);
|
const DisplayDeviceState& state(curr[i]);
|
||||||
|
const int32_t hwcDisplayId =
|
||||||
|
(uint32_t(state.id) < DisplayDevice::DISPLAY_ID_COUNT) ?
|
||||||
|
state.id : getHwComposer().allocateDisplayId();
|
||||||
|
|
||||||
sp<SurfaceTextureClient> stc(
|
sp<SurfaceTextureClient> stc(
|
||||||
new SurfaceTextureClient(state.surface));
|
new SurfaceTextureClient(state.surface));
|
||||||
sp<DisplayDevice> disp = new DisplayDevice(this, state.id,
|
sp<DisplayDevice> disp = new DisplayDevice(this,
|
||||||
stc, 0, mEGLConfig);
|
state.id, hwcDisplayId, stc, 0, mEGLConfig);
|
||||||
mDisplays.add(state.id, disp);
|
mDisplays.add(state.id, disp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1251,12 +1259,13 @@ void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
|
||||||
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
|
void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
|
||||||
{
|
{
|
||||||
HWComposer& hwc(getHwComposer());
|
HWComposer& hwc(getHwComposer());
|
||||||
int32_t id = hw->getDisplayId();
|
int32_t id = hw->getHwcDisplayId();
|
||||||
HWComposer::LayerListIterator cur = hwc.begin(id);
|
HWComposer::LayerListIterator cur = hwc.begin(id);
|
||||||
const HWComposer::LayerListIterator end = hwc.end(id);
|
const HWComposer::LayerListIterator end = hwc.end(id);
|
||||||
|
|
||||||
const size_t fbLayerCount = hwc.getLayerCount(id, HWC_FRAMEBUFFER);
|
const bool hasGlesComposition = hwc.hasGlesComposition(id);
|
||||||
if (cur==end || fbLayerCount) {
|
const bool hasHwcComposition = hwc.hasHwcComposition(id);
|
||||||
|
if (cur==end || hasGlesComposition) {
|
||||||
|
|
||||||
DisplayDevice::makeCurrent(hw, mEGLContext);
|
DisplayDevice::makeCurrent(hw, mEGLContext);
|
||||||
|
|
||||||
|
@ -1265,7 +1274,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
// Never touch the framebuffer if we don't have any framebuffer layers
|
// Never touch the framebuffer if we don't have any framebuffer layers
|
||||||
if (hwc.getLayerCount(id, HWC_OVERLAY)) {
|
if (hasHwcComposition) {
|
||||||
// when using overlays, we assume a fully transparent framebuffer
|
// when using overlays, we assume a fully transparent framebuffer
|
||||||
// NOTE: we could reduce how much we need to clear, for instance
|
// NOTE: we could reduce how much we need to clear, for instance
|
||||||
// remove where there are opaque FB layers. however, on some
|
// remove where there are opaque FB layers. however, on some
|
||||||
|
|
Loading…
Reference in New Issue