Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0d1dd36 authored by Andy McFadden's avatar Andy McFadden
Browse files

Reshuffle FramebufferSurface

FramebufferSurface no longer speaks directly to the FB HAL.  Now
everything goes through HWComposer (which may or may not be
connected to a hardware composer).

Added display index arg to some query methods.

Change-Id: Id3e157d2d4e3555d33afbb703e518b6e92e2d6d5
parent 1fc4f80f
Loading
Loading
Loading
Loading
+17 −54
Original line number Diff line number Diff line
@@ -33,21 +33,12 @@
#include <ui/GraphicBuffer.h>

#include "DisplayHardware/FramebufferSurface.h"
#include "DisplayHardware/HWComposer.h"

// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------

sp<FramebufferSurface> FramebufferSurface::create() {
    sp<FramebufferSurface> 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->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);
    } else {
        ALOGE("Couldn't get gralloc module");
    }
}

status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* buffer) {
@@ -145,12 +121,7 @@ status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>* 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);
}

+6 −13
Original line number Diff line number Diff line
@@ -30,13 +30,13 @@ namespace android {

class Rect;
class String8;
class HWComposer;

// ---------------------------------------------------------------------------

class FramebufferSurface : public ConsumerBase {
public:

    static sp<FramebufferSurface> 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<GraphicBuffer>* 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<GraphicBuffer> mCurrentBuffer;

    // Hardware composer, owned by SurfaceFlinger.
    HWComposer& mHwc;
};

// ---------------------------------------------------------------------------
+142 −69
Original line number Diff line number Diff line
@@ -90,10 +90,9 @@ struct HWComposer::cb_context {

HWComposer::HWComposer(
        const sp<SurfaceFlinger>& 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,22 +106,10 @@ 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,
@@ -140,8 +127,9 @@ HWComposer::HWComposer(
            mHwc->registerProcs(mHwc, &mCBContext->procs);
        }

            // always turn vsync off when we start
        // 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);

        // these IDs are always reserved
@@ -161,17 +149,19 @@ HWComposer::HWComposer(
            mNumDisplays = 1;
        }
    }
    }

    if (fbDev) {
    if (mFbDev) {
        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;
        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);
}

uint32_t HWComposer::getResolutionX(int disp) const {
    return mDisplayData[disp].xres;
}

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() const {
    return mDisplayData[HWC_DISPLAY_PRIMARY].xdpi;
float HWComposer::getDpiX(int disp) const {
    return mDisplayData[disp].xdpi;
}

float HWComposer::getDpiY() const {
    return mDisplayData[HWC_DISPLAY_PRIMARY].ydpi;
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))
{
}

+21 −7
Original line number Diff line number Diff line
@@ -64,8 +64,7 @@ public:

    HWComposer(
            const sp<SurfaceFlinger>& 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<LayerBase> >& 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<SurfaceFlinger>              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
+3 −2
Original line number Diff line number Diff line
@@ -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;
Loading