From 1f0144133777a04d923588f49d8a7d7390ca95b3 Mon Sep 17 00:00:00 2001 From: lihaihong Date: Mon, 18 Nov 2024 09:51:38 +0800 Subject: [PATCH 1/4] Composition with vpp Signed-off-by: lihaihong --- Android.bp | 17 +- backend/Backend.cpp | 52 +-- backend/Backend.h | 1 + gralloc1/gralloc1bufferhandler.cpp | 360 +++++++++++++++ gralloc1/gralloc1bufferhandler.h | 81 ++++ hwc2_device/HwcDisplay.cpp | 45 +- hwc2_device/HwcDisplay.h | 1 + hwc2_device/HwcLayer.cpp | 73 ++++ hwc2_device/HwcLayer.h | 43 +- include/drmhwcgralloc.h | 36 ++ include/nativebufferhandler.h | 61 +++ utils/autolock.cpp | 57 +++ utils/autolock.h | 42 ++ va/varenderer.cpp | 680 +++++++++++++++++++++++++++++ va/varenderer.h | 222 ++++++++++ va/vautils.cpp | 277 ++++++++++++ va/vautils.h | 43 ++ 17 files changed, 2032 insertions(+), 59 deletions(-) create mode 100755 gralloc1/gralloc1bufferhandler.cpp create mode 100755 gralloc1/gralloc1bufferhandler.h create mode 100644 include/drmhwcgralloc.h create mode 100755 include/nativebufferhandler.h create mode 100644 utils/autolock.cpp create mode 100644 utils/autolock.h create mode 100755 va/varenderer.cpp create mode 100755 va/varenderer.h create mode 100755 va/vautils.cpp create mode 100755 va/vautils.h diff --git a/Android.bp b/Android.bp index cb3ac78c..5d22c0b1 100644 --- a/Android.bp +++ b/Android.bp @@ -49,9 +49,18 @@ cc_defaults { "libsync", "libui", "libutils", + "libva", + "libva-android", ], - include_dirs: ["vendor/intel/external/drm-hwcomposer"], + include_dirs: [ + "vendor/intel/external/drm-hwcomposer", + "vendor/intel/external/drm-hwcomposer/va", + "vendor/intel/external/drm-hwcomposer/include", + "hardware/intel/external/minigbm-intel/cros_gralloc", + "hardware/intel/external/libva", + "hardware/intel/external/drm-intel/android", + ], header_libs: [ "android.hardware.graphics.composer3-command-buffer", @@ -68,6 +77,7 @@ cc_defaults { "-DHWC2_USE_CPP11", "-std=c++17", "-DUSE_IMAPPER4_METADATA_API", + "-DUSE_GRALLOC1", ], product_variables: { @@ -111,6 +121,11 @@ filegroup { "hwc2_device/HwcDisplayConfigs.cpp", "hwc2_device/HwcLayer.cpp", "hwc2_device/hwc2_device.cpp", + + "va/varenderer.cpp", + "va/vautils.cpp", + "utils/autolock.cpp", + "gralloc1/gralloc1bufferhandler.cpp", ], } diff --git a/backend/Backend.cpp b/backend/Backend.cpp index 07194f03..98b74593 100644 --- a/backend/Backend.cpp +++ b/backend/Backend.cpp @@ -52,18 +52,6 @@ HWC2::Error Backend::ValidateDisplay(HwcDisplay *display, uint32_t *num_types, std::tie(client_start, client_size) = GetClientLayers(display, layers); MarkValidated(layers, client_start, client_size); - - bool testing_needed = !(client_start == 0 && client_size == layers.size()); - - AtomicCommitArgs a_args = {.test_only = true}; - - if (testing_needed && - display->CreateComposition(a_args) != HWC2::Error::None) { - ++display->total_stats().failed_kms_validate_; - client_start = 0; - client_size = layers.size(); - MarkValidated(layers, 0, client_size); - } } *num_types = client_size; @@ -80,43 +68,15 @@ std::tuple Backend::GetClientLayers( int client_start = -1; size_t client_size = 0; - int device_start = -1; - size_t device_size = 0; for (size_t z_order = 0; z_order < layers.size(); ++z_order) { if (IsClientLayer(display, layers[z_order])) { if (client_start < 0) client_start = (int)z_order; client_size = (z_order - client_start) + 1; } - if (IsVideoLayer(layers[z_order])) { - if (device_start < 0) - device_start = (int)z_order; - device_size = (z_order - device_start) + 1; - } - } - if (device_size == 0) - return GetExtraClientRange(display, layers, client_start, client_size); - else { - bool status = true; - MarkValidated(layers, client_start, client_size); - for (size_t z_order = 0; z_order < layers.size(); ++z_order) { - if (z_order >= client_start && - z_order <= (client_start + client_size - 1) && - IsVideoLayer(layers[z_order])) - status = false; - - if (z_order >= device_start && - z_order <= (device_start + device_size - 1) && - layers[z_order]->GetValidatedType() == HWC2::Composition::Client) - status = false; - } - if (!status) { - ALOGE("status is abnormal"); - return GetExtraClientRange(display, layers, client_start, client_size); - } - return GetExtraClientRange2(display, layers, client_start, client_size, device_start, device_size); } + return std::make_tuple(client_start, client_size); } bool Backend::IsClientLayer(HwcDisplay *display, HwcLayer *layer) { @@ -124,8 +84,7 @@ bool Backend::IsClientLayer(HwcDisplay *display, HwcLayer *layer) { !layer->IsLayerUsableAsDevice() || display->color_transform_hint() != HAL_COLOR_TRANSFORM_IDENTITY || (layer->GetLayerData().pi.RequireScalingOrPhasing() && - display->GetHwc2()->GetResMan().ForcedScalingWithGpu()) || - (!display->IsInHeadlessMode() && display->GetPipe().device->IsIvshmDev()); + display->GetHwc2()->GetResMan().ForcedScalingWithGpu()); } bool Backend::IsVideoLayer(HwcLayer *layer) { @@ -155,10 +114,13 @@ uint32_t Backend::CalcPixOps(const std::vector &layers, void Backend::MarkValidated(std::vector &layers, size_t client_first_z, size_t client_size) { for (size_t z_order = 0; z_order < layers.size(); ++z_order) { - if (z_order >= client_first_z && z_order < client_first_z + client_size) + if (z_order >= client_first_z && z_order < client_first_z + client_size) { layers[z_order]->SetValidatedType(HWC2::Composition::Client); - else + layers[z_order]->SetUseVPPCompose(false); + } else { layers[z_order]->SetValidatedType(HWC2::Composition::Device); + layers[z_order]->SetUseVPPCompose(true); + } } } diff --git a/backend/Backend.h b/backend/Backend.h index 9b4688ec..cc6ab636 100644 --- a/backend/Backend.h +++ b/backend/Backend.h @@ -36,6 +36,7 @@ class Backend { size_t first_z, size_t size); static void MarkValidated(std::vector &layers, size_t client_first_z, size_t client_size); + static void vaMarkValidated(std::vector &layers); static std::tuple GetExtraClientRange( HwcDisplay *display, const std::vector &layers, int client_start, size_t client_size); diff --git a/gralloc1/gralloc1bufferhandler.cpp b/gralloc1/gralloc1bufferhandler.cpp new file mode 100755 index 00000000..3ad8b742 --- /dev/null +++ b/gralloc1/gralloc1bufferhandler.cpp @@ -0,0 +1,360 @@ +/* + * 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 "gralloc1bufferhandler.h" + +#include +#include +#include +#include +#include "vautils.h" +#include +#include "cros_gralloc_handle.h" +#include "drm_fourcc.h" + + +namespace android { + +// static +NativeBufferHandler *NativeBufferHandler::CreateInstance(uint32_t fd) { + Gralloc1BufferHandler *handler = new Gralloc1BufferHandler(fd); + if (!handler) + return NULL; + + if (!handler->Init()) { + ALOGE("Failed to initialize GralocBufferHandlers."); + delete handler; + return NULL; + } + return handler; +} + +Gralloc1BufferHandler::Gralloc1BufferHandler(uint32_t fd) + : fd_(fd), + gralloc_(nullptr), + device_(nullptr), + register_(nullptr), + release_(nullptr), + dimensions_(nullptr), + lock_(nullptr), + unlock_(nullptr), + create_descriptor_(nullptr), + destroy_descriptor_(nullptr), + set_consumer_usage_(nullptr), + set_dimensions_(nullptr), + set_format_(nullptr), + set_producer_usage_(nullptr), + allocate_(nullptr){ +} + +Gralloc1BufferHandler::~Gralloc1BufferHandler() { + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + gralloc1_dvc->common.close(device_); +} + +bool Gralloc1BufferHandler::Init() { + int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, + (const hw_module_t **)&gralloc_); + if (ret) { + ALOGE("Failed to get gralloc module"); + return false; + } + + ret = gralloc_->methods->open(gralloc_, GRALLOC_HARDWARE_MODULE_ID, &device_); + if (ret) { + ALOGE("Failed to open gralloc module"); + return false; + } + + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + register_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_RETAIN)); + release_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_RELEASE)); + lock_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_LOCK)); + unlock_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_UNLOCK)); + + dimensions_ = + reinterpret_cast(gralloc1_dvc->getFunction( + gralloc1_dvc, GRALLOC1_FUNCTION_GET_DIMENSIONS)); + + create_descriptor_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, + GRALLOC1_FUNCTION_CREATE_DESCRIPTOR)); + destroy_descriptor_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, + GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR)); + + set_consumer_usage_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, + GRALLOC1_FUNCTION_SET_CONSUMER_USAGE)); + set_dimensions_ = + reinterpret_cast(gralloc1_dvc->getFunction( + gralloc1_dvc, GRALLOC1_FUNCTION_SET_DIMENSIONS)); + set_format_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_SET_FORMAT)); + set_producer_usage_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, + GRALLOC1_FUNCTION_SET_PRODUCER_USAGE)); + allocate_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_ALLOCATE)); +#ifdef USE_GRALLOC1 + set_modifier_ = reinterpret_cast( + gralloc1_dvc->getFunction(gralloc1_dvc, GRALLOC1_FUNCTION_SET_MODIFIER)); +#endif + return true; +} + +bool Gralloc1BufferHandler::CreateBuffer(uint32_t w, uint32_t h, int format, + DRMHwcNativeHandle *handle, + uint32_t layer_type, + bool *modifier_used, + int64_t preferred_modifier, + bool /*raw_pixel_buffer*/) const { + struct gralloc_handle *temp = new struct gralloc_handle(); + (void)preferred_modifier; + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + uint32_t usage = 0; + uint32_t pixel_format = 0; + bool force_normal_usage = false; + + create_descriptor_(gralloc1_dvc, &temp->gralloc1_buffer_descriptor_t_); + if (format != 0) { + pixel_format = DrmFormatToHALFormat(format); + } + if (pixel_format == 0) { + pixel_format = HAL_PIXEL_FORMAT_RGBA_8888; + } + set_format_(gralloc1_dvc, temp->gralloc1_buffer_descriptor_t_, pixel_format); +#ifdef ENABLE_RBC + if (preferred_modifier != 0) { + uint64_t modifier = 0; + if (set_modifier_) { + if (preferred_modifier != -1) { + modifier = preferred_modifier; + } + set_modifier_(gralloc1_dvc, temp->gralloc1_buffer_descriptor_t_, + modifier); + } + if (modifier_used && modifier != DRM_FORMAT_MOD_NONE) { + *modifier_used = true; + } + } else { + *modifier_used = false; + } +#else + if (modifier_used) { + *modifier_used = false; + } +#endif + if (layer_type == 3){ +// !IsSupportedMediaFormat(format)) { + ALOGD("Forcing normal usage for Video Layer. \n"); + force_normal_usage = true; + } + + if ((layer_type == 0) || force_normal_usage) { + usage |= GRALLOC1_CONSUMER_USAGE_HWCOMPOSER | + GRALLOC1_PRODUCER_USAGE_GPU_RENDER_TARGET | + GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE; + layer_type = 0; + } else if (layer_type == 3 || + layer_type == 2) { + switch (pixel_format) { + case HAL_PIXEL_FORMAT_YCbCr_422_I: + case HAL_PIXEL_FORMAT_Y8: + usage |= GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE | + GRALLOC1_PRODUCER_USAGE_VIDEO_DECODER; + break; + default: + usage |= GRALLOC1_PRODUCER_USAGE_CAMERA | + GRALLOC1_CONSUMER_USAGE_CAMERA | + GRALLOC1_PRODUCER_USAGE_VIDEO_DECODER | + GRALLOC1_CONSUMER_USAGE_GPU_TEXTURE; + } + } else if (layer_type == 1) { + usage |= GRALLOC1_CONSUMER_USAGE_CURSOR; + } + set_consumer_usage_(gralloc1_dvc, temp->gralloc1_buffer_descriptor_t_, usage); + set_producer_usage_(gralloc1_dvc, temp->gralloc1_buffer_descriptor_t_, usage); + set_dimensions_(gralloc1_dvc, temp->gralloc1_buffer_descriptor_t_, w, h); + allocate_(gralloc1_dvc, 1, &temp->gralloc1_buffer_descriptor_t_, + &temp->handle_); + if (!temp) { + ALOGE("Failed to allocate buffer \n"); + } + *handle = temp; + return true; +} + +bool Gralloc1BufferHandler::ReleaseBuffer(DRMHwcNativeHandle handle) const { + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + release_(gralloc1_dvc, handle->handle_); + + if (handle->gralloc1_buffer_descriptor_t_ > 0) + destroy_descriptor_(gralloc1_dvc, handle->gralloc1_buffer_descriptor_t_); + + return true; +} + +void Gralloc1BufferHandler::DestroyHandle(DRMHwcNativeHandle handle) const { + if (handle) { + int ret = native_handle_close((native_handle_t* )handle->handle_); + if (ret){ + ALOGE("Failed to close native handle %d", ret); + return; + } + if (NULL != handle->handle_) + ret = native_handle_delete((native_handle_t* )handle->handle_); + if (NULL != handle->handle_){ + delete handle->handle_; + handle->handle_= NULL; + } + } +} + +bool Gralloc1BufferHandler::ImportBuffer(DRMHwcNativeHandle handle) const { + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + register_(gralloc1_dvc, handle->handle_); + + return true; +} + +uint32_t Gralloc1BufferHandler::GetTotalPlanes(DRMHwcNativeHandle handle) const { + // return handle->meta_data_.num_planes_; + (void)handle; + return 0; +} + +void Gralloc1BufferHandler::CopyHandle(DRMHwcNativeHandle source, + DRMHwcNativeHandle target) const { + // *target = source; + cros_gralloc_handle *source_handle = (cros_gralloc_handle *)source->handle_; + cros_gralloc_handle *target_handle = (cros_gralloc_handle *)target->handle_; + target_handle->format = source_handle->format; + // target_handle->tiling_mode = source_handle->tiling_mode; + target_handle->width = source_handle->width; + target_handle->height = source_handle->height; + target_handle->droid_format = source_handle->droid_format; + // target_handle->is_interlaced = source_handle->is_interlaced; + int32_t numplanes = source_handle->numFds; + target_handle->numFds = source_handle->numFds; + for (int32_t p = 0; p < numplanes; p++) { + target_handle->offsets[p] = source_handle->offsets[p]; + target_handle->strides[p] = source_handle->strides[p]; + target_handle->fds[p] = source_handle->fds[p]; + target_handle->format_modifiers[p] =source_handle->format_modifiers[p]; + } + target_handle->consumer_usage = source_handle->consumer_usage; +} + +void *Gralloc1BufferHandler::Map(DRMHwcNativeHandle handle, uint32_t x, uint32_t y, + uint32_t width, uint32_t height, + uint32_t * /*stride*/, void **map_data, + size_t /*plane*/) const { + cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle->handle_; + if (!gr_handle) { + ALOGE("could not find gralloc drm handle"); + return NULL; + } + + int acquireFence = -1; + gralloc1_rect_t rect{}; + rect.left = x; + rect.top = y; + rect.width = width; + rect.height = height; + + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + uint32_t status = lock_(gralloc1_dvc, handle->handle_, + GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN, + GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN, &rect, + map_data, acquireFence); + return (GRALLOC1_ERROR_NONE == status) ? *map_data : NULL; +} + +int32_t Gralloc1BufferHandler::UnMap(DRMHwcNativeHandle handle, + void * /*map_data*/) const { + cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle->handle_; + if (!gr_handle) { + ALOGE("could not find gralloc drm handle"); + return GRALLOC1_ERROR_BAD_HANDLE; + } + + int releaseFence = 0; + gralloc1_device_t *gralloc1_dvc = + reinterpret_cast(device_); + return unlock_(gralloc1_dvc, handle->handle_, &releaseFence); +} + +bool Gralloc1BufferHandler::GetInterlace(DRMHwcNativeHandle handle) const { + if(!handle) + return true; + return false; +} + +#ifdef ENABLE_DUMP_YUV_DATA +void Gralloc1BufferHandler::DumpBuffer(buffer_handle_t handle) { + if (NULL == handle) + return; + char dump_file[256] = {0}; + cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)handle; + native_handle_t *handle_copy; + uint8_t* pixels = nullptr; + GraphicBufferMapper &gm(GraphicBufferMapper::get()); + int ret = gm.importBuffer(handle, gr_handle->width, gr_handle->height, 1, + DrmFormatToHALFormat(gr_handle->format), gr_handle->usage, + gr_handle->pixel_stride, const_cast(&handle_copy)); + + if (ret != 0) { + ALOGE("Failed to import buffer while dumping"); + } else { + ret = gm.lock(handle_copy, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_NEVER, + Rect(gr_handle->width, gr_handle->height), reinterpret_cast(&pixels)); + if (ret != 0) { + ALOGE("Failed to lock buffer while dumping"); + } else { + char ctime[32]; + time_t t = time(0); + static int i = 0; + if (i >= 500) + i = 0; + strftime(ctime, sizeof(ctime), "%Y-%m-%d", localtime(&t)); + sprintf(dump_file, "/data/local/traces/dump_%dx%d_0x%x_%s_%d", gr_handle->width, gr_handle->height, gr_handle->format, ctime,i++); + int file_fd = 0; + file_fd = open(dump_file, O_RDWR|O_CREAT, 0666); + if (file_fd == -1) { + ALOGE("Failed to open %s while dumping", dump_file); + } else { + write(file_fd, pixels, gr_handle->sizes[0]); + close(file_fd); + } + gm.unlock(handle_copy); + gm.freeBuffer(handle_copy); + } + } +} +#endif + +} // namespace hwcomposer diff --git a/gralloc1/gralloc1bufferhandler.h b/gralloc1/gralloc1bufferhandler.h new file mode 100755 index 00000000..9ac5db2c --- /dev/null +++ b/gralloc1/gralloc1bufferhandler.h @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#ifndef OS_ANDROID_DRM_Gralloc1BufferHandler_H_ +#define OS_ANDROID_DRM_Gralloc1BufferHandler_H_ +#include +#include + +#include + +#include +#include "vautils.h" + +namespace android { +class Gralloc1BufferHandler : public NativeBufferHandler { + public: + explicit Gralloc1BufferHandler(uint32_t fd); + ~Gralloc1BufferHandler() override; + + bool Init(); + + bool CreateBuffer(uint32_t w, uint32_t h, int format, DRMHwcNativeHandle *handle, + uint32_t layer_type = 0, + bool *modifier_used = NULL, int64_t modifier = -1, + bool raw_pixel_buffer = false) const override; + bool ReleaseBuffer(DRMHwcNativeHandle handle) const override; + void DestroyHandle(DRMHwcNativeHandle handle) const override; + bool ImportBuffer(DRMHwcNativeHandle handle) const override; + void CopyHandle(DRMHwcNativeHandle source, + DRMHwcNativeHandle target) const override; + uint32_t GetTotalPlanes(DRMHwcNativeHandle handle) const override; + void *Map(DRMHwcNativeHandle handle, uint32_t x, uint32_t y, uint32_t width, + uint32_t height, uint32_t *stride, void **map_data, + size_t plane) const override; + int32_t UnMap(DRMHwcNativeHandle handle, void *map_data) const override; + + uint32_t GetFd() const override { + return fd_; + } + + bool GetInterlace(DRMHwcNativeHandle handle) const override; +#ifdef ENABLE_DUMP_YUV_DATA + static void DumpBuffer(buffer_handle_t handle); +#endif + private: + uint32_t ConvertHalFormatToDrm(uint32_t hal_format); + uint32_t fd_; + const hw_module_t *gralloc_; + hw_device_t *device_; + GRALLOC1_PFN_RETAIN register_; + GRALLOC1_PFN_RELEASE release_; + GRALLOC1_PFN_GET_DIMENSIONS dimensions_; + GRALLOC1_PFN_LOCK lock_; + GRALLOC1_PFN_UNLOCK unlock_; + GRALLOC1_PFN_CREATE_DESCRIPTOR create_descriptor_; + GRALLOC1_PFN_DESTROY_DESCRIPTOR destroy_descriptor_; + GRALLOC1_PFN_SET_CONSUMER_USAGE set_consumer_usage_; + GRALLOC1_PFN_SET_DIMENSIONS set_dimensions_; + GRALLOC1_PFN_SET_FORMAT set_format_; + GRALLOC1_PFN_SET_PRODUCER_USAGE set_producer_usage_; + GRALLOC1_PFN_ALLOCATE allocate_; +#ifdef USE_GRALLOC1 + GRALLOC1_PFN_SET_MODIFIER set_modifier_; +#endif +}; + +} // namespace android +#endif // OS_ANDROID_Gralloc1BufferHandler_H_ diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 6a250e85..ad395a70 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -93,6 +93,7 @@ HwcDisplay::HwcDisplay(hwc2_display_t handle, HWC2::DisplayType type, handle_(handle), type_(type), client_layer_(this), + va_compose_layer_(this), color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) { // clang-format off color_transform_matrix_ = {1.0, 0.0, 0.0, 0.0, @@ -523,7 +524,17 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { .top = 0, .right = static_cast(staged_mode_->h_display()), .bottom = static_cast(staged_mode_->v_display())}); - + va_compose_layer_.SetLayerDisplayFrame( + (hwc_rect_t){.left = 0, + .top = 0, + .right = static_cast(staged_mode_->h_display()), + .bottom = static_cast(staged_mode_->v_display())}); + va_compose_layer_.SetLayerSourceCrop( + (hwc_frect_t){.left = 0, + .top = 0, + .right = static_cast(staged_mode_->h_display()), + .bottom = static_cast(staged_mode_->v_display())}); + va_compose_layer_.SetLayerBlendMode(HWC2_BLEND_MODE_PREMULTIPLIED); configs_.active_config_id = staged_mode_config_id_; a_args.display_mode = *staged_mode_; @@ -536,12 +547,19 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { // order the layers by z-order bool use_client_layer = false; + bool use_vpp_compose = false; uint32_t client_z_order = UINT32_MAX; std::map z_map; + std::map vpp_z_map; for (std::pair &l : layers_) { switch (l.second.GetValidatedType()) { case HWC2::Composition::Device: - z_map.emplace(std::make_pair(l.second.GetZOrder(), &l.second)); + if (l.second.GetUseVPPCompose()) { + use_vpp_compose = true; + vpp_z_map.emplace(std::make_pair(l.second.GetZOrder(), &l.second)); + } else { + z_map.emplace(std::make_pair(l.second.GetZOrder(), &l.second)); + } break; case HWC2::Composition::Client: // Place it at the z_order of the lowest client layer @@ -552,13 +570,28 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { continue; } } - if (use_client_layer) - z_map.emplace(std::make_pair(client_z_order, &client_layer_)); - - if (z_map.empty()) + if (use_client_layer) { + if (use_vpp_compose) { + vpp_z_map.emplace(std::make_pair(client_z_order, &client_layer_)); + } else { + z_map.emplace(std::make_pair(client_z_order, &client_layer_)); + } + } + if (z_map.empty() && vpp_z_map.empty()) return HWC2::Error::BadLayer; std::vector composition_layers; + for (std::pair &l : vpp_z_map) { + l.second->PopulateLayerData(a_args.test_only); + if (l.second->GetLayerData().acquire_fence.Get() > 0) + sync_wait(l.second->GetLayerData().acquire_fence.Get(), -1); + va_compose_layer_.addVaLayerMapData(l.first, l.second); + } + + if (vpp_z_map.size() > 0) { + va_compose_layer_.vaPopulateLayerData(a_args.test_only); + composition_layers.emplace_back(va_compose_layer_.GetLayerData().Clone()); + } /* Import & populate */ for (std::pair &l : z_map) { diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index 38ee6d96..8441c47c 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h @@ -227,6 +227,7 @@ class HwcDisplay { std::map layers_; HwcLayer client_layer_; + HwcVaLayer va_compose_layer_; int32_t color_mode_{}; std::vector current_color_mode_ = {HAL_COLOR_MODE_NATIVE, HAL_COLOR_MODE_BT2020, HAL_COLOR_MODE_BT2100_PQ, HAL_COLOR_MODE_BT2100_HLG, /*HAL_COLOR_MODE_DISPLAY_BT2020*/}; std::array color_transform_matrix_{}; diff --git a/hwc2_device/HwcLayer.cpp b/hwc2_device/HwcLayer.cpp index 22fa477b..ae9a9403 100644 --- a/hwc2_device/HwcLayer.cpp +++ b/hwc2_device/HwcLayer.cpp @@ -367,4 +367,77 @@ void HwcLayer::SwChainClearCache() { swchain_reassembled_ = false; } +HwcVaLayer::HwcVaLayer(HwcDisplay *parent_display) : HwcLayer(parent_display){ + +} + +void HwcVaLayer::vaImportFb() { + if (!media_renderer_) { + media_renderer_.reset(new VARenderer()); + if (!media_renderer_->Init(parent_->GetPipe().device->GetFd())) { + ALOGE("Failed to initialize Media va Renderer \n"); + media_renderer_.reset(nullptr); + } else { + ALOGD("Succeeded to initialize Media va Renderer"); + } + } + media_renderer_->startRender(this, DRM_FORMAT_XBGR8888); + buffer_handle_ = media_renderer_->getPreBuffer(); + buffer_handle_updated_ = false; + layer_data_.fb = {}; + + auto unique_id = BufferInfoGetter::GetInstance()->GetUniqueId(buffer_handle_); + if (unique_id && SwChainGetBufferFromCache(*unique_id)) { + return; + } + + layer_data_.bi = BufferInfoGetter::GetInstance()->GetBoInfo(buffer_handle_); + if (!layer_data_.bi) { + ALOGW("Unable to get buffer information (0x%p)", buffer_handle_); + bi_get_failed_ = true; + return; + } + + /* + consider device is virtio-gpu + check if pixel blend mode is supported + */ + bool is_pixel_blend_mode_supported = true; + auto planes = parent_->GetPipe().GetUsablePlanes(); + if (planes.size() == 1 && !planes.begin()->get()->Get()->IsPixBlendModeSupported()) + is_pixel_blend_mode_supported = false; + + layer_data_ + .fb = parent_->GetPipe().device->GetDrmFbImporter().GetOrCreateFbId( + &layer_data_.bi.value(), is_pixel_blend_mode_supported); + + if (!layer_data_.fb) { + ALOGV("Unable to create framebuffer object for buffer 0x%p", + buffer_handle_); + fb_import_failed_ = true; + return; + } + + if (unique_id) { + SwChainAddCurrentBuffer(*unique_id); + } +} +void HwcVaLayer::vaPopulateLayerData(bool test) { + vaImportFb(); + + if (blend_mode_ != BufferBlendMode::kUndefined) { + layer_data_.bi->blend_mode = blend_mode_; + } + if (color_space_ != BufferColorSpace::kUndefined) { + layer_data_.bi->color_space = color_space_; + } + if (sample_range_ != BufferSampleRange::kUndefined) { + layer_data_.bi->sample_range = sample_range_; + } + + if (!test) { + layer_data_.acquire_fence = std::move(acquire_fence_); + } + va_z_map.clear(); +} } // namespace android \ No newline at end of file diff --git a/hwc2_device/HwcLayer.h b/hwc2_device/HwcLayer.h index 96026061..0c5dfc81 100644 --- a/hwc2_device/HwcLayer.h +++ b/hwc2_device/HwcLayer.h @@ -21,7 +21,9 @@ #include "bufferinfo/BufferInfoGetter.h" #include "compositor/LayerData.h" - +#include "va/varenderer.h" +#include +#include namespace android { class HwcDisplay; @@ -42,6 +44,12 @@ class HwcLayer { void SetValidatedType(HWC2::Composition type) { validated_type_ = type; } + void SetUseVPPCompose(bool use_vpp_compose) { + use_vpp_compose_ = use_vpp_compose; + } + bool GetUseVPPCompose() { + return use_vpp_compose_; + } bool IsTypeChanged() const { return sf_type_ != validated_type_; } @@ -81,7 +89,7 @@ class HwcLayer { const int32_t *keys, const float *metadata); - private: + protected: // sf_type_ stores the initial type given to us by surfaceflinger, // validated_type_ stores the type after running ValidateDisplay HWC2::Composition sf_type_ = HWC2::Composition::Invalid; @@ -106,20 +114,23 @@ class HwcLayer { buffer_handle_t buffer_handle_{}; bool buffer_handle_updated_{}; - bool prior_buffer_scanout_flag_{}; + bool prior_buffer_scanout_flag_; HwcDisplay *const parent_; /* Layer state */ public: + BufferBlendMode GetBlendMode() {return blend_mode_;} void PopulateLayerData(bool test); - buffer_handle_t GetBufferHandle() {return buffer_handle_;} bool IsLayerUsableAsDevice() const { return !bi_get_failed_ && !fb_import_failed_ && buffer_handle_ != nullptr; } - - private: + bool IsProtectedLayer() { + auto gr_handle = (const struct cros_gralloc_handle*)GetBufferHandle(); + return gr_handle && gr_handle->usage & GRALLOC_USAGE_HW_VIDEO_ENCODER;//GRALLOC_USAGE_PROTECTED + } + protected: void ImportFb(); bool bi_get_failed_{}; bool fb_import_failed_{}; @@ -128,7 +139,7 @@ class HwcLayer { public: void SwChainClearCache(); - private: + protected: struct SwapChainElement { std::optional bi; std::shared_ptr fb; @@ -141,8 +152,26 @@ class HwcLayer { std::map swchain_cache_; std::map swchain_lookup_table_; bool swchain_reassembled_{}; + bool use_vpp_compose_ = false; }; +class HwcVaLayer : public HwcLayer{ +public: + explicit HwcVaLayer(HwcDisplay *parent_display); + + void addVaLayerMapData(int zorder, HwcLayer* layer){ + va_z_map.emplace(std::make_pair(zorder, layer)); + } + std::map>& getVaLayerMapData(){ + return va_z_map; + } + void vaPopulateLayerData(bool test); +private: + void vaImportFb(); +private: + std::map> va_z_map; + std::unique_ptr media_renderer_ = nullptr; +}; } // namespace android #endif diff --git a/include/drmhwcgralloc.h b/include/drmhwcgralloc.h new file mode 100644 index 00000000..db54802c --- /dev/null +++ b/include/drmhwcgralloc.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef ANDROID_DRMHWCGRALLOC_H_ +#define ANDROID_DRMHWCGRALLOC_H_ + +#include + +#define HWC_DRM_BO_MAX_PLANES 4 +typedef struct hwc_drm_bo { + uint32_t width; + uint32_t height; + uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */ + uint32_t hal_format; /* HAL_PIXEL_FORMAT_* */ + uint32_t usage; + uint32_t pitches[HWC_DRM_BO_MAX_PLANES]; + uint32_t offsets[HWC_DRM_BO_MAX_PLANES]; + uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES]; + uint64_t modifiers[HWC_DRM_BO_MAX_PLANES]; + int acquire_fence_fd; +} hwc_drm_bo_t; + +#endif // ANDROID_DRMHWCGRALLOC_H_ diff --git a/include/nativebufferhandler.h b/include/nativebufferhandler.h new file mode 100755 index 00000000..2b25e0c6 --- /dev/null +++ b/include/nativebufferhandler.h @@ -0,0 +1,61 @@ +/* +// Copyright (c) 2016 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. +*/ + +#ifndef PUBLIC_DMRNATIVEBUFFERHANDLER_H_ +#define PUBLIC_DMRNATIVEBUFFERHANDLER_H_ + +#include +#include +#include "vautils.h" + +namespace android { + +class NativeBufferHandler { + public: + static NativeBufferHandler *CreateInstance(uint32_t fd); + + virtual ~NativeBufferHandler() { + } + + virtual bool CreateBuffer(uint32_t w, uint32_t h, int format, + DRMHwcNativeHandle *handle = NULL, + uint32_t layer_type = 0, + bool *modifier_used = NULL, int64_t modifier = -1, + bool raw_pixel_buffer = false) const = 0; + + virtual bool ReleaseBuffer(DRMHwcNativeHandle handle) const = 0; + + virtual void DestroyHandle(DRMHwcNativeHandle handle) const = 0; + + virtual bool ImportBuffer(DRMHwcNativeHandle handle) const = 0; + + virtual void CopyHandle(DRMHwcNativeHandle source, + DRMHwcNativeHandle target) const = 0; + + virtual uint32_t GetTotalPlanes(DRMHwcNativeHandle handle) const = 0; + + virtual void *Map(DRMHwcNativeHandle handle, uint32_t x, uint32_t y, + uint32_t width, uint32_t height, uint32_t *stride, + void **map_data, size_t plane) const = 0; + + virtual int32_t UnMap(DRMHwcNativeHandle handle, void *map_data) const = 0; + + virtual uint32_t GetFd() const = 0; + virtual bool GetInterlace(DRMHwcNativeHandle handle) const = 0; +}; + +} // namespace android +#endif // PUBLIC_NATIVEBUFFERHANDLER_H_ diff --git a/utils/autolock.cpp b/utils/autolock.cpp new file mode 100644 index 00000000..3342e46a --- /dev/null +++ b/utils/autolock.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2015 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 ATRACE_TAG ATRACE_TAG_GRAPHICS +#define LOG_TAG "hwc-drm-auto-lock" + +#include "autolock.h" + +#include + +#include + +#include "utils/log.h" + +namespace android { + +int AutoLock::Lock() { + if (locked_) { + ALOGE("Invalid attempt to double lock AutoLock %s", name_); + return -EINVAL; + } + int ret = pthread_mutex_lock(mutex_); + if (ret) { + ALOGE("Failed to acquire %s lock %d", name_, ret); + return ret; + } + locked_ = true; + return 0; +} + +int AutoLock::Unlock() { + if (!locked_) { + ALOGE("Invalid attempt to unlock unlocked AutoLock %s", name_); + return -EINVAL; + } + int ret = pthread_mutex_unlock(mutex_); + if (ret) { + ALOGE("Failed to release %s lock %d", name_, ret); + return ret; + } + locked_ = false; + return 0; +} +} // namespace android diff --git a/utils/autolock.h b/utils/autolock.h new file mode 100644 index 00000000..006406a0 --- /dev/null +++ b/utils/autolock.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 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 + +namespace android { + +class AutoLock { + public: + AutoLock(pthread_mutex_t *mutex, const char *const name) + : mutex_(mutex), name_(name) { + } + ~AutoLock() { + if (locked_) + Unlock(); + } + + AutoLock(const AutoLock &rhs) = delete; + AutoLock &operator=(const AutoLock &rhs) = delete; + + int Lock(); + int Unlock(); + + private: + pthread_mutex_t *const mutex_; + bool locked_ = false; + const char *const name_; +}; +} // namespace android diff --git a/va/varenderer.cpp b/va/varenderer.cpp new file mode 100755 index 00000000..b8843699 --- /dev/null +++ b/va/varenderer.cpp @@ -0,0 +1,680 @@ +/* +// Copyright (c) 2017 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. +*/ +#include "va/sysdeps.h" +#include "varenderer.h" + +#include +#include +#include +#include +#include "va/va_backend.h" +#include "va/va_internal.h" +// #include "va/va_fool.h" +#include "va/va_android.h" +#include "va/va_drmcommon.h" +#include "va/drm/va_drm_utils.h" + +#include +#include +#include +#include +#include +#include "cros_gralloc_handle.h" +#include "vautils.h" +#include +#include "utils/autolock.h" +#include +// #include "drmhwcomposer.h" +#include "hwc2_device/HwcLayer.h" +namespace android { +#define ANDROID_DISPLAY_HANDLE 0x18C34078 +#define CHECK_SYMBOL(func) { if (!func) printf("func %s not found\n", #func); return VA_STATUS_ERROR_UNKNOWN; } +#define DEVICE_NAME "/dev/dri/renderD128" +#ifdef LOG_TAG +#undef LOG_TAG +#define LOG_TAG "hwc-varender" +#endif +VARenderer::~VARenderer() { + DestroyContext(); + if (va_display_) { + vaTerminate(va_display_); + } + DRMHwcNativeHandle temp_handle; + if(native_handles.size() == NATIVE_BUFFER_VECTOR_SIZE){ + for( int32_t i=0; iReleaseBuffer(temp_handle); + buffer_handler_->DestroyHandle(temp_handle); + } + native_handles.clear(); + } + if(native_rotation_handles.size() == NATIVE_BUFFER_VECTOR_SIZE){ + for( int32_t i=0; iReleaseBuffer(temp_handle); + buffer_handler_->DestroyHandle(temp_handle); + } + native_rotation_handles.clear(); + } + if(native_active_handles.size() == NATIVE_BUFFER_VECTOR_SIZE){ + for( int32_t i=0; iReleaseBuffer(temp_handle); + buffer_handler_->DestroyHandle(temp_handle); + } + native_active_handles.clear(); + } + ReleaseCache(); +} + +bool VARenderer::Init(uint32_t fd) { + unsigned int native_display = ANDROID_DISPLAY_HANDLE; + buffer_handler_.reset(NativeBufferHandler::CreateInstance(fd)); + VAStatus ret = VA_STATUS_SUCCESS; + va_display_ = vaGetDisplay(&native_display); + if (!va_display_) { + ALOGE("vaGetDisplay failed\n"); + return false; + } + ret = pthread_mutex_init(&lock_, NULL); + if (ret) + ALOGE("Failed to initialize the mutex lock %d\n", ret); + int major, minor; + ret = vaInitialize(va_display_, &major, &minor); + if (ret == VA_STATUS_SUCCESS) { + AllocateCache(DEFAULT_LAYER_NUM); + } + return ret == VA_STATUS_SUCCESS ? true : false; +} + +void VARenderer::ReleaseCache() { + if (va_buffer_id_) { + free(va_buffer_id_); + va_buffer_id_ = nullptr; + } + if (surface_in_) { + free(surface_in_); + surface_in_ = nullptr; + } + if (surface_region_) { + free(surface_region_); + surface_region_ = nullptr; + } + if (output_region_) { + free(output_region_); + output_region_ = nullptr; + } +} + +bool VARenderer::NeedResizeCache(uint32_t layer_num) { + return layer_num > layer_capacity_; +} + +bool VARenderer::AllocateCache(uint32_t layer_capacity) { + surface_in_ = (VASurfaceID*)malloc(sizeof(VASurfaceID) * layer_capacity); + va_buffer_id_ = (VABufferID*)malloc(sizeof(VABufferID) * layer_capacity); + surface_region_ = (VARectangle*)malloc(sizeof(VARectangle) * layer_capacity); + output_region_ = (VARectangle*)malloc(sizeof(VARectangle) * layer_capacity); + if (surface_in_ == nullptr || va_buffer_id_ == nullptr || + surface_region_ == nullptr || output_region_ == nullptr) { + ReleaseCache(); + return false; + } + layer_capacity_ = layer_capacity; + return true; +} + +bool VARenderer::ResizeCache(uint32_t layer_num) { + ReleaseCache(); + uint32_t step_num = ((layer_num - layer_capacity_) / LAYER_STEP + 1); + + ALOGD("VARenderer resize cache from %d to %d, layer_num %d", + layer_capacity_, layer_capacity_ + step_num * LAYER_STEP, layer_num); + + return AllocateCache(layer_capacity_ + step_num * LAYER_STEP); +} + +bool VARenderer::QueryVAProcFilterCaps(VAContextID context, + VAProcFilterType type, void* caps, + uint32_t* num) { + VAStatus ret = + vaQueryVideoProcFilterCaps(va_display_, context, type, caps, num); + if (ret != VA_STATUS_SUCCESS) + ALOGE("Query Filter Caps failed\n"); + return ret == VA_STATUS_SUCCESS ? true : false; +} + +bool VARenderer::MapVAProcFilterColorModetoHwc(HWCColorControl& vppmode, + VAProcColorBalanceType vamode) { + switch (vamode) { + case VAProcColorBalanceHue: + vppmode = HWCColorControl::kColorHue; + break; + case VAProcColorBalanceSaturation: + vppmode = HWCColorControl::kColorSaturation; + break; + case VAProcColorBalanceBrightness: + vppmode = HWCColorControl::kColorBrightness; + break; + case VAProcColorBalanceContrast: + vppmode = HWCColorControl::kColorContrast; + break; + default: + return false; + } + return true; +} + +bool VARenderer::SetVAProcFilterColorDefaultValue( + VAProcFilterCapColorBalance* caps) { + HWCColorControl mode; + for (int i = 0; i < VAProcColorBalanceCount; i++) { + if (MapVAProcFilterColorModetoHwc(mode, caps[i].type)) { + colorbalance_caps_[mode].caps_ = caps[i]; + colorbalance_caps_[mode].value_ = caps[i].range.default_value; + } + } + sharp_caps_.value_ = sharp_caps_.caps_.range.default_value; + update_caps_ = true; + return true; +} + +bool VARenderer::SetVAProcFilterDeinterlaceDefaultMode() { + if (deinterlace_caps_.mode_ != VAProcDeinterlacingNone) { + deinterlace_caps_.mode_ = VAProcDeinterlacingNone; + update_caps_ = true; + } + return true; +} + +bool VARenderer::SetVAProcFilterColorValue(HWCColorControl mode, + const HWCColorProp& prop) { + if (mode == HWCColorControl::kColorHue || + mode == HWCColorControl::kColorSaturation || + mode == HWCColorControl::kColorBrightness || + mode == HWCColorControl::kColorContrast) { + if (prop.use_default_) { + if (!colorbalance_caps_[mode].use_default_) { + colorbalance_caps_[mode].use_default_ = true; + update_caps_ = true; + } + } else if (prop.value_ != colorbalance_caps_[mode].value_) { + if (prop.value_ > colorbalance_caps_[mode].caps_.range.max_value || + prop.value_ < colorbalance_caps_[mode].caps_.range.min_value) { + ALOGE("VA Filter value out of range. Mode %d range shoud be %f~%f\n", + mode, colorbalance_caps_[mode].caps_.range.min_value, + colorbalance_caps_[mode].caps_.range.max_value); + return false; + } + colorbalance_caps_[mode].value_ = prop.value_; + colorbalance_caps_[mode].use_default_ = false; + update_caps_ = true; + } + return true; + } else if (mode == HWCColorControl::kColorSharpness) { + if (prop.use_default_) { + if (!sharp_caps_.use_default_) { + sharp_caps_.use_default_ = true; + update_caps_ = true; + } + } else if (prop.value_ != sharp_caps_.value_) { + if (prop.value_ > sharp_caps_.caps_.range.max_value || + prop.value_ < sharp_caps_.caps_.range.min_value) { + ALOGE("VA Filter sharp value out of range. should be %f~%f\n", + sharp_caps_.caps_.range.min_value, + sharp_caps_.caps_.range.max_value); + return false; + } + sharp_caps_.value_ = prop.value_; + sharp_caps_.use_default_ = false; + update_caps_ = true; + } + return true; + } else { + ALOGE("VA Filter undefined color mode\n"); + return false; + } +} + +unsigned int VARenderer::GetVAProcFilterScalingMode(uint32_t mode) { + if (deinterlace_caps_.mode_ == VAProcDeinterlacingNone) { + switch (mode) { + case 1: + return VA_FILTER_SCALING_FAST; + case 2: + return VA_FILTER_SCALING_HQ; + default: + return VA_FILTER_SCALING_HQ; + } + } else + return VA_FILTER_SCALING_FAST; +} + + +//get vasurface by the buffer_hande_t from the layer +int VARenderer::getSurfaceIn(buffer_handle_t bufferHandle, VADisplay display, VASurfaceID* surface, + uint32_t format, uint32_t width, uint32_t height){ + if (NULL == bufferHandle) { + return -1; + } + cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)bufferHandle; + if ((gr_handle->width == 0) || (gr_handle->height == 0)){ + return -1; + } + + VASurfaceAttribExternalBuffers external; + memset(&external, 0, sizeof(external)); + int32_t numplanes = gr_handle->numFds; + if (numplanes > 1) + --numplanes; + uint32_t rt_format = DrmFormatToRTFormat(format); + uint32_t total_planes = numplanes; + external.pixel_format = DrmFormatToVAFormat(format); + external.width = width; + external.height = height; + external.num_planes = total_planes; + uintptr_t prime_fds[total_planes]; + for (unsigned int i = 0; i < total_planes; i++) { + external.pitches[i] = gr_handle->strides[i]; + external.offsets[i] = gr_handle->offsets[i]; + prime_fds[i] = gr_handle->fds[i]; + } + external.num_buffers = total_planes; + external.buffers = prime_fds; + external.data_size = gr_handle->total_size; + VASurfaceAttrib attribs[2]; + attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; + attribs[0].type = VASurfaceAttribMemoryType; + attribs[0].value.type = VAGenericValueTypeInteger; + attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; + attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; + attribs[1].type = VASurfaceAttribExternalBufferDescriptor; + attribs[1].value.type = VAGenericValueTypePointer; + attribs[1].value.value.p = &external; + VAStatus ret = vaCreateSurfaces(display, rt_format, external.width, external.height, + surface, 1, attribs, 2); + if (ret != VA_STATUS_SUCCESS) + ALOGE("Failed to create VASurface from drmbuffer with ret %d", ret); + return ret; +} + +bool VARenderer::startRender(HwcVaLayer* layer,uint32_t format){ + + int64_t modifier = 0; + uint32_t usage =3; + VAStatus ret = VA_STATUS_SUCCESS; + bool modifer_succeeded = false; + DRMHwcNativeHandle temp_handle = 0; + uint32_t input_layer_numer = 1; + std::map> va_layer_map = layer->getVaLayerMapData(); + input_layer_numer = va_layer_map.size(); + int connector_width = layer->GetLayerData().pi.display_frame.right - layer->GetLayerData().pi.display_frame.left; + int connector_height = layer->GetLayerData().pi.display_frame.bottom - layer->GetLayerData().pi.display_frame.top; + int rt_format = DrmFormatToRTFormat(format); + if(render_target_format_ != rt_format) + render_target_format_ = rt_format; + if ((layer->GetLayerData().pi.transform == kHwcTransform270) || + (layer->GetLayerData().pi.transform == kHwcTransform90)) + modifier = I915_FORMAT_MOD_Y_TILED; + else + modifier = 0; + + //if don't init the context , create the va context and gralloc buffer for the native_handles + std::vector relese_handles; + AutoLock lock(&lock_, __func__); + ret = lock.Lock(); + if (va_context_ == VA_INVALID_ID ) { + if (!CreateContext()) { + ALOGE("Failed to create VA context"); + return false; + } + for( int32_t i=0; iCreateBuffer(connector_width,connector_height,format, + &temp_handle,usage,&modifer_succeeded,modifier); + if (modifier == 0) { + native_handles.push_back(temp_handle); + native_active_handles.push_back(temp_handle); + }else{ + native_rotation_handles.push_back(temp_handle); + native_active_handles.push_back(temp_handle); + } + } + modifier_bak = modifier; + current_handle_position = 0; + } + if (modifier_bak !=modifier) { + if (modifier == I915_FORMAT_MOD_Y_TILED) { + if (native_rotation_handles.size() == 0) { + for( int32_t i=0; iCreateBuffer(connector_width,connector_height,format, + &temp_handle,usage,&modifer_succeeded,modifier); + native_rotation_handles.push_back(temp_handle); + } + } + native_handles.swap(native_active_handles); + native_active_handles.swap(native_rotation_handles); + } else { + if (native_handles.size() == 0) { + for( int32_t i=0; iCreateBuffer(connector_width,connector_height,format, + &temp_handle,usage,&modifer_succeeded,modifier); + native_handles.push_back(temp_handle); + } + } + native_rotation_handles.swap(native_active_handles); + native_active_handles.swap(native_handles); + } + modifier_bak = modifier; + current_handle_position = 0; + } + + //create va output surface + VASurfaceID surface_out = VA_INVALID_ID; + for (int i =0; ihandle_, va_display_, + &surface_out, format, connector_width, connector_height); + if (VA_STATUS_SUCCESS != ret) { + if (current_handle_position == (NATIVE_BUFFER_VECTOR_SIZE - 1 )) + current_handle_position = 0; + else + current_handle_position ++; + }else + break; + } + if (VA_STATUS_SUCCESS != ret) { + ALOGE("Failed to create VASurface"); + return false; + } + ret = vaBeginPicture(va_display_, va_context_, surface_out); + std::vector pipeline_buffers(va_layer_map.size(), va_display_); + if (NeedResizeCache(va_layer_map.size())) { + if (!ResizeCache(va_layer_map.size())) { + ALOGE("There is no enough memory, layers count is %zd", va_layer_map.size()); + return false; + } + } + uint8_t index = 0; + for (std::map::reverse_iterator a = va_layer_map.rbegin(); a != va_layer_map.rend(); a++,index++) { + ScopedVABufferID* pipeline_buffer = &pipeline_buffers[index]; + VAProcPipelineParameterBuffer pipe_param = {}; + cros_gralloc_handle *gr_handle_t = (cros_gralloc_handle *)a->second->GetBufferHandle(); + hwc_frect_t source_crop = a->second->GetLayerData().pi.source_crop; + //VARectangle surface_region; + //create va input surface + surface_region_[index].x = source_crop.left;//gr_handle->left; + surface_region_[index].y = source_crop.top;//gr_handle->top; + surface_region_[index].width = source_crop.right - source_crop.left; + surface_region_[index].height = source_crop.bottom - source_crop.top; + + if ((0 == surface_region_[index].width) || (0 == surface_region_[index].height)) { + ALOGE("Invalid source crop, zorder = %d", a->second->GetZOrder()); + continue; + } + hwc_rect_t display_frame = a->second->GetLayerData().pi.display_frame; + //VARectangle output_region; + output_region_[index].x = display_frame.left; + output_region_[index].y = display_frame.top; + output_region_[index].width = display_frame.right - display_frame.left; + output_region_[index].height = display_frame.bottom - display_frame.top; + ret = getSurfaceIn(a->second->GetBufferHandle(), va_display_, surface_in_ + index, + gr_handle_t->format, gr_handle_t->width, gr_handle_t->height); + if (VA_STATUS_SUCCESS != ret) { + ALOGE("Failed to create VASurface"); + return false; + } + pipe_param.surface = *(surface_in_ + index); + pipe_param.surface_region = &surface_region_[index]; + pipe_param.surface_color_standard = VAProcColorStandardBT601; + pipe_param.output_region = &output_region_[index]; + pipe_param.output_color_standard = VAProcColorStandardBT601; + VABlendState bs = {}; + bs.flags = VA_BLEND_PREMULTIPLIED_ALPHA; + pipe_param.blend_state = &bs; + pipe_param.filter_flags = GetVAProcFilterScalingMode(1); + if (filters_.size()) + pipe_param.filters = filters_.data(); + pipe_param.num_filters = static_cast(filters_.size()); +#if VA_MAJOR_VERSION >= 1 + // currently rotation is only supported by VA on Android. + uint32_t rotation = 0, mirror = 0; + HWCTransformToVA(layer->GetLayerData().pi.transform, rotation, mirror); + pipe_param.rotation_state = rotation; + pipe_param.mirror_state = mirror; +#endif +#ifdef VA_SUPPORT_COLOR_RANGE + uint32_t dataspace = layer->dataspace; + if ((dataspace & HAL_DATASPACE_RANGE_FULL) != 0) { + pipe_param.input_color_properties.color_range = VA_SOURCE_RANGE_FULL; + } +#endif + if (a->second->IsProtectedLayer()) { + pipe_param.input_surface_flag = 1; + } + if (!pipeline_buffer->CreateBuffer(va_context_, VAProcPipelineParameterBufferType, + sizeof(VAProcPipelineParameterBuffer), 1, &pipe_param)) { + ALOGE("Failed to create VAPipelineBuffer"); + return false; + } + va_buffer_id_[index] = pipeline_buffer->buffer(); + } + ret |= vaRenderPicture(va_display_, va_context_, &va_buffer_id_[0], va_layer_map.size()); + if (ret != VA_STATUS_SUCCESS) { + ALOGE("Failed to vaRenderPicture, ret = %d\n", ret); + return false; + } + + ret |= vaEndPicture(va_display_, va_context_); + if (ret != VA_STATUS_SUCCESS) { + ALOGE(" Failed to vaEndPicture, ret = %d\n", ret); + } + vaSyncSurface(va_display_, surface_out); + current_handle_position++; + if (current_handle_position >= NATIVE_BUFFER_VECTOR_SIZE) + current_handle_position = 0; + + vaDestroySurfaces(va_display_, surface_in_, va_layer_map.size()); + vaDestroySurfaces(va_display_, &surface_out, 1); + return true; +} + +bool VARenderer::LoadCaps() { + VAProcFilterCapColorBalance colorbalancecaps[VAProcColorBalanceCount]; + uint32_t colorbalance_num = VAProcColorBalanceCount; + uint32_t sharp_num = 1; + uint32_t deinterlace_num = VAProcDeinterlacingCount; + memset(colorbalancecaps, 0, + sizeof(VAProcFilterCapColorBalance) * VAProcColorBalanceCount); + if (!QueryVAProcFilterCaps(va_context_, VAProcFilterColorBalance, + colorbalancecaps, &colorbalance_num)) { + return false; + } + if (!QueryVAProcFilterCaps(va_context_, VAProcFilterSharpening, + &sharp_caps_.caps_, &sharp_num)) { + return false; + } + if (!QueryVAProcFilterCaps(va_context_, VAProcFilterDeinterlacing, + &deinterlace_caps_.caps_, &deinterlace_num)) { + return false; + } + + SetVAProcFilterColorDefaultValue(&colorbalancecaps[0]); + SetVAProcFilterDeinterlaceDefaultMode(); + + return true; +} + +bool VARenderer::CreateContext() { + DestroyContext(); + VAConfigAttrib config_attrib; + config_attrib.type = VAConfigAttribRTFormat; + config_attrib.value = render_target_format_; + VAStatus ret = + vaCreateConfig(va_display_, VAProfileNone, VAEntrypointVideoProc, + &config_attrib, 1, &va_config_); + if (ret != VA_STATUS_SUCCESS) { + ALOGE("Failed to create VA Config"); + return false; + } + // These parameters are not used in vaCreateContext so just set them to dummy + int width = 1; + int height = 1; + ret = vaCreateContext(va_display_, va_config_, width, height, 0x00, nullptr, + 0, &va_context_); + + update_caps_ = true; + if (ret == VA_STATUS_SUCCESS) { + if (!LoadCaps() || !UpdateCaps()) + return false; + } + return ret == VA_STATUS_SUCCESS ? true : false; +} + +void VARenderer::DestroyContext() { + if (va_context_ != VA_INVALID_ID) { + vaDestroyContext(va_display_, va_context_); + va_context_ = VA_INVALID_ID; + } + if (va_config_ != VA_INVALID_ID) { + vaDestroyConfig(va_display_, va_config_); + va_config_ = VA_INVALID_ID; + } + std::vector().swap(filters_); + std::vector().swap(cb_elements_); + std::vector().swap(sharp_); +} + +bool VARenderer::UpdateCaps() { + if (!update_caps_) { + return true; + } + + update_caps_ = false; + + std::vector cb_elements(1, va_display_); + std::vector sharp(1, va_display_); + std::vector deinterlace(1, va_display_); + + std::vector().swap(filters_); + std::vector().swap(cb_elements_); + std::vector().swap(sharp_); + std::vector().swap(deinterlace_); + + VAProcFilterParameterBufferColorBalance cbparam[VAProcColorBalanceCount]; + VAProcFilterParameterBuffer sharpparam; + VAProcFilterParameterBufferDeinterlacing deinterlaceparam; + memset(cbparam, 0, VAProcColorBalanceCount * + sizeof(VAProcFilterParameterBufferColorBalance)); + int index = 0; + for (auto itr = colorbalance_caps_.begin(); itr != colorbalance_caps_.end(); + itr++) { + if (itr->second.use_default_) { + itr->second.value_ = itr->second.caps_.range.default_value; + } + if (fabs(itr->second.value_ - itr->second.caps_.range.default_value) >= + itr->second.caps_.range.step) { + cbparam[index].type = VAProcFilterColorBalance; + cbparam[index].value = itr->second.value_; + cbparam[index].attrib = itr->second.caps_.type; + index++; + } + } + + if (index) { + if (!cb_elements[0].CreateBuffer( + va_context_, VAProcFilterParameterBufferType, + sizeof(VAProcFilterParameterBufferColorBalance), index, cbparam)) { + ALOGE("Create color fail\n"); + return false; + } + filters_.push_back(cb_elements[0].buffer()); + } + cb_elements_.swap(cb_elements); + + if (sharp_caps_.use_default_) { + sharp_caps_.value_ = sharp_caps_.caps_.range.default_value; + } + if (fabs(sharp_caps_.value_ - sharp_caps_.caps_.range.default_value) >= + sharp_caps_.caps_.range.step) { + sharpparam.value = sharp_caps_.value_; + sharpparam.type = VAProcFilterSharpening; + if (!sharp[0].CreateBuffer(va_context_, VAProcFilterParameterBufferType, + sizeof(VAProcFilterParameterBuffer), 1, + &sharpparam)) { + return false; + } + filters_.push_back(sharp[0].buffer()); + } + sharp_.swap(sharp); + + if (deinterlace_caps_.mode_ != VAProcDeinterlacingNone) { + deinterlaceparam.algorithm = deinterlace_caps_.mode_; + deinterlaceparam.type = VAProcFilterDeinterlacing; + if (!deinterlace[0].CreateBuffer( + va_context_, VAProcFilterParameterBufferType, + sizeof(VAProcFilterParameterBufferDeinterlacing), 1, + &deinterlaceparam)) { + return false; + } + filters_.push_back(deinterlace[0].buffer()); + } + deinterlace_.swap(deinterlace); + + return true; +} + +#if VA_MAJOR_VERSION >= 1 +void VARenderer::HWCTransformToVA(uint32_t transform, uint32_t& rotation, + uint32_t& mirror) { + rotation = VA_ROTATION_NONE; + mirror = VA_MIRROR_NONE; + + if (transform & kHwcReflectX) + mirror |= VA_MIRROR_HORIZONTAL; + if (transform & kHwcReflectY) + mirror |= VA_MIRROR_VERTICAL; + + if (mirror == VA_MIRROR_NONE || + mirror == (VA_MIRROR_HORIZONTAL | VA_MIRROR_VERTICAL)) { + transform &= ~kHwcReflectX; + transform &= ~kHwcReflectY; + switch (transform) { + case kHwcTransform270: + rotation = VA_ROTATION_270; + break; + case kHwcTransform180: + rotation = VA_ROTATION_180; + break; + case kHwcTransform90: + rotation = VA_ROTATION_90; + break; + default: + break; + } + } else { + // Fixme? WA added. VA is using rotation then mirror order + // CTS Cameration orientation is expecting mirror, then rotation + // WA added to use inverse rotation to make the same result + if (transform & kHwcTransform180) + rotation = VA_ROTATION_180; + else if (transform & kHwcTransform90) + rotation = VA_ROTATION_270; + else if (transform & kHwcTransform270) + rotation = VA_ROTATION_90; + } +} +#endif + +} // namespace android diff --git a/va/varenderer.h b/va/varenderer.h new file mode 100755 index 00000000..0e1f7b98 --- /dev/null +++ b/va/varenderer.h @@ -0,0 +1,222 @@ +/* +// Copyright (c) 2016 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. +*/ + +#ifndef COMMON_DRM_COMPOSITOR_VA_VARENDERER_H_ +#define COMMON_DRM_COMPOSITOR_VA_VARENDERER_H_ + +#include +#include +#include +#include "include/nativebufferhandler.h" +#include +#include +#include "vautils.h" +#define NATIVE_BUFFER_VECTOR_SIZE 3 + +namespace android { + +struct OverlayLayer; +struct DrmHwcLayer; +class NativeSurface; +class HwcLayer; +class HwcVaLayer; +class ScopedVABufferID { + public: + ScopedVABufferID(VADisplay display) : display_(display) { + } + + ~ScopedVABufferID() { + if (buffer_ != VA_INVALID_ID) + vaDestroyBuffer(display_, buffer_); + } + + bool CreateBuffer(VAContextID context, VABufferType type, uint32_t size, + uint32_t num, void* data) { + VAStatus ret = + vaCreateBuffer(display_, context, type, size, num, data, &buffer_); + return ret == VA_STATUS_SUCCESS ? true : false; + } + + operator VABufferID() const { + return buffer_; + } + + VABufferID buffer() const { + return buffer_; + } + + VABufferID& buffer() { + return buffer_; + } + + private: + VADisplay display_; + VABufferID buffer_ = VA_INVALID_ID; +}; + +struct HwcColorBalanceCap { + VAProcFilterCapColorBalance caps_; + float value_; + bool use_default_ = true; +}; + + +enum class HWCColorControl : int32_t { + kColorHue = 0, + kColorSaturation = 1, + kColorBrightness = 2, + kColorContrast = 3, + kColorSharpness = 4 +}; + +struct HWCColorProp { + float value_ = 0.0; + bool use_default_ = true; +}; + +enum class HWCDeinterlaceFlag : int32_t { + kDeinterlaceFlagNone = 0, + kDeinterlaceFlagForce = 1, + kDeinterlaceFlagAuto = 2 +}; + +enum class HWCDeinterlaceControl : int32_t { + kDeinterlaceNone = 0, + kDeinterlaceBob = 1, + kDeinterlaceWeave = 2, + kDeinterlaceMotionAdaptive = 3, + kDeinterlaceMotionCompensated = 4 +}; + +struct HWCDeinterlaceProp { + HWCDeinterlaceFlag flag_; + HWCDeinterlaceControl mode_; +}; + +enum HWCTransform : uint32_t { + kHwcIdentity = 0, + kHwcReflectX = 1 << 0, + kHwcReflectY = 1 << 1, + kHwcTransform90 = 1 << 2, + kHwcTransform180 = 1 << 3, + kHwcTransform270 = 1 << 4, + kHwcTransform45 = kHwcTransform90 | kHwcReflectY, + kHwcTransform135 = kHwcTransform90 | kHwcReflectX, + kHwcMaxTransform = 8 +}; + +enum HWCRotation { + kHwcRotateNone = 0, + kHwcRotate90, + kHwcRotate180, + kHwcRotate270, + kHwcMaxRotate +}; + + +struct HwcFilterCap { + VAProcFilterCap caps_; + float value_; + bool use_default_ = true; +}; + +typedef struct _HwcDeinterlaceCap { + VAProcFilterCapDeinterlacing caps_[VAProcDeinterlacingCount]; + VAProcDeinterlacingType mode_; +} HwcDeinterlaceCap; + +class VARenderer { + public: + VARenderer() = default; + ~VARenderer(); + + bool Init(uint32_t fd) ; + bool startRender(HwcVaLayer* layer,uint32_t format); + void InsertFence(int32_t /*kms_fence*/) { + } + + void SetDisableExplicitSync(bool /*disable_explicit_sync*/) { + } + buffer_handle_t getPreBuffer(){ + int temp =0 ; + if(current_handle_position ==0){ + temp = NATIVE_BUFFER_VECTOR_SIZE -1 ; + }else if(current_handle_position ==-1){ + return 0; + }else{ + temp = current_handle_position -1; + } + return native_active_handles.at(temp)->handle_; + } + + private: + bool QueryVAProcFilterCaps(VAContextID context, VAProcFilterType type, + void* caps, uint32_t* num); + unsigned int GetVAProcFilterScalingMode(uint32_t mode); + bool SetVAProcFilterColorValue(HWCColorControl type, + const HWCColorProp& prop); + bool SetVAProcFilterColorDefaultValue(VAProcFilterCapColorBalance* caps); + bool SetVAProcFilterDeinterlaceDefaultMode(); + bool MapVAProcFilterColorModetoHwc(HWCColorControl& vppmode, + VAProcColorBalanceType vamode); + bool CreateContext(); + void DestroyContext(); + bool LoadCaps(); + bool UpdateCaps(); + + int getSurfaceIn(buffer_handle_t bufferHandle, VADisplay display, + VASurfaceID* surface,uint32_t format,uint32_t width, uint32_t height); +#if VA_MAJOR_VERSION >= 1 + void HWCTransformToVA(uint32_t transform, uint32_t& rotation, + uint32_t& mirror); +#endif + bool NeedResizeCache(uint32_t layer_num); + bool ResizeCache(uint32_t layer_num); + void ReleaseCache(); + bool AllocateCache(uint32_t layer_num); + bool update_caps_ = false; + void* va_display_ = nullptr; + std::vector filters_; + std::vector cb_elements_; + std::vector sharp_; + std::vector deinterlace_; + std::map colorbalance_caps_; + HwcFilterCap sharp_caps_; + HwcDeinterlaceCap deinterlace_caps_; + int render_target_format_ = VA_RT_FORMAT_YUV420; + VAContextID va_context_ = VA_INVALID_ID; + VAConfigID va_config_ = VA_INVALID_ID; + + mutable pthread_mutex_t lock_; + + int64_t modifier_bak = -1; + std::vector native_handles; + std::vector native_rotation_handles; + std::vector native_active_handles; + int current_handle_position = 0; + + std::unique_ptr buffer_handler_; + VASurfaceID *surface_in_ = nullptr; + VABufferID *va_buffer_id_= nullptr; + VARectangle *surface_region_ = nullptr; + VARectangle *output_region_ = nullptr; + const uint32_t DEFAULT_LAYER_NUM = 10; + const uint32_t LAYER_STEP = 5; + uint32_t layer_capacity_ = 0; +}; + +} // namespace android +#endif // COMMON_COMPOSITOR_VA_VARENDERER_H_ diff --git a/va/vautils.cpp b/va/vautils.cpp new file mode 100755 index 00000000..0397295b --- /dev/null +++ b/va/vautils.cpp @@ -0,0 +1,277 @@ +/* +// Copyright (c) 2017 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. +*/ + +#include "vautils.h" + +#include + +#include +#include +#include + +namespace android { + +enum { HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL = 0x100, + HAL_PIXEL_FORMAT_NV12_LINEAR_INTEL = 0x101, + HAL_PIXEL_FORMAT_YCrCb_422_H_INTEL = 0x102, + HAL_PIXEL_FORMAT_NV12_LINEAR_PACKED_INTEL = 0x103, + HAL_PIXEL_FORMAT_YCbCr_422_H_INTEL = 0x104, + HAL_PIXEL_FORMAT_NV12_X_TILED_INTEL = 0x105, + HAL_PIXEL_FORMAT_RGBA_5551_INTEL = 0x106, + HAL_PIXEL_FORMAT_RGBA_4444_INTEL = 0x107, + HAL_PIXEL_FORMAT_GENERIC_8BIT_INTEL = 0x108, + HAL_PIXEL_FORMAT_YCbCr_411_INTEL = 0x109, + HAL_PIXEL_FORMAT_YCbCr_420_H_INTEL = 0x10A, + HAL_PIXEL_FORMAT_YCbCr_422_V_INTEL = 0x10B, + HAL_PIXEL_FORMAT_YCbCr_444_INTEL = 0x10C, + HAL_PIXEL_FORMAT_RGBP_INTEL = 0x10D, + HAL_PIXEL_FORMAT_BGRP_INTEL = 0x10E, + HAL_PIXEL_FORMAT_NV12_LINEAR_CAMERA_INTEL = 0x10F, + HAL_PIXEL_FORMAT_P010_INTEL = 0x110, + HAL_PIXEL_FORMAT_Z16_INTEL = 0x111, + HAL_PIXEL_FORMAT_UVMAP64_INTEL = 0x112, + HAL_PIXEL_FORMAT_A2R10G10B10_INTEL = 0x113, + HAL_PIXEL_FORMAT_A2B10G10R10_INTEL = 0x114, + HAL_PIXEL_FORMAT_YCrCb_NORMAL_INTEL = 0x115, + HAL_PIXEL_FORMAT_YCrCb_SWAPUVY_INTEL = 0x116, + HAL_PIXEL_FORMAT_YCrCb_SWAPUV_INTEL = 0x117, + HAL_PIXEL_FORMAT_YCrCb_SWAPY_INTEL = 0x118, + HAL_PIXEL_FORMAT_X2R10G10B10_INTEL = 0x119, + HAL_PIXEL_FORMAT_X2B10G10R10_INTEL = 0x11A, + HAL_PIXEL_FORMAT_P016_INTEL = 0x11C, + HAL_PIXEL_FORMAT_Y210_INTEL = 0x11D, + HAL_PIXEL_FORMAT_Y216_INTEL = 0x11E, + HAL_PIXEL_FORMAT_Y410_INTEL = 0x11F, + HAL_PIXEL_FORMAT_Y416_INTEL = 0x120, + HAL_PIXEL_FORMAT_Y8I_INTEL = 0x121, + HAL_PIXEL_FORMAT_Y12I_INTEL = 0x122, + HAL_PIXEL_FORMAT_YUYV_INTEL = HAL_PIXEL_FORMAT_YCrCb_NORMAL_INTEL, + HAL_PIXEL_FORMAT_YUY2_INTEL = HAL_PIXEL_FORMAT_YCrCb_NORMAL_INTEL, + HAL_PIXEL_FORMAT_VYUY_INTEL = HAL_PIXEL_FORMAT_YCrCb_SWAPUVY_INTEL, + HAL_PIXEL_FORMAT_YVYU_INTEL = HAL_PIXEL_FORMAT_YCrCb_SWAPUV_INTEL, + HAL_PIXEL_FORMAT_UYVY_INTEL = HAL_PIXEL_FORMAT_YCrCb_SWAPY_INTEL, + HAL_PIXEL_FORMAT_NV12_TILED_INTEL = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, + HAL_PIXEL_FORMAT_NV12_INTEL = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, + HAL_PIXEL_FORMAT_INTEL_NV12 = HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL, + HAL_PIXEL_FORMAT_NV12 = 0x10F, + HAL_PIXEL_FORMAT_YUV420PackedSemiPlanar_INTEL = 0x7FA00E00, + HAL_PIXEL_FORMAT_YUV420PackedSemiPlanar_Tiled_INTEL = 0x7FA00F00, +}; + +int DrmFormatToVAFormat(int format) { + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV12_Y_TILED_INTEL: + return VA_FOURCC_NV12; + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YVU420_ANDROID: + return VA_FOURCC_YV12; + case DRM_FORMAT_YUV420: + return VA_FOURCC('I', '4', '2', '0'); + case DRM_FORMAT_YUV422: + return VA_FOURCC_YUY2; + case DRM_FORMAT_UYVY: + return VA_FOURCC_UYVY; + case DRM_FORMAT_YUYV: + return VA_FOURCC_YUY2; + case DRM_FORMAT_P010: + return VA_FOURCC_P010; + case DRM_FORMAT_ABGR8888: + return VA_FOURCC_RGBA; + case DRM_FORMAT_XBGR8888: + return VA_FOURCC_RGBX; + case DRM_FORMAT_RGBA8888: + return VA_FOURCC_BGRA; + case DRM_FORMAT_ARGB8888: + return VA_FOURCC_ABGR; + case DRM_FORMAT_YVYU: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_AYUV: + default: + ALOGE("Unable to convert to VAFormat from format %x", format); + break; + } + return 0; +} + + bool IsSupportedMediaFormat(uint32_t format) { + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_P010: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_AYUV: + case DRM_FORMAT_NV12_Y_TILED_INTEL: + case DRM_FORMAT_NV21: + case DRM_FORMAT_YVU420_ANDROID: + return true; + default: + break; + } + return false; +} + + +int DrmFormatToRTFormat(int format) { + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV12_Y_TILED_INTEL: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YVU420_ANDROID: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_YUYV: + case DRM_FORMAT_YVYU: + case DRM_FORMAT_VYUY: + return VA_RT_FORMAT_YUV420; + case DRM_FORMAT_YUV422: + return VA_RT_FORMAT_YUV422; + case DRM_FORMAT_YUV444: + return VA_RT_FORMAT_YUV444; + case DRM_FORMAT_P010: + return VA_RT_FORMAT_YUV420_10BPP; + case DRM_FORMAT_ABGR8888: + return VA_RT_FORMAT_RGB32; + case DRM_FORMAT_XBGR8888: + return VA_RT_FORMAT_RGB32; + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_RGBA8888: + return VA_RT_FORMAT_RGB32; + default: + ALOGE("Unable to convert to RTFormat from format %x", format); + break; + } + return 0; +} + int DrmFormatToHALFormat(int format) { + switch (format) { + case DRM_FORMAT_BGRA8888: + return HAL_PIXEL_FORMAT_RGBA_8888; + case DRM_FORMAT_BGRX8888: + return HAL_PIXEL_FORMAT_RGBX_8888; + case DRM_FORMAT_BGR888: + return HAL_PIXEL_FORMAT_RGB_888; + case DRM_FORMAT_BGR565: + return HAL_PIXEL_FORMAT_RGB_565; + case DRM_FORMAT_ARGB8888: + return HAL_PIXEL_FORMAT_BGRA_8888; + case DRM_FORMAT_YVU420: + return HAL_PIXEL_FORMAT_YV12; + case DRM_FORMAT_R8: + return HAL_PIXEL_FORMAT_BLOB; + case DRM_FORMAT_GR88: + case DRM_FORMAT_R16: + return HAL_PIXEL_FORMAT_Y16; + case DRM_FORMAT_ABGR8888: + return HAL_PIXEL_FORMAT_RGBA_8888; + case DRM_FORMAT_RGB332: //('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */ + return 0; + case DRM_FORMAT_BGR233: //('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */ + return 0; + + case DRM_FORMAT_XRGB4444: + case DRM_FORMAT_XBGR4444: + case DRM_FORMAT_RGBX4444: + case DRM_FORMAT_BGRX4444: + case DRM_FORMAT_ARGB4444: + case DRM_FORMAT_ABGR4444: + case DRM_FORMAT_RGBA4444: + case DRM_FORMAT_BGRA4444: + return 0; + case DRM_FORMAT_XRGB1555: + case DRM_FORMAT_XBGR1555: + case DRM_FORMAT_RGBX5551: + case DRM_FORMAT_BGRX5551: + case DRM_FORMAT_ARGB1555: + case DRM_FORMAT_ABGR1555: + case DRM_FORMAT_RGBA5551: + case DRM_FORMAT_BGRA5551: + return 0; + case DRM_FORMAT_RGB565: + return HAL_PIXEL_FORMAT_RGB_565; + case DRM_FORMAT_RGB888: + return HAL_PIXEL_FORMAT_RGB_888; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_RGBA8888: + return 0; + case DRM_FORMAT_ABGR2101010: + return HAL_PIXEL_FORMAT_RGBA_1010102; + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_RGBX1010102: + case DRM_FORMAT_BGRX1010102: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_RGBA1010102: + case DRM_FORMAT_BGRA1010102: + return 0; + case DRM_FORMAT_YUYV: + return HAL_PIXEL_FORMAT_YCbCr_422_I; + case DRM_FORMAT_YVYU: + case DRM_FORMAT_UYVY: + case DRM_FORMAT_VYUY: + case DRM_FORMAT_AYUV: + ALOGE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_NV12: + return HAL_PIXEL_FORMAT_NV12; + case DRM_FORMAT_NV21: + return HAL_PIXEL_FORMAT_YCrCb_420_SP; + case DRM_FORMAT_NV16: + return HAL_PIXEL_FORMAT_YCbCr_422_SP; + case DRM_FORMAT_NV61: + case DRM_FORMAT_YUV410: + case DRM_FORMAT_YVU410: + case DRM_FORMAT_YUV411: + case DRM_FORMAT_YVU411: + ALOGE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_YUV420: + return HAL_PIXEL_FORMAT_YCbCr_420_888; + case DRM_FORMAT_YVU420_ANDROID: + return HAL_PIXEL_FORMAT_YV12; + case DRM_FORMAT_YUV422: + return HAL_PIXEL_FORMAT_YCbCr_422_888; + case DRM_FORMAT_YVU422: + ALOGE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_YUV444: + return HAL_PIXEL_FORMAT_YCbCr_444_888; + case DRM_FORMAT_YVU444: + ALOGE("YUV format using RGB buffer \n"); + return 0; + case DRM_FORMAT_NV12_Y_TILED_INTEL: + return HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL; + case DRM_FORMAT_P010: + return HAL_PIXEL_FORMAT_P010_INTEL; + default: + return 0; + break; + } + + return DRM_FORMAT_NONE; +} + +} // namespace android diff --git a/va/vautils.h b/va/vautils.h new file mode 100755 index 00000000..881ac3a7 --- /dev/null +++ b/va/vautils.h @@ -0,0 +1,43 @@ +/* +// Copyright (c) 2016 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. +*/ + +#ifndef COMMON_DRM_COMPOSITOR_VA_VAUTILS_H_ +#define COMMON_DRM_COMPOSITOR_VA_VAUTILS_H_ +#include +#include + +namespace android { +#define DRM_FORMAT_NONE fourcc_code('0', '0', '0', '0') +#define DRM_FORMAT_YVU420_ANDROID fourcc_code('9', '9', '9', '7') +#define DRM_FORMAT_NV12_Y_TILED_INTEL fourcc_code('9', '9', '9', '6') +#define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') /* 2x2 subsampled Cr:Cb plane 10 bits per channel */ + +struct gralloc_handle { + buffer_handle_t handle_ = NULL; + uint64_t gralloc1_buffer_descriptor_t_ = 0; +}; + +typedef struct gralloc_handle* DRMHwcNativeHandle; + + +int DrmFormatToVAFormat(int format); +int DrmFormatToRTFormat(int format); +int DrmFormatToHALFormat(int format) ; +bool IsSupportedMediaFormat(uint32_t format); + +} // namespace android + +#endif // COMMON_COMPOSITOR_VA_VAUTILS_H_ From 207792d4c6295f9fa42c373ec2a3649dfef13c62 Mon Sep 17 00:00:00 2001 From: Weifeng Liu Date: Wed, 25 Dec 2024 09:19:26 +0000 Subject: [PATCH 2/4] varenderer: Create VA surface with PRIME_2 API ...as PRIME_2 API allows us to set modifier. Signed-off-by: Weifeng Liu --- va/varenderer.cpp | 55 ++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/va/varenderer.cpp b/va/varenderer.cpp index b8843699..f4846a2c 100755 --- a/va/varenderer.cpp +++ b/va/varenderer.cpp @@ -275,37 +275,38 @@ int VARenderer::getSurfaceIn(buffer_handle_t bufferHandle, VADisplay display, VA return -1; } - VASurfaceAttribExternalBuffers external; - memset(&external, 0, sizeof(external)); - int32_t numplanes = gr_handle->numFds; - if (numplanes > 1) - --numplanes; - uint32_t rt_format = DrmFormatToRTFormat(format); - uint32_t total_planes = numplanes; - external.pixel_format = DrmFormatToVAFormat(format); - external.width = width; - external.height = height; - external.num_planes = total_planes; - uintptr_t prime_fds[total_planes]; - for (unsigned int i = 0; i < total_planes; i++) { - external.pitches[i] = gr_handle->strides[i]; - external.offsets[i] = gr_handle->offsets[i]; - prime_fds[i] = gr_handle->fds[i]; - } - external.num_buffers = total_planes; - external.buffers = prime_fds; - external.data_size = gr_handle->total_size; - VASurfaceAttrib attribs[2]; + auto bi = BufferInfoGetter::GetInstance()->GetBoInfo(bufferHandle); + const uint32_t rt_format = DrmFormatToRTFormat(format); + std::array attribs; + VADRMPRIMESurfaceDescriptor desc{}; + + desc.fourcc = DrmFormatToVAFormat(format); + desc.width = width; + desc.height = height; + desc.num_objects = 1; + desc.objects[0].fd = gr_handle->fds[0]; + desc.objects[0].size = gr_handle->total_size; + desc.objects[0].drm_format_modifier = bi->modifiers[0]; + desc.num_layers = 1; + desc.layers[0].drm_format = format; + desc.layers[0].num_planes = gr_handle->numFds; + desc.layers[0].object_index[0] = 0; + for (unsigned i = 0; i < gr_handle->numFds; ++i) { + desc.layers[0].offset[i] = gr_handle->offsets[i]; + desc.layers[0].pitch[i] = gr_handle->strides[i]; + } + + attribs[0].type = (VASurfaceAttribType)VASurfaceAttribMemoryType; attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; - attribs[0].type = VASurfaceAttribMemoryType; attribs[0].value.type = VAGenericValueTypeInteger; - attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; - attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; + attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2; attribs[1].type = VASurfaceAttribExternalBufferDescriptor; + attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; attribs[1].value.type = VAGenericValueTypePointer; - attribs[1].value.value.p = &external; - VAStatus ret = vaCreateSurfaces(display, rt_format, external.width, external.height, - surface, 1, attribs, 2); + attribs[1].value.value.p = (void *)&desc; + + VAStatus ret = vaCreateSurfaces(display, rt_format, width, height, + surface, 1, attribs.data(), attribs.size()); if (ret != VA_STATUS_SUCCESS) ALOGE("Failed to create VASurface from drmbuffer with ret %d", ret); return ret; From f992a52057f4617d6595169fa27e110a5ff6c3b3 Mon Sep 17 00:00:00 2001 From: lihaihong Date: Thu, 26 Dec 2024 15:01:48 +0800 Subject: [PATCH 3/4] Check offset when planes number is greater than 1 Signed-off-by: lihaihong --- va/varenderer.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/va/varenderer.cpp b/va/varenderer.cpp index f4846a2c..180fb3fb 100755 --- a/va/varenderer.cpp +++ b/va/varenderer.cpp @@ -289,9 +289,16 @@ int VARenderer::getSurfaceIn(buffer_handle_t bufferHandle, VADisplay display, VA desc.objects[0].drm_format_modifier = bi->modifiers[0]; desc.num_layers = 1; desc.layers[0].drm_format = format; - desc.layers[0].num_planes = gr_handle->numFds; + int planes = 1; + if (gr_handle->numFds > 1) { + for (int i = 1; i < gr_handle->numFds; i++) { + if (gr_handle->offsets[i] > 0) + ++planes; + } + } + desc.layers[0].num_planes = planes; desc.layers[0].object_index[0] = 0; - for (unsigned i = 0; i < gr_handle->numFds; ++i) { + for (unsigned i = 0; i < desc.layers[0].num_planes; ++i) { desc.layers[0].offset[i] = gr_handle->offsets[i]; desc.layers[0].pitch[i] = gr_handle->strides[i]; } From 2ae8599f270cb9e273ed0a107bcd425eb581f4bc Mon Sep 17 00:00:00 2001 From: lihaihong Date: Tue, 21 Jan 2025 15:35:12 +0800 Subject: [PATCH 4/4] ATRACE debug pm Signed-off-by: lihaihong --- hwc2_device/HwcDisplay.cpp | 18 +++++++++++------- va/varenderer.cpp | 17 +++++++++++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index ad395a70..c70686c9 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -508,6 +508,7 @@ HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements, } HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { + ATRACE_NAME("CreateComposition"); if (IsInHeadlessMode()) { ALOGE("%s: Display is in headless mode, should never reach here", __func__); return HWC2::Error::None; @@ -582,9 +583,12 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { std::vector composition_layers; for (std::pair &l : vpp_z_map) { - l.second->PopulateLayerData(a_args.test_only); - if (l.second->GetLayerData().acquire_fence.Get() > 0) + // l.second->PopulateLayerData(a_args.test_only); + + if (l.second->GetLayerData().acquire_fence.Get() > 0) { + ATRACE_NAME("sync_wait-before-va"); sync_wait(l.second->GetLayerData().acquire_fence.Get(), -1); + } va_compose_layer_.addVaLayerMapData(l.first, l.second); } @@ -651,19 +655,19 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805 */ HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) { + ATRACE_NAME("PresentDisplay"); if (expectedPresentTime_.has_value() && expectedPresentTime_->timestampNanos > 0) { static const int64_t kOneSecondNs = 1LL * 1000 * 1000 * 1000; struct timespec vsync {}; clock_gettime(CLOCK_MONOTONIC, &vsync); int64_t timestamp = (int64_t)vsync.tv_sec * kOneSecondNs + (int64_t)vsync.tv_nsec; - int64_t half_period = (1E9 / staged_mode_->v_refresh()) / 2; - if ((expectedPresentTime_->timestampNanos - timestamp) > half_period) { - int64_t sleep_ms = (expectedPresentTime_->timestampNanos - timestamp - half_period) / (1000 * 1000); + int64_t period = (1E9 / staged_mode_->v_refresh()); + if ((expectedPresentTime_->timestampNanos - timestamp) > period) { + ATRACE_NAME("Wait for expected present time"); + int64_t sleep_ms = (expectedPresentTime_->timestampNanos - timestamp - period) / (1000 * 1000); std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms)); } expectedPresentTime_ = std::nullopt; - } else { - std::this_thread::sleep_for(std::chrono::nanoseconds((int64_t)(1E9 / staged_mode_->v_refresh()) / 2)); } if (IsInHeadlessMode()) { *out_present_fence = -1; diff --git a/va/varenderer.cpp b/va/varenderer.cpp index 180fb3fb..0559f23c 100755 --- a/va/varenderer.cpp +++ b/va/varenderer.cpp @@ -37,9 +37,13 @@ #include #include "utils/autolock.h" #include -// #include "drmhwcomposer.h" +#include + #include "hwc2_device/HwcLayer.h" namespace android { + #undef ATRACE_TAG +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + #define ANDROID_DISPLAY_HANDLE 0x18C34078 #define CHECK_SYMBOL(func) { if (!func) printf("func %s not found\n", #func); return VA_STATUS_ERROR_UNKNOWN; } #define DEVICE_NAME "/dev/dri/renderD128" @@ -483,12 +487,17 @@ bool VARenderer::startRender(HwcVaLayer* layer,uint32_t format){ ALOGE("Failed to vaRenderPicture, ret = %d\n", ret); return false; } - - ret |= vaEndPicture(va_display_, va_context_); + { + ATRACE_NAME("vaEndPicture"); + ret |= vaEndPicture(va_display_, va_context_); + } if (ret != VA_STATUS_SUCCESS) { ALOGE(" Failed to vaEndPicture, ret = %d\n", ret); } - vaSyncSurface(va_display_, surface_out); + { + ATRACE_NAME("vaSyncSurface"); + vaSyncSurface(va_display_, surface_out); + } current_handle_position++; if (current_handle_position >= NATIVE_BUFFER_VECTOR_SIZE) current_handle_position = 0;