1/* 2// Copyright (c) 2014 Intel Corporation 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15*/ 16 17#define ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) 18 19#include <hardware/hardware.h> 20#include <string.h> 21#include <stdio.h> 22#include <fcntl.h> 23#include <errno.h> 24#include <common/utils/HwcTrace.h> 25#include <Hwcomposer.h> 26#include <utils/Trace.h> 27 28#define GET_HWC_RETURN_X_IF_NULL(X) \ 29 CTRACE(); \ 30 Hwcomposer *hwc = static_cast<Hwcomposer*>(dev); \ 31 do {\ 32 if (!hwc) { \ 33 ELOGTRACE("invalid HWC device."); \ 34 return X; \ 35 } \ 36 } while (0) 37 38 39#define GET_HWC_RETURN_ERROR_IF_NULL() GET_HWC_RETURN_X_IF_NULL(-EINVAL) 40#define GET_HWC_RETURN_VOID_IF_NULL() GET_HWC_RETURN_X_IF_NULL() 41 42 43namespace android { 44namespace intel { 45 46static int hwc_prepare(struct hwc_composer_device_1 *dev, 47 size_t numDisplays, 48 hwc_display_contents_1_t** displays) 49{ 50 ATRACE_CALL(); 51 GET_HWC_RETURN_ERROR_IF_NULL(); 52 if (!hwc->prepare(numDisplays, displays)) { 53 ELOGTRACE("failed to prepare"); 54 return -EINVAL; 55 } 56 return 0; 57} 58 59static int hwc_set(struct hwc_composer_device_1 *dev, 60 size_t numDisplays, 61 hwc_display_contents_1_t **displays) 62{ 63 ATRACE_CALL(); 64 GET_HWC_RETURN_ERROR_IF_NULL(); 65 if (!hwc->commit(numDisplays, displays)) { 66 ELOGTRACE("failed to commit"); 67 return -EINVAL; 68 } 69 return 0; 70} 71 72static void hwc_dump(struct hwc_composer_device_1 *dev, 73 char *buff, 74 int buff_len) 75{ 76 GET_HWC_RETURN_VOID_IF_NULL(); 77 hwc->dump(buff, buff_len, 0); 78} 79 80void hwc_registerProcs(struct hwc_composer_device_1 *dev, 81 hwc_procs_t const *procs) 82{ 83 GET_HWC_RETURN_VOID_IF_NULL(); 84 hwc->registerProcs(procs); 85} 86 87static int hwc_device_close(struct hw_device_t * /* dev */) 88{ 89 CTRACE(); 90 Hwcomposer::releaseInstance(); 91 return 0; 92} 93 94static int hwc_query(struct hwc_composer_device_1 * /* dev */, 95 int what, int* /* value */) 96{ 97 (void) what; 98 ALOGTRACE("what = %d", what); 99 return -EINVAL; 100} 101 102static int hwc_eventControl(struct hwc_composer_device_1 *dev, 103 int disp, 104 int event, 105 int enabled) 106{ 107 bool ret; 108 ATRACE_CALL(); 109 GET_HWC_RETURN_ERROR_IF_NULL(); 110 111 switch (event) { 112 case HWC_EVENT_VSYNC: 113 ret = hwc->vsyncControl(disp, enabled); 114 if (ret == false) { 115 ELOGTRACE("failed to control vsync"); 116 return -EINVAL; 117 } 118 break; 119 default: 120 WLOGTRACE("unsupported event %d", event); 121 break; 122 } 123 124 return 0; 125} 126 127static int hwc_getDisplayConfigs(hwc_composer_device_1_t *dev, 128 int disp, 129 uint32_t *configs, 130 size_t *numConfigs) 131{ 132 ATRACE_CALL(); 133 GET_HWC_RETURN_ERROR_IF_NULL(); 134 bool ret = hwc->getDisplayConfigs(disp, configs, numConfigs); 135 if (ret == false) { 136 WLOGTRACE("failed to get configs of disp %d", disp); 137 return -EINVAL; 138 } 139 140 return 0; 141} 142 143static int hwc_getDisplayAttributes(hwc_composer_device_1_t *dev, 144 int disp, 145 uint32_t config, 146 const uint32_t *attributes, 147 int32_t *values) 148{ 149 ATRACE_CALL(); 150 GET_HWC_RETURN_ERROR_IF_NULL(); 151 bool ret = hwc->getDisplayAttributes(disp, config, attributes, values); 152 if (ret == false) { 153 WLOGTRACE("failed to get attributes of disp %d", disp); 154 return -EINVAL; 155 } 156 157 return 0; 158} 159 160static int hwc_compositionComplete(hwc_composer_device_1_t *dev, int disp) 161{ 162 ATRACE_CALL(); 163 GET_HWC_RETURN_ERROR_IF_NULL(); 164 bool ret = hwc->compositionComplete(disp); 165 if (ret == false) { 166 ELOGTRACE("failed for disp %d", disp); 167 return -EINVAL; 168 } 169 170 return 0; 171} 172 173static int hwc_setPowerMode(hwc_composer_device_1_t *dev, int disp, int mode) 174{ 175 ATRACE_CALL(); 176 GET_HWC_RETURN_ERROR_IF_NULL(); 177 bool ret = hwc->setPowerMode(disp, mode); 178 if (ret == false) { 179 WLOGTRACE("failed to set power mode of disp %d", disp); 180 return -EINVAL; 181 } 182 183 return 0; 184} 185 186static int hwc_getActiveConfig(hwc_composer_device_1_t *dev, int disp) 187{ 188 ATRACE_CALL(); 189 GET_HWC_RETURN_ERROR_IF_NULL(); 190 int ret = hwc->getActiveConfig(disp); 191 if (ret == -1) { 192 WLOGTRACE("failed to get active config of disp %d", disp); 193 return -EINVAL; 194 } 195 196 return ret; 197} 198 199static int hwc_setActiveConfig(hwc_composer_device_1_t *dev, int disp, int index) 200{ 201 ATRACE_CALL(); 202 GET_HWC_RETURN_ERROR_IF_NULL(); 203 bool ret = hwc->setActiveConfig(disp, index); 204 if (ret == false) { 205 WLOGTRACE("failed to set active config of disp %d", disp); 206 return -EINVAL; 207 } 208 209 return 0; 210} 211 212// Todo: add hwc_setCursorPositionAsync after supporting patches 213/* 214static int hwc_setCursorPositionAsync(hwc_composer_device_1_t *dev, int disp, int x, int y) 215{ 216 ATRACE_CALL(); 217 GET_HWC_RETURN_ERROR_IF_NULL(); 218 bool ret = hwc->setCursorPositionAsync(disp, x, y); 219 if (ret == false) { 220 WLOGTRACE("failed to set cursor position of disp %d", disp); 221 return -EINVAL; 222 } 223 224 return 0; 225} 226*/ 227 228//------------------------------------------------------------------------------ 229 230static int hwc_device_open(const struct hw_module_t* module, 231 const char* name, 232 struct hw_device_t** device) 233{ 234 if (!name) { 235 ELOGTRACE("invalid name."); 236 return -EINVAL; 237 } 238 239 ALOGTRACE("open device %s", name); 240 241 if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) { 242 ELOGTRACE("try to open unknown HWComposer %s", name); 243 return -EINVAL; 244 } 245 246 Hwcomposer& hwc = Hwcomposer::getInstance(); 247 // initialize our state here 248 if (hwc.initialize() == false) { 249 ELOGTRACE("failed to intialize HWComposer"); 250 Hwcomposer::releaseInstance(); 251 return -EINVAL; 252 } 253 254 // initialize the procs 255 hwc.hwc_composer_device_1_t::common.tag = HARDWARE_DEVICE_TAG; 256 hwc.hwc_composer_device_1_t::common.module = 257 const_cast<hw_module_t*>(module); 258 hwc.hwc_composer_device_1_t::common.close = hwc_device_close; 259 260 hwc.hwc_composer_device_1_t::prepare = hwc_prepare; 261 hwc.hwc_composer_device_1_t::set = hwc_set; 262 hwc.hwc_composer_device_1_t::dump = hwc_dump; 263 hwc.hwc_composer_device_1_t::registerProcs = hwc_registerProcs; 264 hwc.hwc_composer_device_1_t::query = hwc_query; 265 266 hwc.hwc_composer_device_1_t::eventControl = hwc_eventControl; 267 hwc.hwc_composer_device_1_t::getDisplayConfigs = hwc_getDisplayConfigs; 268 hwc.hwc_composer_device_1_t::getDisplayAttributes = hwc_getDisplayAttributes; 269 270 // This is used to hack FBO switch flush issue in SurfaceFlinger. 271 hwc.hwc_composer_device_1_t::reserved_proc[0] = (void*)hwc_compositionComplete; 272 hwc.hwc_composer_device_1_t::common.version = HWC_DEVICE_API_VERSION_1_4; 273 hwc.hwc_composer_device_1_t::setPowerMode = hwc_setPowerMode; 274 hwc.hwc_composer_device_1_t::getActiveConfig = hwc_getActiveConfig; 275 hwc.hwc_composer_device_1_t::setActiveConfig = hwc_setActiveConfig; 276 // Todo: add hwc_setCursorPositionAsync after supporting patches 277 hwc.hwc_composer_device_1_t::setCursorPositionAsync = NULL; 278 279 *device = &hwc.hwc_composer_device_1_t::common; 280 281 return 0; 282} 283 284} // namespace intel 285} // namespace android 286 287static struct hw_module_methods_t hwc_module_methods = { 288 open: android::intel::hwc_device_open 289}; 290 291hwc_module_t HAL_MODULE_INFO_SYM = { 292 common: { 293 tag: HARDWARE_MODULE_TAG, 294 version_major: 1, 295 version_minor: 4, 296 id: HWC_HARDWARE_MODULE_ID, 297 name: "Intel Hardware Composer", 298 author: "Intel", 299 methods: &hwc_module_methods, 300 dso: 0, 301 reserved: { 0 }, 302 } 303}; 304