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