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
This commit is contained in:
Andy McFadden 2012-09-10 14:08:09 -07:00
parent 1fc4f80fc3
commit b0d1dd36f1
6 changed files with 202 additions and 158 deletions

View File

@ -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->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<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);
}

View File

@ -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;
};
// ---------------------------------------------------------------------------

View File

@ -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,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 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
mAllocatedDisplayIDs.markBit(i);
}
// these IDs are always reserved
for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
mAllocatedDisplayIDs.markBit(i);
}
// the number of displays we actually have depends on the
// hw composer version
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
// 1.2 adds support for virtual displays
mNumDisplays = MAX_DISPLAYS;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// 1.1 adds support for multiple displays
mNumDisplays = HWC_NUM_DISPLAY_TYPES;
} else {
mNumDisplays = 1;
}
// the number of displays we actually have depends on the
// hw composer version
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
// 1.2 adds support for virtual displays
mNumDisplays = MAX_DISPLAYS;
} else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
// 1.1 adds support for multiple displays
mNumDisplays = HWC_NUM_DISPLAY_TYPES;
} else {
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);
}
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))
{
}

View File

@ -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

View File

@ -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;

View File

@ -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<HWComposer::EventHandler *>(this));
// Initialize the main display
// create native window to main display
sp<FramebufferSurface> fbs = FramebufferSurface::create();
sp<FramebufferSurface> 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<HWComposer::EventHandler *>(this),
fbs->getFbHal());
// initialize our drawing state
mDrawingState = mCurrentState;
@ -500,8 +500,8 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& 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<IBinder>& 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",