| /* |
| * 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t destroy_virtual_display(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| void dump(hwc2_device_t* /*device*/, uint32_t* /*out_size*/, |
| char* /*out_buffer*/) |
| { |
| return; |
| } |
| |
| uint32_t get_max_virtual_display_count(hwc2_device_t* /*device*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t present_display(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/, int32_t* /*out_present_fence*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t set_color_mode(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/, android_color_mode_t /*mode*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t set_color_transform(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/, const float* /*matrix*/, |
| android_color_transform_t /*hint*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t set_output_buffer(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/, buffer_handle_t /*buffer*/, |
| int32_t /*release_fence*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t set_cursor_position(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/, hwc2_layer_t /*layer*/, int32_t /*x*/, |
| int32_t /*y*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| hwc2_error_t set_layer_surface_damage(hwc2_device_t* /*device*/, |
| hwc2_display_t /*display*/, hwc2_layer_t /*layer*/, |
| hwc_region_t /*damage*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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*/) |
| { |
| return HWC2_ERROR_NONE; |
| } |
| |
| 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; |
| } |