summaryrefslogtreecommitdiff
path: root/moorefield_hdmi/common/base
diff options
context:
space:
mode:
authorGuilhem IMBERTON <guilhem.imberton@intel.com>2015-04-10 09:45:39 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-04-10 09:45:39 +0000
commit3f021f9136639ae37de057ac74e5bc74b37e0fd6 (patch)
treea5d415fbd762c72f5075adf4d9596292c9314004 /moorefield_hdmi/common/base
parentb6cd081e90a23a60aa6488f40c07f86fac5a48d6 (diff)
parent5094bbf4cbe9b244d79ce5ec52a9285978fff311 (diff)
downloadhwcomposer-3f021f9136639ae37de057ac74e5bc74b37e0fd6.tar.gz
am 5094bbf4: Moving Moorefield HWComposer in dedicated directory
* commit '5094bbf4cbe9b244d79ce5ec52a9285978fff311': Moving Moorefield HWComposer in dedicated directory
Diffstat (limited to 'moorefield_hdmi/common/base')
-rwxr-xr-xmoorefield_hdmi/common/base/DisplayAnalyzer.cpp141
-rwxr-xr-xmoorefield_hdmi/common/base/DisplayAnalyzer.h72
-rwxr-xr-xmoorefield_hdmi/common/base/Drm.cpp755
-rwxr-xr-xmoorefield_hdmi/common/base/Drm.h107
-rwxr-xr-xmoorefield_hdmi/common/base/HwcLayer.cpp347
-rw-r--r--moorefield_hdmi/common/base/HwcLayer.h122
-rwxr-xr-xmoorefield_hdmi/common/base/HwcLayerList.cpp1044
-rwxr-xr-xmoorefield_hdmi/common/base/HwcLayerList.h109
-rw-r--r--moorefield_hdmi/common/base/HwcModule.cpp313
-rwxr-xr-xmoorefield_hdmi/common/base/Hwcomposer.cpp519
-rw-r--r--moorefield_hdmi/common/base/SimpleThread.h38
11 files changed, 3567 insertions, 0 deletions
diff --git a/moorefield_hdmi/common/base/DisplayAnalyzer.cpp b/moorefield_hdmi/common/base/DisplayAnalyzer.cpp
new file mode 100755
index 0000000..7e5737f
--- /dev/null
+++ b/moorefield_hdmi/common/base/DisplayAnalyzer.cpp
@@ -0,0 +1,141 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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.
+*/
+
+#include <common/utils/HwcTrace.h>
+#include <Hwcomposer.h>
+#include <common/base/DisplayAnalyzer.h>
+
+namespace android {
+namespace intel {
+
+DisplayAnalyzer::DisplayAnalyzer()
+ : mInitialized(false),
+ mCachedNumDisplays(0),
+ mCachedDisplays(0),
+ mPendingEvents(),
+ mEventMutex()
+{
+}
+
+DisplayAnalyzer::~DisplayAnalyzer()
+{
+}
+
+bool DisplayAnalyzer::initialize()
+{
+ mCachedNumDisplays = 0;
+ mCachedDisplays = 0;
+ mPendingEvents.clear();
+ mInitialized = true;
+
+ return true;
+}
+
+void DisplayAnalyzer::deinitialize()
+{
+ mPendingEvents.clear();
+ mInitialized = false;
+}
+
+void DisplayAnalyzer::analyzeContents(
+ size_t numDisplays, hwc_display_contents_1_t** displays)
+{
+ // cache and use them only in this context during analysis
+ mCachedNumDisplays = numDisplays;
+ mCachedDisplays = displays;
+
+ handlePendingEvents();
+}
+
+void DisplayAnalyzer::postHotplugEvent(bool connected)
+{
+ // handle hotplug event (vsync switch) asynchronously
+ Event e;
+ e.type = HOTPLUG_EVENT;
+ e.bValue = connected;
+ postEvent(e);
+ Hwcomposer::getInstance().invalidate();
+}
+
+void DisplayAnalyzer::postEvent(Event& e)
+{
+ Mutex::Autolock lock(mEventMutex);
+ mPendingEvents.add(e);
+}
+
+bool DisplayAnalyzer::getEvent(Event& e)
+{
+ Mutex::Autolock lock(mEventMutex);
+ if (mPendingEvents.size() == 0) {
+ return false;
+ }
+ e = mPendingEvents[0];
+ mPendingEvents.removeAt(0);
+ return true;
+}
+
+void DisplayAnalyzer::handlePendingEvents()
+{
+ // handle one event per analysis to avoid blocking surface flinger
+ // some event may take lengthy time to process
+ Event e;
+ if (!getEvent(e)) {
+ return;
+ }
+
+ switch (e.type) {
+ case HOTPLUG_EVENT:
+ handleHotplugEvent(e.bValue);
+ break;
+ }
+}
+
+void DisplayAnalyzer::handleHotplugEvent(bool connected)
+{
+ if (connected) {
+ for (int i = 0; i < mCachedNumDisplays; i++) {
+ setCompositionType(i, HWC_FRAMEBUFFER, true);
+ }
+ }
+}
+
+void DisplayAnalyzer::setCompositionType(hwc_display_contents_1_t *display, int type)
+{
+ for (size_t i = 0; i < display->numHwLayers - 1; i++) {
+ hwc_layer_1_t *layer = &display->hwLayers[i];
+ if (layer) layer->compositionType = type;
+ }
+}
+
+void DisplayAnalyzer::setCompositionType(int device, int type, bool reset)
+{
+ hwc_display_contents_1_t *content = mCachedDisplays[device];
+ if (content == NULL) {
+ ELOGTRACE("Invalid device %d", device);
+ return;
+ }
+
+ // don't need to set geometry changed if layers are just needed to be marked
+ if (reset) {
+ content->flags |= HWC_GEOMETRY_CHANGED;
+ }
+
+ setCompositionType(content, type);
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/moorefield_hdmi/common/base/DisplayAnalyzer.h b/moorefield_hdmi/common/base/DisplayAnalyzer.h
new file mode 100755
index 0000000..239cd0a
--- /dev/null
+++ b/moorefield_hdmi/common/base/DisplayAnalyzer.h
@@ -0,0 +1,72 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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 DISPLAY_ANALYZER_H
+#define DISPLAY_ANALYZER_H
+
+#include <utils/threads.h>
+#include <utils/Vector.h>
+
+
+namespace android {
+namespace intel {
+
+
+class DisplayAnalyzer {
+public:
+ DisplayAnalyzer();
+ virtual ~DisplayAnalyzer();
+
+public:
+ bool initialize();
+ void deinitialize();
+ void analyzeContents(size_t numDisplays, hwc_display_contents_1_t** displays);
+ void postHotplugEvent(bool connected);
+
+private:
+ enum DisplayEventType {
+ HOTPLUG_EVENT,
+ };
+
+ struct Event {
+ int type;
+
+ union {
+ bool bValue;
+ int nValue;
+ };
+ };
+ inline void postEvent(Event& e);
+ inline bool getEvent(Event& e);
+ void handlePendingEvents();
+ void handleHotplugEvent(bool connected);
+ inline void setCompositionType(hwc_display_contents_1_t *content, int type);
+ inline void setCompositionType(int device, int type, bool reset);
+
+
+private:
+ bool mInitialized;
+ int mCachedNumDisplays;
+ hwc_display_contents_1_t** mCachedDisplays;
+ Vector<Event> mPendingEvents;
+ Mutex mEventMutex;
+};
+
+} // namespace intel
+} // namespace android
+
+
+
+#endif /* DISPLAY_ANALYZER_H */
diff --git a/moorefield_hdmi/common/base/Drm.cpp b/moorefield_hdmi/common/base/Drm.cpp
new file mode 100755
index 0000000..007d308
--- /dev/null
+++ b/moorefield_hdmi/common/base/Drm.cpp
@@ -0,0 +1,755 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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.
+*/
+#include <fcntl.h>
+#include <errno.h>
+#include <common/utils/HwcTrace.h>
+#include <IDisplayDevice.h>
+#include <DrmConfig.h>
+#include <common/base/Drm.h>
+#include <Hwcomposer.h>
+
+namespace android {
+namespace intel {
+
+Drm::Drm()
+ : mDrmFd(0),
+ mLock(),
+ mInitialized(false)
+{
+ memset(&mOutputs, 0, sizeof(mOutputs));
+}
+
+Drm::~Drm()
+{
+ WARN_IF_NOT_DEINIT();
+}
+
+bool Drm::initialize()
+{
+ if (mInitialized) {
+ WLOGTRACE("Drm object has been initialized");
+ return true;
+ }
+
+ const char *path = DrmConfig::getDrmPath();
+ mDrmFd = open(path, O_RDWR, 0);
+ if (mDrmFd < 0) {
+ ELOGTRACE("failed to open Drm, error: %s", strerror(errno));
+ return false;
+ }
+ DLOGTRACE("mDrmFd = %d", mDrmFd);
+
+ memset(&mOutputs, 0, sizeof(mOutputs));
+ mInitialized = true;
+ return true;
+}
+
+void Drm::deinitialize()
+{
+ for (int i = 0; i < OUTPUT_MAX; i++) {
+ resetOutput(i);
+ }
+
+ if (mDrmFd) {
+ close(mDrmFd);
+ mDrmFd = 0;
+ }
+ mInitialized = false;
+}
+
+bool Drm::detect(int device)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ Mutex::Autolock _l(mLock);
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0 ) {
+ return false;
+ }
+
+ resetOutput(outputIndex);
+
+ // get drm resources
+ drmModeResPtr resources = drmModeGetResources(mDrmFd);
+ if (!resources) {
+ ELOGTRACE("fail to get drm resources, error: %s", strerror(errno));
+ return false;
+ }
+
+ drmModeConnectorPtr connector = NULL;
+ DrmOutput *output = &mOutputs[outputIndex];
+ bool ret = false;
+
+ // find connector for the given device
+ for (int i = 0; i < resources->count_connectors; i++) {
+ if (!resources->connectors || !resources->connectors[i]) {
+ ELOGTRACE("fail to get drm resources connectors, error: %s", strerror(errno));
+ continue;
+ }
+
+ connector = drmModeGetConnector(mDrmFd, resources->connectors[i]);
+ if (!connector) {
+ ELOGTRACE("drmModeGetConnector failed");
+ continue;
+ }
+
+ if (connector->connector_type != DrmConfig::getDrmConnector(device)) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ if (connector->connection != DRM_MODE_CONNECTED) {
+ ILOGTRACE("device %d is not connected", device);
+ drmModeFreeConnector(connector);
+ ret = true;
+ break;
+ }
+
+ output->connector = connector;
+ output->connected = true;
+
+ // get proper encoder for the given connector
+ if (connector->encoder_id) {
+ ILOGTRACE("Drm connector has encoder attached on device %d", device);
+ output->encoder = drmModeGetEncoder(mDrmFd, connector->encoder_id);
+ if (!output->encoder) {
+ ELOGTRACE("failed to get encoder from a known encoder id");
+ // fall through to get an encoder
+ }
+ }
+ if (!output->encoder) {
+ ILOGTRACE("getting encoder for device %d", device);
+ drmModeEncoderPtr encoder;
+ for (int j = 0; j < resources->count_encoders; j++) {
+ if (!resources->encoders || !resources->encoders[j]) {
+ ELOGTRACE("fail to get drm resources encoders, error: %s", strerror(errno));
+ continue;
+ }
+
+ encoder = drmModeGetEncoder(mDrmFd, resources->encoders[i]);
+ if (!encoder) {
+ ELOGTRACE("drmModeGetEncoder failed");
+ continue;
+ }
+ if (encoder->encoder_type == DrmConfig::getDrmEncoder(device)) {
+ output->encoder = encoder;
+ break;
+ }
+ drmModeFreeEncoder(encoder);
+ encoder = NULL;
+ }
+ }
+ if (!output->encoder) {
+ ELOGTRACE("failed to get drm encoder");
+ break;
+ }
+
+ // get an attached crtc or spare crtc
+ if (output->encoder->crtc_id) {
+ ILOGTRACE("Drm encoder has crtc attached on device %d", device);
+ output->crtc = drmModeGetCrtc(mDrmFd, output->encoder->crtc_id);
+ if (!output->crtc) {
+ ELOGTRACE("failed to get crtc from a known crtc id");
+ // fall through to get a spare crtc
+ }
+ }
+ if (!output->crtc) {
+ ILOGTRACE("getting crtc for device %d", device);
+ drmModeCrtcPtr crtc;
+ for (int j = 0; j < resources->count_crtcs; j++) {
+ if (!resources->crtcs || !resources->crtcs[j]) {
+ ELOGTRACE("fail to get drm resources crtcs, error: %s", strerror(errno));
+ continue;
+ }
+
+ crtc = drmModeGetCrtc(mDrmFd, resources->crtcs[j]);
+ if (!crtc) {
+ ELOGTRACE("drmModeGetCrtc failed");
+ continue;
+ }
+ // check if legal crtc to the encoder
+ if (output->encoder->possible_crtcs & (1<<j)) {
+ if (crtc->buffer_id == 0) {
+ output->crtc = crtc;
+ break;
+ }
+ }
+ drmModeFreeCrtc(crtc);
+ }
+ }
+ if (!output->crtc) {
+ ELOGTRACE("failed to get drm crtc");
+ break;
+ }
+
+ // current mode
+ if (output->crtc->mode_valid) {
+ ILOGTRACE("mode is valid, kernel mode settings");
+ memcpy(&output->mode, &output->crtc->mode, sizeof(drmModeModeInfo));
+ ret = true;
+ } else {
+ ELOGTRACE("mode is invalid. Kernel mode setting is not completed");
+ ret = false;
+ }
+
+ if (outputIndex == OUTPUT_PRIMARY) {
+ if (!readIoctl(DRM_PSB_PANEL_ORIENTATION, &output->panelOrientation, sizeof(int))) {
+ ELOGTRACE("failed to get device %d orientation", device);
+ output->panelOrientation = PANEL_ORIENTATION_0;
+ }
+ } else {
+ output->panelOrientation = PANEL_ORIENTATION_0;
+ }
+ break;
+ }
+
+ if (!ret) {
+ if (output->connector == NULL && outputIndex != OUTPUT_PRIMARY) {
+ // a fatal failure on primary device
+ // non fatal on secondary device
+ WLOGTRACE("device %d is disabled?", device);
+ ret = true;
+ }
+ resetOutput(outputIndex);
+ } else if (output->connected) {
+ ILOGTRACE("mode is: %dx%d@%dHz", output->mode.hdisplay, output->mode.vdisplay, output->mode.vrefresh);
+ }
+
+ drmModeFreeResources(resources);
+ return ret;
+}
+
+bool Drm::isSameDrmMode(drmModeModeInfoPtr value,
+ drmModeModeInfoPtr base) const
+{
+ if (base->hdisplay == value->hdisplay &&
+ base->vdisplay == value->vdisplay &&
+ base->vrefresh == value->vrefresh &&
+ (base->flags & value->flags) == value->flags) {
+ VLOGTRACE("Drm mode is not changed");
+ return true;
+ }
+
+ return false;
+}
+
+bool Drm::setDrmMode(int device, drmModeModeInfo& value)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ Mutex::Autolock _l(mLock);
+
+ if (device != IDisplayDevice::DEVICE_EXTERNAL) {
+ WLOGTRACE("Setting mode on invalid device %d", device);
+ return false;
+ }
+
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0 ) {
+ ELOGTRACE("invalid device");
+ return false;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (!output->connected) {
+ ELOGTRACE("device is not connected");
+ return false;
+ }
+
+ if (output->connector->count_modes <= 0) {
+ ELOGTRACE("invalid count of modes");
+ return false;
+ }
+
+ drmModeModeInfoPtr mode;
+ int index = 0;
+ for (int i = 0; i < output->connector->count_modes; i++) {
+ mode = &output->connector->modes[i];
+ if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+ index = i;
+ }
+ if (isSameDrmMode(&value, mode)) {
+ index = i;
+ break;
+ }
+ }
+
+ mode = &output->connector->modes[index];
+ return setDrmMode(outputIndex, mode);
+}
+
+bool Drm::setRefreshRate(int device, int hz)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ Mutex::Autolock _l(mLock);
+
+ if (device != IDisplayDevice::DEVICE_EXTERNAL) {
+ WLOGTRACE("Setting mode on invalid device %d", device);
+ return false;
+ }
+
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0 ) {
+ ELOGTRACE("invalid device");
+ return false;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (!output->connected) {
+ ELOGTRACE("device is not connected");
+ return false;
+ }
+
+ if (output->connector->count_modes <= 0) {
+ ELOGTRACE("invalid count of modes");
+ return false;
+ }
+
+ drmModeModeInfoPtr mode;
+ int index = 0;
+ for (int i = 0; i < output->connector->count_modes; i++) {
+ mode = &output->connector->modes[i];
+ if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+ index = i;
+ }
+ if (mode->hdisplay == output->mode.hdisplay &&
+ mode->vdisplay == output->mode.vdisplay &&
+ mode->vrefresh == (uint32_t)hz) {
+ index = i;
+ break;
+ }
+ }
+
+ mode = &output->connector->modes[index];
+ return setDrmMode(outputIndex, mode);
+}
+
+bool Drm::writeReadIoctl(unsigned long cmd, void *data,
+ unsigned long size)
+{
+ int err;
+
+ if (mDrmFd <= 0) {
+ ELOGTRACE("drm is not initialized");
+ return false;
+ }
+
+ if (!data || !size) {
+ ELOGTRACE("invalid parameters");
+ return false;
+ }
+
+ err = drmCommandWriteRead(mDrmFd, cmd, data, size);
+ if (err) {
+ WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
+ return false;
+ }
+
+ return true;
+}
+
+bool Drm::writeIoctl(unsigned long cmd, void *data,
+ unsigned long size)
+{
+ int err;
+
+ if (mDrmFd <= 0) {
+ ELOGTRACE("drm is not initialized");
+ return false;
+ }
+
+ if (!data || !size) {
+ ELOGTRACE("invalid parameters");
+ return false;
+ }
+
+ err = drmCommandWrite(mDrmFd, cmd, data, size);
+ if (err) {
+ WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool Drm::readIoctl(unsigned long cmd, void *data,
+ unsigned long size)
+{
+ int err;
+
+ if (mDrmFd <= 0) {
+ ELOGTRACE("drm is not initialized");
+ return false;
+ }
+
+ if (!data || !size) {
+ ELOGTRACE("invalid parameters");
+ return false;
+ }
+
+ err = drmCommandRead(mDrmFd, cmd, data, size);
+ if (err) {
+ WLOGTRACE("failed to call %ld ioctl with failure %d", cmd, err);
+ return false;
+ }
+
+ return true;
+}
+
+
+int Drm::getDrmFd() const
+{
+ return mDrmFd;
+}
+
+bool Drm::getModeInfo(int device, drmModeModeInfo& mode)
+{
+ Mutex::Autolock _l(mLock);
+
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0 ) {
+ return false;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (output->connected == false) {
+ ELOGTRACE("device is not connected");
+ return false;
+ }
+
+ if (output->mode.hdisplay == 0 || output->mode.vdisplay == 0) {
+ ELOGTRACE("invalid width or height");
+ return false;
+ }
+
+ memcpy(&mode, &output->mode, sizeof(drmModeModeInfo));
+
+#ifdef INTEL_SUPPORT_HDMI_PRIMARY
+ // FIXME: use default fb size instead of hdmi mode, because to
+ // support hdmi primary, we cannot report dynamic mode to SF.
+ mode.hdisplay = DEFAULT_DRM_FB_WIDTH;
+ mode.vdisplay = DEFAULT_DRM_FB_HEIGHT;
+#endif
+
+ return true;
+}
+
+bool Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height)
+{
+ Mutex::Autolock _l(mLock);
+
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0 ) {
+ return false;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (output->connected == false) {
+ ELOGTRACE("device is not connected");
+ return false;
+ }
+
+ width = output->connector->mmWidth;
+ height = output->connector->mmHeight;
+ return true;
+}
+
+bool Drm::getDisplayResolution(int device, uint32_t& width, uint32_t& height)
+{
+ Mutex::Autolock _l(mLock);
+
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0) {
+ return false;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (output->connected == false) {
+ ELOGTRACE("device is not connected");
+ return false;
+ }
+
+ width = output->mode.hdisplay;
+ height = output->mode.vdisplay;
+
+ if (!width || !height) {
+ ELOGTRACE("invalid width or height");
+ return false;
+ }
+ return true;
+}
+
+bool Drm::isConnected(int device)
+{
+ Mutex::Autolock _l(mLock);
+
+ int output = getOutputIndex(device);
+ if (output < 0 ) {
+ return false;
+ }
+
+ return mOutputs[output].connected;
+}
+
+bool Drm::setDpmsMode(int device, int mode)
+{
+ Mutex::Autolock _l(mLock);
+
+ int output = getOutputIndex(device);
+ if (output < 0 ) {
+ return false;
+ }
+
+ if (mode != IDisplayDevice::DEVICE_DISPLAY_OFF &&
+ mode != IDisplayDevice::DEVICE_DISPLAY_STANDBY &&
+ mode != IDisplayDevice::DEVICE_DISPLAY_ON) {
+ ELOGTRACE("invalid mode %d", mode);
+ return false;
+ }
+
+ DrmOutput *out = &mOutputs[output];
+ if (!out->connected) {
+ ELOGTRACE("device is not connected");
+ return false;
+ }
+
+ drmModePropertyPtr props;
+ for (int i = 0; i < out->connector->count_props; i++) {
+ props = drmModeGetProperty(mDrmFd, out->connector->props[i]);
+ if (!props) {
+ continue;
+ }
+
+ if (strcmp(props->name, "DPMS") == 0) {
+ int ret = drmModeConnectorSetProperty(
+ mDrmFd,
+ out->connector->connector_id,
+ props->prop_id,
+ (mode == IDisplayDevice::DEVICE_DISPLAY_ON) ? DRM_MODE_DPMS_ON :
+ IDisplayDevice::DEVICE_DISPLAY_STANDBY == mode ?
+ DRM_MODE_DPMS_STANDBY : DRM_MODE_DPMS_OFF);
+ drmModeFreeProperty(props);
+ if (ret != 0) {
+ ELOGTRACE("unable to set DPMS %d", mode);
+ return false;
+ } else {
+ return true;
+ }
+ }
+ drmModeFreeProperty(props);
+ }
+ return false;
+}
+
+void Drm::resetOutput(int index)
+{
+ DrmOutput *output = &mOutputs[index];
+
+ output->connected = false;
+ memset(&output->mode, 0, sizeof(drmModeModeInfo));
+
+ if (output->connector) {
+ drmModeFreeConnector(output->connector);
+ output->connector = 0;
+ }
+ if (output->encoder) {
+ drmModeFreeEncoder(output->encoder);
+ output->encoder = 0;
+ }
+ if (output->crtc) {
+ drmModeFreeCrtc(output->crtc);
+ output->crtc = 0;
+ }
+ if (output->fbId) {
+ drmModeRmFB(mDrmFd, output->fbId);
+ output->fbId = 0;
+ }
+ if (output->fbHandle) {
+ Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(output->fbHandle);
+ output->fbHandle = 0;
+ }
+}
+
+bool Drm::initDrmMode(int outputIndex)
+{
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (output->connector->count_modes <= 0) {
+ ELOGTRACE("invalid count of modes");
+ return false;
+ }
+
+ drmModeModeInfoPtr mode;
+ int index = 0;
+ for (int i = 0; i < output->connector->count_modes; i++) {
+ mode = &output->connector->modes[i];
+ if (mode->type & DRM_MODE_TYPE_PREFERRED) {
+ index = i;
+ break;
+ }
+ }
+
+ return setDrmMode(outputIndex, &output->connector->modes[index]);
+}
+
+bool Drm::setDrmMode(int index, drmModeModeInfoPtr mode)
+{
+ DrmOutput *output = &mOutputs[index];
+
+ int oldFbId =0;
+ int oldFbHandle = 0;
+
+ drmModeModeInfo currentMode;
+ memcpy(&currentMode, &output->mode, sizeof(drmModeModeInfo));
+
+ if (isSameDrmMode(mode, &currentMode))
+ return true;
+
+
+ if (output->fbId) {
+ oldFbId = output->fbId ;
+ output->fbId = 0;
+ }
+
+ if (output->fbHandle) {
+ oldFbHandle = output->fbHandle;
+ output->fbHandle = 0;
+ }
+
+ // allocate frame buffer
+ int stride = 0;
+#ifdef INTEL_SUPPORT_HDMI_PRIMARY
+ output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
+ DEFAULT_DRM_FB_WIDTH, DEFAULT_DRM_FB_HEIGHT, &stride);
+#else
+ output->fbHandle = Hwcomposer::getInstance().getBufferManager()->allocFrameBuffer(
+ mode->hdisplay, mode->vdisplay, &stride);
+#endif
+ if (output->fbHandle == 0) {
+ ELOGTRACE("failed to allocate frame buffer");
+ return false;
+ }
+
+ int ret = 0;
+ ret = drmModeAddFB(
+ mDrmFd,
+#ifdef INTEL_SUPPORT_HDMI_PRIMARY
+ DEFAULT_DRM_FB_WIDTH,
+ DEFAULT_DRM_FB_HEIGHT,
+#else
+ mode->hdisplay,
+ mode->vdisplay,
+#endif
+ DrmConfig::getFrameBufferDepth(),
+ DrmConfig::getFrameBufferBpp(),
+ stride,
+ output->fbHandle,
+ &output->fbId);
+ if (ret != 0) {
+ ELOGTRACE("drmModeAddFB failed, error: %d", ret);
+ return false;
+ }
+
+ ILOGTRACE("mode set: %dx%d@%dHz", mode->hdisplay, mode->vdisplay, mode->vrefresh);
+
+ ret = drmModeSetCrtc(mDrmFd, output->crtc->crtc_id, output->fbId, 0, 0,
+ &output->connector->connector_id, 1, mode);
+ if (ret == 0) {
+ //save mode
+ memcpy(&output->mode, mode, sizeof(drmModeModeInfo));
+ } else {
+ ELOGTRACE("drmModeSetCrtc failed. error: %d", ret);
+ }
+
+ if (oldFbId) {
+ drmModeRmFB(mDrmFd, oldFbId);
+ }
+
+ if (oldFbHandle) {
+ Hwcomposer::getInstance().getBufferManager()->freeFrameBuffer(oldFbHandle);
+ }
+
+ return ret == 0;
+}
+
+int Drm::getOutputIndex(int device)
+{
+ switch (device) {
+ case IDisplayDevice::DEVICE_PRIMARY:
+ return OUTPUT_PRIMARY;
+ case IDisplayDevice::DEVICE_EXTERNAL:
+ return OUTPUT_EXTERNAL;
+ default:
+ ELOGTRACE("invalid display device");
+ break;
+ }
+
+ return -1;
+}
+
+int Drm::getPanelOrientation(int device)
+{
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0) {
+ ELOGTRACE("invalid device");
+ return PANEL_ORIENTATION_0;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (output->connected == false) {
+ ELOGTRACE("device is not connected");
+ return PANEL_ORIENTATION_0;
+ }
+
+ return output->panelOrientation;
+}
+
+// HWC 1.4 requires that we return all of the compatible configs in getDisplayConfigs
+// this is needed so getActiveConfig/setActiveConfig work correctly. It is up to the
+// user space to decide what speed to send.
+drmModeModeInfoPtr Drm::detectAllConfigs(int device, int *modeCount)
+{
+ RETURN_NULL_IF_NOT_INIT();
+ Mutex::Autolock _l(mLock);
+
+ if (modeCount != NULL)
+ *modeCount = 0;
+ else
+ return NULL;
+
+ int outputIndex = getOutputIndex(device);
+ if (outputIndex < 0) {
+ ELOGTRACE("invalid device");
+ return NULL;
+ }
+
+ DrmOutput *output= &mOutputs[outputIndex];
+ if (!output->connected) {
+ ELOGTRACE("device is not connected");
+ return NULL;
+ }
+
+ if (output->connector->count_modes <= 0) {
+ ELOGTRACE("invalid count of modes");
+ return NULL;
+ }
+
+ *modeCount = output->connector->count_modes;
+ return output->connector->modes;
+}
+
+} // namespace intel
+} // namespace android
+
diff --git a/moorefield_hdmi/common/base/Drm.h b/moorefield_hdmi/common/base/Drm.h
new file mode 100755
index 0000000..ff77ffd
--- /dev/null
+++ b/moorefield_hdmi/common/base/Drm.h
@@ -0,0 +1,107 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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 __DRM_H__
+#define __DRM_H__
+
+#include <utils/Mutex.h>
+#include <linux/psb_drm.h>
+
+extern "C" {
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+}
+
+namespace android {
+namespace intel {
+
+enum {
+ PANEL_ORIENTATION_0 = 0,
+ PANEL_ORIENTATION_180
+};
+
+#ifdef INTEL_SUPPORT_HDMI_PRIMARY
+enum {
+ DEFAULT_DRM_FB_WIDTH = 1920,
+ DEFAULT_DRM_FB_HEIGHT = 1080,
+};
+#endif
+
+class Drm {
+public:
+ Drm();
+ virtual ~Drm();
+public:
+ bool initialize();
+ void deinitialize();
+ bool detect(int device);
+ bool setDrmMode(int device, drmModeModeInfo& value);
+ bool setRefreshRate(int device, int hz);
+ bool writeReadIoctl(unsigned long cmd, void *data,
+ unsigned long size);
+ bool writeIoctl(unsigned long cmd, void *data,
+ unsigned long size);
+ bool readIoctl(unsigned long cmd, void *data,
+ unsigned long size);
+
+ bool isConnected(int device);
+ bool setDpmsMode(int device, int mode);
+ int getDrmFd() const;
+ bool getModeInfo(int device, drmModeModeInfo& mode);
+ bool getPhysicalSize(int device, uint32_t& width, uint32_t& height);
+ bool getDisplayResolution(int device, uint32_t& width, uint32_t& height);
+ bool isSameDrmMode(drmModeModeInfoPtr mode, drmModeModeInfoPtr base) const;
+ int getPanelOrientation(int device);
+
+ drmModeModeInfoPtr detectAllConfigs(int device, int *modeCount);
+
+private:
+ bool initDrmMode(int index);
+ bool setDrmMode(int index, drmModeModeInfoPtr mode);
+ void resetOutput(int index);
+
+ // map device type to output index, return -1 if not mapped
+ inline int getOutputIndex(int device);
+
+private:
+ // DRM object index
+ enum {
+ OUTPUT_PRIMARY = 0,
+ OUTPUT_EXTERNAL,
+ OUTPUT_MAX,
+ };
+
+ struct DrmOutput {
+ drmModeConnectorPtr connector;
+ drmModeEncoderPtr encoder;
+ drmModeCrtcPtr crtc;
+ drmModeModeInfo mode;
+ uint32_t fbHandle;
+ uint32_t fbId;
+ int connected;
+ int panelOrientation;
+ } mOutputs[OUTPUT_MAX];
+
+ int mDrmFd;
+ Mutex mLock;
+ bool mInitialized;
+};
+
+} // namespace intel
+} // namespace android
+
+
+
+#endif /* __DRM_H__ */
diff --git a/moorefield_hdmi/common/base/HwcLayer.cpp b/moorefield_hdmi/common/base/HwcLayer.cpp
new file mode 100755
index 0000000..554fb93
--- /dev/null
+++ b/moorefield_hdmi/common/base/HwcLayer.cpp
@@ -0,0 +1,347 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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.
+*/
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <common/base/HwcLayer.h>
+#include <Hwcomposer.h>
+#include <GraphicBuffer.h>
+#include <IDisplayDevice.h>
+#include <DisplayQuery.h>
+#include <PlaneCapabilities.h>
+
+
+namespace android {
+namespace intel {
+
+inline bool operator==(const hwc_rect_t& x, const hwc_rect_t& y)
+{
+ return (x.top == y.top &&
+ x.bottom == y.bottom &&
+ x.left == y.left &&
+ x.right == y.right);
+}
+
+inline bool operator !=(const hwc_rect_t& x, const hwc_rect_t& y)
+{
+ return !operator==(x, y);
+}
+
+inline bool operator ==(const hwc_frect_t& x, const hwc_frect_t& y)
+{
+ return (x.top == y.top &&
+ x.bottom == y.bottom &&
+ x.left == y.left &&
+ x.right == y.right);
+}
+
+inline bool operator !=(const hwc_frect_t& x, const hwc_frect_t& y)
+{
+ return !operator==(x, y);
+}
+
+HwcLayer::HwcLayer(int index, hwc_layer_1_t *layer)
+ : mIndex(index),
+ mZOrder(index + 1), // 0 is reserved for frame buffer target
+ mDevice(0),
+ mLayer(layer),
+ mPlane(0),
+ mFormat(DataBuffer::FORMAT_INVALID),
+ mWidth(0),
+ mHeight(0),
+ mUsage(0),
+ mHandle(0),
+ mIsProtected(false),
+ mType(LAYER_FB),
+ mPriority(0),
+ mTransform(0),
+ mUpdated(false)
+{
+ memset(&mSourceCropf, 0, sizeof(mSourceCropf));
+ memset(&mDisplayFrame, 0, sizeof(mDisplayFrame));
+ memset(&mStride, 0, sizeof(mStride));
+
+ mPlaneCandidate = false;
+ setupAttributes();
+}
+
+HwcLayer::~HwcLayer()
+{
+ if (mPlane) {
+ WLOGTRACE("HwcLayer is not cleaned up");
+ }
+
+ mLayer = NULL;
+ mPlane = NULL;
+}
+
+bool HwcLayer::attachPlane(DisplayPlane* plane, int device)
+{
+ if (mPlane) {
+ ELOGTRACE("failed to attach plane, plane exists");
+ return false;
+ }
+
+ if (!plane) {
+ ELOGTRACE("Invalid plane");
+ return false;
+ }
+
+ mDevice = device;
+ //plane->setZOrder(mIndex);
+ plane->assignToDevice(device);
+ mPlane = plane;
+ return true;
+}
+
+DisplayPlane* HwcLayer::detachPlane()
+{
+ // reset plane's z order
+ if (mPlane)
+ mPlane->setZOrder(-1);
+ DisplayPlane *plane = mPlane;
+ mPlane = 0;
+ mDevice = 0;
+ return plane;
+}
+
+void HwcLayer::setType(uint32_t type)
+{
+ if (!mLayer)
+ return;
+
+ switch (type) {
+ case LAYER_OVERLAY:
+ case LAYER_SKIPPED:
+ mLayer->compositionType = HWC_OVERLAY;
+ mLayer->hints |= HWC_HINT_CLEAR_FB;
+ break;
+ // NOTE: set compositionType to HWC_FRAMEBUFFER here so that we have
+ // a chance to submit the primary changes to HW.
+ // Upper layer HWComposer will reset the compositionType automatically.
+ case LAYER_FB:
+ case LAYER_FORCE_FB:
+ mLayer->compositionType = HWC_FRAMEBUFFER;
+ break;
+ case LAYER_SIDEBAND:
+ mLayer->compositionType = HWC_SIDEBAND;
+ break;
+ case LAYER_CURSOR_OVERLAY:
+ mLayer->compositionType = HWC_CURSOR_OVERLAY;
+ break;
+ default:
+ break;
+ }
+
+ mType = type;
+}
+
+uint32_t HwcLayer::getType() const
+{
+ return mType;
+}
+
+void HwcLayer::setCompositionType(int32_t type)
+{
+ mLayer->compositionType = type;
+}
+
+int32_t HwcLayer::getCompositionType() const
+{
+ return mLayer->compositionType;
+}
+
+int HwcLayer::getIndex() const
+{
+ return mIndex;
+}
+
+int HwcLayer::getZOrder() const
+{
+ return mZOrder;
+}
+
+uint32_t HwcLayer::getFormat() const
+{
+ return mFormat;
+}
+
+uint32_t HwcLayer::getBufferWidth() const
+{
+ return mWidth;
+}
+
+uint32_t HwcLayer::getBufferHeight() const
+{
+ return mHeight;
+}
+
+const stride_t& HwcLayer::getBufferStride() const
+{
+ return mStride;
+}
+
+uint32_t HwcLayer::getUsage() const
+{
+ return mUsage;
+}
+
+uint32_t HwcLayer::getHandle() const
+{
+ return mHandle;
+}
+
+uint32_t HwcLayer::getTransform() const
+{
+ return mTransform;
+}
+
+bool HwcLayer::isProtected() const
+{
+ return mIsProtected;
+}
+
+hwc_layer_1_t* HwcLayer::getLayer() const
+{
+ return mLayer;
+}
+
+DisplayPlane* HwcLayer::getPlane() const
+{
+ return mPlane;
+}
+
+void HwcLayer::setPriority(uint32_t priority)
+{
+ mPriority = priority;
+}
+
+uint32_t HwcLayer::getPriority() const
+{
+ return mPriority;
+}
+
+bool HwcLayer::update(hwc_layer_1_t *layer)
+{
+ // update layer
+ mLayer = layer;
+ setupAttributes();
+
+ // if not a FB layer & a plane was attached update plane's data buffer
+ if (mPlane) {
+ mPlane->setPosition(layer->displayFrame.left,
+ layer->displayFrame.top,
+ layer->displayFrame.right - layer->displayFrame.left,
+ layer->displayFrame.bottom - layer->displayFrame.top);
+ mPlane->setSourceCrop(layer->sourceCropf.left,
+ layer->sourceCropf.top,
+ layer->sourceCropf.right - layer->sourceCropf.left,
+ layer->sourceCropf.bottom - layer->sourceCropf.top);
+ mPlane->setTransform(layer->transform);
+ mPlane->setPlaneAlpha(layer->planeAlpha, layer->blending);
+ bool ret = mPlane->setDataBuffer((uint32_t)layer->handle);
+ if (ret == true) {
+ return true;
+ }
+ DLOGTRACE("failed to set data buffer, reset handle to 0!!");
+ mHandle = 0;
+ if (!mIsProtected) {
+ // typical case: rotated buffer is not ready or handle is null
+ return false;
+ } else {
+ // protected video has to be rendered using overlay.
+ // if buffer is not ready overlay will still be attached to this layer
+ // but rendering needs to be skipped.
+ WLOGTRACE("ignoring result of data buffer setting for protected video");
+ return true;
+ }
+ }
+
+ return true;
+}
+
+bool HwcLayer::isUpdated()
+{
+ return mUpdated;
+}
+
+void HwcLayer::postFlip()
+{
+ mUpdated = false;
+ if (mPlane) {
+ mPlane->postFlip();
+ }
+}
+
+void HwcLayer::setupAttributes()
+{
+ if ((mLayer->flags & HWC_SKIP_LAYER) ||
+ mTransform != mLayer->transform ||
+ mSourceCropf != mLayer->sourceCropf ||
+ mDisplayFrame != mLayer->displayFrame ||
+ mHandle != (uint32_t)mLayer->handle ||
+ DisplayQuery::isVideoFormat(mFormat)) {
+ // TODO: same handle does not mean there is always no update
+ mUpdated = true;
+ }
+
+ // update handle always as it can become "NULL"
+ // if the given layer is not ready
+ mTransform = mLayer->transform;
+ mSourceCropf = mLayer->sourceCropf;
+ mDisplayFrame = mLayer->displayFrame;
+ mHandle = (uint32_t)mLayer->handle;
+
+ if (mFormat != DataBuffer::FORMAT_INVALID) {
+ // other attributes have been set.
+ return;
+ }
+
+ if (mLayer->handle == NULL) {
+ VLOGTRACE("invalid handle");
+ return;
+ }
+
+ BufferManager *bm = Hwcomposer::getInstance().getBufferManager();
+ if (bm == NULL) {
+ // TODO: this check is redundant
+ return;
+ }
+
+ DataBuffer *buffer = bm->lockDataBuffer((uint32_t)mLayer->handle);
+ if (!buffer) {
+ ELOGTRACE("failed to get buffer");
+ } else {
+ mFormat = buffer->getFormat();
+ mWidth = buffer->getWidth();
+ mHeight = buffer->getHeight();
+ mStride = buffer->getStride();
+ mPriority = (mSourceCropf.right - mSourceCropf.left) * (mSourceCropf.bottom - mSourceCropf.top);
+ mPriority <<= LAYER_PRIORITY_SIZE_OFFSET;
+ mPriority |= mIndex;
+ GraphicBuffer *gBuffer = (GraphicBuffer*)buffer;
+ mUsage = gBuffer->getUsage();
+ mIsProtected = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);
+ if (mIsProtected) {
+ mPriority |= LAYER_PRIORITY_PROTECTED;
+ } else if (PlaneCapabilities::isFormatSupported(DisplayPlane::PLANE_OVERLAY, this)) {
+ mPriority |= LAYER_PRIORITY_OVERLAY;
+ }
+ bm->unlockDataBuffer(buffer);
+ }
+}
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/common/base/HwcLayer.h b/moorefield_hdmi/common/base/HwcLayer.h
new file mode 100644
index 0000000..95dbf34
--- /dev/null
+++ b/moorefield_hdmi/common/base/HwcLayer.h
@@ -0,0 +1,122 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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_LAYER_H
+#define HWC_LAYER_H
+
+#include <hardware/hwcomposer.h>
+#include <DisplayPlane.h>
+
+
+namespace android {
+namespace intel {
+
+class HwcLayer {
+public:
+ enum {
+ // LAYER_FB layers are marked as HWC_FRAMEBUFFER.
+ // And a LAYER_FB can become HWC_OVERLAY layers during
+ // revisiting layer list.
+ LAYER_FB = 0,
+ // LAYER_FORCE_FB layers are marked as HWC_FRAMEBUFFER.
+ // And a LAYER_FORCE_FB can never become HWC_OVERLAY layers during
+ // revisiting layer list.
+ LAYER_FORCE_FB,
+ // LAYER_OVERLAY layers are marked as HWC_OVERLAY
+ LAYER_OVERLAY,
+ // LAYER_SKIPPED layers are marked as HWC_OVERLAY with no plane attached
+ LAYER_SKIPPED,
+ // LAYER_FRAMEBUFFER_TARGET layers are marked as HWC_FRAMEBUFFER_TARGET
+ LAYER_FRAMEBUFFER_TARGET,
+ // LAYER_SIDEBAND layers have alternate path bypassing HWC after setup
+ LAYER_SIDEBAND,
+ // LAYER_CURSOR_OVERLAY layers support hardware cursor planes
+ LAYER_CURSOR_OVERLAY,
+ };
+
+ enum {
+ LAYER_PRIORITY_OVERLAY = 0x60000000UL,
+ LAYER_PRIORITY_PROTECTED = 0x70000000UL,
+ LAYER_PRIORITY_SIZE_OFFSET = 4,
+ };
+public:
+ HwcLayer(int index, hwc_layer_1_t *layer);
+ virtual ~HwcLayer();
+
+ // plane operations
+ bool attachPlane(DisplayPlane *plane, int device);
+ DisplayPlane* detachPlane();
+
+ void setType(uint32_t type);
+ uint32_t getType() const;
+ int32_t getCompositionType() const;
+ void setCompositionType(int32_t type);
+
+ int getIndex() const;
+ int getZOrder() const;
+ uint32_t getFormat() const;
+ uint32_t getBufferWidth() const;
+ uint32_t getBufferHeight() const;
+ const stride_t& getBufferStride() const;
+ uint32_t getUsage() const;
+ uint32_t getHandle() const;
+ uint32_t getTransform() const;
+ bool isProtected() const;
+ hwc_layer_1_t* getLayer() const;
+ DisplayPlane* getPlane() const;
+
+ void setPriority(uint32_t priority);
+ uint32_t getPriority() const;
+
+ bool update(hwc_layer_1_t *layer);
+ void postFlip();
+ bool isUpdated();
+
+public:
+ // temporary solution for plane assignment
+ bool mPlaneCandidate;
+
+private:
+ void setupAttributes();
+
+private:
+ const int mIndex;
+ int mZOrder;
+ int mDevice;
+ hwc_layer_1_t *mLayer;
+ DisplayPlane *mPlane;
+ uint32_t mFormat;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ stride_t mStride;
+ uint32_t mUsage;
+ uint32_t mHandle;
+ bool mIsProtected;
+ uint32_t mType;
+ uint32_t mPriority;
+ uint32_t mTransform;
+
+ // for smart composition
+ hwc_frect_t mSourceCropf;
+ hwc_rect_t mDisplayFrame;
+ bool mUpdated;
+};
+
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* HWC_LAYER_H */
diff --git a/moorefield_hdmi/common/base/HwcLayerList.cpp b/moorefield_hdmi/common/base/HwcLayerList.cpp
new file mode 100755
index 0000000..171cf85
--- /dev/null
+++ b/moorefield_hdmi/common/base/HwcLayerList.cpp
@@ -0,0 +1,1044 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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.
+*/
+#include <common/utils/HwcTrace.h>
+#include <common/base/Drm.h>
+#include <common/base/HwcLayerList.h>
+#include <Hwcomposer.h>
+#include <GraphicBuffer.h>
+#include <IDisplayDevice.h>
+#include <PlaneCapabilities.h>
+#include <DisplayQuery.h>
+#include <hal_public.h>
+
+namespace android {
+namespace intel {
+
+HwcLayerList::HwcLayerList(hwc_display_contents_1_t *list, int disp)
+ : mList(list),
+ mLayerCount(0),
+ mLayers(),
+ mFBLayers(),
+ mSpriteCandidates(),
+ mOverlayCandidates(),
+ mZOrderConfig(),
+ mFrameBufferTarget(NULL),
+ mDisplayIndex(disp)
+{
+ initialize();
+}
+
+HwcLayerList::~HwcLayerList()
+{
+ deinitialize();
+}
+
+bool HwcLayerList::checkSupported(int planeType, HwcLayer *hwcLayer)
+{
+ bool valid = false;
+ hwc_layer_1_t& layer = *(hwcLayer->getLayer());
+
+ // if layer was forced to use FB
+ if (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) {
+ VLOGTRACE("layer was forced to use HWC_FRAMEBUFFER");
+ return false;
+ }
+
+ // check layer flags
+ if (layer.flags & HWC_SKIP_LAYER) {
+ VLOGTRACE("plane type %d: (skip layer flag was set)", planeType);
+ return false;
+ }
+
+ if (layer.handle == 0) {
+ WLOGTRACE("invalid buffer handle");
+ return false;
+ }
+
+ // check usage
+ if (!hwcLayer->getUsage() & GRALLOC_USAGE_HW_COMPOSER) {
+ WLOGTRACE("not a composer layer");
+ return false;
+ }
+
+ // check layer transform
+ valid = PlaneCapabilities::isTransformSupported(planeType, hwcLayer);
+ if (!valid) {
+ VLOGTRACE("plane type %d: (bad transform)", planeType);
+ return false;
+ }
+
+ // check buffer format
+ valid = PlaneCapabilities::isFormatSupported(planeType, hwcLayer);
+ if (!valid) {
+ VLOGTRACE("plane type %d: (bad buffer format)", planeType);
+ return false;
+ }
+
+ // check buffer size
+ valid = PlaneCapabilities::isSizeSupported(planeType, hwcLayer);
+ if (!valid) {
+ VLOGTRACE("plane type %d: (bad buffer size)", planeType);
+ return false;
+ }
+
+ // check layer blending
+ valid = PlaneCapabilities::isBlendingSupported(planeType, hwcLayer);
+ if (!valid) {
+ VLOGTRACE("plane type %d: (bad blending)", planeType);
+ return false;
+ }
+
+ // check layer scaling
+ valid = PlaneCapabilities::isScalingSupported(planeType, hwcLayer);
+ if (!valid) {
+ VLOGTRACE("plane type %d: (bad scaling)", planeType);
+ return false;
+ }
+
+ // TODO: check visible region?
+ return true;
+}
+
+bool HwcLayerList::checkRgbOverlaySupported(HwcLayer *hwcLayer)
+{
+ bool valid = false;
+ hwc_layer_1_t& layer = *(hwcLayer->getLayer());
+
+ // if layer was forced to use FB
+ if (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) {
+ VLOGTRACE("layer was forced to use HWC_FRAMEBUFFER");
+ return false;
+ }
+
+ // check layer flags
+ if (layer.flags & HWC_SKIP_LAYER) {
+ VLOGTRACE("skip layer flag was set");
+ return false;
+ }
+
+ if (layer.handle == 0) {
+ WLOGTRACE("invalid buffer handle");
+ return false;
+ }
+
+ // check usage
+ if (!hwcLayer->getUsage() & GRALLOC_USAGE_HW_COMPOSER) {
+ WLOGTRACE("not a composer layer");
+ return false;
+ }
+
+ uint32_t format = hwcLayer->getFormat();
+ if (format != HAL_PIXEL_FORMAT_BGRA_8888 &&
+ format != HAL_PIXEL_FORMAT_BGRX_8888) {
+ return false;
+ }
+
+ uint32_t h = hwcLayer->getBufferHeight();
+ const stride_t& stride = hwcLayer->getBufferStride();
+ if (stride.rgb.stride > 4096) {
+ return false;
+ }
+
+ uint32_t blending = (uint32_t)hwcLayer->getLayer()->blending;
+ if (blending != HWC_BLENDING_NONE) {
+ return false;
+ }
+
+ uint32_t trans = hwcLayer->getLayer()->transform;
+ if (trans != 0) {
+ return false;
+ }
+
+ hwc_frect_t& src = hwcLayer->getLayer()->sourceCropf;
+ hwc_rect_t& dest = hwcLayer->getLayer()->displayFrame;
+ int srcW = (int)src.right - (int)src.left;
+ int srcH = (int)src.bottom - (int)src.top;
+ int dstW = dest.right - dest.left;
+ int dstH = dest.bottom - dest.top;
+ if (srcW != dstW || srcH != dstH) {
+ return false;
+ }
+ return true;
+}
+
+bool HwcLayerList::checkCursorSupported(HwcLayer *hwcLayer)
+{
+ bool valid = false;
+ hwc_layer_1_t& layer = *(hwcLayer->getLayer());
+
+ // if layer was forced to use FB
+ if (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) {
+ VLOGTRACE("layer was forced to use HWC_FRAMEBUFFER");
+ return false;
+ }
+
+ // check layer flags
+ if (layer.flags & HWC_SKIP_LAYER) {
+ VLOGTRACE("skip layer flag was set");
+ return false;
+ }
+
+ if (!(layer.flags & HWC_IS_CURSOR_LAYER)) {
+ VLOGTRACE("not a cursor layer");
+ return false;
+ }
+
+ if (hwcLayer->getIndex() != mLayerCount - 2) {
+ WLOGTRACE("cursor layer is not on top of zorder");
+ return false;
+ }
+
+ if (layer.handle == 0) {
+ WLOGTRACE("invalid buffer handle");
+ return false;
+ }
+
+ // check usage
+ if (!hwcLayer->getUsage() & GRALLOC_USAGE_HW_COMPOSER) {
+ WLOGTRACE("not a composer layer");
+ return false;
+ }
+
+ uint32_t format = hwcLayer->getFormat();
+ if (format != HAL_PIXEL_FORMAT_BGRA_8888 &&
+ format != HAL_PIXEL_FORMAT_RGBA_8888) {
+ WLOGTRACE("unexpected color format %u for cursor", format);
+ return false;
+ }
+
+ uint32_t trans = hwcLayer->getLayer()->transform;
+ if (trans != 0) {
+ WLOGTRACE("unexpected transform %u for cursor", trans);
+ return false;
+ }
+
+ hwc_frect_t& src = hwcLayer->getLayer()->sourceCropf;
+ hwc_rect_t& dest = hwcLayer->getLayer()->displayFrame;
+ int srcW = (int)src.right - (int)src.left;
+ int srcH = (int)src.bottom - (int)src.top;
+ int dstW = dest.right - dest.left;
+ int dstH = dest.bottom - dest.top;
+ if (srcW != dstW || srcH != dstH) {
+ WLOGTRACE("unexpected scaling for cursor: %dx%d => %dx%d",
+ srcW, srcH, dstW, dstH);
+ //return false;
+ }
+
+ if (srcW > 256 || srcH > 256) {
+ WLOGTRACE("unexpected size %dx%d for cursor", srcW, srcH);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool HwcLayerList::initialize()
+{
+ if (!mList || mList->numHwLayers == 0) {
+ ELOGTRACE("invalid hwc list");
+ return false;
+ }
+
+ mLayerCount = (int)mList->numHwLayers;
+ mLayers.setCapacity(mLayerCount);
+ mFBLayers.setCapacity(mLayerCount);
+ mSpriteCandidates.setCapacity(mLayerCount);
+ mOverlayCandidates.setCapacity(mLayerCount);
+ mCursorCandidates.setCapacity(mLayerCount);
+ mZOrderConfig.setCapacity(mLayerCount);
+ Hwcomposer& hwc = Hwcomposer::getInstance();
+
+ PriorityVector rgbOverlayLayers;
+ rgbOverlayLayers.setCapacity(mLayerCount);
+
+ for (int i = 0; i < mLayerCount; i++) {
+ hwc_layer_1_t *layer = &mList->hwLayers[i];
+ if (!layer) {
+ DEINIT_AND_RETURN_FALSE("layer %d is null", i);
+ }
+
+ HwcLayer *hwcLayer = new HwcLayer(i, layer);
+ if (!hwcLayer) {
+ DEINIT_AND_RETURN_FALSE("failed to allocate hwc layer %d", i);
+ }
+
+ if (layer->compositionType == HWC_FRAMEBUFFER_TARGET) {
+ hwcLayer->setType(HwcLayer::LAYER_FRAMEBUFFER_TARGET);
+ mFrameBufferTarget = hwcLayer;
+ } else if (layer->compositionType == HWC_OVERLAY){
+ // skipped layer, filtered by Display Analyzer
+ hwcLayer->setType(HwcLayer::LAYER_SKIPPED);
+ } else if (layer->compositionType == HWC_FORCE_FRAMEBUFFER) {
+ layer->compositionType = HWC_FRAMEBUFFER;
+ hwcLayer->setType(HwcLayer::LAYER_FORCE_FB);
+ // add layer to FB layer list for zorder check during plane assignment
+ mFBLayers.add(hwcLayer);
+ } else if (layer->compositionType == HWC_FRAMEBUFFER) {
+ // by default use GPU composition
+ hwcLayer->setType(HwcLayer::LAYER_FB);
+ mFBLayers.add(hwcLayer);
+ if (!DisplayQuery::forceFbScaling(mDisplayIndex)) {
+ if (checkCursorSupported(hwcLayer)) {
+ mCursorCandidates.add(hwcLayer);
+ } else if (checkRgbOverlaySupported(hwcLayer)) {
+ rgbOverlayLayers.add(hwcLayer);
+ } else if (checkSupported(DisplayPlane::PLANE_SPRITE, hwcLayer)) {
+ mSpriteCandidates.add(hwcLayer);
+ } else if (checkSupported(DisplayPlane::PLANE_OVERLAY, hwcLayer)) {
+ mOverlayCandidates.add(hwcLayer);
+ } else {
+ // noncandidate layer
+ }
+ } else {
+ if (checkSupported(DisplayPlane::PLANE_SPRITE, hwcLayer) &&
+ mLayerCount == 2) {
+ // if fb scaling, support only one RGB layer on HWC
+ mSpriteCandidates.add(hwcLayer);
+ } else if (checkSupported(DisplayPlane::PLANE_OVERLAY, hwcLayer)) {
+ mOverlayCandidates.add(hwcLayer);
+ } else {
+ // noncandidate layer
+ }
+ }
+ } else if (layer->compositionType == HWC_SIDEBAND){
+ hwcLayer->setType(HwcLayer::LAYER_SIDEBAND);
+ } else {
+ DEINIT_AND_RETURN_FALSE("invalid composition type %d", layer->compositionType);
+ }
+ // add layer to layer list
+ mLayers.add(hwcLayer);
+ }
+
+ if (mFrameBufferTarget == NULL) {
+ ELOGTRACE("no frame buffer target?");
+ return false;
+ }
+
+ // If has layer besides of FB_Target, but no FBLayers, skip plane allocation
+ // Note: There is case that SF passes down a layerlist with only FB_Target
+ // layer; we need to have this FB_Target to be flipped as well, otherwise it
+ // will have the buffer queue blocked. (The buffer hold by driver cannot be
+ // released if new buffers' flip is skipped).
+ if ((mFBLayers.size() == 0) && (mLayers.size() > 1)) {
+ VLOGTRACE("no FB layers, skip plane allocation");
+ return true;
+ }
+
+ bool hasOverlay = mOverlayCandidates.size() != 0;
+ while (rgbOverlayLayers.size()) {
+ HwcLayer *hwcLayer = rgbOverlayLayers.top();
+ if (hasOverlay) {
+ mSpriteCandidates.add(hwcLayer);
+ } else {
+ mOverlayCandidates.add(hwcLayer);
+ }
+ rgbOverlayLayers.removeItemsAt(0);
+ }
+
+ allocatePlanes();
+ //dump();
+ return true;
+}
+
+void HwcLayerList::deinitialize()
+{
+ if (mLayerCount == 0) {
+ return;
+ }
+
+ DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();
+ for (int i = 0; i < mLayerCount; i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ if (hwcLayer) {
+ DisplayPlane *plane = hwcLayer->detachPlane();
+ if (plane) {
+ planeManager->reclaimPlane(mDisplayIndex, *plane);
+ }
+ }
+ delete hwcLayer;
+ }
+
+ mLayers.clear();
+ mFBLayers.clear();
+ mOverlayCandidates.clear();
+ mSpriteCandidates.clear();
+ mCursorCandidates.clear();
+ mZOrderConfig.clear();
+ mFrameBufferTarget = NULL;
+ mLayerCount = 0;
+}
+
+
+bool HwcLayerList::allocatePlanes()
+{
+ return assignCursorPlanes();
+}
+
+bool HwcLayerList::assignCursorPlanes()
+{
+ int cursorCandidates = (int)mCursorCandidates.size();
+ if (cursorCandidates == 0) {
+ return assignOverlayPlanes();
+ }
+
+ DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();
+ int planeNumber = planeManager->getFreePlanes(mDisplayIndex, DisplayPlane::PLANE_CURSOR);
+ if (planeNumber == 0) {
+ DLOGTRACE("no cursor plane available. candidates %d", cursorCandidates);
+ return assignOverlayPlanes();
+ }
+
+ if (planeNumber > cursorCandidates) {
+ // assuming all cursor planes have the same capabilities, just
+ // need up to number of candidates for plane assignment
+ planeNumber = cursorCandidates;
+ }
+
+ for (int i = planeNumber; i >= 0; i--) {
+ // assign as many cursor planes as possible
+ if (assignCursorPlanes(0, i)) {
+ return true;
+ }
+ if (mZOrderConfig.size() != 0) {
+ ELOGTRACE("ZOrder config is not cleaned up!");
+ }
+ }
+ return false;
+}
+
+
+bool HwcLayerList::assignCursorPlanes(int index, int planeNumber)
+{
+ // index indicates position in mCursorCandidates to start plane assignment
+ if (planeNumber == 0) {
+ return assignOverlayPlanes();
+ }
+
+ int cursorCandidates = (int)mCursorCandidates.size();
+ for (int i = index; i <= cursorCandidates - planeNumber; i++) {
+ ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_CURSOR, mCursorCandidates[i]);
+ if (assignCursorPlanes(i + 1, planeNumber - 1)) {
+ return true;
+ }
+ removeZOrderLayer(zlayer);
+ }
+ return false;
+}
+
+bool HwcLayerList::assignOverlayPlanes()
+{
+ int overlayCandidates = (int)mOverlayCandidates.size();
+ if (overlayCandidates == 0) {
+ return assignSpritePlanes();
+ }
+
+ DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();
+ int planeNumber = planeManager->getFreePlanes(mDisplayIndex, DisplayPlane::PLANE_OVERLAY);
+ if (planeNumber == 0) {
+ DLOGTRACE("no overlay plane available. candidates %d", overlayCandidates);
+ return assignSpritePlanes();
+ }
+
+ if (planeNumber > overlayCandidates) {
+ // assuming all overlay planes have the same capabilities, just
+ // need up to number of candidates for plane assignment
+ planeNumber = overlayCandidates;
+ }
+
+ for (int i = planeNumber; i >= 0; i--) {
+ // assign as many overlay planes as possible
+ if (assignOverlayPlanes(0, i)) {
+ return true;
+ }
+ if (mZOrderConfig.size() != 0) {
+ ELOGTRACE("ZOrder config is not cleaned up!");
+ }
+ }
+ return false;
+}
+
+
+bool HwcLayerList::assignOverlayPlanes(int index, int planeNumber)
+{
+ // index indicates position in mOverlayCandidates to start plane assignment
+ if (planeNumber == 0) {
+ return assignSpritePlanes();
+ }
+
+ int overlayCandidates = (int)mOverlayCandidates.size();
+ for (int i = index; i <= overlayCandidates - planeNumber; i++) {
+ ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_OVERLAY, mOverlayCandidates[i]);
+ if (assignOverlayPlanes(i + 1, planeNumber - 1)) {
+ return true;
+ }
+ removeZOrderLayer(zlayer);
+ }
+ return false;
+}
+
+bool HwcLayerList::assignSpritePlanes()
+{
+ int spriteCandidates = (int)mSpriteCandidates.size();
+ if (spriteCandidates == 0) {
+ return assignPrimaryPlane();
+ }
+
+ // number does not include primary plane
+ DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();
+ int planeNumber = planeManager->getFreePlanes(mDisplayIndex, DisplayPlane::PLANE_SPRITE);
+ if (planeNumber == 0) {
+ VLOGTRACE("no sprite plane available, candidates %d", spriteCandidates);
+ return assignPrimaryPlane();
+ }
+
+ if (planeNumber > spriteCandidates) {
+ // assuming all sprite planes have the same capabilities, just
+ // need up to number of candidates for plane assignment
+ planeNumber = spriteCandidates;
+ }
+
+ for (int i = planeNumber; i >= 0; i--) {
+ // assign as many sprite planes as possible
+ if (assignSpritePlanes(0, i)) {
+ return true;
+ }
+
+ if (mOverlayCandidates.size() == 0 && mZOrderConfig.size() != 0) {
+ ELOGTRACE("ZOrder config is not cleaned up!");
+ }
+ }
+ return false;
+}
+
+
+bool HwcLayerList::assignSpritePlanes(int index, int planeNumber)
+{
+ if (planeNumber == 0) {
+ return assignPrimaryPlane();
+ }
+
+ int spriteCandidates = (int)mSpriteCandidates.size();
+ for (int i = index; i <= spriteCandidates - planeNumber; i++) {
+ ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_SPRITE, mSpriteCandidates[i]);
+ if (assignSpritePlanes(i + 1, planeNumber - 1)) {
+ return true;
+ }
+ removeZOrderLayer(zlayer);
+ }
+ return false;
+}
+
+bool HwcLayerList::assignPrimaryPlane()
+{
+ // find a sprit layer that is not candidate but has lower priority than candidates.
+ HwcLayer *spriteLayer = NULL;
+ for (int i = (int)mSpriteCandidates.size() - 1; i >= 0; i--) {
+ if (mSpriteCandidates[i]->mPlaneCandidate)
+ break;
+
+ spriteLayer = mSpriteCandidates[i];
+ }
+
+ int candidates = (int)mZOrderConfig.size();
+ int layers = (int)mFBLayers.size();
+ bool ok = false;
+
+ if (candidates == layers - 1 && spriteLayer != NULL) {
+ // primary plane is configured as sprite, all sprite candidates are offloaded to display planes
+ ok = assignPrimaryPlaneHelper(spriteLayer);
+ if (!ok) {
+ VLOGTRACE("failed to use primary as sprite plane");
+ }
+ } else if (candidates == 0) {
+ // none assigned, use primary plane for frame buffer target and set zorder to 0
+ ok = assignPrimaryPlaneHelper(mFrameBufferTarget, 0);
+ if (!ok) {
+ ELOGTRACE("failed to compose all layers to primary plane, should never happen");
+ }
+ } else if (candidates == layers) {
+ // all assigned, primary plane may be used during ZOrder config.
+ ok = attachPlanes();
+ if (!ok) {
+ VLOGTRACE("failed to assign layers without primary");
+ }
+ } else {
+ // check if the remaining planes can be composed to frame buffer target (FBT)
+ // look up a legitimate Z order position to place FBT.
+ for (int i = 0; i < layers && !ok; i++) {
+ if (mFBLayers[i]->mPlaneCandidate) {
+ continue;
+ }
+ if (useAsFrameBufferTarget(mFBLayers[i])) {
+ ok = assignPrimaryPlaneHelper(mFrameBufferTarget, mFBLayers[i]->getZOrder());
+ if (!ok) {
+ VLOGTRACE("failed to use zorder %d for frame buffer target",
+ mFBLayers[i]->getZOrder());
+ }
+ }
+ }
+ if (!ok) {
+ VLOGTRACE("no possible zorder for frame buffer target");
+ }
+
+ }
+ return ok;
+}
+
+bool HwcLayerList::assignPrimaryPlaneHelper(HwcLayer *hwcLayer, int zorder)
+{
+ int type = DisplayPlane::PLANE_PRIMARY;
+
+ ZOrderLayer *zlayer = addZOrderLayer(type, hwcLayer, zorder);
+ bool ok = attachPlanes();
+ if (!ok) {
+ removeZOrderLayer(zlayer);
+ }
+ return ok;
+}
+
+bool HwcLayerList::attachPlanes()
+{
+ DisplayPlaneManager *planeManager = Hwcomposer::getInstance().getPlaneManager();
+ if (!planeManager->isValidZOrder(mDisplayIndex, mZOrderConfig)) {
+ VLOGTRACE("invalid z order, size of config %d", mZOrderConfig.size());
+ return false;
+ }
+
+ if (!planeManager->assignPlanes(mDisplayIndex, mZOrderConfig)) {
+ WLOGTRACE("failed to assign planes");
+ return false;
+ }
+
+ VLOGTRACE("============= plane assignment===================");
+ for (int i = 0; i < (int)mZOrderConfig.size(); i++) {
+ ZOrderLayer *zlayer = mZOrderConfig.itemAt(i);
+ if (zlayer->plane == NULL || zlayer->hwcLayer == NULL) {
+ ELOGTRACE("invalid ZOrderLayer, should never happen!!");
+ return false;
+ }
+
+ zlayer->plane->setZOrder(i);
+
+ if (zlayer->plane->getType() == DisplayPlane::PLANE_CURSOR) {
+ zlayer->hwcLayer->setType(HwcLayer::LAYER_CURSOR_OVERLAY);
+ mFBLayers.remove(zlayer->hwcLayer);
+ } else if (zlayer->hwcLayer != mFrameBufferTarget) {
+ zlayer->hwcLayer->setType(HwcLayer::LAYER_OVERLAY);
+ // update FB layers for smart composition
+ mFBLayers.remove(zlayer->hwcLayer);
+ }
+
+ zlayer->hwcLayer->attachPlane(zlayer->plane, mDisplayIndex);
+
+ VLOGTRACE("total %d, layer %d, type %d, index %d, zorder %d",
+ mLayerCount - 1,
+ zlayer->hwcLayer->getIndex(),
+ zlayer->plane->getType(),
+ zlayer->plane->getIndex(),
+ zlayer->zorder);
+
+ delete zlayer;
+ }
+
+ mZOrderConfig.clear();
+ return true;
+}
+
+bool HwcLayerList::useAsFrameBufferTarget(HwcLayer *target)
+{
+ // check if zorder of target can be used as zorder of frame buffer target
+ // eligible only when all noncandidate layers can be merged to the target layer:
+ // 1) noncandidate layer and candidate layer below the target layer can't overlap
+ // if candidate layer is on top of non candidate layer, as "noncandidate layer" needs
+ // to be moved up to target layer in z order;
+ // 2) noncandidate layer and candidate layers above the target layer can't overlap
+ // if candidate layer is below noncandidate layer, as "noncandidate layer" needs
+ // to be moved down to target layer in z order.
+
+ int targetLayerIndex = target->getIndex();
+
+ // check candidate and noncandidate layers below this candidate does not overlap
+ for (int below = 0; below < targetLayerIndex; below++) {
+ if (mFBLayers[below]->mPlaneCandidate) {
+ continue;
+ } else {
+ // check candidate layer above this noncandidate layer does not overlap
+ for (int above = below + 1; above < targetLayerIndex; above++) {
+ if (mFBLayers[above]->mPlaneCandidate == false) {
+ continue;
+ }
+ if (hasIntersection(mFBLayers[above], mFBLayers[below])) {
+ return false;
+ }
+ }
+ }
+ }
+
+ // check candidate and noncandidate layers above this candidate does not overlap
+ for (unsigned int above = targetLayerIndex + 1; above < mFBLayers.size(); above++) {
+ if (mFBLayers[above]->mPlaneCandidate) {
+ continue;
+ } else {
+ // check candidate layer below this noncandidate layer does not overlap
+ for (unsigned int below = targetLayerIndex + 1; below < above; below++) {
+ if (mFBLayers[below]->mPlaneCandidate == false) {
+ continue;
+ }
+ if (hasIntersection(mFBLayers[above], mFBLayers[below])) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool HwcLayerList::hasIntersection(HwcLayer *la, HwcLayer *lb)
+{
+ hwc_layer_1_t *a = la->getLayer();
+ hwc_layer_1_t *b = lb->getLayer();
+ hwc_rect_t *aRect = &a->displayFrame;
+ hwc_rect_t *bRect = &b->displayFrame;
+
+ if (bRect->right <= aRect->left ||
+ bRect->left >= aRect->right ||
+ bRect->top >= aRect->bottom ||
+ bRect->bottom <= aRect->top)
+ return false;
+
+ return true;
+}
+
+ZOrderLayer* HwcLayerList::addZOrderLayer(int type, HwcLayer *hwcLayer, int zorder)
+{
+ ZOrderLayer *layer = new ZOrderLayer;
+ layer->planeType = type;
+ layer->hwcLayer = hwcLayer;
+ layer->zorder = (zorder != -1) ? zorder : hwcLayer->getZOrder();
+ layer->plane = NULL;
+
+ if (hwcLayer->mPlaneCandidate) {
+ ELOGTRACE("plane is candidate!, order = %d", zorder);
+ }
+
+ hwcLayer->mPlaneCandidate = true;
+
+ if ((int)mZOrderConfig.indexOf(layer) >= 0) {
+ ELOGTRACE("layer exists!");
+ }
+
+ mZOrderConfig.add(layer);
+ return layer;
+}
+
+void HwcLayerList::removeZOrderLayer(ZOrderLayer *layer)
+{
+ if ((int)mZOrderConfig.indexOf(layer) < 0) {
+ ELOGTRACE("layer does not exist!");
+ }
+
+ mZOrderConfig.remove(layer);
+
+ if (layer->hwcLayer->mPlaneCandidate == false) {
+ ELOGTRACE("plane is not candidate!, order %d", layer->zorder);
+ }
+ layer->hwcLayer->mPlaneCandidate = false;
+ delete layer;
+}
+
+void HwcLayerList::setupSmartComposition()
+{
+ uint32_t compositionType = HWC_OVERLAY;
+ HwcLayer *hwcLayer = NULL;
+
+ // setup smart composition only there's no update on all FB layers
+ for (size_t i = 0; i < mFBLayers.size(); i++) {
+ hwcLayer = mFBLayers.itemAt(i);
+ if (hwcLayer->isUpdated()) {
+ compositionType = HWC_FRAMEBUFFER;
+ }
+ }
+
+ VLOGTRACE("smart composition enabled %s",
+ (compositionType == HWC_OVERLAY) ? "TRUE" : "FALSE");
+ for (size_t i = 0; i < mFBLayers.size(); i++) {
+ hwcLayer = mFBLayers.itemAt(i);
+ switch (hwcLayer->getType()) {
+ case HwcLayer::LAYER_FB:
+ case HwcLayer::LAYER_FORCE_FB:
+ hwcLayer->setCompositionType(compositionType);
+ break;
+ default:
+ ELOGTRACE("Invalid layer type %d", hwcLayer->getType());
+ break;
+ }
+ }
+}
+
+#if 1 // support overlay fallback to GLES
+
+bool HwcLayerList::update(hwc_display_contents_1_t *list)
+{
+ bool ret;
+
+ // basic check to make sure the consistance
+ if (!list) {
+ ELOGTRACE("null layer list");
+ return false;
+ }
+
+ if ((int)list->numHwLayers != mLayerCount) {
+ ELOGTRACE("layer count doesn't match (%d, %d)", list->numHwLayers, mLayerCount);
+ return false;
+ }
+
+ // update list
+ mList = list;
+
+ bool ok = true;
+ // update all layers, call each layer's update()
+ for (int i = 0; i < mLayerCount; i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ if (!hwcLayer) {
+ ELOGTRACE("no HWC layer for layer %d", i);
+ continue;
+ }
+
+ if (!hwcLayer->update(&list->hwLayers[i])) {
+ ok = false;
+ hwcLayer->setCompositionType(HWC_FORCE_FRAMEBUFFER);
+ }
+ }
+
+ if (!ok) {
+ ILOGTRACE("overlay fallback to GLES. flags: %#x", list->flags);
+ for (int i = 0; i < mLayerCount - 1; i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ if (hwcLayer->getPlane() &&
+ (hwcLayer->getCompositionType() == HWC_OVERLAY ||
+ hwcLayer->getCompositionType() == HWC_CURSOR_OVERLAY)) {
+ hwcLayer->setCompositionType(HWC_FRAMEBUFFER);
+ }
+ }
+ mLayers.itemAt(mLayerCount - 1)->setCompositionType(HWC_FRAMEBUFFER_TARGET);
+ deinitialize();
+ mList = list;
+ initialize();
+
+ // update all layers again after plane re-allocation
+ for (int i = 0; i < mLayerCount; i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ if (!hwcLayer) {
+ ELOGTRACE("no HWC layer for layer %d", i);
+ continue;
+ }
+
+ if (!hwcLayer->update(&list->hwLayers[i])) {
+ DLOGTRACE("fallback to GLES update failed on layer[%d]!\n", i);
+ }
+ }
+ }
+
+ setupSmartComposition();
+ return true;
+}
+
+#else
+
+bool HwcLayerList::update(hwc_display_contents_1_t *list)
+{
+ bool ret;
+
+ // basic check to make sure the consistance
+ if (!list) {
+ ELOGTRACE("null layer list");
+ return false;
+ }
+
+ if ((int)list->numHwLayers != mLayerCount) {
+ ELOGTRACE("layer count doesn't match (%d, %d)", list->numHwLayers, mLayerCount);
+ return false;
+ }
+
+ // update list
+ mList = list;
+
+ // update all layers, call each layer's update()
+ for (int i = 0; i < mLayerCount; i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ if (!hwcLayer) {
+ ELOGTRACE("no HWC layer for layer %d", i);
+ continue;
+ }
+
+ hwcLayer->update(&list->hwLayers[i]);
+ }
+
+ setupSmartComposition();
+ return true;
+}
+
+#endif
+
+DisplayPlane* HwcLayerList::getPlane(uint32_t index) const
+{
+ HwcLayer *hwcLayer;
+
+ if (index >= mLayers.size()) {
+ ELOGTRACE("invalid layer index %d", index);
+ return 0;
+ }
+
+ hwcLayer = mLayers.itemAt(index);
+ if ((hwcLayer->getType() == HwcLayer::LAYER_FB) ||
+ (hwcLayer->getType() == HwcLayer::LAYER_FORCE_FB) ||
+ (hwcLayer->getType() == HwcLayer::LAYER_SKIPPED)) {
+ return 0;
+ }
+
+ if (hwcLayer->getHandle() == 0) {
+ DLOGTRACE("plane is attached with invalid handle");
+ return 0;
+ }
+
+ return hwcLayer->getPlane();
+}
+
+void HwcLayerList::postFlip()
+{
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ hwcLayer->postFlip();
+ }
+}
+
+void HwcLayerList::dump(Dump& d)
+{
+ d.append("Layer list: (number of layers %d):\n", mLayers.size());
+ d.append(" LAYER | TYPE | PLANE | INDEX | Z Order \n");
+ d.append("-------+------------------------+----------------------------\n");
+ for (size_t i = 0; i < mLayers.size(); i++) {
+ HwcLayer *hwcLayer = mLayers.itemAt(i);
+ DisplayPlane *plane;
+ int planeIndex = -1;
+ int zorder = -1;
+ const char *type = "HWC_FB";
+ const char *planeType = "N/A";
+
+ if (hwcLayer) {
+ switch (hwcLayer->getType()) {
+ case HwcLayer::LAYER_FB:
+ case HwcLayer::LAYER_FORCE_FB:
+ type = "HWC_FB";
+ break;
+ case HwcLayer::LAYER_OVERLAY:
+ case HwcLayer::LAYER_SKIPPED:
+ type = "HWC_OVERLAY";
+ break;
+ case HwcLayer::LAYER_FRAMEBUFFER_TARGET:
+ type = "HWC_FRAMEBUFFER_TARGET";
+ break;
+ case HwcLayer::LAYER_SIDEBAND:
+ type = "HWC_SIDEBAND";
+ break;
+ case HwcLayer::LAYER_CURSOR_OVERLAY:
+ type = "HWC_CURSOR_OVERLAY";
+ break;
+ default:
+ type = "Unknown";
+ }
+
+ plane = hwcLayer->getPlane();
+ if (plane) {
+ planeIndex = plane->getIndex();
+ zorder = plane->getZOrder();
+ switch (plane->getType()) {
+ case DisplayPlane::PLANE_OVERLAY:
+ planeType = "OVERLAY";
+ break;
+ case DisplayPlane::PLANE_SPRITE:
+ planeType = "SPRITE";
+ break;
+ case DisplayPlane::PLANE_PRIMARY:
+ planeType = "PRIMARY";
+ break;
+ case DisplayPlane::PLANE_CURSOR:
+ planeType = "CURSOR";
+ break;
+ default:
+ planeType = "Unknown";
+ }
+ }
+
+ d.append(" %2d | %22s | %8s | %3D | %3D \n",
+ i, type, planeType, planeIndex, zorder);
+ }
+ }
+}
+
+
+void HwcLayerList::dump()
+{
+ static char const* compositionTypeName[] = {
+ "GLES",
+ "HWC",
+ "BG",
+ "FBT",
+ "SB",
+ "CUR",
+ "N/A"};
+
+ static char const* planeTypeName[] = {
+ "SPRITE",
+ "OVERLAY",
+ "PRIMARY",
+ "CURSOR",
+ "UNKNOWN"};
+
+ DLOGTRACE(" numHwLayers = %u, flags = %08x", mList->numHwLayers, mList->flags);
+
+ DLOGTRACE(" type | handle | hints | flags | tr | blend | alpha | format | source crop | frame | index | zorder | plane ");
+ DLOGTRACE("------+----------+-------+-------+----+-------+-------+----------+-----------------------------------+---------------------------+-------+--------+---------");
+
+
+ for (int i = 0 ; i < mLayerCount ; i++) {
+ const hwc_layer_1_t&l = mList->hwLayers[i];
+ DisplayPlane *plane = mLayers[i]->getPlane();
+ int planeIndex = -1;
+ int zorder = -1;
+ const char *planeType = "N/A";
+ if (plane) {
+ planeIndex = plane->getIndex();
+ zorder = plane->getZOrder();
+ planeType = planeTypeName[plane->getType()];
+ }
+
+ DLOGTRACE(
+ " %4s | %8x | %5x | %5x | %2x | %5x | %5x | %8x | [%7.1f,%7.1f,%7.1f,%7.1f] | [%5d,%5d,%5d,%5d] | %5d | %6d | %7s ",
+ compositionTypeName[l.compositionType],
+ mLayers[i]->getHandle(), l.hints, l.flags, l.transform, l.blending, l.planeAlpha, mLayers[i]->getFormat(),
+ l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
+ l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+ planeIndex, zorder, planeType);
+ }
+
+}
+
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/common/base/HwcLayerList.h b/moorefield_hdmi/common/base/HwcLayerList.h
new file mode 100755
index 0000000..f933e7a
--- /dev/null
+++ b/moorefield_hdmi/common/base/HwcLayerList.h
@@ -0,0 +1,109 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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_LAYER_LIST_H
+#define HWC_LAYER_LIST_H
+
+#include <common/utils/Dump.h>
+#include <hardware/hwcomposer.h>
+#include <utils/SortedVector.h>
+#include <DataBuffer.h>
+#include <DisplayPlane.h>
+#include <DisplayPlaneManager.h>
+#include <common/base/HwcLayer.h>
+
+namespace android {
+namespace intel {
+
+
+class HwcLayerList {
+public:
+ HwcLayerList(hwc_display_contents_1_t *list, int disp);
+ virtual ~HwcLayerList();
+
+public:
+ virtual bool initialize();
+ virtual void deinitialize();
+
+ virtual bool update(hwc_display_contents_1_t *list);
+ virtual DisplayPlane* getPlane(uint32_t index) const;
+
+ void postFlip();
+
+ // dump interface
+ virtual void dump(Dump& d);
+
+
+private:
+ bool checkSupported(int planeType, HwcLayer *hwcLayer);
+ bool checkRgbOverlaySupported(HwcLayer *hwcLayer);
+ bool checkCursorSupported(HwcLayer *hwcLayer);
+ bool allocatePlanes();
+ bool assignCursorPlanes();
+ bool assignCursorPlanes(int index, int planeNumber);
+ bool assignOverlayPlanes();
+ bool assignOverlayPlanes(int index, int planeNumber);
+ bool assignSpritePlanes();
+ bool assignSpritePlanes(int index, int planeNumber);
+ bool assignPrimaryPlane();
+ bool assignPrimaryPlaneHelper(HwcLayer *hwcLayer, int zorder = -1);
+ bool attachPlanes();
+ bool useAsFrameBufferTarget(HwcLayer *target);
+ bool hasIntersection(HwcLayer *la, HwcLayer *lb);
+ ZOrderLayer* addZOrderLayer(int type, HwcLayer *hwcLayer, int zorder = -1);
+ void removeZOrderLayer(ZOrderLayer *layer);
+ void setupSmartComposition();
+ void dump();
+
+private:
+ class HwcLayerVector : public SortedVector<HwcLayer*> {
+ public:
+ HwcLayerVector() {}
+ virtual int do_compare(const void* lhs, const void* rhs) const {
+ const HwcLayer* l = *(HwcLayer**)lhs;
+ const HwcLayer* r = *(HwcLayer**)rhs;
+ // sorted from index 0 to n
+ return l->getIndex() - r->getIndex();
+ }
+ };
+
+ class PriorityVector : public SortedVector<HwcLayer*> {
+ public:
+ PriorityVector() {}
+ virtual int do_compare(const void* lhs, const void* rhs) const {
+ const HwcLayer* l = *(HwcLayer**)lhs;
+ const HwcLayer* r = *(HwcLayer**)rhs;
+ return r->getPriority() - l->getPriority();
+ }
+ };
+
+ hwc_display_contents_1_t *mList;
+ int mLayerCount;
+
+ HwcLayerVector mLayers;
+ HwcLayerVector mFBLayers;
+ PriorityVector mSpriteCandidates;
+ PriorityVector mOverlayCandidates;
+ PriorityVector mCursorCandidates;
+ ZOrderConfig mZOrderConfig;
+ HwcLayer *mFrameBufferTarget;
+ int mDisplayIndex;
+};
+
+} // namespace intel
+} // namespace android
+
+
+#endif /* HWC_LAYER_LIST_H */
diff --git a/moorefield_hdmi/common/base/HwcModule.cpp b/moorefield_hdmi/common/base/HwcModule.cpp
new file mode 100644
index 0000000..ce8d478
--- /dev/null
+++ b/moorefield_hdmi/common/base/HwcModule.cpp
@@ -0,0 +1,313 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL)
+
+#include <hardware/hardware.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <common/utils/HwcTrace.h>
+#include <Hwcomposer.h>
+#include <utils/Trace.h>
+
+#define GET_HWC_RETURN_X_IF_NULL(X) \
+ CTRACE(); \
+ Hwcomposer *hwc = static_cast<Hwcomposer*>(dev); \
+ do {\
+ if (!hwc) { \
+ ELOGTRACE("invalid HWC device."); \
+ return X; \
+ } \
+ } while (0)
+
+
+#define GET_HWC_RETURN_ERROR_IF_NULL() GET_HWC_RETURN_X_IF_NULL(-EINVAL)
+#define GET_HWC_RETURN_VOID_IF_NULL() GET_HWC_RETURN_X_IF_NULL()
+
+
+namespace android {
+namespace intel {
+
+static int hwc_prepare(struct hwc_composer_device_1 *dev,
+ size_t numDisplays,
+ hwc_display_contents_1_t** displays)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ if (!hwc->prepare(numDisplays, displays)) {
+ ELOGTRACE("failed to prepare");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int hwc_set(struct hwc_composer_device_1 *dev,
+ size_t numDisplays,
+ hwc_display_contents_1_t **displays)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ if (!hwc->commit(numDisplays, displays)) {
+ ELOGTRACE("failed to commit");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static void hwc_dump(struct hwc_composer_device_1 *dev,
+ char *buff,
+ int buff_len)
+{
+ GET_HWC_RETURN_VOID_IF_NULL();
+ hwc->dump(buff, buff_len, 0);
+}
+
+void hwc_registerProcs(struct hwc_composer_device_1 *dev,
+ hwc_procs_t const *procs)
+{
+ GET_HWC_RETURN_VOID_IF_NULL();
+ hwc->registerProcs(procs);
+}
+
+static int hwc_device_close(struct hw_device_t * /* dev */)
+{
+ CTRACE();
+ Hwcomposer::releaseInstance();
+ return 0;
+}
+
+static int hwc_query(struct hwc_composer_device_1 * /* dev */,
+ int what, int* /* value */)
+{
+ (void) what;
+ ALOGTRACE("what = %d", what);
+ return -EINVAL;
+}
+
+static int hwc_eventControl(struct hwc_composer_device_1 *dev,
+ int disp,
+ int event,
+ int enabled)
+{
+ bool ret;
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+
+ switch (event) {
+ case HWC_EVENT_VSYNC:
+ ret = hwc->vsyncControl(disp, enabled);
+ if (ret == false) {
+ ELOGTRACE("failed to control vsync");
+ return -EINVAL;
+ }
+ break;
+ default:
+ WLOGTRACE("unsupported event %d", event);
+ break;
+ }
+
+ return 0;
+}
+
+static int hwc_blank(hwc_composer_device_1_t *dev, int disp, int blank)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->blank(disp, blank);
+ if (ret == false) {
+ ELOGTRACE("failed to blank disp %d, blank %d", disp, blank);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hwc_getDisplayConfigs(hwc_composer_device_1_t *dev,
+ int disp,
+ uint32_t *configs,
+ size_t *numConfigs)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->getDisplayConfigs(disp, configs, numConfigs);
+ if (ret == false) {
+ WLOGTRACE("failed to get configs of disp %d", disp);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hwc_getDisplayAttributes(hwc_composer_device_1_t *dev,
+ int disp,
+ uint32_t config,
+ const uint32_t *attributes,
+ int32_t *values)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->getDisplayAttributes(disp, config, attributes, values);
+ if (ret == false) {
+ WLOGTRACE("failed to get attributes of disp %d", disp);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hwc_compositionComplete(hwc_composer_device_1_t *dev, int disp)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->compositionComplete(disp);
+ if (ret == false) {
+ ELOGTRACE("failed for disp %d", disp);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hwc_setPowerMode(hwc_composer_device_1_t *dev, int disp, int mode)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->setPowerMode(disp, mode);
+ if (ret == false) {
+ WLOGTRACE("failed to set power mode of disp %d", disp);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hwc_getActiveConfig(hwc_composer_device_1_t *dev, int disp)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ int ret = hwc->getActiveConfig(disp);
+ if (ret == -1) {
+ WLOGTRACE("failed to get active config of disp %d", disp);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+static int hwc_setActiveConfig(hwc_composer_device_1_t *dev, int disp, int index)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->setActiveConfig(disp, index);
+ if (ret == false) {
+ WLOGTRACE("failed to set active config of disp %d", disp);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hwc_setCursorPositionAsync(hwc_composer_device_1_t *dev, int disp, int x, int y)
+{
+ ATRACE_CALL();
+ GET_HWC_RETURN_ERROR_IF_NULL();
+ bool ret = hwc->setCursorPositionAsync(disp, x, y);
+ if (ret == false) {
+ WLOGTRACE("failed to set cursor position of disp %d", disp);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+
+static int hwc_device_open(const struct hw_module_t* module,
+ const char* name,
+ struct hw_device_t** device)
+{
+ if (!name) {
+ ELOGTRACE("invalid name.");
+ return -EINVAL;
+ }
+
+ ALOGTRACE("open device %s", name);
+
+ if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) {
+ ELOGTRACE("try to open unknown HWComposer %s", name);
+ return -EINVAL;
+ }
+
+ Hwcomposer& hwc = Hwcomposer::getInstance();
+ // initialize our state here
+ if (hwc.initialize() == false) {
+ ELOGTRACE("failed to intialize HWComposer");
+ Hwcomposer::releaseInstance();
+ return -EINVAL;
+ }
+
+ // initialize the procs
+ hwc.hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG;
+ hwc.hwc_composer_device_1_t::common.module =
+ const_cast<hw_module_t*>(module);
+ hwc.hwc_composer_device_1_t::common.close = hwc_device_close;
+
+ hwc.hwc_composer_device_1_t::prepare = hwc_prepare;
+ hwc.hwc_composer_device_1_t::set = hwc_set;
+ hwc.hwc_composer_device_1_t::dump = hwc_dump;
+ hwc.hwc_composer_device_1_t::registerProcs = hwc_registerProcs;
+ hwc.hwc_composer_device_1_t::query = hwc_query;
+
+ hwc.hwc_composer_device_1_t::eventControl = hwc_eventControl;
+ hwc.hwc_composer_device_1_t::getDisplayConfigs = hwc_getDisplayConfigs;
+ hwc.hwc_composer_device_1_t::getDisplayAttributes = hwc_getDisplayAttributes;
+
+ // This is used to hack FBO switch flush issue in SurfaceFlinger.
+ hwc.hwc_composer_device_1_t::reserved_proc[0] = (void*)hwc_compositionComplete;
+ hwc.hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4;
+ hwc.hwc_composer_device_1_t::setPowerMode = hwc_setPowerMode;
+ hwc.hwc_composer_device_1_t::getActiveConfig = hwc_getActiveConfig;
+ hwc.hwc_composer_device_1_t::setActiveConfig = hwc_setActiveConfig;
+ // Todo: add hwc_setCursorPositionAsync after supporting patches
+ hwc.hwc_composer_device_1_t::setCursorPositionAsync = NULL;
+
+ *device = &hwc.hwc_composer_device_1_t::common;
+
+ return 0;
+}
+
+} // namespace intel
+} // namespace android
+
+static struct hw_module_methods_t hwc_module_methods = {
+ open: android::intel::hwc_device_open
+};
+
+hwc_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 4,
+ id: HWC_HARDWARE_MODULE_ID,
+ name: "Intel Hardware Composer",
+ author: "Intel",
+ methods: &hwc_module_methods,
+ dso: 0,
+ reserved: { 0 },
+ }
+};
diff --git a/moorefield_hdmi/common/base/Hwcomposer.cpp b/moorefield_hdmi/common/base/Hwcomposer.cpp
new file mode 100755
index 0000000..eac1448
--- /dev/null
+++ b/moorefield_hdmi/common/base/Hwcomposer.cpp
@@ -0,0 +1,519 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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.
+*/
+#include <common/utils/HwcTrace.h>
+#include <Hwcomposer.h>
+#include <common/utils/Dump.h>
+#include <UeventObserver.h>
+
+namespace android {
+namespace intel {
+
+Hwcomposer* Hwcomposer::sInstance(0);
+
+Hwcomposer::Hwcomposer()
+ : mProcs(0),
+ mDrm(0),
+ mPlaneManager(0),
+ mBufferManager(0),
+ mDisplayAnalyzer(0),
+ mDisplayContext(0),
+ mUeventObserver(0),
+ mInitialized(false)
+{
+ CTRACE();
+
+ mDisplayDevices.setCapacity(IDisplayDevice::DEVICE_COUNT);
+ mDisplayDevices.clear();
+}
+
+Hwcomposer::~Hwcomposer()
+{
+ CTRACE();
+ deinitialize();
+}
+
+bool Hwcomposer::initCheck() const
+{
+ return mInitialized;
+}
+
+bool Hwcomposer::prepare(size_t numDisplays,
+ hwc_display_contents_1_t** displays)
+{
+ bool ret = true;
+
+ RETURN_FALSE_IF_NOT_INIT();
+ ALOGTRACE("display count = %d", numDisplays);
+
+ if (!numDisplays || !displays) {
+ ELOGTRACE("invalid parameters");
+ return false;
+ }
+
+ mDisplayAnalyzer->analyzeContents(numDisplays, displays);
+
+ // disable reclaimed planes
+ mPlaneManager->disableReclaimedPlanes();
+
+ // reclaim all allocated planes if possible
+ for (size_t i = 0; i < numDisplays; i++) {
+ if (i >= mDisplayDevices.size()) {
+ continue;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(i);
+ if (!device) {
+ VLOGTRACE("device %d doesn't exist", i);
+ continue;
+ }
+ device->prePrepare(displays[i]);
+ }
+
+ for (size_t i = 0; i < numDisplays; i++) {
+ if (i >= mDisplayDevices.size()) {
+ continue;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(i);
+ if (!device) {
+ VLOGTRACE("device %d doesn't exist", i);
+ continue;
+ }
+ ret = device->prepare(displays[i]);
+ if (ret == false) {
+ ELOGTRACE("failed to do prepare for device %d", i);
+ continue;
+ }
+ }
+
+ return ret;
+}
+
+bool Hwcomposer::commit(size_t numDisplays,
+ hwc_display_contents_1_t **displays)
+{
+ bool ret = true;
+
+ RETURN_FALSE_IF_NOT_INIT();
+ ALOGTRACE("display count = %d", numDisplays);
+
+ if (!numDisplays || !displays) {
+ ELOGTRACE("invalid parameters");
+ return false;
+ }
+
+ mDisplayContext->commitBegin(numDisplays, displays);
+
+ for (size_t i = 0; i < numDisplays; i++) {
+ if (i >= mDisplayDevices.size()) {
+ continue;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(i);
+ if (!device) {
+ VLOGTRACE("device %d doesn't exist", i);
+ continue;
+ }
+
+ if (!device->isConnected()) {
+ VLOGTRACE("device %d is disconnected", i);
+ continue;
+ }
+
+ ret = device->commit(displays[i], mDisplayContext);
+ if (ret == false) {
+ ELOGTRACE("failed to do commit for device %d", i);
+ continue;
+ }
+ }
+
+ mDisplayContext->commitEnd(numDisplays, displays);
+ // return true always
+ return true;
+}
+
+bool Hwcomposer::vsyncControl(int disp, int enabled)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ ALOGTRACE("disp = %d, enabled = %d", disp, enabled);
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+ if (disp >= (int) mDisplayDevices.size()) {
+ return false;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return false;
+ }
+
+ return device->vsyncControl(enabled ? true : false);
+}
+
+bool Hwcomposer::blank(int disp, int blank)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+ ALOGTRACE("disp = %d, blank = %d", disp, blank);
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+ if (disp >= (int) mDisplayDevices.size()) {
+ return false;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return false;
+ }
+
+ return device->blank(blank ? true : false);
+}
+
+bool Hwcomposer::getDisplayConfigs(int disp,
+ uint32_t *configs,
+ size_t *numConfigs)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+ if (disp >= (int) mDisplayDevices.size()) {
+ return false;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device %d found", disp);
+ return false;
+ }
+
+ return device->getDisplayConfigs(configs, numConfigs);
+}
+
+bool Hwcomposer::getDisplayAttributes(int disp,
+ uint32_t config,
+ const uint32_t *attributes,
+ int32_t *values)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+ if (disp >= (int) mDisplayDevices.size()) {
+ return false;
+ }
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return false;
+ }
+
+ return device->getDisplayAttributes(config, attributes, values);
+}
+
+bool Hwcomposer::compositionComplete(int disp)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+
+ mDisplayContext->compositionComplete();
+ if (disp >= (int) mDisplayDevices.size()) {
+ return false;
+ }
+
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return false;
+ }
+
+ return device->compositionComplete();
+}
+
+bool Hwcomposer::setPowerMode(int disp, int mode)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return false;
+ }
+
+ return device->setPowerMode(mode);
+}
+
+int Hwcomposer::getActiveConfig(int disp)
+{
+ RETURN_NULL_IF_NOT_INIT();
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return -1;
+ }
+
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return -1;
+ }
+
+ return device->getActiveConfig();
+}
+
+bool Hwcomposer::setActiveConfig(int disp, int index)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+
+ IDisplayDevice *device = mDisplayDevices.itemAt(disp);
+ if (!device) {
+ ELOGTRACE("no device found");
+ return false;
+ }
+
+ return device->setActiveConfig(index);
+}
+
+bool Hwcomposer::setCursorPositionAsync(int disp, int x, int y)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ if (disp != HWC_DISPLAY_PRIMARY && disp != HWC_DISPLAY_EXTERNAL) {
+ ELOGTRACE("invalid disp %d", disp);
+ return false;
+ }
+
+ return mDisplayContext->setCursorPosition(disp, x, y);
+}
+
+void Hwcomposer::vsync(int disp, int64_t timestamp)
+{
+ RETURN_VOID_IF_NOT_INIT();
+
+ if (mProcs && mProcs->vsync) {
+ VLOGTRACE("report vsync on disp %d, timestamp %llu", disp, timestamp);
+ // workaround to pretend vsync is from primary display
+ // Display will freeze if vsync is from external display.
+ mProcs->vsync(const_cast<hwc_procs_t*>(mProcs), IDisplayDevice::DEVICE_PRIMARY, timestamp);
+ }
+}
+
+void Hwcomposer::hotplug(__attribute__((unused))int disp, bool connected)
+{
+ RETURN_VOID_IF_NOT_INIT();
+
+#ifndef INTEL_SUPPORT_HDMI_PRIMARY
+ if (mProcs && mProcs->hotplug) {
+ DLOGTRACE("report hotplug on disp %d, connected %d", disp, connected);
+ mProcs->hotplug(const_cast<hwc_procs_t*>(mProcs), disp, connected);
+ DLOGTRACE("hotplug callback processed and returned!");
+ }
+#endif
+
+ mDisplayAnalyzer->postHotplugEvent(connected);
+}
+
+void Hwcomposer::invalidate()
+{
+ RETURN_VOID_IF_NOT_INIT();
+
+ if (mProcs && mProcs->invalidate) {
+ DLOGTRACE("invalidating screen...");
+ mProcs->invalidate(const_cast<hwc_procs_t*>(mProcs));
+ }
+}
+
+bool Hwcomposer::release()
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ return true;
+}
+
+bool Hwcomposer::dump(char *buff, int buff_len, int * /* cur_len */)
+{
+ RETURN_FALSE_IF_NOT_INIT();
+
+ Dump d(buff, buff_len);
+
+ // dump composer status
+ d.append("Hardware Composer state:");
+ // dump device status
+ for (size_t i= 0; i < mDisplayDevices.size(); i++) {
+ IDisplayDevice *device = mDisplayDevices.itemAt(i);
+ if (device)
+ device->dump(d);
+ }
+
+ // dump plane manager status
+ if (mPlaneManager)
+ mPlaneManager->dump(d);
+
+ // dump buffer manager status
+ if (mBufferManager)
+ mBufferManager->dump(d);
+
+ return true;
+}
+
+void Hwcomposer::registerProcs(hwc_procs_t const *procs)
+{
+ CTRACE();
+
+ if (!procs) {
+ WLOGTRACE("procs is NULL");
+ }
+ mProcs = procs;
+}
+
+bool Hwcomposer::initialize()
+{
+ CTRACE();
+
+ // create drm
+ mDrm = new Drm();
+ if (!mDrm || !mDrm->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to create DRM");
+ }
+
+ // create buffer manager
+ mBufferManager = createBufferManager();
+ if (!mBufferManager || !mBufferManager->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to create buffer manager");
+ }
+
+ // create display plane manager
+ mPlaneManager = createDisplayPlaneManager();
+ if (!mPlaneManager || !mPlaneManager->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to create display plane manager");
+ }
+
+ mDisplayContext = createDisplayContext();
+ if (!mDisplayContext || !mDisplayContext->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to create display context");
+ }
+
+ mUeventObserver = new UeventObserver();
+ if (!mUeventObserver || !mUeventObserver->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to initialize uevent observer");
+ }
+
+ // create display device
+ for (int i = 0; i < IDisplayDevice::DEVICE_COUNT; i++) {
+ IDisplayDevice *device = createDisplayDevice(i, *mPlaneManager);
+ if (!device || !device->initialize()) {
+ DEINIT_AND_DELETE_OBJ(device);
+ DEINIT_AND_RETURN_FALSE("failed to create device %d", i);
+ }
+ // add this device
+ mDisplayDevices.insertAt(device, i, 1);
+ }
+
+ mDisplayAnalyzer = new DisplayAnalyzer();
+ if (!mDisplayAnalyzer || !mDisplayAnalyzer->initialize()) {
+ DEINIT_AND_RETURN_FALSE("failed to initialize display analyzer");
+ }
+
+ // all initialized, starting uevent observer
+ mUeventObserver->start();
+
+ mInitialized = true;
+ return true;
+}
+
+void Hwcomposer::deinitialize()
+{
+ DEINIT_AND_DELETE_OBJ(mDisplayAnalyzer);
+
+ DEINIT_AND_DELETE_OBJ(mUeventObserver);
+ // destroy display devices
+ for (size_t i = 0; i < mDisplayDevices.size(); i++) {
+ IDisplayDevice *device = mDisplayDevices.itemAt(i);
+ DEINIT_AND_DELETE_OBJ(device);
+ }
+ mDisplayDevices.clear();
+
+ DEINIT_AND_DELETE_OBJ(mDisplayContext);
+ DEINIT_AND_DELETE_OBJ(mPlaneManager);
+ DEINIT_AND_DELETE_OBJ(mBufferManager);
+ DEINIT_AND_DELETE_OBJ(mDrm);
+ mInitialized = false;
+}
+
+Drm* Hwcomposer::getDrm()
+{
+ return mDrm;
+}
+
+DisplayPlaneManager* Hwcomposer::getPlaneManager()
+{
+ return mPlaneManager;
+}
+
+BufferManager* Hwcomposer::getBufferManager()
+{
+ return mBufferManager;
+}
+
+IDisplayContext* Hwcomposer::getDisplayContext()
+{
+ return mDisplayContext;
+}
+
+DisplayAnalyzer* Hwcomposer::getDisplayAnalyzer()
+{
+ return mDisplayAnalyzer;
+}
+
+IDisplayDevice* Hwcomposer::getDisplayDevice(int disp)
+{
+ if (disp < 0 || disp >= IDisplayDevice::DEVICE_COUNT) {
+ ELOGTRACE("invalid disp %d", disp);
+ return NULL;
+ }
+ if (disp >= (int) mDisplayDevices.size()) {
+ return NULL;
+ }
+ return mDisplayDevices.itemAt(disp);
+}
+
+UeventObserver* Hwcomposer::getUeventObserver()
+{
+ return mUeventObserver;
+}
+
+
+} // namespace intel
+} // namespace android
diff --git a/moorefield_hdmi/common/base/SimpleThread.h b/moorefield_hdmi/common/base/SimpleThread.h
new file mode 100644
index 0000000..ade0e84
--- /dev/null
+++ b/moorefield_hdmi/common/base/SimpleThread.h
@@ -0,0 +1,38 @@
+/*
+// Copyright (c) 2014 Intel Corporation 
+//
+// 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 SIMPLE_THREAD_H
+#define SIMPLE_THREAD_H
+
+#include <utils/threads.h>
+
+#define DECLARE_THREAD(THREADNAME, THREADOWNER) \
+ class THREADNAME: public Thread { \
+ public: \
+ THREADNAME(THREADOWNER *owner) { mOwner = owner; } \
+ THREADNAME() { mOwner = NULL; } \
+ private: \
+ virtual bool threadLoop() { return mOwner->threadLoop(); } \
+ private: \
+ THREADOWNER *mOwner; \
+ }; \
+ friend class THREADNAME; \
+ bool threadLoop(); \
+ sp<THREADNAME> mThread;
+
+
+#endif /* SIMPLE_THREAD_H */
+