blob: 53b191cac42a1e859a73a9841d4cddd860e3123a [file] [log] [blame]
/*
* Copyright (C) 2016 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.
*/
#include <cutils/log.h>
#include <inttypes.h>
#include <cstdlib>
#include <new>
#include <array>
#include "hwc2.h"
static int hwc2_device_open(const struct hw_module_t *module, const char *name,
struct hw_device_t **device);
static int32_t hwc2_device_close(struct hw_device_t *device);
static struct hw_module_methods_t hwc2_module_methods = {
.open = hwc2_device_open
};
hw_module_t HAL_MODULE_INFO_SYM = {
.tag = HARDWARE_MODULE_TAG,
.id = HWC_HARDWARE_MODULE_ID,
.name = "NVIDIA Tegra hwcomposer module",
.author = "AOSP",
.methods = &hwc2_module_methods,
};
hwc2_error_t create_virtual_display(hwc2_device_t *device, uint32_t width,
uint32_t height, android_pixel_format_t *format,
hwc2_display_t *out_display)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->create_virtual_display(width, height, format, out_display);
}
hwc2_error_t destroy_virtual_display(hwc2_device_t *device,
hwc2_display_t display)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->destroy_virtual_display(display);
}
void dump(hwc2_device_t *device, uint32_t *out_size, char *out_buffer)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
dev->dump_hwc2(out_size, out_buffer);
}
uint32_t get_max_virtual_display_count(hwc2_device_t *device)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_max_virtual_display_count();
}
hwc2_error_t register_callback(hwc2_device_t *device,
hwc2_callback_descriptor_t descriptor,
hwc2_callback_data_t callback_data, hwc2_function_pointer_t pointer)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->register_callback(descriptor, callback_data, pointer);
}
hwc2_error_t accept_display_changes(hwc2_device_t *device,
hwc2_display_t display)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->accept_display_changes(display);
}
hwc2_error_t create_layer(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t *out_layer)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->create_layer(display, out_layer);
}
hwc2_error_t destroy_layer(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->destroy_layer(display, layer);
}
hwc2_error_t get_active_config(hwc2_device_t *device, hwc2_display_t display,
hwc2_config_t *out_config)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_active_config(display, out_config);
}
hwc2_error_t get_changed_composition_types(hwc2_device_t *device,
hwc2_display_t display, uint32_t *out_num_elements,
hwc2_layer_t *out_layers, hwc2_composition_t *out_types)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_changed_composition_types(display, out_num_elements,
out_layers, out_types);
}
hwc2_error_t get_client_target_support(hwc2_device_t *device,
hwc2_display_t display, uint32_t width, uint32_t height,
android_pixel_format_t format, android_dataspace_t dataspace)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_client_target_support(display, width, height, format,
dataspace);
}
hwc2_error_t get_color_modes(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_modes, android_color_mode_t *out_modes)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_color_modes(display, out_num_modes, out_modes);
}
hwc2_error_t get_display_attribute(hwc2_device_t *device,
hwc2_display_t display, hwc2_config_t config,
hwc2_attribute_t attribute, int32_t *out_value)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_display_attribute(display, config, attribute, out_value);
}
hwc2_error_t get_display_configs(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_configs, hwc2_config_t *out_configs)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_display_configs(display, out_num_configs, out_configs);
}
hwc2_error_t get_display_name(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_size, char *out_name)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_display_name(display, out_size, out_name);
}
hwc2_error_t get_display_requests(hwc2_device_t *device, hwc2_display_t display,
hwc2_display_request_t *out_display_requests,
uint32_t *out_num_elements, hwc2_layer_t *out_layers,
hwc2_layer_request_t *out_layer_requests)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_display_requests(display, out_display_requests,
out_num_elements, out_layers, out_layer_requests);
}
hwc2_error_t get_display_type(hwc2_device_t *device, hwc2_display_t display,
hwc2_display_type_t *out_type)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_display_type(display, out_type);
}
hwc2_error_t get_doze_support(hwc2_device_t *device, hwc2_display_t display,
int32_t *out_support)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_doze_support(display, out_support);
}
hwc2_error_t get_hdr_capabilities(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_types, android_hdr_t *out_types,
float *out_max_luminance, float *out_max_average_luminance,
float *out_min_luminance)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_hdr_capabilities(display, out_num_types, out_types,
out_max_luminance, out_max_average_luminance, out_min_luminance);
}
hwc2_error_t get_release_fences(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_elements, hwc2_layer_t *out_layers,
int32_t *out_fences)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->get_release_fences(display, out_num_elements, out_layers,
out_fences);
}
hwc2_error_t present_display(hwc2_device_t *device, hwc2_display_t display,
int32_t *out_present_fence)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->present_display(display, out_present_fence);
}
hwc2_error_t set_active_config(hwc2_device_t *device, hwc2_display_t display,
hwc2_config_t config)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_active_config(display, config);
}
hwc2_error_t set_client_target(hwc2_device_t *device, hwc2_display_t display,
buffer_handle_t target, int32_t acquire_fence,
android_dataspace_t dataspace, hwc_region_t damage)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_client_target(display, target, acquire_fence, dataspace,
damage);
}
hwc2_error_t set_color_mode(hwc2_device_t *device, hwc2_display_t display,
android_color_mode_t mode)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_color_mode(display, mode);
}
hwc2_error_t set_color_transform(hwc2_device_t *device, hwc2_display_t display,
const float *matrix, android_color_transform_t hint)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_color_transform(display, matrix, hint);
}
hwc2_error_t set_output_buffer(hwc2_device_t *device, hwc2_display_t display,
buffer_handle_t buffer, int32_t release_fence)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_output_buffer(display, buffer, release_fence);
}
hwc2_error_t set_power_mode(hwc2_device_t *device, hwc2_display_t display,
hwc2_power_mode_t mode)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_power_mode(display, mode);
}
hwc2_error_t set_vsync_enabled(hwc2_device_t *device, hwc2_display_t display,
hwc2_vsync_t enabled)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_vsync_enabled(display, static_cast<hwc2_vsync_t>(enabled));
}
hwc2_error_t validate_display(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_types, uint32_t *out_num_requests)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->validate_display(display, out_num_types, out_num_requests);
}
hwc2_error_t set_cursor_position(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, int32_t x, int32_t y)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_cursor_position(display, layer, x, y);
}
hwc2_error_t set_layer_buffer(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, buffer_handle_t buffer, int32_t acquire_fence)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_buffer(display, layer, buffer, acquire_fence);
}
hwc2_error_t set_layer_surface_damage(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer, hwc_region_t damage)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_surface_damage(display, layer, damage);
}
hwc2_error_t set_layer_blend_mode(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, hwc2_blend_mode_t mode)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_blend_mode(display, layer, mode);
}
hwc2_error_t set_layer_color(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer,
hwc_color_t color)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_color(display, layer, color);
}
hwc2_error_t set_layer_composition_type(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer, hwc2_composition_t type)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_composition_type(display, layer, type);
}
hwc2_error_t set_layer_dataspace(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, android_dataspace_t dataspace)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_dataspace(display, layer, dataspace);
}
hwc2_error_t set_layer_display_frame(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer, hwc_rect_t frame)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_display_frame(display, layer, frame);
}
hwc2_error_t set_layer_plane_alpha(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer, float alpha)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_plane_alpha(display, layer, alpha);
}
hwc2_error_t set_layer_source_crop(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer, hwc_frect_t crop)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_source_crop(display, layer, crop);
}
hwc2_error_t set_layer_transform(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, hwc_transform_t transform)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_transform(display, layer, transform);
}
hwc2_error_t set_layer_visible_region(hwc2_device_t *device,
hwc2_display_t display, hwc2_layer_t layer, hwc_region_t visible)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_visible_region(display, layer, visible);
}
hwc2_error_t set_layer_z_order(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, uint32_t z)
{
hwc2_dev *dev = reinterpret_cast<hwc2_context *>(device)->hwc2_dev;
return dev->set_layer_z_order(display, layer, z);
}
/* Indexed using the hwc2_function_descriptor_t enum to find the corresponding
* function */
static const std::array<hwc2_function_pointer_t, 44> hwc2_func_ptrs = {{
/* Index 0 corresponds to HWC2_FUNCTION_INVALID */
(hwc2_function_pointer_t) nullptr,
(hwc2_function_pointer_t) accept_display_changes,
(hwc2_function_pointer_t) create_layer,
(hwc2_function_pointer_t) create_virtual_display,
(hwc2_function_pointer_t) destroy_layer,
(hwc2_function_pointer_t) destroy_virtual_display,
(hwc2_function_pointer_t) dump,
(hwc2_function_pointer_t) get_active_config,
(hwc2_function_pointer_t) get_changed_composition_types,
(hwc2_function_pointer_t) get_client_target_support,
(hwc2_function_pointer_t) get_color_modes,
(hwc2_function_pointer_t) get_display_attribute,
(hwc2_function_pointer_t) get_display_configs,
(hwc2_function_pointer_t) get_display_name,
(hwc2_function_pointer_t) get_display_requests,
(hwc2_function_pointer_t) get_display_type,
(hwc2_function_pointer_t) get_doze_support,
(hwc2_function_pointer_t) get_hdr_capabilities,
(hwc2_function_pointer_t) get_max_virtual_display_count,
(hwc2_function_pointer_t) get_release_fences,
(hwc2_function_pointer_t) present_display,
(hwc2_function_pointer_t) register_callback,
(hwc2_function_pointer_t) set_active_config,
(hwc2_function_pointer_t) set_client_target,
(hwc2_function_pointer_t) set_color_mode,
(hwc2_function_pointer_t) set_color_transform,
(hwc2_function_pointer_t) set_cursor_position,
(hwc2_function_pointer_t) set_layer_blend_mode,
(hwc2_function_pointer_t) set_layer_buffer,
(hwc2_function_pointer_t) set_layer_color,
(hwc2_function_pointer_t) set_layer_composition_type,
(hwc2_function_pointer_t) set_layer_dataspace,
(hwc2_function_pointer_t) set_layer_display_frame,
(hwc2_function_pointer_t) set_layer_plane_alpha,
(hwc2_function_pointer_t) nullptr, /*set_layer_sideband_stream unsupported*/
(hwc2_function_pointer_t) set_layer_source_crop,
(hwc2_function_pointer_t) set_layer_surface_damage,
(hwc2_function_pointer_t) set_layer_transform,
(hwc2_function_pointer_t) set_layer_visible_region,
(hwc2_function_pointer_t) set_layer_z_order,
(hwc2_function_pointer_t) set_output_buffer,
(hwc2_function_pointer_t) set_power_mode,
(hwc2_function_pointer_t) set_vsync_enabled,
(hwc2_function_pointer_t) validate_display,
}};
hwc2_function_pointer_t get_function(struct hwc2_device* /*device*/,
/*hwc2_function_descriptor_t*/ int32_t descriptor)
{
if (descriptor == HWC2_FUNCTION_INVALID ||
static_cast<size_t>(descriptor) >= hwc2_func_ptrs.size()) {
ALOGW("invalid descriptor");
return nullptr;
}
return hwc2_func_ptrs[descriptor];
}
void get_capabilities(struct hwc2_device* /*device*/, uint32_t *out_count,
/*hwc2_capability_t*/ int32_t* /*outCapabilities*/)
{
*out_count = 0;
}
static int32_t hwc2_device_close(struct hw_device_t *device)
{
hwc2_context *ctx = reinterpret_cast<hwc2_context *>(device);
delete ctx->hwc2_dev;
delete ctx;
return 0;
}
static int hwc2_device_open(const struct hw_module_t *module, const char *name,
struct hw_device_t **hw_device)
{
if (strcmp(name, HWC_HARDWARE_COMPOSER))
return -EINVAL;
hwc2_context *ctx = new hwc2_context();
if (!ctx) {
ALOGE("failed to allocate hwc2_context");
return -ENOMEM;
}
ctx->hwc2_device.common.tag = HARDWARE_DEVICE_TAG;
ctx->hwc2_device.common.version = HWC_DEVICE_API_VERSION_2_0;
ctx->hwc2_device.common.module = const_cast<hw_module_t *>(module);
ctx->hwc2_device.common.close = hwc2_device_close;
ctx->hwc2_device.getFunction = get_function;
ctx->hwc2_device.getCapabilities = get_capabilities;
ctx->hwc2_dev = new hwc2_dev();
if (!ctx->hwc2_dev) {
ALOGE("failed to allocate hwc2_dev");
delete ctx;
return -ENOMEM;
}
int ret = ctx->hwc2_dev->open_adf_device();
if (ret < 0) {
ALOGE("failed to open adf device: %s", strerror(ret));
delete ctx->hwc2_dev;
delete ctx;
return ret;
}
*hw_device = &ctx->hwc2_device.common;
return 0;
}