blob: 954688e5dfe2746f0bd50e0d9926898ba214b65b [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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 LOG_TAG "hwc.cf_x86"
#define HWC_REMOVE_DEPRECATED_VERSIONS 1
#define IS_TARGET_FRAMEBUFFER(x) ((x) == HWC_FRAMEBUFFER_TARGET)
#define IS_PRIMARY_DISPLAY(x) ((x) == HWC_DISPLAY_PRIMARY)
#define CUTF_CVM_HWC_DEVICE_API_VERSION HWC_DEVICE_API_VERSION_1_1
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <string>
#include "log/log.h"
#include "guest/hals/hwcomposer/common/hwcomposer.h"
#include "guest/libs/platform_support/api_level_fixes.h"
#include "hardware/hwcomposer.h"
#include "hardware/hwcomposer_defs.h"
typedef hwc_composer_device_1_t cutf_cvm_hwc_device;
struct cutf_cvm_hwc_composer_device_1_t {
cutf_cvm_hwc_device base;
cvd::hwc_composer_device_data_t vsync_data;
};
static int cutf_cvm_hwc_prepare(cutf_cvm_hwc_device* dev __unused, size_t numDisplays,
hwc_display_contents_1_t** displays) {
hwc_display_contents_1_t* list = displays[HWC_DISPLAY_PRIMARY];
if (!numDisplays || !displays || !list)
return 0;
for (size_t i = 0; i < list->numHwLayers; i++) {
if (IS_TARGET_FRAMEBUFFER(list->hwLayers[i].compositionType)) {
continue;
}
list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
}
return 0;
}
static int cutf_cvm_hwc_set(cutf_cvm_hwc_device* dev __unused, size_t numDisplays __unused,
hwc_display_contents_1_t** displays __unused) {
// TODO: b/125482910
return 0;
}
static void cutf_cvm_hwc_register_procs(cutf_cvm_hwc_device* dev,
const hwc_procs_t* procs) {
struct cutf_cvm_hwc_composer_device_1_t* pdev =
(struct cutf_cvm_hwc_composer_device_1_t*)dev;
pdev->vsync_data.procs = procs;
}
static int cutf_cvm_hwc_query(cutf_cvm_hwc_device* dev __unused, int what __unused, int* value) {
// TODO: b/125482910
struct cutf_cvm_hwc_composer_device_1_t* pdev =
(struct cutf_cvm_hwc_composer_device_1_t*)dev;
switch (what) {
case HWC_BACKGROUND_LAYER_SUPPORTED:
*value = 0;
break;
case HWC_VSYNC_PERIOD:
*value = pdev->vsync_data.vsync_period_ns;
break;
default:
// unsupported query
ALOGE("%s: badness unsupported query what=%d", __FUNCTION__, what);
return -EINVAL;
}
return 0;
}
static int cutf_cvm_hwc_event_control(
cutf_cvm_hwc_device* /*dev*/, int /*dpy*/, int event __unused, int /*enabled*/) {
// TODO: b/125482910
return 0;
}
static int cutf_cvm_hwc_blank(cutf_cvm_hwc_device* /*dev*/, int disp __unused, int /*blank*/) {
// TODO: b/125482910
return 0;
}
static void cutf_cvm_hwc_dump(cutf_cvm_hwc_device* dev __unused, char* buff __unused, int buff_len __unused) {
// TODO: b/125482910
}
static int cutf_cvm_hwc_get_display_configs(cutf_cvm_hwc_device* /*dev*/, int disp __unused,
uint32_t* configs __unused, size_t* numConfigs __unused) {
// TODO: b/125482910
return 0;
}
static int32_t cutf_cvm_hwc_attribute(struct cutf_cvm_hwc_composer_device_1_t* pdev,
const uint32_t attribute) {
// TODO: b/125482910
switch (attribute) {
case HWC_DISPLAY_VSYNC_PERIOD:
return pdev->vsync_data.vsync_period_ns;
case HWC_DISPLAY_WIDTH:
return 720;
case HWC_DISPLAY_HEIGHT:
return 1280;
case HWC_DISPLAY_DPI_X:
ALOGI("%s: Reporting DPI_X of %d", __FUNCTION__, 1);
// The number of pixels per thousand inches
return 240000;
case HWC_DISPLAY_DPI_Y:
ALOGI("%s: Reporting DPI_Y of %d", __FUNCTION__, 1);
// The number of pixels per thousand inches
return 240000;
default:
ALOGE("%s: unknown display attribute %u", __FUNCTION__, attribute);
return -EINVAL;
}
}
static int cutf_cvm_hwc_get_display_attributes(cutf_cvm_hwc_device* dev __unused, int disp __unused,
uint32_t config __unused,
const uint32_t* attributes __unused,
int32_t* values __unused) {
struct cutf_cvm_hwc_composer_device_1_t* pdev =
(struct cutf_cvm_hwc_composer_device_1_t*)dev;
if (!IS_PRIMARY_DISPLAY(disp)) {
ALOGE("%s: unknown display type %u", __FUNCTION__, disp);
return -EINVAL;
}
for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
values[i] = cutf_cvm_hwc_attribute(pdev, attributes[i]);
}
return 0;
}
static int cutf_cvm_hwc_close(hw_device_t* device) {
struct cutf_cvm_hwc_composer_device_1_t* dev =
(struct cutf_cvm_hwc_composer_device_1_t*)device;
delete dev;
return 0;
}
static int cutf_cvm_hwc_open(const struct hw_module_t* module, const char* name,
struct hw_device_t** device) {
ALOGI("%s", __FUNCTION__);
if (strcmp(name, HWC_HARDWARE_COMPOSER) != 0) {
ALOGE("%s: called with bad name %s", __FUNCTION__, name);
return -EINVAL;
}
cutf_cvm_hwc_composer_device_1_t* dev = new cutf_cvm_hwc_composer_device_1_t();
if (!dev) {
ALOGE("%s: failed to allocate dev", __FUNCTION__);
return -ENOMEM;
}
const int refreshRate = 60;
const int nsPerSec = 1000000000;
dev->vsync_data.vsync_period_ns = nsPerSec / refreshRate;
struct timespec rt;
if (clock_gettime(CLOCK_MONOTONIC, &rt) != 0) {
ALOGE("%s: error in clock_gettime: %s", __FUNCTION__, strerror(errno));
}
dev->vsync_data.vsync_base_timestamp = int64_t(rt.tv_sec) * nsPerSec + rt.tv_nsec;
dev->base.common.tag = HARDWARE_DEVICE_TAG;
dev->base.common.version = CUTF_CVM_HWC_DEVICE_API_VERSION;
dev->base.common.module = const_cast<hw_module_t*>(module);
dev->base.common.close = cutf_cvm_hwc_close;
dev->base.prepare = cutf_cvm_hwc_prepare;
dev->base.set = cutf_cvm_hwc_set;
dev->base.query = cutf_cvm_hwc_query;
dev->base.registerProcs = cutf_cvm_hwc_register_procs;
dev->base.dump = cutf_cvm_hwc_dump;
dev->base.blank = cutf_cvm_hwc_blank;
dev->base.eventControl = cutf_cvm_hwc_event_control;
dev->base.getDisplayConfigs = cutf_cvm_hwc_get_display_configs;
dev->base.getDisplayAttributes = cutf_cvm_hwc_get_display_attributes;
int ret = pthread_create(&dev->vsync_data.vsync_thread, NULL, cvd::hwc_vsync_thread, &dev->vsync_data);
if (ret != 0) {
ALOGE("%s: failed to start vsync thread: %s", __FUNCTION__, strerror(ret));
dev->base.common.close(&dev->base.common);
return -ret;
}
*device = &dev->base.common;
return ret;
}
static struct hw_module_methods_t cutf_cvm_hwc_module_methods = {
cutf_cvm_hwc_open,
};
hwc_module_t HAL_MODULE_INFO_SYM = {{HARDWARE_MODULE_TAG,
HWC_MODULE_API_VERSION_0_1,
HARDWARE_HAL_API_VERSION,
HWC_HARDWARE_MODULE_ID,
"cutf_cvm hwcomposer module",
"Google",
&cutf_cvm_hwc_module_methods,
NULL,
{0}}};