HWC 1.1: hook up hotplug event, use new display config queries
Change-Id: I2fd359e5fc7e1948072c6bc6b6fe47ea5e8025c1
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 75c228d..283d149 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -132,23 +132,21 @@
mCBContext->hwc = this;
mCBContext->procs.invalidate = &hook_invalidate;
mCBContext->procs.vsync = &hook_vsync;
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+ mCBContext->procs.hotplug = &hook_hotplug;
+ else
+ mCBContext->procs.hotplug = NULL;
memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
mHwc->registerProcs(mHwc, &mCBContext->procs);
}
// always turn vsync off when we start
needVSyncThread = false;
- mHwc->eventControl(mHwc, 0, HWC_EVENT_VSYNC, 0);
-
- int period;
- if (mHwc->query(mHwc, HWC_VSYNC_PERIOD, &period) == NO_ERROR) {
- mDisplayData[HWC_DISPLAY_PRIMARY].refresh = nsecs_t(period);
- }
+ mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
// these IDs are always reserved
for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
mAllocatedDisplayIDs.markBit(i);
- // TODO: we query xdpi / ydpi / refresh
}
// the number of displays we actually have depends on the
@@ -166,7 +164,9 @@
}
if (fbDev) {
- // if we're here it means we are on version 1.0
+ ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
+ "should only have fbdev if no hwc or hwc is 1.0");
+
DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
disp.xdpi = fbDev->xdpi;
disp.ydpi = fbDev->ydpi;
@@ -176,8 +176,11 @@
}
if (disp.refresh == 0) {
disp.refresh = nsecs_t(1e9 / 60.0);
- ALOGW("getting VSYNC period thin air: %lld", mDisplayData[HWC_DISPLAY_PRIMARY].refresh);
+ ALOGW("getting VSYNC period from thin air: %lld",
+ mDisplayData[HWC_DISPLAY_PRIMARY].refresh);
}
+ } else if (mHwc) {
+ queryDisplayProperties(HWC_DISPLAY_PRIMARY);
}
if (needVSyncThread) {
@@ -207,24 +210,111 @@
ctx->hwc->invalidate();
}
-void HWComposer::hook_vsync(const struct hwc_procs* procs, int dpy,
+void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
int64_t timestamp) {
cb_context* ctx = reinterpret_cast<cb_context*>(
const_cast<hwc_procs_t*>(procs));
- ctx->hwc->vsync(dpy, timestamp);
+ ctx->hwc->vsync(disp, timestamp);
+}
+
+void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
+ int connected) {
+ cb_context* ctx = reinterpret_cast<cb_context*>(
+ const_cast<hwc_procs_t*>(procs));
+ ctx->hwc->hotplug(disp, connected);
}
void HWComposer::invalidate() {
mFlinger->repaintEverything();
}
-void HWComposer::vsync(int dpy, int64_t timestamp) {
+void HWComposer::vsync(int disp, int64_t timestamp) {
ATRACE_INT("VSYNC", ++mVSyncCount&1);
- mEventHandler.onVSyncReceived(dpy, timestamp);
+ mEventHandler.onVSyncReceived(disp, timestamp);
Mutex::Autolock _l(mLock);
mLastHwVSync = timestamp;
}
+void HWComposer::hotplug(int disp, int connected) {
+ if (disp == HWC_DISPLAY_PRIMARY || disp >= HWC_NUM_DISPLAY_TYPES) {
+ ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
+ disp, connected);
+ return;
+ }
+
+ if (connected)
+ queryDisplayProperties(disp);
+
+ // TODO: tell someone else about this
+}
+
+static const uint32_t DISPLAY_ATTRIBUTES[] = {
+ HWC_DISPLAY_VSYNC_PERIOD,
+ HWC_DISPLAY_RESOLUTION_X,
+ HWC_DISPLAY_RESOLUTION_Y,
+ HWC_DISPLAY_DPI_X,
+ HWC_DISPLAY_DPI_Y,
+ HWC_DISPLAY_NO_ATTRIBUTE,
+};
+#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
+
+// http://developer.android.com/reference/android/util/DisplayMetrics.html
+#define ANDROID_DENSITY_TV 213
+#define ANDROID_DENSITY_XHIGH 320
+
+void HWComposer::queryDisplayProperties(int disp) {
+ ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+
+ int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
+ memset(values, 0, sizeof(values));
+
+ uint32_t config;
+ size_t numConfigs = 1;
+ status_t err = mHwc->getDisplayConfigs(mHwc, disp, &config, &numConfigs);
+ if (err == NO_ERROR) {
+ mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES,
+ values);
+ }
+
+ int32_t w = 0, h = 0;
+ for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+ switch (DISPLAY_ATTRIBUTES[i]) {
+ case HWC_DISPLAY_VSYNC_PERIOD:
+ mDisplayData[disp].refresh = nsecs_t(values[i]);
+ break;
+ case HWC_DISPLAY_RESOLUTION_X:
+ // TODO: we'll probably want to remember this eventually
+ w = values[i];
+ break;
+ case HWC_DISPLAY_RESOLUTION_Y:
+ // TODO: we'll probably want to remember this eventually
+ h = values[i];
+ break;
+ case HWC_DISPLAY_DPI_X:
+ mDisplayData[disp].xdpi = values[i] / 1000.0f;
+ break;
+ case HWC_DISPLAY_DPI_Y:
+ mDisplayData[disp].ydpi = values[i] / 1000.0f;
+ break;
+ default:
+ ALOG_ASSERT(false, "unknown display attribute %#x",
+ DISPLAY_ATTRIBUTES[i]);
+ break;
+ }
+ }
+
+ if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) {
+ // is there anything smarter we can do?
+ if (h >= 1080) {
+ mDisplayData[disp].xdpi = ANDROID_DENSITY_XHIGH;
+ mDisplayData[disp].ydpi = ANDROID_DENSITY_XHIGH;
+ } else {
+ mDisplayData[disp].xdpi = ANDROID_DENSITY_TV;
+ mDisplayData[disp].ydpi = ANDROID_DENSITY_TV;
+ }
+ }
+}
+
int32_t HWComposer::allocateDisplayId() {
if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
return NO_MEMORY;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 7b92d2e..8852ab6 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -53,7 +53,7 @@
public:
class EventHandler {
friend class HWComposer;
- virtual void onVSyncReceived(int dpy, nsecs_t timestamp) = 0;
+ virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0;
protected:
virtual ~EventHandler() {}
};
@@ -242,12 +242,16 @@
struct cb_context;
static void hook_invalidate(const struct hwc_procs* procs);
- static void hook_vsync(const struct hwc_procs* procs, int dpy,
+ static void hook_vsync(const struct hwc_procs* procs, int disp,
int64_t timestamp);
+ static void hook_hotplug(const struct hwc_procs* procs, int disp,
+ int connected);
inline void invalidate();
- inline void vsync(int dpy, int64_t timestamp);
+ inline void vsync(int disp, int64_t timestamp);
+ inline void hotplug(int disp, int connected);
+ void queryDisplayProperties(int disp);
struct DisplayData {
DisplayData() : xdpi(0), ydpi(0), refresh(0),