/* // 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_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; } // Todo: add hwc_setCursorPositionAsync after supporting patches /* 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 }, } };