Enable changing display configuration
This allows querying and switching display device configurations through the ISurfaceComposer/SurfaceComposerClient interface. Bug: 14320401 Change-Id: I8c22165698950e5da32204c1c4da92122f91a715
This commit is contained in:
parent
39c5e9f876
commit
7f7da32569
|
@ -113,9 +113,18 @@ public:
|
|||
*/
|
||||
virtual void unblank(const sp<IBinder>& display) = 0;
|
||||
|
||||
/* returns information about a display
|
||||
/* returns information for each configuration of the given display
|
||||
* intended to be used to get information about built-in displays */
|
||||
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) = 0;
|
||||
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
|
||||
Vector<DisplayInfo>* configs) = 0;
|
||||
|
||||
/* indicates which of the configurations returned by getDisplayInfo is
|
||||
* currently active */
|
||||
virtual int getActiveConfig(const sp<IBinder>& display) = 0;
|
||||
|
||||
/* specifies which configuration (of those returned by getDisplayInfo)
|
||||
* should be used */
|
||||
virtual status_t setActiveConfig(const sp<IBinder>& display, int id) = 0;
|
||||
|
||||
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
|
||||
* This function will fail if there is a secure window on screen.
|
||||
|
@ -158,7 +167,9 @@ public:
|
|||
AUTHENTICATE_SURFACE,
|
||||
BLANK,
|
||||
UNBLANK,
|
||||
GET_DISPLAY_INFO,
|
||||
GET_DISPLAY_CONFIGS,
|
||||
GET_ACTIVE_CONFIG,
|
||||
SET_ACTIVE_CONFIG,
|
||||
CONNECT_DISPLAY,
|
||||
CAPTURE_SCREEN,
|
||||
CLEAR_ANIMATION_FRAME_STATS,
|
||||
|
|
|
@ -66,8 +66,21 @@ public:
|
|||
status_t linkToComposerDeath(const sp<IBinder::DeathRecipient>& recipient,
|
||||
void* cookie = NULL, uint32_t flags = 0);
|
||||
|
||||
// Get information about a display
|
||||
static status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
|
||||
// Get a list of supported configurations for a given display
|
||||
static status_t getDisplayConfigs(const sp<IBinder>& display,
|
||||
Vector<DisplayInfo>* configs);
|
||||
|
||||
// Get the DisplayInfo for the currently-active configuration
|
||||
static status_t getDisplayInfo(const sp<IBinder>& display,
|
||||
DisplayInfo* info);
|
||||
|
||||
// Get the index of the current active configuration (relative to the list
|
||||
// returned by getDisplayInfo)
|
||||
static int getActiveConfig(const sp<IBinder>& display);
|
||||
|
||||
// Set a new active configuration using an index relative to the list
|
||||
// returned by getDisplayInfo
|
||||
static status_t setActiveConfig(const sp<IBinder>& display, int id);
|
||||
|
||||
/* triggers screen off and waits for it to complete */
|
||||
static void blankDisplay(const sp<IBinder>& display);
|
||||
|
|
|
@ -33,7 +33,6 @@ struct DisplayInfo {
|
|||
float density;
|
||||
uint8_t orientation;
|
||||
bool secure;
|
||||
uint8_t reserved[2];
|
||||
};
|
||||
|
||||
/* Display orientations as defined in Surface.java and ISurfaceComposer.h. */
|
||||
|
|
|
@ -220,13 +220,43 @@ public:
|
|||
remote()->transact(BnSurfaceComposer::UNBLANK, data, &reply);
|
||||
}
|
||||
|
||||
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info)
|
||||
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
|
||||
Vector<DisplayInfo>* configs)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
data.writeStrongBinder(display);
|
||||
remote()->transact(BnSurfaceComposer::GET_DISPLAY_INFO, data, &reply);
|
||||
memcpy(info, reply.readInplace(sizeof(DisplayInfo)), sizeof(DisplayInfo));
|
||||
remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply);
|
||||
status_t result = reply.readInt32();
|
||||
if (result == NO_ERROR) {
|
||||
size_t numConfigs = static_cast<size_t>(reply.readInt32());
|
||||
configs->clear();
|
||||
configs->resize(numConfigs);
|
||||
for (size_t c = 0; c < numConfigs; ++c) {
|
||||
memcpy(&(configs->editItemAt(c)),
|
||||
reply.readInplace(sizeof(DisplayInfo)),
|
||||
sizeof(DisplayInfo));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
virtual int getActiveConfig(const sp<IBinder>& display)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
data.writeStrongBinder(display);
|
||||
remote()->transact(BnSurfaceComposer::GET_ACTIVE_CONFIG, data, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
virtual status_t setActiveConfig(const sp<IBinder>& display, int id)
|
||||
{
|
||||
Parcel data, reply;
|
||||
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
|
||||
data.writeStrongBinder(display);
|
||||
data.writeInt32(id);
|
||||
remote()->transact(BnSurfaceComposer::SET_ACTIVE_CONFIG, data, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
|
@ -357,12 +387,33 @@ status_t BnSurfaceComposer::onTransact(
|
|||
unblank(display);
|
||||
return NO_ERROR;
|
||||
}
|
||||
case GET_DISPLAY_INFO: {
|
||||
case GET_DISPLAY_CONFIGS: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
DisplayInfo info;
|
||||
Vector<DisplayInfo> configs;
|
||||
sp<IBinder> display = data.readStrongBinder();
|
||||
status_t result = getDisplayInfo(display, &info);
|
||||
memcpy(reply->writeInplace(sizeof(DisplayInfo)), &info, sizeof(DisplayInfo));
|
||||
status_t result = getDisplayConfigs(display, &configs);
|
||||
reply->writeInt32(result);
|
||||
if (result == NO_ERROR) {
|
||||
reply->writeInt32(static_cast<int32_t>(configs.size()));
|
||||
for (size_t c = 0; c < configs.size(); ++c) {
|
||||
memcpy(reply->writeInplace(sizeof(DisplayInfo)),
|
||||
&configs[c], sizeof(DisplayInfo));
|
||||
}
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
case GET_ACTIVE_CONFIG: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
sp<IBinder> display = data.readStrongBinder();
|
||||
int id = getActiveConfig(display);
|
||||
reply->writeInt32(id);
|
||||
return NO_ERROR;
|
||||
}
|
||||
case SET_ACTIVE_CONFIG: {
|
||||
CHECK_INTERFACE(ISurfaceComposer, data, reply);
|
||||
sp<IBinder> display = data.readStrongBinder();
|
||||
int id = data.readInt32();
|
||||
status_t result = setActiveConfig(display, id);
|
||||
reply->writeInt32(result);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
|
|
@ -623,10 +623,36 @@ void SurfaceComposerClient::setDisplayProjection(const sp<IBinder>& token,
|
|||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
status_t SurfaceComposerClient::getDisplayInfo(
|
||||
const sp<IBinder>& display, DisplayInfo* info)
|
||||
status_t SurfaceComposerClient::getDisplayConfigs(
|
||||
const sp<IBinder>& display, Vector<DisplayInfo>* configs)
|
||||
{
|
||||
return ComposerService::getComposerService()->getDisplayInfo(display, info);
|
||||
return ComposerService::getComposerService()->getDisplayConfigs(display, configs);
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::getDisplayInfo(const sp<IBinder>& display,
|
||||
DisplayInfo* info) {
|
||||
Vector<DisplayInfo> configs;
|
||||
status_t result = getDisplayConfigs(display, &configs);
|
||||
if (result != NO_ERROR) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int activeId = getActiveConfig(display);
|
||||
if (activeId < 0) {
|
||||
ALOGE("No active configuration found");
|
||||
return NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
*info = configs[activeId];
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
|
||||
return ComposerService::getComposerService()->getActiveConfig(display);
|
||||
}
|
||||
|
||||
status_t SurfaceComposerClient::setActiveConfig(const sp<IBinder>& display, int id) {
|
||||
return ComposerService::getComposerService()->setActiveConfig(display, id);
|
||||
}
|
||||
|
||||
void SurfaceComposerClient::blankDisplay(const sp<IBinder>& token) {
|
||||
|
|
|
@ -170,20 +170,15 @@ HWComposer::HWComposer(
|
|||
|
||||
DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
|
||||
disp.connected = true;
|
||||
disp.width = mFbDev->width;
|
||||
disp.height = mFbDev->height;
|
||||
disp.format = mFbDev->format;
|
||||
disp.xdpi = mFbDev->xdpi;
|
||||
disp.ydpi = mFbDev->ydpi;
|
||||
if (disp.refresh == 0) {
|
||||
disp.refresh = nsecs_t(1e9 / mFbDev->fps);
|
||||
ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh);
|
||||
}
|
||||
if (disp.refresh == 0) {
|
||||
disp.refresh = nsecs_t(1e9 / 60.0);
|
||||
ALOGW("getting VSYNC period from thin air: %lld",
|
||||
mDisplayData[HWC_DISPLAY_PRIMARY].refresh);
|
||||
}
|
||||
DisplayConfig config = DisplayConfig();
|
||||
config.width = mFbDev->width;
|
||||
config.height = mFbDev->height;
|
||||
config.xdpi = mFbDev->xdpi;
|
||||
config.ydpi = mFbDev->ydpi;
|
||||
config.refresh = nsecs_t(1e9 / mFbDev->fps);
|
||||
disp.configs.push_back(config);
|
||||
disp.currentConfig = 0;
|
||||
} else if (mHwc) {
|
||||
// here we're guaranteed to have at least HWC 1.1
|
||||
for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
|
||||
|
@ -342,55 +337,63 @@ status_t HWComposer::queryDisplayProperties(int disp) {
|
|||
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);
|
||||
const size_t MAX_NUM_CONFIGS = 128;
|
||||
uint32_t configs[MAX_NUM_CONFIGS] = {0};
|
||||
size_t numConfigs = MAX_NUM_CONFIGS;
|
||||
status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
|
||||
if (err != NO_ERROR) {
|
||||
// this can happen if an unpluggable display is not connected
|
||||
mDisplayData[disp].connected = false;
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mHwc->getDisplayAttributes(mHwc, disp, config, DISPLAY_ATTRIBUTES, values);
|
||||
if (err != NO_ERROR) {
|
||||
// we can't get this display's info. turn it off.
|
||||
mDisplayData[disp].connected = false;
|
||||
return err;
|
||||
}
|
||||
|
||||
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_WIDTH:
|
||||
mDisplayData[disp].width = values[i];
|
||||
break;
|
||||
case HWC_DISPLAY_HEIGHT:
|
||||
mDisplayData[disp].height = 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[%d] %#x",
|
||||
i, DISPLAY_ATTRIBUTES[i]);
|
||||
break;
|
||||
mDisplayData[disp].currentConfig = 0;
|
||||
for (size_t c = 0; c < numConfigs; ++c) {
|
||||
err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
|
||||
DISPLAY_ATTRIBUTES, values);
|
||||
if (err != NO_ERROR) {
|
||||
// we can't get this display's info. turn it off.
|
||||
mDisplayData[disp].connected = false;
|
||||
return err;
|
||||
}
|
||||
|
||||
DisplayConfig config = DisplayConfig();
|
||||
for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
|
||||
switch (DISPLAY_ATTRIBUTES[i]) {
|
||||
case HWC_DISPLAY_VSYNC_PERIOD:
|
||||
config.refresh = nsecs_t(values[i]);
|
||||
break;
|
||||
case HWC_DISPLAY_WIDTH:
|
||||
config.width = values[i];
|
||||
break;
|
||||
case HWC_DISPLAY_HEIGHT:
|
||||
config.height = values[i];
|
||||
break;
|
||||
case HWC_DISPLAY_DPI_X:
|
||||
config.xdpi = values[i] / 1000.0f;
|
||||
break;
|
||||
case HWC_DISPLAY_DPI_Y:
|
||||
config.ydpi = values[i] / 1000.0f;
|
||||
break;
|
||||
default:
|
||||
ALOG_ASSERT(false, "unknown display attribute[%d] %#x",
|
||||
i, DISPLAY_ATTRIBUTES[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
|
||||
float dpi = getDefaultDensity(config.height);
|
||||
config.xdpi = dpi;
|
||||
config.ydpi = dpi;
|
||||
}
|
||||
|
||||
mDisplayData[disp].configs.push_back(config);
|
||||
}
|
||||
|
||||
// FIXME: what should we set the format to?
|
||||
mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
mDisplayData[disp].connected = true;
|
||||
if (mDisplayData[disp].xdpi == 0.0f || mDisplayData[disp].ydpi == 0.0f) {
|
||||
float dpi = getDefaultDensity(h);
|
||||
mDisplayData[disp].xdpi = dpi;
|
||||
mDisplayData[disp].ydpi = dpi;
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -400,10 +403,12 @@ status_t HWComposer::setVirtualDisplayProperties(int32_t id,
|
|||
!mAllocatedDisplayIDs.hasBit(id)) {
|
||||
return BAD_INDEX;
|
||||
}
|
||||
mDisplayData[id].width = w;
|
||||
mDisplayData[id].height = h;
|
||||
size_t configId = mDisplayData[id].currentConfig;
|
||||
mDisplayData[id].format = format;
|
||||
mDisplayData[id].xdpi = mDisplayData[id].ydpi = getDefaultDensity(h);
|
||||
DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
|
||||
config.width = w;
|
||||
config.height = h;
|
||||
config.xdpi = config.ydpi = getDefaultDensity(h);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -414,6 +419,8 @@ int32_t HWComposer::allocateDisplayId() {
|
|||
int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
|
||||
mAllocatedDisplayIDs.markBit(id);
|
||||
mDisplayData[id].connected = true;
|
||||
mDisplayData[id].configs.resize(1);
|
||||
mDisplayData[id].currentConfig = 0;
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -430,31 +437,21 @@ status_t HWComposer::freeDisplayId(int32_t id) {
|
|||
return NO_ERROR;
|
||||
}
|
||||
|
||||
nsecs_t HWComposer::getRefreshPeriod(int disp) const {
|
||||
return mDisplayData[disp].refresh;
|
||||
}
|
||||
|
||||
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[disp]) % mDisplayData[disp].refresh);
|
||||
size_t configId = mDisplayData[disp].currentConfig;
|
||||
return now - ((now - mLastHwVSync[disp]) %
|
||||
mDisplayData[disp].configs[configId].refresh);
|
||||
}
|
||||
|
||||
sp<Fence> HWComposer::getDisplayFence(int disp) const {
|
||||
return mDisplayData[disp].lastDisplayFence;
|
||||
}
|
||||
|
||||
uint32_t HWComposer::getWidth(int disp) const {
|
||||
return mDisplayData[disp].width;
|
||||
}
|
||||
|
||||
uint32_t HWComposer::getHeight(int disp) const {
|
||||
return mDisplayData[disp].height;
|
||||
}
|
||||
|
||||
uint32_t HWComposer::getFormat(int disp) const {
|
||||
if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
|
||||
return HAL_PIXEL_FORMAT_RGBA_8888;
|
||||
|
@ -463,16 +460,41 @@ uint32_t HWComposer::getFormat(int disp) const {
|
|||
}
|
||||
}
|
||||
|
||||
bool HWComposer::isConnected(int disp) const {
|
||||
return mDisplayData[disp].connected;
|
||||
}
|
||||
|
||||
uint32_t HWComposer::getWidth(int disp) const {
|
||||
size_t currentConfig = mDisplayData[disp].currentConfig;
|
||||
return mDisplayData[disp].configs[currentConfig].width;
|
||||
}
|
||||
|
||||
uint32_t HWComposer::getHeight(int disp) const {
|
||||
size_t currentConfig = mDisplayData[disp].currentConfig;
|
||||
return mDisplayData[disp].configs[currentConfig].height;
|
||||
}
|
||||
|
||||
float HWComposer::getDpiX(int disp) const {
|
||||
return mDisplayData[disp].xdpi;
|
||||
size_t currentConfig = mDisplayData[disp].currentConfig;
|
||||
return mDisplayData[disp].configs[currentConfig].xdpi;
|
||||
}
|
||||
|
||||
float HWComposer::getDpiY(int disp) const {
|
||||
return mDisplayData[disp].ydpi;
|
||||
size_t currentConfig = mDisplayData[disp].currentConfig;
|
||||
return mDisplayData[disp].configs[currentConfig].ydpi;
|
||||
}
|
||||
|
||||
bool HWComposer::isConnected(int disp) const {
|
||||
return mDisplayData[disp].connected;
|
||||
nsecs_t HWComposer::getRefreshPeriod(int disp) const {
|
||||
size_t currentConfig = mDisplayData[disp].currentConfig;
|
||||
return mDisplayData[disp].configs[currentConfig].refresh;
|
||||
}
|
||||
|
||||
const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
|
||||
return mDisplayData[disp].configs;
|
||||
}
|
||||
|
||||
size_t HWComposer::getCurrentConfig(int disp) const {
|
||||
return mDisplayData[disp].currentConfig;
|
||||
}
|
||||
|
||||
void HWComposer::eventControl(int disp, int event, int enabled) {
|
||||
|
@ -536,7 +558,10 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
|||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
|
||||
disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
|
||||
memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
|
||||
const hwc_rect_t r = { 0, 0, (int) disp.width, (int) disp.height };
|
||||
const DisplayConfig& currentConfig =
|
||||
disp.configs[disp.currentConfig];
|
||||
const hwc_rect_t r = { 0, 0,
|
||||
(int) currentConfig.width, (int) currentConfig.height };
|
||||
disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
|
||||
disp.framebufferTarget->hints = 0;
|
||||
disp.framebufferTarget->flags = 0;
|
||||
|
@ -546,8 +571,10 @@ status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
|
|||
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
|
||||
disp.framebufferTarget->sourceCropf.left = 0;
|
||||
disp.framebufferTarget->sourceCropf.top = 0;
|
||||
disp.framebufferTarget->sourceCropf.right = disp.width;
|
||||
disp.framebufferTarget->sourceCropf.bottom = disp.height;
|
||||
disp.framebufferTarget->sourceCropf.right =
|
||||
currentConfig.width;
|
||||
disp.framebufferTarget->sourceCropf.bottom =
|
||||
currentConfig.height;
|
||||
} else {
|
||||
disp.framebufferTarget->sourceCrop = r;
|
||||
}
|
||||
|
@ -1050,9 +1077,14 @@ void HWComposer::dump(String8& result) const {
|
|||
const Vector< sp<Layer> >& visibleLayersSortedByZ =
|
||||
mFlinger->getLayerSortedByZForHwcDisplay(i);
|
||||
|
||||
result.appendFormat(
|
||||
" Display[%zd] : %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n",
|
||||
i, disp.width, disp.height, disp.xdpi, disp.ydpi, disp.refresh);
|
||||
|
||||
result.appendFormat(" Display[%zd] configurations (* current):\n", i);
|
||||
for (size_t c = 0; c < disp.configs.size(); ++c) {
|
||||
const DisplayConfig& config(disp.configs[c]);
|
||||
result.appendFormat(" %s%zd: %ux%u, xdpi=%f, ydpi=%f, refresh=%" PRId64 "\n",
|
||||
c == disp.currentConfig ? "* " : "", c, config.width, config.height,
|
||||
config.xdpi, config.ydpi, config.refresh);
|
||||
}
|
||||
|
||||
if (disp.list) {
|
||||
result.appendFormat(
|
||||
|
@ -1181,9 +1213,9 @@ bool HWComposer::VSyncThread::threadLoop() {
|
|||
}
|
||||
|
||||
HWComposer::DisplayData::DisplayData()
|
||||
: width(0), height(0), format(HAL_PIXEL_FORMAT_RGBA_8888),
|
||||
xdpi(0.0f), ydpi(0.0f),
|
||||
refresh(0),
|
||||
: configs(),
|
||||
currentConfig(0),
|
||||
format(HAL_PIXEL_FORMAT_RGBA_8888),
|
||||
connected(false),
|
||||
hasFbComp(false), hasOvComp(false),
|
||||
capacity(0), list(NULL),
|
||||
|
|
|
@ -247,17 +247,31 @@ public:
|
|||
|
||||
void eventControl(int disp, int event, int enabled);
|
||||
|
||||
struct DisplayConfig {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
float xdpi;
|
||||
float ydpi;
|
||||
nsecs_t refresh;
|
||||
};
|
||||
|
||||
// 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;
|
||||
sp<Fence> getDisplayFence(int disp) const;
|
||||
uint32_t getFormat(int disp) const;
|
||||
bool isConnected(int disp) const;
|
||||
|
||||
// These return the values for the current config of a given display index.
|
||||
// To get the values for all configs, use getConfigs below.
|
||||
uint32_t getWidth(int disp) const;
|
||||
uint32_t getHeight(int disp) const;
|
||||
uint32_t getFormat(int disp) const;
|
||||
float getDpiX(int disp) const;
|
||||
float getDpiY(int disp) const;
|
||||
bool isConnected(int disp) const;
|
||||
nsecs_t getRefreshPeriod(int disp) const;
|
||||
|
||||
const Vector<DisplayConfig>& getConfigs(int disp) const;
|
||||
size_t getCurrentConfig(int disp) const;
|
||||
|
||||
status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
|
||||
uint32_t format);
|
||||
|
@ -306,16 +320,12 @@ private:
|
|||
status_t setFramebufferTarget(int32_t id,
|
||||
const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
|
||||
|
||||
|
||||
struct DisplayData {
|
||||
DisplayData();
|
||||
~DisplayData();
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
Vector<DisplayConfig> configs;
|
||||
size_t currentConfig;
|
||||
uint32_t format; // pixel format from FB hal, for pre-hwc-1.1
|
||||
float xdpi;
|
||||
float ydpi;
|
||||
nsecs_t refresh;
|
||||
bool connected;
|
||||
bool hasFbComp;
|
||||
bool hasOvComp;
|
||||
|
|
|
@ -502,7 +502,12 @@ bool SurfaceFlinger::authenticateSurfaceTexture(
|
|||
return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
|
||||
status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
|
||||
Vector<DisplayInfo>* configs) {
|
||||
if (configs == NULL) {
|
||||
return BAD_VALUE;
|
||||
}
|
||||
|
||||
int32_t type = NAME_NOT_FOUND;
|
||||
for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
|
||||
if (display == mBuiltinDisplays[i]) {
|
||||
|
@ -515,10 +520,6 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo*
|
|||
return type;
|
||||
}
|
||||
|
||||
const HWComposer& hwc(getHwComposer());
|
||||
float xdpi = hwc.getDpiX(type);
|
||||
float ydpi = hwc.getDpiY(type);
|
||||
|
||||
// TODO: Not sure if display density should handled by SF any longer
|
||||
class Density {
|
||||
static int getDensityFromProperty(char const* propName) {
|
||||
|
@ -536,41 +537,63 @@ status_t SurfaceFlinger::getDisplayInfo(const sp<IBinder>& display, DisplayInfo*
|
|||
return getDensityFromProperty("ro.sf.lcd_density"); }
|
||||
};
|
||||
|
||||
if (type == DisplayDevice::DISPLAY_PRIMARY) {
|
||||
// The density of the device is provided by a build property
|
||||
float density = Density::getBuildDensity() / 160.0f;
|
||||
if (density == 0) {
|
||||
// the build doesn't provide a density -- this is wrong!
|
||||
// use xdpi instead
|
||||
ALOGE("ro.sf.lcd_density must be defined as a build property");
|
||||
density = xdpi / 160.0f;
|
||||
}
|
||||
if (Density::getEmuDensity()) {
|
||||
// if "qemu.sf.lcd_density" is specified, it overrides everything
|
||||
xdpi = ydpi = density = Density::getEmuDensity();
|
||||
density /= 160.0f;
|
||||
}
|
||||
info->density = density;
|
||||
configs->clear();
|
||||
|
||||
// TODO: this needs to go away (currently needed only by webkit)
|
||||
sp<const DisplayDevice> hw(getDefaultDisplayDevice());
|
||||
info->orientation = hw->getOrientation();
|
||||
} else {
|
||||
// TODO: where should this value come from?
|
||||
static const int TV_DENSITY = 213;
|
||||
info->density = TV_DENSITY / 160.0f;
|
||||
info->orientation = 0;
|
||||
const Vector<HWComposer::DisplayConfig>& hwConfigs =
|
||||
getHwComposer().getConfigs(type);
|
||||
for (size_t c = 0; c < hwConfigs.size(); ++c) {
|
||||
const HWComposer::DisplayConfig& hwConfig = hwConfigs[c];
|
||||
DisplayInfo info = DisplayInfo();
|
||||
|
||||
float xdpi = hwConfig.xdpi;
|
||||
float ydpi = hwConfig.ydpi;
|
||||
|
||||
if (type == DisplayDevice::DISPLAY_PRIMARY) {
|
||||
// The density of the device is provided by a build property
|
||||
float density = Density::getBuildDensity() / 160.0f;
|
||||
if (density == 0) {
|
||||
// the build doesn't provide a density -- this is wrong!
|
||||
// use xdpi instead
|
||||
ALOGE("ro.sf.lcd_density must be defined as a build property");
|
||||
density = xdpi / 160.0f;
|
||||
}
|
||||
if (Density::getEmuDensity()) {
|
||||
// if "qemu.sf.lcd_density" is specified, it overrides everything
|
||||
xdpi = ydpi = density = Density::getEmuDensity();
|
||||
density /= 160.0f;
|
||||
}
|
||||
info.density = density;
|
||||
|
||||
// TODO: this needs to go away (currently needed only by webkit)
|
||||
sp<const DisplayDevice> hw(getDefaultDisplayDevice());
|
||||
info.orientation = hw->getOrientation();
|
||||
} else {
|
||||
// TODO: where should this value come from?
|
||||
static const int TV_DENSITY = 213;
|
||||
info.density = TV_DENSITY / 160.0f;
|
||||
info.orientation = 0;
|
||||
}
|
||||
|
||||
info.w = hwConfig.width;
|
||||
info.h = hwConfig.height;
|
||||
info.xdpi = xdpi;
|
||||
info.ydpi = ydpi;
|
||||
info.fps = float(1e9 / hwConfig.refresh);
|
||||
|
||||
// All non-virtual displays are currently considered secure.
|
||||
info.secure = true;
|
||||
|
||||
configs->push_back(info);
|
||||
}
|
||||
|
||||
info->w = hwc.getWidth(type);
|
||||
info->h = hwc.getHeight(type);
|
||||
info->xdpi = xdpi;
|
||||
info->ydpi = ydpi;
|
||||
info->fps = float(1e9 / hwc.getRefreshPeriod(type));
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
// All non-virtual displays are currently considered secure.
|
||||
info->secure = true;
|
||||
int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int id) {
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,10 @@ private:
|
|||
virtual void blank(const sp<IBinder>& display);
|
||||
// called when screen is turning back on
|
||||
virtual void unblank(const sp<IBinder>& display);
|
||||
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info);
|
||||
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
|
||||
Vector<DisplayInfo>* configs);
|
||||
virtual int getActiveConfig(const sp<IBinder>& display);
|
||||
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
|
||||
virtual status_t clearAnimationFrameStats();
|
||||
virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue