From bae7205d6190289878aa39c4abbfd2e3af7ab724 Mon Sep 17 00:00:00 2001 From: "Li, HaihongX" Date: Thu, 12 May 2022 16:22:47 +0800 Subject: [PATCH] Enable vpp composition in drm-hwc There are two options to decide which layers use vpp. If WITH_LIBVA_ALL is defined, both graphic and video layers will use bpp. If WITH_LIBVA_VIDEO is defined, only video layer will use bpp. If none of them is defined, no layer will use bpp. Can change option in Android.mk, default defined option is WITH_LIBVA_ALL. Composite more layers one time. Tracked-On: OAM-102122 Signed-off-by: Li, HaihongX --- ...12-Enable-vpp-composition-in-drm-hwc.patch | 2723 +++++++++++++++++ 1 file changed, 2723 insertions(+) create mode 100644 aosp_diff/preliminary/external/drm_hwcomposer/0012-Enable-vpp-composition-in-drm-hwc.patch diff --git a/aosp_diff/preliminary/external/drm_hwcomposer/0012-Enable-vpp-composition-in-drm-hwc.patch b/aosp_diff/preliminary/external/drm_hwcomposer/0012-Enable-vpp-composition-in-drm-hwc.patch new file mode 100644 index 0000000000..11bb762165 --- /dev/null +++ b/aosp_diff/preliminary/external/drm_hwcomposer/0012-Enable-vpp-composition-in-drm-hwc.patch @@ -0,0 +1,2723 @@ +From a35478d2c6801ee68a9c193a0e3866267b4ef7e4 Mon Sep 17 00:00:00 2001 +From: "Li, HaihongX" +Date: Mon, 9 May 2022 14:26:06 +0800 +Subject: [PATCH] Enable vpp composition in drm-hwc + +There are two options to decide which layers use vpp. +If WITH_LIBVA_ALL is defined, both graphic and video +layers will use bpp. If WITH_LIBVA_VIDEO is defined, +only video layer will use bpp. If none of them is +defined, no layer will use bpp. Can change option in +Android.mk, default defined option is WITH_LIBVA_ALL. + +Tracked-On: OAM-102122 +Signed-off-by: Li, HaihongX +--- + Android.bp | 153 ------- + Android.mk | 83 ++++ + DrmHwcTwo.cpp | 88 +++- + DrmHwcTwo.h | 4 + + backend/Backend.cpp | 34 +- + backend/Backend.h | 1 + + compositor/DrmDisplayCompositor.cpp | 18 +- + drm/DrmFbImporter.cpp | 77 +++- + drm/DrmFbImporter.h | 12 +- + gralloc1/gralloc1bufferhandler.cpp | 360 +++++++++++++++ + gralloc1/gralloc1bufferhandler.h | 81 ++++ + include/drmhwcomposer.h | 72 ++- + include/nativebufferhandler.h | 61 +++ + tests/Android.bp | 35 -- + utils/hwcutils.cpp | 67 ++- + va/varenderer.cpp | 673 ++++++++++++++++++++++++++++ + va/varenderer.h | 222 +++++++++ + va/vautils.cpp | 277 ++++++++++++ + va/vautils.h | 43 ++ + 19 files changed, 2143 insertions(+), 218 deletions(-) + delete mode 100644 Android.bp + create mode 100644 Android.mk + create mode 100755 gralloc1/gralloc1bufferhandler.cpp + create mode 100755 gralloc1/gralloc1bufferhandler.h + create mode 100755 include/nativebufferhandler.h + delete mode 100644 tests/Android.bp + 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 +deleted file mode 100644 +index ddf66fb..0000000 +--- a/Android.bp ++++ /dev/null +@@ -1,153 +0,0 @@ +-// 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. +- +-// ===================== +-// libdrmhwc_utils.a +-// ===================== +-cc_library_static { +- name: "libdrmhwc_utils", +- +- srcs: ["utils/Worker.cpp"], +- +- include_dirs: [ +- "external/drm_hwcomposer", +- "external/drm_hwcomposer/include", +- ], +- +- cflags: [ +- "-Wall", +- "-Werror", +- ], +- +- vendor: true, +- +-} +- +-// ===================== +-// hwcomposer.drm.so +-// ===================== +-cc_defaults { +- name: "hwcomposer.drm_defaults", +- +- shared_libs: [ +- "libcutils", +- "libdrm", +- "libhardware", +- "libhidlbase", +- "liblog", +- "libsync", +- "libui", +- "libutils", +- ], +- +- include_dirs: [ +- "external/drm_hwcomposer", +- "external/drm_hwcomposer/include", +- ], +- +- static_libs: ["libdrmhwc_utils"], +- +- cflags: [ +- "-Wall", +- "-Werror", +- ], +- +- cppflags: [ +- "-DHWC2_INCLUDE_STRINGIFICATION", +- "-DHWC2_USE_CPP11", +- ], +- +- product_variables: { +- platform_sdk_version: { +- cflags: ["-DPLATFORM_SDK_VERSION=%d"], +- }, +- }, +- +- relative_install_path: "hw", +- vendor: true, +-} +- +-cc_library_static { +- name: "drm_hwcomposer", +- defaults: ["hwcomposer.drm_defaults"], +- srcs: [ +- "DrmHwcTwo.cpp", +- +- "bufferinfo/BufferInfoGetter.cpp", +- "bufferinfo/BufferInfoMapperMetadata.cpp", +- +- "compositor/DrmDisplayComposition.cpp", +- "compositor/DrmDisplayCompositor.cpp", +- "compositor/Planner.cpp", +- +- "drm/DrmConnector.cpp", +- "drm/DrmCrtc.cpp", +- "drm/DrmDevice.cpp", +- "drm/DrmEncoder.cpp", +- "drm/DrmEventListener.cpp", +- "drm/DrmFbImporter.cpp", +- "drm/DrmMode.cpp", +- "drm/DrmPlane.cpp", +- "drm/DrmProperty.cpp", +- "drm/ResourceManager.cpp", +- "drm/VSyncWorker.cpp", +- +- "utils/autolock.cpp", +- "utils/hwcutils.cpp", +- +- "backend/Backend.cpp", +- "backend/BackendClient.cpp", +- "backend/BackendManager.cpp", +- "backend/BackendRCarDu.cpp", +- ], +-} +- +-cc_library_shared { +- name: "hwcomposer.drm", +- defaults: ["hwcomposer.drm_defaults"], +- whole_static_libs: ["drm_hwcomposer"], +- srcs: ["bufferinfo/legacy/BufferInfoLibdrm.cpp"], +-} +- +-cc_library_shared { +- name: "hwcomposer.drm_minigbm", +- defaults: ["hwcomposer.drm_defaults"], +- whole_static_libs: ["drm_hwcomposer"], +- srcs: ["bufferinfo/legacy/BufferInfoMinigbm.cpp"], +- include_dirs: ["external/minigbm/cros_gralloc"], +-} +- +-// Used by hwcomposer.drm_imagination +-filegroup { +- name: "drm_hwcomposer_platformimagination", +- srcs: ["bufferinfo/legacy/BufferInfoImagination.cpp"], +-} +- +-// Used by hwcomposer.drm_hikey and hwcomposer.drm_hikey960 +-filegroup { +- name: "drm_hwcomposer_platformhisi", +- srcs: ["bufferinfo/legacy/BufferInfoMaliHisi.cpp"], +-} +- +-// Used by hwcomposer.drm_meson +-filegroup { +- name: "drm_hwcomposer_platformmeson", +- srcs: ["bufferinfo/legacy/BufferInfoMaliMeson.cpp"], +-} +- +-// Used by hwcomposer.drm_mediatek +-filegroup { +- name: "drm_hwcomposer_platformmediatek", +- srcs: ["bufferinfo/legacy/BufferInfoMaliMediatek.cpp"], +-} +diff --git a/Android.mk b/Android.mk +new file mode 100644 +index 0000000..9d93c73 +--- /dev/null ++++ b/Android.mk +@@ -0,0 +1,83 @@ ++# 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. ++ ++LOCAL_PATH:= $(call my-dir) ++ ++include $(CLEAR_VARS) ++ ++LOCAL_SHARED_LIBRARIES := \ ++ libcutils \ ++ libdrm \ ++ libhardware \ ++ libhidlbase \ ++ liblog \ ++ libsync \ ++ libui \ ++ libutils \ ++ libva \ ++ libva-android \ ++ ++LOCAL_SRC_FILES := \ ++ utils/Worker.cpp \ ++ DrmHwcTwo.cpp \ ++ bufferinfo/BufferInfoGetter.cpp \ ++ bufferinfo/BufferInfoMapperMetadata.cpp \ ++ compositor/DrmDisplayComposition.cpp \ ++ compositor/DrmDisplayCompositor.cpp \ ++ compositor/Planner.cpp \ ++ drm/DrmConnector.cpp \ ++ drm/DrmCrtc.cpp \ ++ drm/DrmDevice.cpp \ ++ drm/DrmEncoder.cpp \ ++ drm/DrmEventListener.cpp \ ++ drm/DrmFbImporter.cpp \ ++ drm/DrmMode.cpp \ ++ drm/DrmPlane.cpp \ ++ drm/DrmProperty.cpp \ ++ drm/ResourceManager.cpp \ ++ drm/VSyncWorker.cpp \ ++ utils/autolock.cpp \ ++ utils/hwcutils.cpp \ ++ backend/Backend.cpp \ ++ backend/BackendClient.cpp \ ++ backend/BackendManager.cpp \ ++ backend/BackendRCarDu.cpp \ ++ gralloc1/gralloc1bufferhandler.cpp \ ++ va/vautils.cpp \ ++ va/varenderer.cpp \ ++ ++LOCAL_C_INCLUDES += \ ++ external/drm_hwcomposer \ ++ external/drm_hwcomposer/va \ ++ external/drm_hwcomposer/include \ ++ hardware/intel/external/minigbm-intel/cros_gralloc \ ++ hardware/intel/external/libva \ ++ hardware/intel/external/drm-intel/android \ ++ ++LOCAL_CPPFLAGS += -DHWC2_INCLUDE_STRINGIFICATION ++LOCAL_CPPFLAGS += -DHWC2_USE_CPP11 ++LOCAL_CPPFLAGS += -DUSE_GRALLOC1 ++LOCAL_CPPFLAGS += -DENABLE_RBC ++LOCAL_CPPFLAGS += -DPLATFORM_SDK_VERSION=30 ++LOCAL_CPPFLAGS += -DWITH_LIBVA_ALL ++LOCAL_CPPFLAGS += \ ++ -Wall \ ++ -Werror \ ++ ++LOCAL_MODULE := hwcomposer.drm_minigbm ++LOCAL_PROPRIETARY_MODULE := true ++LOCAL_MODULE_RELATIVE_PATH := hw ++LOCAL_MODULE_CLASS := SHARED_LIBRARIES ++LOCAL_MODULE_SUFFIX := $(TARGET_SHLIB_SUFFIX) ++include $(BUILD_SHARED_LIBRARY) +diff --git a/DrmHwcTwo.cpp b/DrmHwcTwo.cpp +index db4c528..55888fb 100644 +--- a/DrmHwcTwo.cpp ++++ b/DrmHwcTwo.cpp +@@ -35,6 +35,8 @@ + #include "compositor/DrmDisplayComposition.h" + #include "utils/log.h" + #include "utils/properties.h" ++#include "cros_gralloc_handle.h" ++#include "va/vautils.h" + + namespace android { + +@@ -638,10 +640,14 @@ void DrmHwcTwo::HwcDisplay::AddFenceToPresentFence(UniqueFd fd) { + + HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { + // order the layers by z-order ++ int ret = 0; ++ bool include_video_layer = false; + bool use_client_layer = false; + uint32_t client_z_order = UINT32_MAX; + std::map z_map; + for (std::pair &l : layers_) { ++ if (l.second.IsVideoLayer()) ++ include_video_layer = true; + switch (l.second.validated_type()) { + case HWC2::Composition::Device: + z_map.emplace(std::make_pair(l.second.z_order(), &l.second)); +@@ -664,22 +670,71 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) { + std::vector composition_layers; + + // now that they're ordered by z, add them to the composition +- for (std::pair &l : z_map) { +- DrmHwcLayer layer; +- l.second->PopulateDrmLayer(&layer); +- int ret = layer.ImportBuffer(drm_); +- if (ret) { +- ALOGE("Failed to import layer, ret=%d", ret); +- return HWC2::Error::NoResources; ++#if defined(WITH_LIBVA_VIDEO) ++ if (include_video_layer && !use_client_layer) { ++#elif defined(WITH_LIBVA_ALL) ++ if (!use_client_layer) { ++#endif ++#if defined(WITH_LIBVA_VIDEO) ++ for (std::pair &l : z_map) { ++ if (l.second->IsVideoLayer()) { ++#elif defined(WITH_LIBVA_ALL) ++ auto iterator = z_map.begin(); ++#endif ++#if defined(WITH_LIBVA_VIDEO) || defined(WITH_LIBVA_ALL) ++ DrmVaComposeHwcLayer va_compose_layer; ++ DrmHwcLayer clientlayer; ++ DrmHwcLayer layera[z_map.size()]; ++#endif ++#if defined(WITH_LIBVA_VIDEO) ++ l.second->PopulateDrmLayer(&va_compose_layer); ++#elif defined(WITH_LIBVA_ALL) ++ iterator->second->PopulateDrmLayer(&va_compose_layer); ++#endif ++#if defined(WITH_LIBVA_VIDEO) || defined(WITH_LIBVA_ALL) ++ client_layer_.PopulateDrmLayer(&clientlayer); ++ va_compose_layer.SetDisplayFrame(clientlayer.display_frame); ++ va_compose_layer.SetSourceCrop(clientlayer.source_crop); ++ int index =0; ++ for (std::pair &a : z_map) { ++ a.second->PopulateDrmLayer(&layera[index]); ++ va_compose_layer.addVaLayerMapData(a.first, &layera[index]); ++ index++; ++ } ++ ret = va_compose_layer.vaImportBuffer(drm_); ++ if (ret) { ++ ALOGE("Failed to import va layer, ret=%d", ret); ++ return HWC2::Error::NoResources; ++ } ++ composition_layers.emplace_back(std::move(va_compose_layer)); ++#endif ++#if defined(WITH_LIBVA_VIDEO) ++ break; ++ } ++ } ++#endif ++#if defined(WITH_LIBVA_VIDEO) || defined(WITH_LIBVA_ALL) ++ }else{ ++#endif ++ for (std::pair &l : z_map) { ++ DrmHwcLayer layer; ++ l.second->PopulateDrmLayer(&layer); ++ int ret = layer.ImportBuffer(drm_); ++ if (ret) { ++ ALOGE("Failed to import layer, ret=%d", ret); ++ return HWC2::Error::NoResources; ++ } ++ composition_layers.emplace_back(std::move(layer)); + } +- composition_layers.emplace_back(std::move(layer)); +- } + ++#if defined(WITH_LIBVA_VIDEO) || defined(WITH_LIBVA_ALL) ++ } ++#endif + auto composition = std::make_unique(crtc_, + planner_.get()); + + // TODO(nobody): Don't always assume geometry changed +- int ret = composition->SetLayers(composition_layers.data(), ++ ret = composition->SetLayers(composition_layers.data(), + composition_layers.size(), true); + if (ret) { + ALOGE("Failed to set layers in the composition ret=%d", ret); +@@ -778,6 +833,13 @@ HWC2::Error DrmHwcTwo::HwcDisplay::SetActiveConfig(hwc2_config_t config) { + .bottom = static_cast(mode->v_display())}; + client_layer_.SetLayerDisplayFrame(display_frame); + ++#if defined(WITH_LIBVA_ALL) ++ hwc_frect_t source_crop = {.left = 0.0f, ++ .top = 0.0f, ++ .right = static_cast(mode->h_display()), ++ .bottom = static_cast(mode->v_display())}; ++ client_layer_.SetLayerSourceCrop(source_crop); ++#endif + return HWC2::Error::None; + } + +@@ -1084,6 +1146,11 @@ HWC2::Error DrmHwcTwo::HwcLayer::SetLayerBuffer(buffer_handle_t buffer, + + set_buffer(buffer); + acquire_fence_ = UniqueFd(acquire_fence); ++ if (NULL != buffer) { ++ cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)(buffer); ++ if ((NULL != gr_handle) && (IsSupportedMediaFormat(gr_handle->format))) ++ layer_type_ = kLayerVideo; ++ } + return HWC2::Error::None; + } + +@@ -1182,6 +1249,7 @@ void DrmHwcTwo::HwcLayer::PopulateDrmLayer(DrmHwcLayer *layer) { + layer->source_crop = source_crop_; + layer->SetTransform(static_cast(transform_)); + layer->dataspace = dataspace_; ++ layer->SetVideoLayer(IsVideoLayer()); + } + + void DrmHwcTwo::HandleDisplayHotplug(hwc2_display_t displayid, int state) { +diff --git a/DrmHwcTwo.h b/DrmHwcTwo.h +index 911c38b..9f208f3 100644 +--- a/DrmHwcTwo.h ++++ b/DrmHwcTwo.h +@@ -88,6 +88,9 @@ class DrmHwcTwo : public hwc2_device_t { + + void PopulateDrmLayer(DrmHwcLayer *layer); + ++ bool IsVideoLayer(){ ++ return layer_type_ == kLayerVideo; ++ } + bool RequireScalingOrPhasing() { + float src_width = source_crop_.right - source_crop_.left; + float src_height = source_crop_.bottom - source_crop_.top; +@@ -144,6 +147,7 @@ class DrmHwcTwo : public hwc2_device_t { + HWC2::Transform transform_ = HWC2::Transform::None; + uint32_t z_order_ = 0; + android_dataspace_t dataspace_ = HAL_DATASPACE_UNKNOWN; ++ DrmHwcLayerType layer_type_ = kLayerNormal; + }; + + class HwcDisplay { +diff --git a/backend/Backend.cpp b/backend/Backend.cpp +index 44afd14..c311df9 100644 +--- a/backend/Backend.cpp ++++ b/backend/Backend.cpp +@@ -20,7 +20,7 @@ + + #include "BackendManager.h" + #include "bufferinfo/BufferInfoGetter.h" +- ++#include "utils/log.h" + namespace android { + + HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, +@@ -40,9 +40,26 @@ HWC2::Error Backend::ValidateDisplay(DrmHwcTwo::HwcDisplay *display, + MarkValidated(layers, client_start, client_size); + } else { + std::tie(client_start, client_size) = GetClientLayers(display, layers); ++ bool include_video_layer = false; ++ for (int z_order = 0; z_order < layers.size(); ++z_order) { ++ if (layers[z_order]->IsVideoLayer()) { ++ include_video_layer = true; ++ } ++ } ++#if defined(WITH_LIBVA_VIDEO) ++ if (include_video_layer) ++#endif ++#if defined(WITH_LIBVA_VIDEO) || defined(WITH_LIBVA_ALL) ++ vaMarkValidated(layers); ++#endif ++#if defined(WITH_LIBVA_VIDEO) ++ else ++ MarkValidated(layers, client_start, client_size); ++#endif + +- MarkValidated(layers, client_start, client_size); +- ++#if !defined(WITH_LIBVA_VIDEO) && !defined(WITH_LIBVA_ALL) ++ MarkValidated(layers, client_start, client_size); ++#endif + bool testing_needed = !(client_start == 0 && client_size == layers.size()); + + if (testing_needed && +@@ -119,6 +136,17 @@ void Backend::MarkValidated(std::vector &layers, + } + } + ++void Backend::vaMarkValidated(std::vector &layers) { ++ for (int z_order = 0; z_order < layers.size(); ++z_order) { ++ if (layers[z_order]->sf_type() == HWC2::Composition::SolidColor || ++ layers[z_order]->sf_type() == HWC2::Composition::Sideband || ++ layers[z_order]->sf_type() == HWC2::Composition::Client) ++ layers[z_order]->set_validated_type(layers[z_order]->sf_type()); ++ else ++ layers[z_order]->set_validated_type(HWC2::Composition::Device); ++ } ++} ++ + std::tuple Backend::GetExtraClientRange( + DrmHwcTwo::HwcDisplay *display, + const std::vector &layers, int client_start, +diff --git a/backend/Backend.h b/backend/Backend.h +index fc9a733..c934195 100644 +--- a/backend/Backend.h ++++ b/backend/Backend.h +@@ -39,6 +39,7 @@ class Backend { + size_t first_z, size_t size); + void MarkValidated(std::vector &layers, + size_t client_first_z, size_t client_size); ++ void vaMarkValidated(std::vector &layers); + std::tuple GetExtraClientRange( + DrmHwcTwo::HwcDisplay *display, + const std::vector &layers, int client_start, +diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp +index f741b6f..9bfd9ff 100644 +--- a/compositor/DrmDisplayCompositor.cpp ++++ b/compositor/DrmDisplayCompositor.cpp +@@ -337,14 +337,18 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp, + rotation |= DRM_MODE_REFLECT_X; + if (layer.transform & DrmHwcTransform::kFlipV) + rotation |= DRM_MODE_REFLECT_Y; +- if (layer.transform & DrmHwcTransform::kRotate90) +- rotation |= DRM_MODE_ROTATE_90; +- else if (layer.transform & DrmHwcTransform::kRotate180) +- rotation |= DRM_MODE_ROTATE_180; +- else if (layer.transform & DrmHwcTransform::kRotate270) +- rotation |= DRM_MODE_ROTATE_270; +- else ++ if (layer.IsVideoLayer()) { + rotation |= DRM_MODE_ROTATE_0; ++ }else { ++ if (layer.transform & DrmHwcTransform::kRotate90) ++ rotation |= DRM_MODE_ROTATE_90; ++ else if (layer.transform & DrmHwcTransform::kRotate180) ++ rotation |= DRM_MODE_ROTATE_180; ++ else if (layer.transform & DrmHwcTransform::kRotate270) ++ rotation |= DRM_MODE_ROTATE_270; ++ else ++ rotation |= DRM_MODE_ROTATE_0; ++ } + + if (fence_fd >= 0) { + int prop_id = plane->in_fence_fd_property().id(); +diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp +index 80c9994..b18bb2d 100644 +--- a/drm/DrmFbImporter.cpp ++++ b/drm/DrmFbImporter.cpp +@@ -25,10 +25,11 @@ + + #include + #include +- ++#include "bufferinfo/BufferInfoGetter.h" + #include "utils/log.h" + #include "utils/properties.h" +- ++#include "cros_gralloc_handle.h" ++#include "gralloc1/gralloc1bufferhandler.h" + namespace android { + + auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, +@@ -74,7 +75,8 @@ auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle, + &local->gem_handles_[0], &bo->pitches[0], + &bo->offsets[0], &local->fb_id_, 0); + } else { +- if (bo->format == DRM_FORMAT_NV12_Y_TILED_INTEL) { ++ if (bo->format == DRM_FORMAT_NV12_Y_TILED_INTEL || ++ bo->format == DRM_FORMAT_NV12) { + for (uint32_t i = num_planes; i < HWC_DRM_BO_MAX_PLANES; i++) { + bo->modifiers[i] = DRM_FORMAT_MOD_NONE; + local->gem_handles_[i] = 0; +@@ -124,6 +126,19 @@ DrmFbIdHandle::~DrmFbIdHandle() { + } + } + ++DrmFbImporter::DrmFbImporter(std::shared_ptr drm) ++ : drm_(std::move(drm)){ ++ if (!media_renderer_) { ++ media_renderer_.reset(new VARenderer()); ++ if (!media_renderer_->Init(drm_->fd())) { ++ ALOGE("Failed to initialize Media va Renderer \n"); ++ media_renderer_.reset(nullptr); ++ } else { ++ ALOGD("Succeeded to initialize Media va Renderer"); ++ } ++ } ++} ++ + auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo) + -> std::shared_ptr { + /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */ +@@ -159,4 +174,60 @@ auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo) + return fb_id_handle; + } + ++ ++auto DrmFbImporter::vaGetOrCreateFbId(DrmHwcLayer* layer) ++ -> std::shared_ptr { ++ layer->buffer_info = hwc_drm_bo_t{}; ++ buffer_handle_t buffer_handle = layer->get_usable_handle(); ++#if defined(WITH_LIBVA_VIDEO) ++ cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)layer->get_usable_handle(); ++ if (IsSupportedMediaFormat(gr_handle->format)) { ++#endif ++ media_renderer_->startRender(layer, DRM_FORMAT_ABGR8888); ++ buffer_handle = media_renderer_->getPreBuffer(); ++#ifdef ENABLE_DUMP_YUV_DATA ++ Gralloc1BufferHandler::DumpBuffer(buffer_handle); ++#endif ++#if defined(WITH_LIBVA_VIDEO) ++ } ++#endif ++ int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(buffer_handle, ++ &layer->buffer_info); ++ if (ret) { ++ ALOGE("Failed to convert buffer info %d", ret); ++ return std::shared_ptr(); ++ } ++ /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */ ++ GemHandle first_handle = 0; ++ int32_t err = drmPrimeFDToHandle(drm_->fd(), layer->buffer_info.prime_fds[0], &first_handle); ++ ++ if (err != 0) { ++ ALOGE("Failed to import prime fd %d ret=%d", layer->buffer_info.prime_fds[0], err); ++ return std::shared_ptr(); ++ } ++ ++ auto drm_fb_id_cached = drm_fb_id_handle_cache_.find(first_handle); ++ ++ if (drm_fb_id_cached != drm_fb_id_handle_cache_.end()) { ++ if (auto drm_fb_id_handle_shared = drm_fb_id_cached->second) { ++ return drm_fb_id_handle_shared; ++ } ++ drm_fb_id_handle_cache_.erase(drm_fb_id_cached); ++ } ++ ++ /* Cleanup cached empty weak pointers */ ++ const int minimal_cleanup_size = 128; ++ if (drm_fb_id_handle_cache_.size() > minimal_cleanup_size) { ++ CleanupEmptyCacheElements(); ++ } ++ ++ /* No DrmFbIdHandle found in cache, create framebuffer object */ ++ auto fb_id_handle = DrmFbIdHandle::CreateInstance(&layer->buffer_info, first_handle, drm_); ++ if (fb_id_handle) { ++ drm_fb_id_handle_cache_[first_handle] = fb_id_handle; ++ } ++ ++ return fb_id_handle; ++} ++ + } // namespace android +diff --git a/drm/DrmFbImporter.h b/drm/DrmFbImporter.h +index 6d4910a..f37bdbf 100644 +--- a/drm/DrmFbImporter.h ++++ b/drm/DrmFbImporter.h +@@ -25,7 +25,7 @@ + + #include "drm/DrmDevice.h" + #include "drmhwcgralloc.h" +- ++#include "va/varenderer.h" + #ifndef DRM_FORMAT_INVALID + #define DRM_FORMAT_INVALID 0 + #endif +@@ -62,9 +62,11 @@ class DrmFbIdHandle { + + class DrmFbImporter { + public: +- explicit DrmFbImporter(std::shared_ptr drm) +- : drm_(std::move(drm)){}; +- ~DrmFbImporter() = default; ++ explicit DrmFbImporter(std::shared_ptr drm); ++ ~DrmFbImporter() { ++ if (NULL != media_renderer_) ++ media_renderer_.reset(nullptr); ++ } + DrmFbImporter(const DrmFbImporter &) = delete; + DrmFbImporter(DrmFbImporter &&) = delete; + auto operator=(const DrmFbImporter &) = delete; +@@ -72,6 +74,7 @@ class DrmFbImporter { + + auto GetOrCreateFbId(hwc_drm_bo_t *bo) -> std::shared_ptr; + ++ auto vaGetOrCreateFbId(DrmHwcLayer* layer) -> std::shared_ptr; + private: + void CleanupEmptyCacheElements() { + for (auto it = drm_fb_id_handle_cache_.begin(); +@@ -83,6 +86,7 @@ class DrmFbImporter { + const std::shared_ptr drm_; + + std::map> drm_fb_id_handle_cache_; ++ std::unique_ptr media_renderer_; + }; + + } // namespace android +diff --git a/gralloc1/gralloc1bufferhandler.cpp b/gralloc1/gralloc1bufferhandler.cpp +new file mode 100755 +index 0000000..408bc59 +--- /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->base.numFds; ++ target_handle->base.numFds = source_handle->base.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 0000000..9ac5db2 +--- /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/include/drmhwcomposer.h b/include/drmhwcomposer.h +index 6528f86..95d2b1f 100644 +--- a/include/drmhwcomposer.h ++++ b/include/drmhwcomposer.h +@@ -33,6 +33,40 @@ namespace android { + + class DrmFbIdHandle; + ++class DrmHwcNativeHandle { ++ public: ++ DrmHwcNativeHandle() = default; ++ ++ DrmHwcNativeHandle(native_handle_t *handle) : handle_(handle) { ++ } ++ ++ DrmHwcNativeHandle(DrmHwcNativeHandle &&rhs) { ++ handle_ = rhs.handle_; ++ rhs.handle_ = NULL; ++ } ++ ++ ~DrmHwcNativeHandle(); ++ ++ DrmHwcNativeHandle &operator=(DrmHwcNativeHandle &&rhs) { ++ Clear(); ++ handle_ = rhs.handle_; ++ rhs.handle_ = NULL; ++ return *this; ++ } ++ ++ int CopyBufferHandle(buffer_handle_t handle, int width, int height, ++ int layerCount, int format, int usage, int stride); ++ ++ void Clear(); ++ ++ buffer_handle_t get() const { ++ return handle_; ++ } ++ ++ private: ++ native_handle_t *handle_ = NULL; ++}; ++ + enum DrmHwcTransform { + kIdentity = 0, + kFlipH = 1 << 0, +@@ -42,6 +76,14 @@ enum DrmHwcTransform { + kRotate270 = 1 << 4, + }; + ++enum DrmHwcLayerType { ++ kLayerNormal = 0, ++ kLayerCursor = 1, ++ kLayerProtected = 2, ++ kLayerVideo = 3, ++ kLayerSolidColor = 4, ++}; ++ + enum class DrmHwcBlending : int32_t { + kNone = HWC_BLENDING_NONE, + kPreMult = HWC_BLENDING_PREMULT, +@@ -50,6 +92,7 @@ enum class DrmHwcBlending : int32_t { + + struct DrmHwcLayer { + buffer_handle_t sf_handle = NULL; ++ DrmHwcNativeHandle handle; + hwc_drm_bo_t buffer_info{}; + std::shared_ptr FbIdHandle; + +@@ -60,19 +103,44 @@ struct DrmHwcLayer { + hwc_frect_t source_crop; + hwc_rect_t display_frame; + android_dataspace_t dataspace; +- ++ DrmHwcLayerType type_ = kLayerNormal; + UniqueFd acquire_fence; + + int ImportBuffer(DrmDevice *drmDevice); +- ++ int vaImportBuffer(DrmDevice *drmDevice); + void SetTransform(int32_t sf_transform); ++ void SetSourceCrop(hwc_frect_t const &crop); ++ void SetDisplayFrame(hwc_rect_t const &frame); ++ void SetVideoLayer(bool isVideo) { ++ if (isVideo) ++ type_ = kLayerVideo; ++ else ++ type_ = kLayerNormal; ++ } + ++ bool IsVideoLayer() const { ++ return type_ == kLayerVideo; ++ } ++ ++ buffer_handle_t get_usable_handle() const { ++ return handle.get() != NULL ? handle.get() : sf_handle; ++ } + bool protected_usage() const { + return (gralloc_buffer_usage & GRALLOC_USAGE_PROTECTED) == + GRALLOC_USAGE_PROTECTED; + } + }; + ++struct DrmVaComposeHwcLayer : DrmHwcLayer{ ++ std::map> va_z_map; ++ void addVaLayerMapData(int zorder, DrmHwcLayer* layer){ ++ va_z_map.emplace(std::make_pair(zorder, layer)); ++ } ++ std::map> getVaLayerMapData(){ ++ return va_z_map; ++ } ++}; ++ + } // namespace android + + #endif +diff --git a/include/nativebufferhandler.h b/include/nativebufferhandler.h +new file mode 100755 +index 0000000..2b25e0c +--- /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/tests/Android.bp b/tests/Android.bp +deleted file mode 100644 +index e30898c..0000000 +--- a/tests/Android.bp ++++ /dev/null +@@ -1,35 +0,0 @@ +-cc_library_shared { +- name: "hwcomposer.filegroups_build_test", +- defaults: ["hwcomposer.drm_defaults"], +- whole_static_libs: ["drm_hwcomposer"], +- +- srcs: [ +- ":drm_hwcomposer_platformhisi", +- ":drm_hwcomposer_platformimagination", +- ":drm_hwcomposer_platformmediatek", +- ":drm_hwcomposer_platformmeson", +- ], +- +- local_include_dirs: [ +- "test_include", +- ], +- +- cppflags: [ +- "-DDISABLE_LEGACY_GETTERS", +- ], +-} +- +-cc_test { +- name: "hwc-drm-tests", +- +- srcs: ["worker_test.cpp"], +- +- vendor: true, +- header_libs: ["libhardware_headers"], +- static_libs: ["libdrmhwc_utils"], +- shared_libs: ["hwcomposer.drm"], +- include_dirs: [ +- "external/drm_hwcomposer", +- "external/drm_hwcomposer/include", +- ], +-} +diff --git a/utils/hwcutils.cpp b/utils/hwcutils.cpp +index 6de6500..412a77f 100644 +--- a/utils/hwcutils.cpp ++++ b/utils/hwcutils.cpp +@@ -38,7 +38,6 @@ int DrmHwcLayer::ImportBuffer(DrmDevice *drmDevice) { + ALOGE("Failed to convert buffer info %d", ret); + return ret; + } +- + FbIdHandle = drmDevice->GetDrmFbImporter().GetOrCreateFbId(&buffer_info); + if (!FbIdHandle) { + ALOGE("Failed to import buffer"); +@@ -48,6 +47,17 @@ int DrmHwcLayer::ImportBuffer(DrmDevice *drmDevice) { + return 0; + } + ++int DrmHwcLayer::vaImportBuffer(DrmDevice *drmDevice) { ++ ++ FbIdHandle = drmDevice->GetDrmFbImporter().vaGetOrCreateFbId(this); ++ if (!FbIdHandle) { ++ ALOGE("Failed to import buffer"); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + void DrmHwcLayer::SetTransform(int32_t sf_transform) { + transform = 0; + // 270* and 180* cannot be combined with flips. More specifically, they +@@ -67,4 +77,59 @@ void DrmHwcLayer::SetTransform(int32_t sf_transform) { + transform |= DrmHwcTransform::kRotate90; + } + } ++ ++void DrmHwcLayer::SetSourceCrop(hwc_frect_t const &crop) { ++ source_crop = crop; ++} ++ ++void DrmHwcLayer::SetDisplayFrame(hwc_rect_t const &frame) { ++ display_frame = frame; ++} ++ ++int DrmHwcNativeHandle::CopyBufferHandle(buffer_handle_t handle, int width, ++ int height, int layerCount, int format, ++ int usage, int stride) { ++ native_handle_t *handle_copy; ++ GraphicBufferMapper &gm(GraphicBufferMapper::get()); ++ int ret; ++ ++#ifdef HWC2_USE_OLD_GB_IMPORT ++ UNUSED(width); ++ UNUSED(height); ++ UNUSED(layerCount); ++ UNUSED(format); ++ UNUSED(usage); ++ UNUSED(stride); ++ ret = gm.importBuffer(handle, const_cast(&handle_copy)); ++#else ++ ret = gm.importBuffer(handle, width, height, layerCount, format, usage, ++ stride, const_cast(&handle_copy)); ++#endif ++ if (ret) { ++ ALOGE("Failed to import buffer handle %d", ret); ++ return ret; ++ } ++ ++ Clear(); ++ ++ handle_ = handle_copy; ++ ++ return 0; ++} ++ ++DrmHwcNativeHandle::~DrmHwcNativeHandle() { ++ Clear(); ++} ++ ++void DrmHwcNativeHandle::Clear() { ++ if (handle_ != NULL) { ++ GraphicBufferMapper &gm(GraphicBufferMapper::get()); ++ int ret = gm.freeBuffer(handle_); ++ if (ret) { ++ ALOGE("Failed to free buffer handle %d", ret); ++ } ++ handle_ = NULL; ++ } ++} ++ + } // namespace android +diff --git a/va/varenderer.cpp b/va/varenderer.cpp +new file mode 100755 +index 0000000..9974cad +--- /dev/null ++++ b/va/varenderer.cpp +@@ -0,0 +1,673 @@ ++/* ++// 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" ++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" ++ ++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->base.numFds; ++ 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(DrmHwcLayer* layer,uint32_t format){ ++ cros_gralloc_handle *gr_handle = (cros_gralloc_handle *)layer->get_usable_handle(); ++ 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 = ((DrmVaComposeHwcLayer *)layer)->getVaLayerMapData(); ++ input_layer_numer = va_layer_map.size(); ++ int connector_width = layer->display_frame.right - layer->display_frame.left; ++ int connector_height = layer->display_frame.bottom - layer->display_frame.top; ++ int rt_format = DrmFormatToRTFormat(format); ++ if(render_target_format_ != rt_format) ++ render_target_format_ = rt_format; ++ if ((layer->transform == kHwcTransform270) || (layer->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; ++ if (gr_handle->format == DRM_FORMAT_NV12_Y_TILED_INTEL) ++ gr_handle->format = DRM_FORMAT_NV12; ++ ++ 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->get_usable_handle(); ++ hwc_frect_t source_crop = a->second->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"); ++ return false; ++ } ++ hwc_rect_t display_frame = a->second->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->get_usable_handle(), 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->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 (!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); ++ } ++ 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 0000000..64a900a +--- /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 "nativebufferhandler.h" ++#include ++#include ++#include "vautils.h" ++ ++#define NATIVE_BUFFER_VECTOR_SIZE 3 ++ ++namespace android { ++ ++struct OverlayLayer; ++struct DrmHwcLayer; ++class NativeSurface; ++ ++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(DrmHwcLayer* 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 0000000..0397295 +--- /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 0000000..881ac3a +--- /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_ +-- +2.36.0 +