From 1bd20e0f9ecd27cc5ad2bdf08b01837ecc10c357 Mon Sep 17 00:00:00 2001 From: Jesse Hall Date: Wed, 29 Aug 2012 10:47:52 -0700 Subject: [PATCH] HWC 1.1: hook up hotplug event, use new display config queries Change-Id: I2fd359e5fc7e1948072c6bc6b6fe47ea5e8025c1 --- .../DisplayHardware/HWComposer.cpp | 116 ++++++++++++++++-- .../DisplayHardware/HWComposer.h | 10 +- 2 files changed, 110 insertions(+), 16 deletions(-) diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 75c228d30..283d149b0 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -132,23 +132,21 @@ HWComposer::HWComposer( 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 ; ixdpi; disp.ydpi = fbDev->ydpi; @@ -176,8 +176,11 @@ HWComposer::HWComposer( } 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 @@ void HWComposer::hook_invalidate(const struct hwc_procs* procs) { 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( const_cast(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( + const_cast(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 7b92d2e22..8852ab6f8 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -53,7 +53,7 @@ class HWComposer 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 @@ private: 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),