display: Enable vsync
* Use the vsync uevents from the kernel to start
surfaceflinger composition.
* This patch also does some code cleanup
- Move copybit specific functions to copybit files.
- Cleanup verbose logging.
Change-Id: I36936e4b0a082cfb0347d8ee7d2bc936e01808e6
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 5067a2a..9808aa5 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -10,6 +10,6 @@
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"hwcomposer\"
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
LOCAL_SRC_FILES := hwc.cpp hwc_video.cpp hwc_utils.cpp \
- hwc_uimirror.cpp hwc_ext_observer.cpp \
- hwc_copybit.cpp
+ hwc_uimirror.cpp hwc_external.cpp \
+ hwc_uevents.cpp hwc_copybit.cpp
include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index 7826a5f..c0bca9d 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -20,8 +20,12 @@
#include <cutils/log.h>
#include <cutils/atomic.h>
+#include <EGL/egl.h>
+#include <overlay.h>
+#include <fb_priv.h>
#include "hwc_utils.h"
+#include "hwc_qbuf.h"
#include "hwc_video.h"
#include "hwc_uimirror.h"
#include "hwc_copybit.h"
@@ -93,6 +97,47 @@
return 0;
}
+static int hwc_eventControl(struct hwc_composer_device* dev,
+ int event, int enabled)
+{
+ int ret = 0;
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ private_module_t* m = reinterpret_cast<private_module_t*>(
+ ctx->mFbDev->common.module);
+ switch(event) {
+ case HWC_EVENT_VSYNC:
+ if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0)
+ ret = -errno;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int hwc_query(struct hwc_composer_device* dev,
+ int param, int* value)
+{
+ hwc_context_t* ctx = (hwc_context_t*)(dev);
+ private_module_t* m = reinterpret_cast<private_module_t*>(
+ ctx->mFbDev->common.module);
+
+ switch (param) {
+ case HWC_BACKGROUND_LAYER_SUPPORTED:
+ // Not supported for now
+ value[0] = 0;
+ break;
+ case HWC_VSYNC_PERIOD:
+ value[0] = 1000000000.0 / m->fps;
+ ALOGI("fps: %d", value[0]);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+
+}
+
static int hwc_set(hwc_composer_device_t *dev,
hwc_display_t dpy,
hwc_surface_t sur,
@@ -119,7 +164,7 @@
static int hwc_device_close(struct hw_device_t *dev)
{
if(!dev) {
- ALOGE("hwc_device_close null device pointer");
+ ALOGE("%s: NULL device pointer", __FUNCTION__);
return -1;
}
closeContext((hwc_context_t*)dev);
@@ -137,14 +182,25 @@
struct hwc_context_t *dev;
dev = (hwc_context_t*)malloc(sizeof(*dev));
memset(dev, 0, sizeof(*dev));
+
+ //Initialize hwc context
initContext(dev);
+
+ //Setup HWC methods
+ hwc_methods_t *methods;
+ methods = (hwc_methods_t *)malloc(sizeof(*methods));
+ memset(methods, 0, sizeof(*methods));
+ methods->eventControl = hwc_eventControl;
+
dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = 0;
+ dev->device.common.version = HWC_DEVICE_API_VERSION_0_3;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = hwc_device_close;
dev->device.prepare = hwc_prepare;
dev->device.set = hwc_set;
dev->device.registerProcs = hwc_registerProcs;
+ dev->device.query = hwc_query;
+ dev->device.methods = methods;
*device = &dev->device.common;
status = 0;
}
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index adcd4dc..7892632 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -18,8 +18,9 @@
* limitations under the License.
*/
+#include <copybit.h>
+#include <genlock.h>
#include "hwc_copybit.h"
-#include "hwc_copybitEngine.h"
namespace qhwc {
@@ -71,6 +72,23 @@
bool CopyBit::sIsLayerSkip = false;
void* CopyBit::egl_lib = NULL;
+void CopyBit::openEglLibAndGethandle()
+{
+ egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
+ if (!egl_lib) {
+ return;
+ }
+ updateEglHandles(egl_lib);
+}
+void CopyBit::closeEglLib()
+{
+ if(egl_lib)
+ ::dlclose(egl_lib);
+
+ egl_lib = NULL;
+ updateEglHandles(NULL);
+}
+
void CopyBit::updateEglHandles(void* egl_lib)
{
if(egl_lib != NULL) {
@@ -365,7 +383,7 @@
if(ctx->hasOverlay)
return false;
- framebuffer_device_t* fbDev = ctx->mFbDevice->getFb();
+ framebuffer_device_t* fbDev = ctx->mFbDev;
if(!fbDev) {
ALOGE("ERROR: canUseCopybit : fb device is invalid");
return false;
@@ -402,27 +420,11 @@
return (renderArea <= (2 * fb_w * fb_h));
}
-void CopyBit::openEglLibAndGethandle()
-{
- egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
- if (!egl_lib) {
- return;
- }
- updateEglHandles(egl_lib);
-}
-void CopyBit::closeEglLib()
-{
- if(egl_lib)
- ::dlclose(egl_lib);
-
- egl_lib = NULL;
- updateEglHandles(NULL);
-}
//CopybitEngine Class functions
-CopybitEngine* CopybitEngine::sInstance = 0;;
+CopybitEngine* CopybitEngine::sInstance = 0;
struct copybit_device_t* CopybitEngine::getEngine() {
return sEngine;
@@ -440,9 +442,11 @@
} else {
ALOGE("FATAL ERROR: copybit open failed.");
}
+ CopyBit::openEglLibAndGethandle();
}
CopybitEngine::~CopybitEngine()
{
+ CopyBit::closeEglLib();
if(sEngine)
{
copybit_close(sEngine);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index adf088b..602898e 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -31,6 +31,11 @@
namespace qhwc {
//Feature for using Copybit to display RGB layers.
+typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
+ EGLDisplay dpy,
+ EGLSurface draw);
+typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
+
class CopyBit {
public:
//Sets up members and prepares copybit if conditions are met
@@ -75,6 +80,20 @@
};
+class CopybitEngine {
+public:
+ ~CopybitEngine();
+ // API to get copybit engine(non static)
+ struct copybit_device_t *getEngine();
+ // API to get singleton
+ static CopybitEngine* getInstance();
+private:
+ CopybitEngine();
+ struct copybit_device_t *sEngine;
+ static CopybitEngine* sInstance; // singleton
+};
+
+
inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex,
bool isYuvLayerSkip) {
sYuvCount = yuvCount;
diff --git a/libhwcomposer/hwc_copybitEngine.h b/libhwcomposer/hwc_copybitEngine.h
deleted file mode 100644
index d627e44..0000000
--- a/libhwcomposer/hwc_copybitEngine.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef HWC_COPYBIT_ENGINE_H
-#define HWC_COPYBIT_ENGINE_H
-
-namespace qhwc {
-class CopybitEngine {
-public:
- ~CopybitEngine();
- // API to get copybit engine(non static)
- struct copybit_device_t *getEngine();
- // API to get singleton
- static CopybitEngine* getInstance();
-
-private:
- CopybitEngine();
- struct copybit_device_t *sEngine;
- static CopybitEngine* sInstance; // singleton
-};
-
-}; //namespace qhwc
-
-#endif //HWC_COPYBIT_ENGINE_H
diff --git a/libhwcomposer/hwc_ext_observer.h b/libhwcomposer/hwc_ext_observer.h
deleted file mode 100644
index e7cb890..0000000
--- a/libhwcomposer/hwc_ext_observer.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
- *
- * Not a Contribution, Apache license notifications and license are
- * retained for attribution purposes only.
-
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HWC_EXT_OBSERVER_H
-#define HWC_EXT_OBSERVER_H
-
-#include <utils/threads.h>
-
-struct hwc_context_t;
-
-namespace qhwc {
-
-class ExtDisplayObserver : public android::Thread
-{
- //Type of external display - OFF, HDMI, WFD
- enum external_display_type {
- EXT_TYPE_NONE,
- EXT_TYPE_HDMI,
- EXT_TYPE_WIFI
- };
-
- // Mirroring state
- enum external_mirroring_state {
- EXT_MIRRORING_OFF,
- EXT_MIRRORING_ON,
- };
- public:
- /*Overrides*/
- virtual bool threadLoop();
- virtual int readyToRun();
- virtual void onFirstRef();
-
- virtual ~ExtDisplayObserver();
- static ExtDisplayObserver *getInstance();
- int getExternalDisplay() const;
- void setHwcContext(hwc_context_t* hwcCtx);
-
- private:
- ExtDisplayObserver();
- void setExternalDisplayStatus(int connected);
- bool readResolution();
- int parseResolution(char* edidStr, int* edidModes, int len);
- void setResolution(int ID);
- bool openFramebuffer();
- bool writeHPDOption(int userOption) const;
- bool isValidMode(int ID);
- void handleUEvent(char* str);
- int getModeOrder(int mode);
- int getBestMode();
-
- int fd;
- int mExternalDisplay;
- int mCurrentID;
- char mEDIDs[128];
- int mEDIDModes[64];
- int mModeCount;
- hwc_context_t *mHwcContext;
- static android::sp<ExtDisplayObserver> sExtDisplayObserverInstance;
-};
-
-}; //qhwc
-// ---------------------------------------------------------------------------
-#endif //HWC_EXT_OBSERVER_H
diff --git a/libhwcomposer/hwc_ext_observer.cpp b/libhwcomposer/hwc_external.cpp
similarity index 61%
rename from libhwcomposer/hwc_ext_observer.cpp
rename to libhwcomposer/hwc_external.cpp
index 2a5ec36..3507134 100644
--- a/libhwcomposer/hwc_ext_observer.cpp
+++ b/libhwcomposer/hwc_external.cpp
@@ -18,10 +18,9 @@
* limitations under the License.
*/
-#define EXT_OBSERVER_DEBUG 0
+#define DEBUG 0
#include <ctype.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
+#include <fcntl.h>
#include <media/IAudioPolicyService.h>
#include <media/AudioSystem.h>
#include <utils/threads.h>
@@ -32,11 +31,10 @@
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/poll.h>
-
-#include <hardware_legacy/uevent.h>
+#include <sys/resource.h>
#include <cutils/properties.h>
#include "hwc_utils.h"
-#include "hwc_ext_observer.h"
+#include "hwc_external.h"
namespace qhwc {
@@ -49,88 +47,19 @@
#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd"
-android::sp<ExtDisplayObserver> ExtDisplayObserver::
- sExtDisplayObserverInstance(0);
-
-ExtDisplayObserver::ExtDisplayObserver() : Thread(false),
- fd(-1), mCurrentID(-1), mHwcContext(NULL)
+ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):fd(-1),
+ mCurrentID(-1), mHwcContext(ctx)
{
//Enable HPD for HDMI
writeHPDOption(1);
}
-ExtDisplayObserver::~ExtDisplayObserver() {
+ExternalDisplay::~ExternalDisplay()
+{
if (fd > 0)
close(fd);
}
-ExtDisplayObserver *ExtDisplayObserver::getInstance() {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s ", __FUNCTION__);
- if(sExtDisplayObserverInstance.get() == NULL)
- sExtDisplayObserverInstance = new ExtDisplayObserver();
- return sExtDisplayObserverInstance.get();
-}
-
-void ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
- if(hwcCtx) {
- mHwcContext = hwcCtx;
- }
- return;
-}
-void ExtDisplayObserver::onFirstRef() {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
- run("ExtDisplayObserver", ANDROID_PRIORITY_DISPLAY);
-}
-
-int ExtDisplayObserver::readyToRun() {
- //Initialize the uevent
- uevent_init();
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: success", __FUNCTION__);
- return android::NO_ERROR;
-}
-
-void ExtDisplayObserver::handleUEvent(char* str){
- int connected = 0;
- // TODO: check for fb2(WFD) driver also
- if(!strcasestr(str, DEVICE_NODE))
- {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
- return;
- }
- // Event will be of the form:
- // change@/devices/virtual/graphics/fb1 ACTION=change
- // DEVPATH=/devices/virtual/graphics/fb1
- // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
- // for now just parse the online or offline are important for us.
- if(!(strncmp(str,"online@",strlen("online@")))) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
- connected = 1;
- readResolution();
- //Get the best mode and set
- // TODO: DO NOT call this for WFD
- setResolution(getBestMode());
- } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
- connected = 0;
- close(fd);
- }
- setExternalDisplayStatus(connected);
-}
-
-bool ExtDisplayObserver::threadLoop()
-{
- static char uEventString[1024];
- memset(uEventString, 0, sizeof(uEventString));
- int count = uevent_next_event(uEventString, sizeof(uEventString));
- if(count) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: UeventString: %s len = %d",
- __FUNCTION__, uEventString, count);
- handleUEvent(uEventString);
- }
- return true;
-}
-
struct disp_mode_timing_type {
int video_format;
@@ -213,7 +142,8 @@
{m1920x1080p25_16_9, 1920, 1080, 528, 44, 148, 4, 5, 36, 74250, false},
{m1920x1080p30_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 74250, false},
};
-int ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len)
+
+int ExternalDisplay::parseResolution(char* edidStr, int* edidModes, int len)
{
char delim = ',';
int count = 0;
@@ -233,7 +163,7 @@
}
return count;
}
-bool ExtDisplayObserver::readResolution()
+bool ExternalDisplay::readResolution()
{
int hdmiEDIDFile = open(SYSFS_EDID_MODES, O_RDONLY, 0);
int len = -1;
@@ -242,16 +172,16 @@
memset(mEDIDModes, 0, sizeof(mEDIDModes));
mModeCount = 0;
if (hdmiEDIDFile < 0) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file '%s' not found",
- __FUNCTION__, SYSFS_EDID_MODES);
+ ALOGD_IF(DEBUG, "%s: edid_modes file '%s' not found",
+ __FUNCTION__, SYSFS_EDID_MODES);
return false;
} else {
len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1);
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: EDID string: %s length = %d",
- __FUNCTION__, mEDIDs, len);
+ ALOGD_IF(DEBUG, "%s: EDID string: %s length = %d",
+ __FUNCTION__, mEDIDs, len);
if ( len <= 0) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file empty '%s'",
- __FUNCTION__, SYSFS_EDID_MODES);
+ ALOGD_IF(DEBUG, "%s: edid_modes file empty '%s'",
+ __FUNCTION__, SYSFS_EDID_MODES);
}
else {
while (len > 1 && isspace(mEDIDs[len-1]))
@@ -263,26 +193,26 @@
if(len > 0) {
// GEt EDID modes from the EDID strings
mModeCount = parseResolution(mEDIDs, mEDIDModes, len);
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: mModeCount = %d", __FUNCTION__,
- mModeCount);
+ ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__,
+ mModeCount);
}
return (strlen(mEDIDs) > 0);
}
-bool ExtDisplayObserver::openFramebuffer()
+bool ExternalDisplay::openFramebuffer()
{
if (fd == -1) {
fd = open("/dev/graphics/fb1", O_RDWR);
if (fd < 0)
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: /dev/graphics/fb1 not available"
- "\n", __FUNCTION__);
+ ALOGD_IF(DEBUG, "%s: /dev/graphics/fb1 not available"
+ "\n", __FUNCTION__);
}
return (fd > 0);
}
-int ExtDisplayObserver::getModeOrder(int mode)
+int ExternalDisplay::getModeOrder(int mode)
{
switch (mode) {
default:
@@ -320,11 +250,11 @@
return 16; //1080p@50Hz
case m1920x1080p60_16_9:
return 17; //1080p@60Hz
- }
+ }
}
// Get the best mode for the current HD TV
-int ExtDisplayObserver::getBestMode() {
+int ExternalDisplay::getBestMode() {
int bestOrder = 0;
int bestMode = m640x480p60_4_3;
@@ -338,14 +268,14 @@
}
}
return bestMode;
- }
+}
-inline bool ExtDisplayObserver::isValidMode(int ID)
+inline bool ExternalDisplay::isValidMode(int ID)
{
return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
}
-void ExtDisplayObserver::setResolution(int ID)
+void ExternalDisplay::setResolution(int ID)
{
struct fb_var_screeninfo info;
if (!openFramebuffer())
@@ -353,29 +283,29 @@
//If its a valid mode and its a new ID - update var_screeninfo
if ((isValidMode(ID)) && mCurrentID != ID) {
const struct disp_mode_timing_type *mode =
- &supported_video_mode_lut[0];
+ &supported_video_mode_lut[0];
unsigned count = sizeof(supported_video_mode_lut)/sizeof
- (*supported_video_mode_lut);
+ (*supported_video_mode_lut);
for (unsigned int i = 0; i < count; ++i) {
const struct disp_mode_timing_type *cur =
- &supported_video_mode_lut[i];
+ &supported_video_mode_lut[i];
if (cur->video_format == ID)
mode = cur;
}
ioctl(fd, FBIOGET_VSCREENINFO, &info);
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
- "(%d,%d,%d) %dMHz>", __FUNCTION__,
- info.reserved[3], info.xres, info.yres,
- info.right_margin, info.hsync_len, info.left_margin,
- info.lower_margin, info.vsync_len, info.upper_margin,
- info.pixclock/1000/1000);
+ ALOGD_IF(DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
+ "(%d,%d,%d) %dMHz>", __FUNCTION__,
+ info.reserved[3], info.xres, info.yres,
+ info.right_margin, info.hsync_len, info.left_margin,
+ info.lower_margin, info.vsync_len, info.upper_margin,
+ info.pixclock/1000/1000);
mode->set_info(info);
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
- "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
- info.reserved[3], info.xres, info.yres,
- info.right_margin, info.hsync_len, info.left_margin,
- info.lower_margin, info.vsync_len, info.upper_margin,
- info.pixclock/1000/1000);
+ ALOGD_IF(DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
+ "(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
+ info.reserved[3], info.xres, info.yres,
+ info.right_margin, info.hsync_len, info.left_margin,
+ info.lower_margin, info.vsync_len, info.upper_margin,
+ info.pixclock/1000/1000);
info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
ioctl(fd, FBIOPUT_VSCREENINFO, &info);
mCurrentID = ID;
@@ -389,53 +319,61 @@
}
-int ExtDisplayObserver::getExternalDisplay() const
+int ExternalDisplay::getExternalDisplay() const
{
- return mExternalDisplay;
+ return mExternalDisplay;
}
-void ExtDisplayObserver::setExternalDisplayStatus(int connected)
+void ExternalDisplay::setExternalDisplayStatus(int connected)
{
hwc_context_t* ctx = mHwcContext;
if(ctx) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: status = %d", __FUNCTION__,
- connected);
+ ALOGD_IF(DEBUG, "%s: status = %d", __FUNCTION__,
+ connected);
+ if(connected) {
+ readResolution();
+ //Get the best mode and set
+ // TODO: DO NOT call this for WFD
+ setResolution(getBestMode());
+ } else {
+ close(fd);
+ }
// Store the external display
- mExternalDisplay = connected;//(external_display_type)value;
+ mExternalDisplay = connected;
//Invalidate
hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
if(!proc) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: HWC proc not registered",
- __FUNCTION__);
+ ALOGD_IF(DEBUG, "%s: HWC proc not registered",
+ __FUNCTION__);
} else {
/* Trigger redraw */
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Invalidate !!", __FUNCTION__);
+ ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__);
proc->invalidate(proc);
}
}
return;
}
-bool ExtDisplayObserver::writeHPDOption(int userOption) const
+bool ExternalDisplay::writeHPDOption(int userOption) const
{
bool ret = true;
int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0);
if (hdmiHPDFile < 0) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: state file '%s' not found : ret%d"
- "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
+ ALOGD_IF(DEBUG, "%s: state file '%s' not found : ret%d"
+ "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
ret = false;
} else {
int err = -1;
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: option = %d", __FUNCTION__,
- userOption);
+ ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__,
+ userOption);
if(userOption)
err = write(hdmiHPDFile, "1", 2);
else
err = write(hdmiHPDFile, "0" , 2);
if (err <= 0) {
- ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: file write failed '%s'",
- __FUNCTION__, SYSFS_HPD);
+ ALOGD_IF(DEBUG, "%s: file write failed '%s'",
+ __FUNCTION__, SYSFS_HPD);
ret = false;
}
close(hdmiHPDFile);
diff --git a/libhwcomposer/hwc_external.h b/libhwcomposer/hwc_external.h
new file mode 100644
index 0000000..9e5f455
--- /dev/null
+++ b/libhwcomposer/hwc_external.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HWC_EXTERNAL_DISPLAY_H
+#define HWC_EXTERNAL_DISPLAY_H
+
+struct hwc_context_t;
+
+namespace qhwc {
+
+class ExternalDisplay
+{
+ //Type of external display - OFF, HDMI, WFD
+ enum external_display_type {
+ EXT_TYPE_NONE,
+ EXT_TYPE_HDMI,
+ EXT_TYPE_WIFI
+ };
+
+ // Mirroring state
+ enum external_mirroring_state {
+ EXT_MIRRORING_OFF,
+ EXT_MIRRORING_ON,
+ };
+ public:
+ ExternalDisplay(hwc_context_t* ctx);
+ ~ExternalDisplay();
+ int getExternalDisplay() const;
+ void setExternalDisplayStatus(int connected);
+
+ private:
+ bool readResolution();
+ int parseResolution(char* edidStr, int* edidModes, int len);
+ void setResolution(int ID);
+ bool openFramebuffer();
+ bool writeHPDOption(int userOption) const;
+ bool isValidMode(int ID);
+ void handleUEvent(char* str, int len);
+ int getModeOrder(int mode);
+ int getBestMode();
+
+ int fd;
+ int mExternalDisplay;
+ int mCurrentID;
+ char mEDIDs[128];
+ int mEDIDModes[64];
+ int mModeCount;
+ hwc_context_t *mHwcContext;
+};
+
+}; //qhwc
+// ---------------------------------------------------------------------------
+#endif //HWC_EXTERNAL_DISPLAY_H
diff --git a/libhwcomposer/hwc_qbuf.h b/libhwcomposer/hwc_qbuf.h
index a0ade8c..6d75964 100644
--- a/libhwcomposer/hwc_qbuf.h
+++ b/libhwcomposer/hwc_qbuf.h
@@ -15,6 +15,9 @@
* limitations under the License.
*/
+#include <gralloc_priv.h>
+#include <genlock.h>
+
// -----------------------------------------------------------------------------
// QueuedBufferStore
//This class holds currently and previously queued buffers.
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
new file mode 100644
index 0000000..a1df74b
--- /dev/null
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are
+ * retained for attribution purposes only.
+
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define DEBUG 0
+#ifndef HWC_OBSERVER_H
+#define HWC_OBSERVER_H
+#include <hardware_legacy/uevent.h>
+#include <utils/Log.h>
+#include <sys/resource.h>
+#include <string.h>
+#include <stdlib.h>
+#include "hwc_utils.h"
+#include "hwc_external.h"
+
+namespace qhwc {
+
+const char* MSMFB_DEVICE_CHANGE = "change@/devices/virtual/graphics/fb0";
+const char* MSMFB_HDMI_NODE = "fb1";
+
+static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
+{
+ int vsync;
+ char* hdmi;
+ int64_t timestamp = 0;
+ const char *str = udata;
+ hwc_procs* proc = reinterpret_cast<hwc_procs*>(ctx->device.reserved_proc[0]);
+
+ vsync = !strncmp(str, MSMFB_DEVICE_CHANGE, strlen(MSMFB_DEVICE_CHANGE));
+ hdmi = strcasestr(str, MSMFB_HDMI_NODE);
+ if(!vsync && !hdmi)
+ return;
+ if(vsync) {
+ str += strlen(str) + 1;
+ while(*str) {
+ if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
+ timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
+ proc->vsync(proc, 0, timestamp);
+ }
+ str += strlen(str) + 1;
+ if(str - udata >= len)
+ break;
+ }
+ }
+
+ if(hdmi) {
+ // parse HDMI events
+ // The event will be of the form:
+ // change@/devices/virtual/graphics/fb1 ACTION=change
+ // DEVPATH=/devices/virtual/graphics/fb1
+ // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
+ // for now just parsing onlin/offline info is enough
+ str = udata;
+ int connected = 0;
+ if(!(strncmp(str,"online@",strlen("online@")))) {
+ connected = 1;
+ } else if(!(strncmp(str,"offline@",strlen("offline@")))) {
+ connected = 0;
+ }
+ ctx->mExtDisplay->setExternalDisplayStatus(connected);
+ }
+
+}
+
+static void *uevent_loop(void *param)
+{
+ int len = 0;
+ static char udata[4096];
+ memset(udata, 0, sizeof(udata));
+ hwc_context_t * ctx = reinterpret_cast<hwc_context_t *>(param);
+
+ setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+ uevent_init();
+
+ while(1) {
+ len = uevent_next_event(udata, sizeof(udata) - 2);
+ handle_uevent(ctx, udata, len);
+ }
+
+ return NULL;
+}
+
+void init_uevent_thread(hwc_context_t* ctx)
+{
+ pthread_t uevent_thread;
+ pthread_create(&uevent_thread, NULL, uevent_loop, (void*) ctx);
+}
+
+}; //namespace
+#endif //HWC_OBSERVER_H
diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp
index 4540be8..9cf91af 100644
--- a/libhwcomposer/hwc_uimirror.cpp
+++ b/libhwcomposer/hwc_uimirror.cpp
@@ -18,12 +18,14 @@
* limitations under the License.
*/
+#define HWC_UI_MIRROR 0
+#include <gralloc_priv.h>
+#include <fb_priv.h>
#include "hwc_uimirror.h"
-#include "hwc_ext_observer.h"
+#include "hwc_external.h"
namespace qhwc {
-#define HWC_UI_MIRROR 0
// Function to get the primary device orientation
// Loops thru the hardware layers and returns the orientation of the max.
@@ -59,7 +61,7 @@
sState = ovutils::OV_CLOSED;
sIsUiMirroringOn = false;
// If external display is connected
- if(ctx->mExtDisplayObserver->getExternalDisplay()) {
+ if(ctx->mExtDisplay->getExternalDisplay()) {
sState = ovutils::OV_UI_MIRROR;
configure(ctx, list);
}
@@ -73,7 +75,7 @@
overlay::Overlay& ov = *(ctx->mOverlay);
// Set overlay state
ov.setState(sState);
- framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
+ framebuffer_device_t *fbDev = ctx->mFbDev;
if(fbDev) {
private_module_t* m = reinterpret_cast<private_module_t*>(
fbDev->common.module);
@@ -143,7 +145,7 @@
overlay::Overlay& ov = *(ctx->mOverlay);
ovutils::eOverlayState state = ov.getState();
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
- framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
+ framebuffer_device_t *fbDev = ctx->mFbDev;
if(fbDev) {
private_module_t* m = reinterpret_cast<private_module_t*>(
fbDev->common.module);
diff --git a/libhwcomposer/hwc_uimirror.h b/libhwcomposer/hwc_uimirror.h
index af43848..98f7896 100644
--- a/libhwcomposer/hwc_uimirror.h
+++ b/libhwcomposer/hwc_uimirror.h
@@ -20,6 +20,7 @@
#ifndef HWC_UIMIRROR_H
#define HWC_UIMIRROR_H
#include "hwc_utils.h"
+#include "overlay.h"
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index ae5c526..870a758 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -15,26 +15,39 @@
* limitations under the License.
*/
+#include <overlay.h>
#include "hwc_utils.h"
#include "mdp_version.h"
#include "hwc_video.h"
-#include "hwc_ext_observer.h"
+#include "hwc_qbuf.h"
#include "hwc_copybit.h"
+#include "hwc_external.h"
+
namespace qhwc {
+
+// Opens Framebuffer device
+static void openFramebufferDevice(hwc_context_t *ctx)
+{
+ hw_module_t const *module;
+ if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
+ framebuffer_open(module, &(ctx->mFbDev));
+ }
+}
+
void initContext(hwc_context_t *ctx)
{
- //XXX: target specific initializations here
+ openFramebufferDevice(ctx);
ctx->mOverlay = overlay::Overlay::getInstance();
ctx->qbuf = new QueuedBufferStore();
ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
- ALOGI("MDP version: %d",ctx->mdpVersion);
-
- ctx->mExtDisplayObserver = ExtDisplayObserver::getInstance();
- ctx->mExtDisplayObserver->setHwcContext(ctx);
- ctx->mFbDevice = FbDevice::getInstance();
ctx->mCopybitEngine = CopybitEngine::getInstance();
- CopyBit::openEglLibAndGethandle();
+ ctx->mExtDisplay = new ExternalDisplay(ctx);
+
+ init_uevent_thread(ctx);
+
+ ALOGI("Initializing Qualcomm Hardware Composer");
+ ALOGI("MDP version: %d", ctx->mdpVersion);
}
void closeContext(hwc_context_t *ctx)
@@ -48,15 +61,25 @@
delete ctx->mCopybitEngine;
ctx->mCopybitEngine = NULL;
}
- if(ctx->mFbDevice) {
- delete ctx->mFbDevice;
- ctx->mFbDevice = NULL;
+
+ if(ctx->mFbDev) {
+ framebuffer_close(ctx->mFbDev);
+ ctx->mFbDev = NULL;
}
+
if(ctx->qbuf) {
delete ctx->qbuf;
ctx->qbuf = NULL;
}
- CopyBit::closeEglLib();
+
+ if(ctx->mExtDisplay) {
+ delete ctx->mExtDisplay;
+ ctx->mExtDisplay = NULL;
+ }
+
+
+ free(const_cast<hwc_methods_t *>(ctx->device.methods));
+
}
void dumpLayer(hwc_layer_t const* l)
@@ -163,33 +186,4 @@
}
}
-//FbDevice class functions
-FbDevice* FbDevice::sInstance = 0;;
-struct framebuffer_device_t* FbDevice::getFb() {
- return sFb;
-}
-
-FbDevice* FbDevice::getInstance() {
- if(sInstance == NULL)
- sInstance = new FbDevice();
- return sInstance;
-}
-
-FbDevice::FbDevice(){
- hw_module_t const *module;
- if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
- framebuffer_open(module, &sFb);
- } else {
- ALOGE("FATAL ERROR: framebuffer open failed.");
- }
-}
-FbDevice::~FbDevice()
-{
- if(sFb)
- {
- framebuffer_close(sFb);
- sFb = NULL;
- }
-}
-
};//namespace
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 0bf30c9..1e405f7 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -17,28 +17,26 @@
#ifndef HWC_UTILS_H
#define HWC_UTILS_H
-#include <cutils/log.h>
-#include <gralloc_priv.h>
+
#include <hardware/hwcomposer.h>
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fb_priv.h>
-#include <overlay.h>
-#include <copybit.h>
-#include <hwc_copybitEngine.h>
-#include <genlock.h>
-#include "hwc_qbuf.h"
-#include <EGL/egl.h>
+#include <gralloc_priv.h>
#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1))
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
#define FINAL_TRANSFORM_MASK 0x000F
+//Fwrd decls
struct hwc_context_t;
+struct framebuffer_device_t;
+
+namespace overlay {
+class Overlay;
+}
+
namespace qhwc {
+//fwrd decl
+class QueuedBufferStore;
enum external_display_type {
EXT_TYPE_NONE,
@@ -53,7 +51,8 @@
};
-class ExtDisplayObserver;
+class ExternalDisplay;
+class CopybitEngine;
// -----------------------------------------------------------------------------
// Utility functions - implemented in hwc_utils.cpp
void dumpLayer(hwc_layer_t const* l);
@@ -78,32 +77,12 @@
static inline bool isBufferLocked(const private_handle_t* hnd) {
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
}
-// -----------------------------------------------------------------------------
-// Copybit specific - inline or implemented in hwc_copybit.cpp
-typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
- EGLDisplay dpy,
- EGLSurface draw);
-typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
-// -----------------------------------------------------------------------------
-// Singleton for Framebuffer device
-class FbDevice{
-public:
- ~FbDevice();
- // API to get Fb device(non static)
- struct framebuffer_device_t *getFb();
- // API to get singleton
- static FbDevice* getInstance();
-
-private:
- FbDevice();
- struct framebuffer_device_t *sFb;
- static FbDevice* sInstance; // singleton
-};
+// Initialize uevent thread
+void init_uevent_thread(hwc_context_t* ctx);
}; //qhwc namespace
-
// -----------------------------------------------------------------------------
// HWC context
// This structure contains overall state
@@ -115,7 +94,7 @@
int overlayInUse;
//Framebuffer device
- qhwc::FbDevice* mFbDevice;
+ framebuffer_device_t *mFbDev;
//Copybit Engine
qhwc::CopybitEngine* mCopybitEngine;
@@ -127,7 +106,8 @@
qhwc::QueuedBufferStore *qbuf;
// External display related information
- qhwc::ExtDisplayObserver*mExtDisplayObserver;
+ qhwc::ExternalDisplay *mExtDisplay;
+
};
#endif //HWC_UTILS_H
diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 180ab86..190e31b 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -15,13 +15,15 @@
* limitations under the License.
*/
+#define VIDEO_DEBUG 0
+#include <overlay.h>
+#include "hwc_qbuf.h"
#include "hwc_video.h"
-#include "hwc_ext_observer.h"
+#include "hwc_external.h"
namespace qhwc {
#define FINAL_TRANSFORM_MASK 0x000F
-#define VIDEO_DEBUG 0
//Static Members
ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
@@ -62,12 +64,12 @@
//Support 1 video layer
if(sYuvCount == 1) {
//Skip on primary, display on ext.
- if(sIsLayerSkip && ctx->mExtDisplayObserver->getExternalDisplay()) {
+ if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
//TODO
//VIDEO_ON_TV_ONLY
} else if(sIsLayerSkip) { //skip on primary, no ext
newState = ovutils::OV_CLOSED;
- } else if(ctx->mExtDisplayObserver->getExternalDisplay()) {
+ } else if(ctx->mExtDisplay->getExternalDisplay()) {
//display on both
newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
} else { //display on primary only