diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index f85f6043e..5fba3f66b 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -33,21 +33,12 @@ #include #include "DisplayHardware/FramebufferSurface.h" +#include "DisplayHardware/HWComposer.h" // ---------------------------------------------------------------------------- namespace android { // ---------------------------------------------------------------------------- -sp FramebufferSurface::create() { - sp result = new FramebufferSurface(); - if (result->fbDev == NULL) { - result = NULL; - } - return result; -} - -// ---------------------------------------------------------------------------- - class GraphicBufferAlloc : public BnGraphicBufferAlloc { public: GraphicBufferAlloc() { }; @@ -66,36 +57,21 @@ public: * */ -FramebufferSurface::FramebufferSurface(): +FramebufferSurface::FramebufferSurface(HWComposer& hwc) : ConsumerBase(new BufferQueue(true, new GraphicBufferAlloc())), - fbDev(0), mCurrentBufferSlot(-1), - mCurrentBuffer(0) + mCurrentBuffer(0), + mHwc(hwc) { - hw_module_t const* module; - - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { - int stride; - int err; - int i; - err = framebuffer_open(module, &fbDev); - ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err)); - - // bail out if we can't initialize the modules - if (!fbDev) - return; - - mName = "FramebufferSurface"; - mBufferQueue->setConsumerName(mName); - mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | - GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); - mBufferQueue->setDefaultBufferFormat(fbDev->format); - mBufferQueue->setDefaultBufferSize(fbDev->width, fbDev->height); - mBufferQueue->setSynchronousMode(true); - mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS); - } else { - ALOGE("Couldn't get gralloc module"); - } + mName = "FramebufferSurface"; + mBufferQueue->setConsumerName(mName); + mBufferQueue->setConsumerUsageBits(GRALLOC_USAGE_HW_FB | + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER); + mBufferQueue->setDefaultBufferFormat(mHwc.getFormat(HWC_DISPLAY_PRIMARY)); + mBufferQueue->setDefaultBufferSize(mHwc.getResolutionX(HWC_DISPLAY_PRIMARY), + mHwc.getResolutionY(HWC_DISPLAY_PRIMARY)); + mBufferQueue->setSynchronousMode(true); + mBufferQueue->setDefaultMaxBufferCount(NUM_FRAME_BUFFERS); } status_t FramebufferSurface::nextBuffer(sp* buffer) { @@ -145,12 +121,7 @@ status_t FramebufferSurface::nextBuffer(sp* buffer) { return NO_ERROR; } -FramebufferSurface::~FramebufferSurface() { - if (fbDev) { - framebuffer_close(fbDev); - } -} - +// Overrides ConsumerBase::onFrameAvailable(), does not call base class impl. void FramebufferSurface::onFrameAvailable() { // XXX: The following code is here temporarily as part of the transition // away from the framebuffer HAL. @@ -161,7 +132,7 @@ void FramebufferSurface::onFrameAvailable() { strerror(-err), err); return; } - err = fbDev->post(fbDev, buf->handle); + err = mHwc.fbPost(buf->handle); if (err != NO_ERROR) { ALOGE("error posting framebuffer: %d", err); } @@ -181,19 +152,11 @@ status_t FramebufferSurface::setUpdateRectangle(const Rect& r) status_t FramebufferSurface::compositionComplete() { - if (fbDev->compositionComplete) { - return fbDev->compositionComplete(fbDev); - } - return INVALID_OPERATION; + return mHwc.fbCompositionComplete(); } void FramebufferSurface::dump(String8& result) { - if (fbDev->common.version >= 1 && fbDev->dump) { - const size_t SIZE = 4096; - char buffer[SIZE]; - fbDev->dump(fbDev, buffer, SIZE); - result.append(buffer); - } + mHwc.fbDump(result); ConsumerBase::dump(result); } diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h index bfa500bea..fd7c5203d 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h @@ -30,13 +30,13 @@ namespace android { class Rect; class String8; +class HWComposer; // --------------------------------------------------------------------------- class FramebufferSurface : public ConsumerBase { public: - - static sp create(); + FramebufferSurface(HWComposer& hwc); bool isUpdateOnDemand() const { return false; } status_t setUpdateRectangle(const Rect& updateRect); @@ -49,22 +49,12 @@ public: // BufferQueue. The new buffer is returned in the 'buffer' argument. status_t nextBuffer(sp* buffer); - // FIXME: currently there are information we can only get from the - // FB HAL, and FB HAL can only be instantiated once on some devices. - // Eventually this functionality will have to move in HWC or somewhere else. - const framebuffer_device_t* getFbHal() const { - return fbDev; - } - private: - FramebufferSurface(); - virtual ~FramebufferSurface(); // this class cannot be overloaded + virtual ~FramebufferSurface() { }; // this class cannot be overloaded virtual void onFrameAvailable(); virtual void freeBufferLocked(int slotIndex); - framebuffer_device_t* fbDev; - // mCurrentBufferIndex is the slot index of the current buffer or // INVALID_BUFFER_SLOT to indicate that either there is no current buffer // or the buffer is not associated with a slot. @@ -73,6 +63,9 @@ private: // mCurrentBuffer is the current buffer or NULL to indicate that there is // no current buffer. sp mCurrentBuffer; + + // Hardware composer, owned by SurfaceFlinger. + HWComposer& mHwc; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index dca27baa2..5c125c807 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -90,10 +90,9 @@ struct HWComposer::cb_context { HWComposer::HWComposer( const sp& flinger, - EventHandler& handler, - framebuffer_device_t const* fbDev) + EventHandler& handler) : mFlinger(flinger), - mModule(0), mHwc(0), mNumDisplays(1), + mFbDev(0), mHwc(0), mNumDisplays(1), mCBContext(new cb_context), mEventHandler(handler), mVSyncCount(0), mDebugForceFakeVSync(false) @@ -107,71 +106,62 @@ HWComposer::HWComposer( mDebugForceFakeVSync = atoi(value); bool needVSyncThread = true; - int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); - ALOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID); - if (err == 0) { - err = hwc_open_1(mModule, &mHwc); - ALOGE_IF(err, "%s device failed to initialize (%s)", - HWC_HARDWARE_COMPOSER, strerror(-err)); - if (err == 0) { - if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) || - hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION || - hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) { - ALOGE("%s device version %#x unsupported, will not be used", - HWC_HARDWARE_COMPOSER, mHwc->common.version); - hwc_close_1(mHwc); - mHwc = NULL; - } + + // Note: some devices may insist that the FB HAL be opened before HWC. + loadFbHalModule(); + loadHwcModule(); + + if (mHwc) { + ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER, + (hwcApiVersion(mHwc) >> 24) & 0xff, + (hwcApiVersion(mHwc) >> 16) & 0xff); + if (mHwc->registerProcs) { + 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); } - if (mHwc) { - ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER, - (hwcApiVersion(mHwc) >> 24) & 0xff, - (hwcApiVersion(mHwc) >> 16) & 0xff); - if (mHwc->registerProcs) { - 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); - } + // don't need a vsync thread if we have a hardware composer + needVSyncThread = false; + // always turn vsync off when we start + mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0); - // always turn vsync off when we start - needVSyncThread = false; - 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; + disp.xres = mFbDev->width; + disp.yres = mFbDev->height; + disp.format = mFbDev->format; + disp.xdpi = mFbDev->xdpi; + disp.ydpi = mFbDev->ydpi; if (disp.refresh == 0) { - disp.refresh = nsecs_t(1e9 / fbDev->fps); + disp.refresh = nsecs_t(1e9 / mFbDev->fps); ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh); } if (disp.refresh == 0) { @@ -197,9 +187,57 @@ HWComposer::~HWComposer() { if (mHwc) { hwc_close_1(mHwc); } + if (mFbDev) { + framebuffer_close(mFbDev); + } delete mCBContext; } +// Load and prepare the hardware composer module. Sets mHwc. +void HWComposer::loadHwcModule() +{ + hw_module_t const* module; + + if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) { + ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID); + return; + } + + int err = hwc_open_1(module, &mHwc); + if (err) { + ALOGE("%s device failed to initialize (%s)", + HWC_HARDWARE_COMPOSER, strerror(-err)); + return; + } + + if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) || + hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION || + hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) { + ALOGE("%s device version %#x unsupported, will not be used", + HWC_HARDWARE_COMPOSER, mHwc->common.version); + hwc_close_1(mHwc); + mHwc = NULL; + return; + } +} + +// Load and prepare the FB HAL, which uses the gralloc module. Sets mFbDev. +void HWComposer::loadFbHalModule() +{ + hw_module_t const* module; + + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) != 0) { + ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID); + return; + } + + int err = framebuffer_open(module, &mFbDev); + if (err) { + ALOGE("framebuffer_open failed (%s)", strerror(-err)); + return; + } +} + status_t HWComposer::initCheck() const { return mHwc ? NO_ERROR : NO_INIT; } @@ -265,6 +303,7 @@ static const uint32_t DISPLAY_ATTRIBUTES[] = { void HWComposer::queryDisplayProperties(int disp) { ALOG_ASSERT(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)); + // use zero as default value for unspecified attributes int32_t values[NUM_DISPLAY_ATTRIBUTES - 1]; memset(values, 0, sizeof(values)); @@ -283,12 +322,10 @@ void HWComposer::queryDisplayProperties(int disp) { 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]; + mDisplayData[disp].xres = values[i]; break; case HWC_DISPLAY_RESOLUTION_Y: - // TODO: we'll probably want to remember this eventually - h = values[i]; + mDisplayData[disp].yres = values[i]; break; case HWC_DISPLAY_DPI_X: mDisplayData[disp].xdpi = values[i] / 1000.0f; @@ -336,25 +373,37 @@ status_t HWComposer::freeDisplayId(int32_t id) { return NO_ERROR; } -nsecs_t HWComposer::getRefreshPeriod() const { - return mDisplayData[HWC_DISPLAY_PRIMARY].refresh; +nsecs_t HWComposer::getRefreshPeriod(int disp) const { + return mDisplayData[disp].refresh; } -nsecs_t HWComposer::getRefreshTimestamp() const { +nsecs_t HWComposer::getRefreshTimestamp(int disp) const { // this returns the last refresh timestamp. // if the last one is not available, we estimate it based on // the refresh period and whatever closest timestamp we have. Mutex::Autolock _l(mLock); nsecs_t now = systemTime(CLOCK_MONOTONIC); - return now - ((now - mLastHwVSync) % mDisplayData[HWC_DISPLAY_PRIMARY].refresh); + return now - ((now - mLastHwVSync) % mDisplayData[disp].refresh); } -float HWComposer::getDpiX() const { - return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi; +uint32_t HWComposer::getResolutionX(int disp) const { + return mDisplayData[disp].xres; } -float HWComposer::getDpiY() const { - return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi; +uint32_t HWComposer::getResolutionY(int disp) const { + return mDisplayData[disp].yres; +} + +uint32_t HWComposer::getFormat(int disp) const { + return mDisplayData[disp].format; +} + +float HWComposer::getDpiX(int disp) const { + return mDisplayData[disp].xdpi; +} + +float HWComposer::getDpiY(int disp) const { + return mDisplayData[disp].ydpi; } void HWComposer::eventControl(int event, int enabled) { @@ -493,6 +542,30 @@ size_t HWComposer::getNumLayers(int32_t id) const { mDisplayData[id].list->numHwLayers : 0; } +int HWComposer::fbPost(buffer_handle_t buffer) +{ + return mFbDev->post(mFbDev, buffer); +} + +int HWComposer::fbCompositionComplete() +{ + if (mFbDev->compositionComplete) { + return mFbDev->compositionComplete(mFbDev); + } else { + return INVALID_OPERATION; + } +} + +void HWComposer::fbDump(String8& result) { + if (mFbDev->common.version >= 1 && mFbDev->dump) { + const size_t SIZE = 4096; + char buffer[SIZE]; + mFbDev->dump(mFbDev, buffer, SIZE); + result.append(buffer); + } +} + + /* * Helper template to implement a concrete HWCLayer * This holds the pointer to the concrete hwc layer type @@ -680,7 +753,7 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, HWComposer::VSyncThread::VSyncThread(HWComposer& hwc) : mHwc(hwc), mEnabled(false), mNextFakeVSync(0), - mRefreshPeriod(hwc.getRefreshPeriod()) + mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY)) { } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index a49a023f8..4c520b1b4 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -64,8 +64,7 @@ public: HWComposer( const sp& flinger, - EventHandler& handler, - framebuffer_device_t const* fbDev); + EventHandler& handler); ~HWComposer(); @@ -107,6 +106,11 @@ public: // needed forward declarations class LayerListIterator; + // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface). + int fbPost(buffer_handle_t buffer); + int fbCompositionComplete(); + void fbDump(String8& result); + /* * Interface to hardware composer's layers functionality. * This abstracts the HAL interface to layers which can evolve in @@ -208,10 +212,15 @@ public: void eventControl(int event, int enabled); - nsecs_t getRefreshPeriod() const; - nsecs_t getRefreshTimestamp() const; - float getDpiX() const; - float getDpiY() const; + // Query display parameters. Pass in a display index (e.g. + // HWC_DISPLAY_PRIMARY). + nsecs_t getRefreshPeriod(int disp) const; + nsecs_t getRefreshTimestamp(int disp) const; + uint32_t getResolutionX(int disp) const; + uint32_t getResolutionY(int disp) const; + uint32_t getFormat(int disp) const; + float getDpiX(int disp) const; + float getDpiY(int disp) const; // this class is only used to fake the VSync event on systems that don't // have it. @@ -236,6 +245,8 @@ public: const Vector< sp >& visibleLayersSortedByZ) const; private: + void loadHwcModule(); + void loadFbHalModule(); LayerListIterator getLayerIterator(int32_t id, size_t index); size_t getNumLayers(int32_t id) const; @@ -261,6 +272,9 @@ private: ~DisplayData() { free(list); } + uint32_t xres; + uint32_t yres; + uint32_t format; // pixel format from FB hal, for pre-hwc-1.1 float xdpi; float ydpi; nsecs_t refresh; @@ -271,7 +285,7 @@ private: }; sp mFlinger; - hw_module_t const* mModule; + framebuffer_device_t* mFbDev; struct hwc_composer_device_1* mHwc; // invariant: mLists[0] != NULL iff mHwc != NULL // mLists[i>0] can be NULL. that display is to be ignored diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index e78059df3..75eff9f6d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -515,7 +515,7 @@ void Layer::onPostComposition() { const size_t offset = mFrameLatencyOffset; mFrameStats[offset].timestamp = mSurfaceTexture->getTimestamp(); mFrameStats[offset].set = systemTime(); - mFrameStats[offset].vsync = hwc.getRefreshTimestamp(); + mFrameStats[offset].vsync = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY); mFrameLatencyOffset = (mFrameLatencyOffset + 1) % 128; mFrameLatencyNeeded = false; } @@ -726,7 +726,8 @@ void Layer::dumpStats(String8& result, char* buffer, size_t SIZE) const { LayerBaseClient::dumpStats(result, buffer, SIZE); const size_t o = mFrameLatencyOffset; - const nsecs_t period = mFlinger->getHwComposer().getRefreshPeriod(); + const nsecs_t period = + mFlinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY); result.appendFormat("%lld\n", period); for (size_t i=0 ; i<128 ; i++) { const size_t index = (o+i) % 128; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index ef910d962..cb2c8c033 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -366,13 +366,18 @@ status_t SurfaceFlinger::readyToRun() ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); - // initialize EGL + // initialize EGL for the default display mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(mEGLDisplay, NULL, NULL); + // Initialize the H/W composer object. There may or may not be an + // actual hardware composer underneath. + mHwc = new HWComposer(this, + *static_cast(this)); + // Initialize the main display // create native window to main display - sp fbs = FramebufferSurface::create(); + sp fbs = new FramebufferSurface(*mHwc); if (fbs == NULL) { ALOGE("Display subsystem failed to initialize. check logs. exiting..."); exit(0); @@ -408,11 +413,6 @@ status_t SurfaceFlinger::readyToRun() mEventThread = new EventThread(this); mEventQueue.setEventThread(mEventThread); - // initialize the H/W composer - mHwc = new HWComposer(this, - *static_cast(this), - fbs->getFbHal()); - // initialize our drawing state mDrawingState = mCurrentState; @@ -500,8 +500,8 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& display, DisplayInfo* } const HWComposer& hwc(getHwComposer()); - float xdpi = hwc.getDpiX(); - float ydpi = hwc.getDpiY(); + float xdpi = hwc.getDpiX(HWC_DISPLAY_PRIMARY); + float ydpi = hwc.getDpiY(HWC_DISPLAY_PRIMARY); // TODO: Not sure if display density should handled by SF any longer class Density { @@ -538,7 +538,7 @@ status_t SurfaceFlinger::getDisplayInfo(const sp& display, DisplayInfo* info->h = hw->getHeight(); info->xdpi = xdpi; info->ydpi = ydpi; - info->fps = float(1e9 / hwc.getRefreshPeriod()); + info->fps = float(1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY)); info->density = density; info->orientation = hw->getOrientation(); // TODO: this needs to go away (currently needed only by webkit) @@ -2018,9 +2018,9 @@ void SurfaceFlinger::dumpAllLocked( mLastSwapBufferTime/1000.0, mLastTransactionTime/1000.0, mTransactionFlags, - 1e9 / hwc.getRefreshPeriod(), - hwc.getDpiX(), - hwc.getDpiY()); + 1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY), + hwc.getDpiX(HWC_DISPLAY_PRIMARY), + hwc.getDpiY(HWC_DISPLAY_PRIMARY)); result.append(buffer); snprintf(buffer, SIZE, " eglSwapBuffers time: %f us\n",