--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef OS_LINUX_IAHWC_H_
+#define OS_LINUX_IAHWC_H_
+
+#include <gbm.h>
+#include <stdint.h>
+
+#define IAHWC_MODULE IAHWC_MODULE_INFO
+#define IAHWC_MODULE_STR "IAHWC_MODULE_INFO"
+
+typedef void (*iahwc_function_ptr_t)();
+typedef uint32_t iahwc_display_t;
+typedef uint32_t iahwc_layer_t;
+typedef void* iahwc_callback_data_t;
+
+struct iahwc_device;
+
+typedef struct iahwc_module {
+ const char* name;
+ int (*open)(const struct iahwc_module* module, struct iahwc_device** device);
+} iahwc_module_t;
+
+typedef struct iahwc_device {
+ struct iahwc_module module;
+ int (*close)(struct iahwc_device* device);
+ iahwc_function_ptr_t (*getFunctionPtr)(struct iahwc_device* device,
+ int descriptor);
+} iahwc_device_t;
+
+typedef enum {
+ IAHWC_ERROR_NONE = 0,
+ IAHWC_ERROR_BAD_CONFIG,
+ IAHWC_ERROR_BAD_DISPLAY,
+ IAHWC_ERROR_BAD_LAYER,
+ IAHWC_ERROR_BAD_PARAMETER,
+ IAHWC_ERROR_HAS_CHANGES,
+ IAHWC_ERROR_NO_RESOURCES,
+ IAHWC_ERROR_NOT_VALIDATED,
+ IAHWC_ERROR_UNSUPPORTED,
+} iahwc_error_t;
+
+enum iahwc_display_configs {
+ IAHWC_CONFIG_WIDTH = 1,
+ IAHWC_CONFIG_HEIGHT = 2,
+ IAHWC_CONFIG_REFRESHRATE = 3,
+ IAHWC_CONFIG_DPIX = 4,
+ IAHWC_CONFIG_DPIY = 5
+};
+
+enum iahwc_function_descriptors {
+ IAHWC_FUNC_INVALID = 0,
+ IAHWC_FUNC_GET_NUM_DISPLAYS,
+ IAHWC_FUNC_REGISTER_CALLBACK,
+ IAHWC_FUNC_DISPLAY_GET_INFO,
+ IAHWC_FUNC_DISPLAY_GET_NAME,
+ IAHWC_FUNC_DISPLAY_GET_CONFIGS,
+ IAHWC_FUNC_DISPLAY_SET_GAMMA,
+ IAHWC_FUNC_DISPLAY_SET_CONFIG,
+ IAHWC_FUNC_DISPLAY_GET_CONFIG,
+ IAHWC_FUNC_DISPLAY_CLEAR_ALL_LAYERS,
+ IAHWC_FUNC_PRESENT_DISPLAY,
+ IAHWC_FUNC_CREATE_LAYER,
+ IAHWC_FUNC_LAYER_SET_BO,
+ IAHWC_FUNC_LAYER_SET_ACQUIRE_FENCE,
+ IAHWC_FUNC_LAYER_SET_USAGE,
+ IAHWC_FUNC_LAYER_SET_TRANSFORM,
+ IAHWC_FUNC_LAYER_SET_SOURCE_CROP,
+ IAHWC_FUNC_LAYER_SET_DISPLAY_FRAME,
+ IAHWC_FUNC_LAYER_SET_SURFACE_DAMAGE,
+};
+
+enum iahwc_callback_descriptor { IAHWC_CALLBACK_VSYNC };
+
+enum iahwc_layer_usage {
+ IAHWC_LAYER_USAGE_CURSOR,
+ IAHWC_LAYER_USAGE_OVERLAY,
+ IAHWC_LAYER_USAGE_NORMAL,
+};
+
+enum iahwc_layer_transform {
+ IAHWC_TRANSFORM_FLIP_H,
+ IAHWC_TRANSFORM_FLIP_V,
+ IAHWC_TRANSFORM_ROT_90,
+ IAHWC_TRANSFORM_ROT_180,
+ IAHWC_TRANSFORM_ROT_270,
+ IAHWC_TRANSFORM_FLIP_H_ROT_90,
+ IAHWC_TRANSFORM_FLIP_V_ROT_90
+};
+
+typedef struct iahwc_rect {
+ int left;
+ int top;
+ int right;
+ int bottom;
+} iahwc_rect_t;
+
+typedef struct iahwc_region {
+ size_t numRects;
+ iahwc_rect_t const* rects;
+} iahwc_region_t;
+
+typedef int (*IAHWC_PFN_GET_NUM_DISPLAYS)(iahwc_device_t*, int* num_displays);
+typedef int (*IAHWC_PFN_REGISTER_CALLBACK)(iahwc_device_t*, int descriptor,
+ iahwc_display_t display_handle,
+ iahwc_callback_data_t data,
+ iahwc_function_ptr_t hook);
+typedef int (*IAHWC_PFN_DISPLAY_GET_INFO)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ uint32_t config, int attribute,
+ int32_t* value);
+typedef int (*IAHWC_PFN_DISPLAY_GET_NAME)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ uint32_t* size, char* name);
+typedef int (*IAHWC_PFN_DISPLAY_GET_CONFIGS)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ uint32_t* num_configs,
+ uint32_t* configs);
+typedef int (*IAHWC_PFN_DISPLAY_SET_GAMMA)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ float r, float g, float b);
+typedef int (*IAHWC_PFN_DISPLAY_SET_CONFIG)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ uint32_t config);
+typedef int (*IAHWC_PFN_DISPLAY_GET_CONFIG)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ uint32_t* config);
+typedef int (*IAHWC_PFN_DISPLAY_CLEAR_ALL_LAYERS)(
+ iahwc_device_t*, iahwc_display_t display_handle);
+typedef int (*IAHWC_PFN_PRESENT_DISPLAY)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ int32_t* release_fd);
+typedef int (*IAHWC_PFN_CREATE_LAYER)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t* layer_handle);
+typedef int (*IAHWC_PFN_LAYER_SET_BO)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t layer_handle,
+ struct gbm_bo*);
+typedef int (*IAHWC_PFN_LAYER_SET_ACQUIRE_FENCE)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t layer_handle,
+ int32_t acquire_fence);
+typedef int (*IAHWC_PFN_LAYER_SET_USAGE)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t layer_handle,
+ int32_t layer_usage);
+typedef int (*IAHWC_PFN_LAYER_SET_TRANSFORM)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t layer_handle,
+ int32_t layer_transform);
+typedef int (*IAHWC_PFN_LAYER_SET_SOURCE_CROP)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t layer_handle,
+ iahwc_rect_t rect);
+typedef int (*IAHWC_PFN_LAYER_SET_DISPLAY_FRAME)(iahwc_device_t*,
+ iahwc_display_t display_handle,
+ iahwc_layer_t layer_handle,
+ iahwc_rect_t rect);
+typedef int (*IAHWC_PFN_LAYER_SET_SURFACE_DAMAGE)(
+ iahwc_device_t*, iahwc_display_t display_handle, iahwc_layer_t layer_handle,
+ iahwc_region_t region);
+typedef int (*IAHWC_PFN_VSYNC)(iahwc_callback_data_t data,
+ iahwc_display_t display, int64_t timestamp);
+#endif // OS_LINUX_IAHWC_H_
--- /dev/null
+/*
+ * 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 "linux_frontend.h"
+#include <commondrmutils.h>
+#include <hwcrect.h>
+
+namespace hwcomposer {
+
+class IAHWCVsyncCallback : public hwcomposer::VsyncCallback {
+ public:
+ IAHWCVsyncCallback(iahwc_callback_data_t data, iahwc_function_ptr_t hook)
+ : data_(data), hook_(hook) {
+ }
+
+ void Callback(uint32_t display, int64_t timestamp) {
+ if (hook_ != NULL) {
+ auto hook = reinterpret_cast<IAHWC_PFN_VSYNC>(hook_);
+ hook(data_, display, timestamp);
+ }
+ }
+
+ private:
+ iahwc_callback_data_t data_;
+ iahwc_function_ptr_t hook_;
+};
+
+IAHWC::IAHWC() {
+ getFunctionPtr = HookGetFunctionPtr;
+ close = HookClose;
+}
+
+int32_t IAHWC::Init() {
+ if (!device_.Initialize()) {
+ fprintf(stderr, "Unable to initialize GPU DEVICE");
+ return IAHWC_ERROR_NO_RESOURCES;
+ }
+
+ std::vector<hwcomposer::NativeDisplay*> displays = device_.GetAllDisplays();
+
+ for (hwcomposer::NativeDisplay* display : displays) {
+ displays_.emplace_back(new IAHWCDisplay());
+ IAHWCDisplay* iahwc_display = displays_.back();
+ iahwc_display->Init(display);
+ }
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::HookOpen(const iahwc_module_t* module, iahwc_device_t** device) {
+ IAHWC* iahwc = new IAHWC();
+ iahwc->Init();
+ *device = iahwc;
+
+ return IAHWC_ERROR_NONE;
+}
+
+iahwc_function_ptr_t IAHWC::HookGetFunctionPtr(iahwc_device_t* /* device */,
+ int func_descriptor) {
+ switch (func_descriptor) {
+ case IAHWC_FUNC_GET_NUM_DISPLAYS:
+ return ToHook<IAHWC_PFN_GET_NUM_DISPLAYS>(
+ DeviceHook<int32_t, decltype(&IAHWC::GetNumDisplays),
+ &IAHWC::GetNumDisplays, int*>);
+ case IAHWC_FUNC_REGISTER_CALLBACK:
+ return ToHook<IAHWC_PFN_REGISTER_CALLBACK>(
+ DeviceHook<int32_t, decltype(&IAHWC::RegisterCallback),
+ &IAHWC::RegisterCallback, int, uint32_t,
+ iahwc_callback_data_t, iahwc_function_ptr_t>);
+ case IAHWC_FUNC_DISPLAY_GET_INFO:
+ return ToHook<IAHWC_PFN_DISPLAY_GET_INFO>(
+ DisplayHook<decltype(&IAHWCDisplay::GetDisplayInfo),
+ &IAHWCDisplay::GetDisplayInfo, uint32_t, int, int32_t*>);
+ case IAHWC_FUNC_DISPLAY_GET_NAME:
+ return ToHook<IAHWC_PFN_DISPLAY_GET_NAME>(
+ DisplayHook<decltype(&IAHWCDisplay::GetDisplayName),
+ &IAHWCDisplay::GetDisplayName, uint32_t*, char*>);
+ case IAHWC_FUNC_DISPLAY_GET_CONFIGS:
+ return ToHook<IAHWC_PFN_DISPLAY_GET_CONFIGS>(
+ DisplayHook<decltype(&IAHWCDisplay::GetDisplayConfigs),
+ &IAHWCDisplay::GetDisplayConfigs, uint32_t*, uint32_t*>);
+ case IAHWC_FUNC_DISPLAY_SET_GAMMA:
+ return ToHook<IAHWC_PFN_DISPLAY_SET_GAMMA>(
+ DisplayHook<decltype(&IAHWCDisplay::SetDisplayGamma),
+ &IAHWCDisplay::SetDisplayGamma, float, float, float>);
+ case IAHWC_FUNC_DISPLAY_SET_CONFIG:
+ return ToHook<IAHWC_PFN_DISPLAY_SET_CONFIG>(
+ DisplayHook<decltype(&IAHWCDisplay::SetDisplayConfig),
+ &IAHWCDisplay::SetDisplayConfig, uint32_t>);
+ case IAHWC_FUNC_DISPLAY_GET_CONFIG:
+ return ToHook<IAHWC_PFN_DISPLAY_GET_CONFIG>(
+ DisplayHook<decltype(&IAHWCDisplay::GetDisplayConfig),
+ &IAHWCDisplay::GetDisplayConfig, uint32_t*>);
+ case IAHWC_FUNC_DISPLAY_CLEAR_ALL_LAYERS:
+ return ToHook<IAHWC_PFN_DISPLAY_CLEAR_ALL_LAYERS>(
+ DisplayHook<decltype(&IAHWCDisplay::ClearAllLayers),
+ &IAHWCDisplay::ClearAllLayers>);
+ case IAHWC_FUNC_PRESENT_DISPLAY:
+ return ToHook<IAHWC_PFN_PRESENT_DISPLAY>(
+ DisplayHook<decltype(&IAHWCDisplay::PresentDisplay),
+ &IAHWCDisplay::PresentDisplay, int32_t*>);
+ case IAHWC_FUNC_CREATE_LAYER:
+ return ToHook<IAHWC_PFN_CREATE_LAYER>(
+ DisplayHook<decltype(&IAHWCDisplay::CreateLayer),
+ &IAHWCDisplay::CreateLayer, uint32_t*>);
+ case IAHWC_FUNC_LAYER_SET_BO:
+ return ToHook<IAHWC_PFN_LAYER_SET_BO>(
+ LayerHook<decltype(&IAHWCLayer::SetBo), &IAHWCLayer::SetBo, gbm_bo*>);
+ case IAHWC_FUNC_LAYER_SET_ACQUIRE_FENCE:
+ return ToHook<IAHWC_PFN_LAYER_SET_ACQUIRE_FENCE>(
+ LayerHook<decltype(&IAHWCLayer::SetAcquireFence),
+ &IAHWCLayer::SetAcquireFence, int32_t>);
+ case IAHWC_FUNC_LAYER_SET_USAGE:
+ return ToHook<IAHWC_PFN_LAYER_SET_USAGE>(
+ LayerHook<decltype(&IAHWCLayer::SetLayerUsage),
+ &IAHWCLayer::SetLayerUsage, int32_t>);
+ case IAHWC_FUNC_LAYER_SET_TRANSFORM:
+ return ToHook<IAHWC_PFN_LAYER_SET_TRANSFORM>(
+ LayerHook<decltype(&IAHWCLayer::SetLayerTransform),
+ &IAHWCLayer::SetLayerTransform, int32_t>);
+ case IAHWC_FUNC_LAYER_SET_SOURCE_CROP:
+ return ToHook<IAHWC_PFN_LAYER_SET_SOURCE_CROP>(
+ LayerHook<decltype(&IAHWCLayer::SetLayerSourceCrop),
+ &IAHWCLayer::SetLayerSourceCrop, iahwc_rect_t>);
+ case IAHWC_FUNC_LAYER_SET_DISPLAY_FRAME:
+ return ToHook<IAHWC_PFN_LAYER_SET_DISPLAY_FRAME>(
+ LayerHook<decltype(&IAHWCLayer::SetLayerDisplayFrame),
+ &IAHWCLayer::SetLayerDisplayFrame, iahwc_rect_t>);
+ case IAHWC_FUNC_LAYER_SET_SURFACE_DAMAGE:
+ return ToHook<IAHWC_PFN_LAYER_SET_SURFACE_DAMAGE>(
+ LayerHook<decltype(&IAHWCLayer::SetLayerSurfaceDamage),
+ &IAHWCLayer::SetLayerSurfaceDamage, iahwc_region_t>);
+ case IAHWC_FUNC_INVALID:
+ default:
+ return NULL;
+ }
+}
+
+int IAHWC::HookClose(iahwc_device_t* dev) {
+ delete dev;
+ return 0;
+}
+
+// private function implementations
+
+int IAHWC::GetNumDisplays(int* num_displays) {
+ *num_displays = 0;
+ for (IAHWCDisplay* display : displays_) {
+ if (display->IsConnected())
+ *num_displays += 1;
+ }
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::RegisterCallback(int32_t description, uint32_t display_id,
+ iahwc_callback_data_t data,
+ iahwc_function_ptr_t hook) {
+ switch (description) {
+ case IAHWC_CALLBACK_VSYNC: {
+ if (display_id >= displays_.size())
+ return IAHWC_ERROR_BAD_DISPLAY;
+ IAHWCDisplay* display = displays_.at(display_id);
+ return display->RegisterVsyncCallback(data, hook);
+ }
+ default:
+ return IAHWC_ERROR_BAD_PARAMETER;
+ }
+}
+
+IAHWC::IAHWCDisplay::IAHWCDisplay() : native_display_(NULL) {
+}
+
+int IAHWC::IAHWCDisplay::Init(hwcomposer::NativeDisplay* display) {
+ native_display_ = display;
+ native_display_->InitializeLayerHashGenerator(4);
+}
+
+int IAHWC::IAHWCDisplay::GetDisplayInfo(uint32_t config, int attribute,
+ int32_t* value) {
+ hwcomposer::HWCDisplayAttribute attrib =
+ static_cast<hwcomposer::HWCDisplayAttribute>(attribute);
+
+ bool ret = native_display_->GetDisplayAttribute(config, attrib, value);
+
+ if (!ret)
+ return IAHWC_ERROR_NO_RESOURCES;
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::GetDisplayName(uint32_t* size, char* name) {
+ bool ret = native_display_->GetDisplayName(size, name);
+
+ if (!ret)
+ return IAHWC_ERROR_NO_RESOURCES;
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::GetDisplayConfigs(uint32_t* num_configs,
+ uint32_t* configs) {
+ bool ret = native_display_->GetDisplayConfigs(num_configs, configs);
+
+ if (!ret)
+ return IAHWC_ERROR_NO_RESOURCES;
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::SetDisplayGamma(float r, float b, float g) {
+ native_display_->SetGamma(r, g, b);
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::SetDisplayConfig(uint32_t config) {
+ bool ret = native_display_->SetActiveConfig(config);
+
+ if (!ret)
+ return IAHWC_ERROR_NO_RESOURCES;
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::GetDisplayConfig(uint32_t* config) {
+ bool ret = native_display_->GetActiveConfig(config);
+
+ if (!ret)
+ return IAHWC_ERROR_NO_RESOURCES;
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::ClearAllLayers() {
+ layers_.clear();
+ native_display_->ResetLayerHashGenerator();
+
+ return IAHWC_ERROR_NONE;
+}
+int IAHWC::IAHWCDisplay::PresentDisplay(int32_t* release_fd) {
+ std::vector<hwcomposer::HwcLayer*> layers;
+ hwcomposer::HwcLayer* cursor_layer = NULL;
+
+ for (auto & [ first, second ] : layers_) {
+ if (second.GetLayerUsage() == IAHWC_LAYER_USAGE_CURSOR)
+ cursor_layer = second.GetLayer();
+ else
+ layers.emplace_back(second.GetLayer());
+ }
+
+ if (cursor_layer)
+ layers.insert(layers.begin(), cursor_layer);
+
+ native_display_->Present(layers, release_fd);
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::CreateLayer(uint32_t* layer_handle) {
+ *layer_handle = native_display_->AcquireId();
+ layers_.emplace(*layer_handle, IAHWCLayer());
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCDisplay::RegisterVsyncCallback(iahwc_callback_data_t data,
+ iahwc_function_ptr_t hook) {
+ auto callback = std::make_shared<IAHWCVsyncCallback>(data, hook);
+ native_display_->VSyncControl(true);
+ int ret = native_display_->RegisterVsyncCallback(std::move(callback),
+ static_cast<int>(0));
+ if (ret) {
+ return IAHWC_ERROR_BAD_DISPLAY;
+ }
+ return IAHWC_ERROR_NONE;
+}
+
+bool IAHWC::IAHWCDisplay::IsConnected() {
+ return native_display_->IsConnected();
+}
+
+IAHWC::IAHWCLayer::IAHWCLayer() {
+ layer_usage_ = IAHWC_LAYER_USAGE_NORMAL;
+}
+
+IAHWC::IAHWCLayer::~IAHWCLayer() {
+ ::close(hwc_handle_.import_data.fd);
+}
+
+int IAHWC::IAHWCLayer::SetBo(gbm_bo* bo) {
+ int32_t width, height;
+
+ ::close(hwc_handle_.import_data.fd);
+
+ width = gbm_bo_get_width(bo);
+ height = gbm_bo_get_height(bo);
+
+ hwc_handle_.import_data.width = width;
+ hwc_handle_.import_data.height = height;
+ hwc_handle_.import_data.format = gbm_bo_get_format(bo);
+ hwc_handle_.import_data.fd = gbm_bo_get_fd(bo);
+ hwc_handle_.import_data.stride = gbm_bo_get_stride(bo);
+ hwc_handle_.total_planes =
+ drm_bo_get_num_planes(hwc_handle_.import_data.format);
+ hwc_handle_.bo = bo;
+ hwc_handle_.hwc_buffer_ = true;
+ hwc_handle_.gbm_flags = 0;
+
+ iahwc_layer_.SetNativeHandle(&hwc_handle_);
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCLayer::SetAcquireFence(int32_t acquire_fence) {
+ iahwc_layer_.SetAcquireFence(acquire_fence);
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCLayer::SetLayerUsage(int32_t layer_usage) {
+ layer_usage_ = layer_usage;
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCLayer::SetLayerTransform(int32_t layer_transform) {
+ // 270* and 180* cannot be combined with flips. More specifically, they
+ // already contain both horizontal and vertical flips, so those fields are
+ // redundant in this case. 90* rotation can be combined with either horizontal
+ // flip or vertical flip, so treat it differently
+ int32_t temp = 0;
+ if (layer_transform == IAHWC_TRANSFORM_ROT_270) {
+ temp = hwcomposer::HWCTransform::kTransform270;
+ } else if (layer_transform == IAHWC_TRANSFORM_ROT_180) {
+ temp = hwcomposer::HWCTransform::kTransform180;
+ } else {
+ if (layer_transform & IAHWC_TRANSFORM_FLIP_H)
+ temp |= hwcomposer::HWCTransform::kReflectX;
+ if (layer_transform & IAHWC_TRANSFORM_FLIP_V)
+ temp |= hwcomposer::HWCTransform::kReflectY;
+ if (layer_transform & IAHWC_TRANSFORM_ROT_90)
+ temp |= hwcomposer::HWCTransform::kTransform90;
+ }
+ iahwc_layer_.SetTransform(temp);
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCLayer::SetLayerSourceCrop(iahwc_rect_t rect) {
+ iahwc_layer_.SetSourceCrop(
+ hwcomposer::HwcRect<float>(rect.left, rect.top, rect.right, rect.bottom));
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCLayer::SetLayerDisplayFrame(iahwc_rect_t rect) {
+ iahwc_layer_.SetDisplayFrame(
+ hwcomposer::HwcRect<float>(rect.left, rect.top, rect.right, rect.bottom),
+ 0);
+
+ return IAHWC_ERROR_NONE;
+}
+
+int IAHWC::IAHWCLayer::SetLayerSurfaceDamage(iahwc_region_t region) {
+ uint32_t num_rects = region.numRects;
+ hwcomposer::HwcRegion hwc_region;
+
+ for (size_t rect = 0; rect < num_rects; ++rect) {
+ hwc_region.emplace_back(region.rects[rect].left, region.rects[rect].top,
+ region.rects[rect].right,
+ region.rects[rect].bottom);
+ }
+
+ iahwc_layer_.SetSurfaceDamage(hwc_region);
+
+ return IAHWC_ERROR_NONE;
+}
+
+hwcomposer::HwcLayer* IAHWC::IAHWCLayer::GetLayer() {
+ return &iahwc_layer_;
+}
+
+} // namespace hwcomposer
+
+iahwc_module_t IAHWC_MODULE_INFO = {
+ .name = "IA Hardware Composer",
+ .open = hwcomposer::IAHWC::HookOpen,
+};
--- /dev/null
+/*
+ * Copyright (c) 2012 Arvin Schnell <arvin.schnell@gmail.com>
+ * Copyright (c) 2012 Rob Clark <rob@ti.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* Based on a egl cube test app originally written by Arvin Schnell */
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <linux/kd.h>
+#include <linux/major.h>
+#include <linux/vt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <unistd.h>
+
+#include <drm_fourcc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+// clang-format off
+#include "esUtil.h"
+#include <EGL/eglext.h>
+#include <GLES2/gl2ext.h>
+// clang-format on
+
+#include <libsync.h>
+
+#include <gpudevice.h>
+#include <hwclayer.h>
+#include <hwcdefs.h>
+#include <nativedisplay.h>
+#include <platformdefines.h>
+#include <spinlock.h>
+
+#include <iahwc.h>
+
+#include "glcubelayerrenderer.h"
+#include "videolayerrenderer.h"
+#include "imagelayerrenderer.h"
+#include "cclayerrenderer.h"
+#include "jsonhandlers.h"
+
+#include <nativebufferhandler.h>
+#include "platformcommondefines.h"
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+int tty;
+
+static void reset_vt() {
+ struct vt_mode mode = {0};
+
+ if (ioctl(tty, KDSETMODE, KD_TEXT))
+ fprintf(stderr, "failed to set KD_TEXT mode on tty: %m\n");
+
+ mode.mode = VT_AUTO;
+ if (ioctl(tty, VT_SETMODE, &mode) < 0)
+ fprintf(stderr, "could not reset vt handling\n");
+
+ exit(0);
+}
+
+static void handle_signal(int sig) {
+ if (sig == 11)
+ printf("received SIGSEGV\n");
+ fflush(stdout);
+ reset_vt();
+}
+
+static int setup_tty() {
+ struct vt_mode mode = {0};
+ struct stat buf;
+ int ret, kd_mode;
+
+ tty = dup(STDIN_FILENO);
+
+ if (fstat(tty, &buf) == -1 || major(buf.st_rdev) != TTY_MAJOR) {
+ fprintf(stderr, "Please run the program in a vt \n");
+ goto err_close;
+ }
+
+ ret = ioctl(tty, KDGETMODE, &kd_mode);
+ if (ret) {
+ fprintf(stderr, "failed to get VT mode: %m\n");
+ return -1;
+ }
+
+ if (kd_mode != KD_TEXT) {
+ fprintf(stderr,
+ "Already in graphics mode, "
+ "is a display server running?\n");
+ goto err_close;
+ }
+
+ ioctl(tty, VT_ACTIVATE, minor(buf.st_rdev));
+ ioctl(tty, VT_WAITACTIVE, minor(buf.st_rdev));
+
+ ret = ioctl(tty, KDSETMODE, KD_GRAPHICS);
+ if (ret) {
+ fprintf(stderr, "failed to set KD_GRAPHICS mode on tty: %m\n");
+ goto err_close;
+ }
+
+ mode.mode = VT_PROCESS;
+ mode.relsig = 0;
+ mode.acqsig = 0;
+ if (ioctl(tty, VT_SETMODE, &mode) < 0) {
+ fprintf(stderr, "failed to take control of vt handling\n");
+ goto err_close;
+ }
+
+ struct sigaction act;
+ act.sa_handler = handle_signal;
+ act.sa_flags = SA_RESETHAND;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGABRT, &act, NULL);
+
+ atexit(reset_vt);
+
+ return 0;
+
+err_close:
+ close(tty);
+ exit(0);
+}
+
+/* Exit after rendering the given number of frames. If 0, then continue
+ * rendering forever.
+ */
+static uint64_t arg_frames = 0;
+
+/*flag set to test displaymode*/
+static int display_mode;
+int force_mode = 0, config_index = 0, print_display_config = 0;
+LAYER_PARAMETER layer_parameter;
+
+glContext gl;
+
+struct iahwc_backend {
+ iahwc_module_t *iahwc_module;
+ iahwc_device_t *iahwc_device;
+ IAHWC_PFN_GET_NUM_DISPLAYS iahwc_get_num_displays;
+ IAHWC_PFN_REGISTER_CALLBACK iahwc_register_callback;
+ IAHWC_PFN_DISPLAY_GET_INFO iahwc_get_display_info;
+ IAHWC_PFN_DISPLAY_GET_NAME iahwc_get_display_name;
+ IAHWC_PFN_DISPLAY_GET_CONFIGS iahwc_get_display_configs;
+ IAHWC_PFN_DISPLAY_SET_GAMMA iahwc_set_display_gamma;
+ IAHWC_PFN_DISPLAY_SET_CONFIG iahwc_set_display_config;
+ IAHWC_PFN_DISPLAY_GET_CONFIG iahwc_get_display_config;
+ IAHWC_PFN_PRESENT_DISPLAY iahwc_present_display;
+ IAHWC_PFN_CREATE_LAYER iahwc_create_layer;
+ IAHWC_PFN_LAYER_SET_BO iahwc_layer_set_bo;
+ IAHWC_PFN_LAYER_SET_ACQUIRE_FENCE iahwc_layer_set_acquire_fence;
+ IAHWC_PFN_LAYER_SET_USAGE iahwc_layer_set_usage;
+ IAHWC_PFN_LAYER_SET_TRANSFORM iahwc_layer_set_transform;
+ IAHWC_PFN_LAYER_SET_SOURCE_CROP iahwc_layer_set_source_crop;
+ IAHWC_PFN_LAYER_SET_DISPLAY_FRAME iahwc_layer_set_display_frame;
+ IAHWC_PFN_LAYER_SET_SURFACE_DAMAGE iahwc_layer_set_surface_damage;
+ IAHWC_PFN_VSYNC iahwc_vsync;
+
+} * backend;
+
+struct frame {
+ std::vector<iahwc_layer_t> layers;
+ std::vector<gbm_bo *> layer_bos;
+ std::vector<std::unique_ptr<LayerRenderer>> layer_renderers;
+ std::vector<std::vector<uint32_t>> layers_fences;
+ std::vector<int32_t> fences;
+};
+
+bool init_gl() {
+ EGLint major, minor, n;
+ static const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3,
+ EGL_NONE};
+
+ static const EGLint config_attribs[] = {EGL_SURFACE_TYPE, EGL_DONT_CARE,
+ EGL_NONE};
+
+ gl.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ if (!eglInitialize(gl.display, &major, &minor)) {
+ printf("failed to initialize EGL\n");
+ return false;
+ }
+
+#define get_proc(name, proc) \
+ do { \
+ gl.name = (proc)eglGetProcAddress(#name); \
+ assert(gl.name); \
+ } while (0)
+ get_proc(glEGLImageTargetRenderbufferStorageOES,
+ PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC);
+ get_proc(eglCreateImageKHR, PFNEGLCREATEIMAGEKHRPROC);
+ get_proc(eglCreateSyncKHR, PFNEGLCREATESYNCKHRPROC);
+ get_proc(eglDestroySyncKHR, PFNEGLDESTROYSYNCKHRPROC);
+ get_proc(eglWaitSyncKHR, PFNEGLWAITSYNCKHRPROC);
+ get_proc(eglClientWaitSyncKHR, PFNEGLCLIENTWAITSYNCKHRPROC);
+ get_proc(eglDupNativeFenceFDANDROID, PFNEGLDUPNATIVEFENCEFDANDROIDPROC);
+ get_proc(glEGLImageTargetTexture2DOES, PFNGLEGLIMAGETARGETTEXTURE2DOESPROC);
+ get_proc(eglDestroyImageKHR, PFNEGLDESTROYIMAGEKHRPROC);
+
+ printf("Using display %p with EGL version %d.%d\n", gl.display, major, minor);
+
+ printf("EGL Version \"%s\"\n", eglQueryString(gl.display, EGL_VERSION));
+ printf("EGL Vendor \"%s\"\n", eglQueryString(gl.display, EGL_VENDOR));
+ printf("EGL Extensions \"%s\"\n", eglQueryString(gl.display, EGL_EXTENSIONS));
+
+ if (!eglBindAPI(EGL_OPENGL_ES_API)) {
+ printf("failed to bind api EGL_OPENGL_ES_API\n");
+ return false;
+ }
+ if (!eglChooseConfig(gl.display, config_attribs, &gl.config, 1, &n) ||
+ n != 1) {
+ printf("failed to choose config: %d\n", n);
+ return false;
+ }
+ gl.context =
+ eglCreateContext(gl.display, gl.config, EGL_NO_CONTEXT, context_attribs);
+ if (gl.context == NULL) {
+ printf("failed to create context\n");
+ return false;
+ }
+ return true;
+}
+
+static struct frame frames[2];
+
+char json_path[1024];
+char log_path[1024];
+TEST_PARAMETERS test_parameters;
+hwcomposer::NativeBufferHandler *buffer_handler;
+
+static uint32_t layerformat2gbmformat(LAYER_FORMAT format,
+ uint32_t *usage_format, uint32_t *usage) {
+ *usage = 0;
+
+ switch (format) {
+ case LAYER_FORMAT_C8:
+ return DRM_FORMAT_C8;
+ case LAYER_FORMAT_R8:
+ return DRM_FORMAT_R8;
+ case LAYER_FORMAT_GR88:
+ return DRM_FORMAT_GR88;
+ case LAYER_FORMAT_RGB332:
+ return DRM_FORMAT_RGB332;
+ case LAYER_FORMAT_BGR233:
+ return DRM_FORMAT_BGR233;
+ case LAYER_FORMAT_XRGB4444:
+ return DRM_FORMAT_XRGB4444;
+ case LAYER_FORMAT_XBGR4444:
+ return DRM_FORMAT_XBGR4444;
+ case LAYER_FORMAT_RGBX4444:
+ return DRM_FORMAT_RGBX4444;
+ case LAYER_FORMAT_BGRX4444:
+ return DRM_FORMAT_BGRX4444;
+ case LAYER_FORMAT_ARGB4444:
+ return DRM_FORMAT_ARGB4444;
+ case LAYER_FORMAT_ABGR4444:
+ return DRM_FORMAT_ABGR4444;
+ case LAYER_FORMAT_RGBA4444:
+ return DRM_FORMAT_RGBA4444;
+ case LAYER_FORMAT_BGRA4444:
+ return DRM_FORMAT_BGRA4444;
+ case LAYER_FORMAT_XRGB1555:
+ return DRM_FORMAT_XRGB1555;
+ case LAYER_FORMAT_XBGR1555:
+ return DRM_FORMAT_XBGR1555;
+ case LAYER_FORMAT_RGBX5551:
+ return DRM_FORMAT_RGBX5551;
+ case LAYER_FORMAT_BGRX5551:
+ return DRM_FORMAT_BGRX5551;
+ case LAYER_FORMAT_ARGB1555:
+ return DRM_FORMAT_ARGB1555;
+ case LAYER_FORMAT_ABGR1555:
+ return DRM_FORMAT_ABGR1555;
+ case LAYER_FORMAT_RGBA5551:
+ return DRM_FORMAT_RGBA5551;
+ case LAYER_FORMAT_BGRA5551:
+ return DRM_FORMAT_BGRA5551;
+ case LAYER_FORMAT_RGB565:
+ return DRM_FORMAT_RGB565;
+ case LAYER_FORMAT_BGR565:
+ return DRM_FORMAT_BGR565;
+ case LAYER_FORMAT_RGB888:
+ return DRM_FORMAT_RGB888;
+ case LAYER_FORMAT_BGR888:
+ return DRM_FORMAT_BGR888;
+ case LAYER_FORMAT_XRGB8888:
+ return DRM_FORMAT_XRGB8888;
+ case LAYER_FORMAT_XBGR8888:
+ return DRM_FORMAT_XBGR8888;
+ case LAYER_FORMAT_RGBX8888:
+ return DRM_FORMAT_RGBX8888;
+ case LAYER_FORMAT_BGRX8888:
+ return DRM_FORMAT_BGRX8888;
+ case LAYER_FORMAT_ARGB8888:
+ return DRM_FORMAT_ARGB8888;
+ case LAYER_FORMAT_ABGR8888:
+ return DRM_FORMAT_ABGR8888;
+ case LAYER_FORMAT_RGBA8888:
+ return DRM_FORMAT_RGBA8888;
+ case LAYER_FORMAT_BGRA8888:
+ return DRM_FORMAT_BGRA8888;
+ case LAYER_FORMAT_XRGB2101010:
+ return DRM_FORMAT_XRGB2101010;
+ case LAYER_FORMAT_XBGR2101010:
+ return DRM_FORMAT_XBGR2101010;
+ case LAYER_FORMAT_RGBX1010102:
+ return DRM_FORMAT_RGBX1010102;
+ case LAYER_FORMAT_BGRX1010102:
+ return DRM_FORMAT_BGRX1010102;
+ case LAYER_FORMAT_ARGB2101010:
+ return DRM_FORMAT_ARGB2101010;
+ case LAYER_FORMAT_ABGR2101010:
+ return DRM_FORMAT_ABGR2101010;
+ case LAYER_FORMAT_RGBA1010102:
+ return DRM_FORMAT_RGBA1010102;
+ case LAYER_FORMAT_BGRA1010102:
+ return DRM_FORMAT_BGRA1010102;
+ case LAYER_FORMAT_YUYV:
+ return DRM_FORMAT_YUYV;
+ case LAYER_FORMAT_YVYU:
+ return DRM_FORMAT_YVYU;
+ case LAYER_FORMAT_UYVY:
+ return DRM_FORMAT_UYVY;
+ case LAYER_FORMAT_VYUY:
+ return DRM_FORMAT_VYUY;
+ case LAYER_FORMAT_AYUV:
+ return DRM_FORMAT_AYUV;
+ case LAYER_FORMAT_NV12:
+ return DRM_FORMAT_NV12;
+ case LAYER_FORMAT_NV21:
+ return DRM_FORMAT_NV21;
+ case LAYER_FORMAT_NV16:
+ return DRM_FORMAT_NV16;
+ case LAYER_FORMAT_NV61:
+ return DRM_FORMAT_NV61;
+ case LAYER_FORMAT_YUV410:
+ return DRM_FORMAT_YUV410;
+ case LAYER_FORMAT_YVU410:
+ return DRM_FORMAT_YVU410;
+ case LAYER_FORMAT_YUV411:
+ return DRM_FORMAT_YUV411;
+ case LAYER_FORMAT_YVU411:
+ return DRM_FORMAT_YVU411;
+ case LAYER_FORMAT_YUV420:
+ return DRM_FORMAT_YUV420;
+ case LAYER_FORMAT_YVU420:
+ return DRM_FORMAT_YVU420;
+ case LAYER_FORMAT_YUV422:
+ return DRM_FORMAT_YUV422;
+ case LAYER_FORMAT_YVU422:
+ return DRM_FORMAT_YVU422;
+ case LAYER_FORMAT_YUV444:
+ return DRM_FORMAT_YUV444;
+ case LAYER_FORMAT_YVU444:
+ return DRM_FORMAT_YVU444;
+ case LAYER_HAL_PIXEL_FORMAT_YV12:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YV12;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_YVU420_ANDROID;
+ case LAYER_HAL_PIXEL_FORMAT_Y8:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_Y8;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_R8;
+ case LAYER_HAL_PIXEL_FORMAT_Y16:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_Y16;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_R16;
+ case LAYER_HAL_PIXEL_FORMAT_YCbCr_444_888:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YCbCr_444_888;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_YUV444;
+ case LAYER_HAL_PIXEL_FORMAT_YCbCr_422_I:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YCbCr_422_I;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_YUYV;
+ case LAYER_HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YCbCr_422_SP;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_NV16;
+ case LAYER_HAL_PIXEL_FORMAT_YCbCr_422_888:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YCbCr_422_888;
+ *usage |= hwcomposer::kLayerVideo;
+ return DRM_FORMAT_YUV422;
+ case LAYER_HAL_PIXEL_FORMAT_YCbCr_420_888:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YCbCr_420_888;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_NV12;
+ case LAYER_HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_YCrCb_420_SP;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_NV21;
+ case LAYER_HAL_PIXEL_FORMAT_RAW16:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_RAW16;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_R16;
+ case LAYER_HAL_PIXEL_FORMAT_RAW_OPAQUE:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_RAW_OPAQUE;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_R16;
+ case LAYER_HAL_PIXEL_FORMAT_BLOB:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_BLOB;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_R8;
+ case LAYER_ANDROID_SCALER_AVAILABLE_FORMATS_RAW16:
+ *usage_format = LAYER_ANDROID_SCALER_AVAILABLE_FORMATS_RAW16;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_R16;
+ case LAYER_HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL:
+ *usage_format = LAYER_HAL_PIXEL_FORMAT_NV12_Y_TILED_INTEL;
+ *usage = hwcomposer::kLayerVideo;
+ return DRM_FORMAT_NV12_Y_TILED_INTEL;
+ case LAYER_FORMAT_UNDEFINED:
+ return (uint32_t)-1;
+ }
+
+ return (uint32_t)-1;
+}
+
+static void fill_hwclayer(iahwc_layer_t layer_handle_,
+ LAYER_PARAMETER *pParameter,
+ LayerRenderer *pRenderer) {
+ backend->iahwc_layer_set_transform(backend->iahwc_device, 0, layer_handle_,
+ pParameter->transform);
+ backend->iahwc_layer_set_source_crop(
+ backend->iahwc_device, 0, layer_handle_,
+ {pParameter->source_crop_x, pParameter->source_crop_y,
+ pParameter->source_crop_width, pParameter->source_crop_height});
+ backend->iahwc_layer_set_display_frame(
+ backend->iahwc_device, 0, layer_handle_,
+ {pParameter->frame_x, pParameter->frame_y, pParameter->frame_width,
+ pParameter->frame_height});
+}
+
+static void init_frames(int32_t width, int32_t height) {
+ size_t LAYER_PARAM_SIZE;
+ if (display_mode) {
+ layer_parameter.type = static_cast<LAYER_TYPE>(0);
+ layer_parameter.format = static_cast<LAYER_FORMAT>(25);
+ layer_parameter.transform = static_cast<LAYER_TRANSFORM>(0);
+ layer_parameter.resource_path = "";
+ layer_parameter.source_width = width;
+ layer_parameter.source_height = height;
+ layer_parameter.source_crop_x = 0;
+ layer_parameter.source_crop_y = 0;
+ layer_parameter.source_crop_width = width;
+ layer_parameter.source_crop_height = height;
+ layer_parameter.frame_x = 0;
+ layer_parameter.frame_y = 0;
+ layer_parameter.frame_width = width;
+ layer_parameter.frame_height = height;
+ LAYER_PARAM_SIZE = 1;
+ } else {
+ parseParametersJson(json_path, &test_parameters);
+ LAYER_PARAM_SIZE = test_parameters.layers_parameters.size();
+ }
+ for (size_t j = 0; j < LAYER_PARAM_SIZE; ++j) {
+ if (!display_mode) {
+ layer_parameter = test_parameters.layers_parameters[j];
+ if (layer_parameter.source_width > width)
+ layer_parameter.source_width = width;
+
+ if (layer_parameter.source_height > height)
+ layer_parameter.source_height = height;
+
+ if (layer_parameter.source_crop_width > width)
+ layer_parameter.source_crop_width = width;
+
+ if (layer_parameter.source_crop_height > height)
+ layer_parameter.source_crop_height = height;
+
+ if (layer_parameter.frame_width > width)
+ layer_parameter.frame_width = width;
+
+ if (layer_parameter.frame_height > height)
+ layer_parameter.frame_height = height;
+ }
+
+ LayerRenderer *renderer = NULL;
+ // hwcomposer::HwcLayer *hwc_layer = NULL;
+ iahwc_layer_t layer_handle_;
+ backend->iahwc_create_layer(backend->iahwc_device, 0, &layer_handle_);
+ uint32_t usage_format, usage;
+ uint64_t modificators[4];
+ uint32_t gbm_format =
+ layerformat2gbmformat(layer_parameter.format, &usage_format, &usage);
+
+ switch (layer_parameter.type) {
+ case LAYER_TYPE_GL:
+ renderer = new GLCubeLayerRenderer(buffer_handler, false);
+ break;
+ default:
+ printf("un-recognized layer type!\n");
+ exit(-1);
+ }
+
+ if (!renderer->Init(layer_parameter.source_width,
+ layer_parameter.source_height, gbm_format, usage_format,
+ usage, &gl, layer_parameter.resource_path.c_str())) {
+ printf("\nrender init not successful\n");
+ exit(-1);
+ }
+
+ fill_hwclayer(layer_handle_, &layer_parameter, renderer);
+ for (size_t i = 0; i < ARRAY_SIZE(frames); ++i) {
+ struct frame *frame = &frames[i];
+ frame->layers_fences.resize(LAYER_PARAM_SIZE);
+ frame->layers.push_back(layer_handle_);
+ frame->layer_renderers.push_back(
+ std::unique_ptr<LayerRenderer>(renderer));
+ gbm_handle *buffer_handle_ = renderer->GetNativeBoHandle();
+ frame->layer_bos.push_back(buffer_handle_->bo);
+ }
+ }
+}
+
+static void print_help(void) {
+ printf(
+ "usage: testjsonlayers [-h|--help] [-f|--frames <frames>] [-j|--json "
+ "<jsonfile>] [-p|--powermode <on/off/doze/dozesuspend>][--displaymode "
+ "<print/forcemode displayconfigindex]\n");
+}
+
+static void parse_args(int argc, char *argv[]) {
+ static const struct option longopts[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"frames", required_argument, NULL, 'f'},
+ {"json", required_argument, NULL, 'j'},
+ {"log", required_argument, NULL, 'l'},
+ {"displaymode", required_argument, &display_mode, 1},
+ {0},
+ };
+
+ char *endptr;
+ int opt;
+ int longindex = 0;
+ FILE *fp;
+
+ /* Suppress getopt's poor error messages */
+ opterr = 0;
+
+ while ((opt = getopt_long(argc, argv, "+:hf:j:l:", longopts,
+ /*longindex*/ &longindex)) != -1) {
+ switch (opt) {
+ case 0:
+ if (!strcmp(optarg, "forcemode")) {
+ force_mode = 1;
+ config_index = atoi(argv[optind++]);
+ }
+ if (!strcmp(optarg, "print")) {
+ print_display_config = 1;
+ }
+ break;
+ case 'h':
+ print_help();
+ exit(0);
+ break;
+ case 'j':
+ if (strlen(optarg) >= 1024) {
+ printf("too long json file path, litmited less than 1024!\n");
+ exit(0);
+ }
+ printf("optarg:%s\n", optarg);
+ strcpy(json_path, optarg);
+ break;
+ case 'f':
+ errno = 0;
+ arg_frames = strtoul(optarg, &endptr, 0);
+ if (errno || *endptr != '\0') {
+ fprintf(stderr, "usage error: invalid value for <frames>\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'l':
+ if (strlen(optarg) >= 1024) {
+ printf(
+ "too long log file path, please provide less than 1024 "
+ "characters!\n");
+ exit(0);
+ }
+ printf("optarg:%s\n", optarg);
+ strcpy(log_path, optarg);
+ fp = freopen(log_path, "w", stdout);
+ fp = freopen(log_path, "a", stderr);
+ if (!fp) {
+ printf("unable to open log file\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case ':':
+ fprintf(stderr, "usage error: %s requires an argument\n",
+ argv[optind - 1]);
+ exit(EXIT_FAILURE);
+ break;
+ case '?':
+ default:
+ assert(opt == '?');
+ fprintf(stderr, "usage error: unknown option '%s'\n", argv[optind - 1]);
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if (optind < argc) {
+ fprintf(stderr, "usage error: trailing args\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char *argv[]) {
+ int ret, fd, primary_width, primary_height;
+ void *iahwc_dl_handle;
+ iahwc_module_t *iahwc_module;
+ iahwc_device_t *iahwc_device;
+ int num_displays, i;
+ uint num_configs;
+ uint32_t *configs, preferred_config;
+ int32_t kms_fence = -1;
+
+ setup_tty();
+
+ backend = new iahwc_backend;
+
+ iahwc_dl_handle = dlopen("libhwcomposer.so", RTLD_NOW);
+ if (!iahwc_dl_handle) {
+ printf("Unable to open libhwcomposer.so: %s\n", dlerror());
+ printf("aborting...\n");
+ abort();
+ }
+
+ iahwc_module = (iahwc_module_t *)dlsym(iahwc_dl_handle, IAHWC_MODULE_STR);
+ iahwc_module->open(iahwc_module, &iahwc_device);
+
+ backend->iahwc_module = iahwc_module;
+ backend->iahwc_device = iahwc_device;
+
+ backend->iahwc_get_num_displays =
+ (IAHWC_PFN_GET_NUM_DISPLAYS)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_GET_NUM_DISPLAYS);
+ backend->iahwc_create_layer =
+ (IAHWC_PFN_CREATE_LAYER)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_CREATE_LAYER);
+ backend->iahwc_get_display_info =
+ (IAHWC_PFN_DISPLAY_GET_INFO)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_DISPLAY_GET_INFO);
+ backend->iahwc_get_display_configs =
+ (IAHWC_PFN_DISPLAY_GET_CONFIGS)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_DISPLAY_GET_CONFIGS);
+ backend->iahwc_get_display_name =
+ (IAHWC_PFN_DISPLAY_GET_NAME)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_DISPLAY_GET_NAME);
+ backend->iahwc_set_display_gamma =
+ (IAHWC_PFN_DISPLAY_SET_GAMMA)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_DISPLAY_SET_GAMMA);
+ backend->iahwc_set_display_config =
+ (IAHWC_PFN_DISPLAY_SET_CONFIG)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_DISPLAY_SET_CONFIG);
+ backend->iahwc_get_display_config =
+ (IAHWC_PFN_DISPLAY_GET_CONFIG)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_DISPLAY_GET_CONFIG);
+ backend->iahwc_present_display =
+ (IAHWC_PFN_PRESENT_DISPLAY)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_PRESENT_DISPLAY);
+ backend->iahwc_layer_set_bo =
+ (IAHWC_PFN_LAYER_SET_BO)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_LAYER_SET_BO);
+ backend->iahwc_layer_set_acquire_fence =
+ (IAHWC_PFN_LAYER_SET_ACQUIRE_FENCE)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_LAYER_SET_ACQUIRE_FENCE);
+ backend->iahwc_layer_set_transform =
+ (IAHWC_PFN_LAYER_SET_TRANSFORM)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_LAYER_SET_TRANSFORM);
+ backend->iahwc_layer_set_source_crop =
+ (IAHWC_PFN_LAYER_SET_SOURCE_CROP)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_LAYER_SET_SOURCE_CROP);
+ backend->iahwc_layer_set_display_frame =
+ (IAHWC_PFN_LAYER_SET_DISPLAY_FRAME)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_LAYER_SET_DISPLAY_FRAME);
+ backend->iahwc_layer_set_surface_damage =
+ (IAHWC_PFN_LAYER_SET_SURFACE_DAMAGE)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_LAYER_SET_SURFACE_DAMAGE);
+ backend->iahwc_register_callback =
+ (IAHWC_PFN_REGISTER_CALLBACK)iahwc_device->getFunctionPtr(
+ iahwc_device, IAHWC_FUNC_REGISTER_CALLBACK);
+
+ parse_args(argc, argv);
+
+ fd = open("/dev/dri/renderD128", O_RDWR);
+ if (fd == -1) {
+ ETRACE("Can't open GPU file");
+ exit(-1);
+ }
+
+ buffer_handler = hwcomposer::NativeBufferHandler::CreateInstance(fd);
+
+ if (!buffer_handler)
+ exit(-1);
+
+ if (!init_gl()) {
+ delete buffer_handler;
+ exit(-1);
+ }
+
+ backend->iahwc_get_num_displays(iahwc_device, &num_displays);
+ printf("Number of displays available is %d\n", num_displays);
+
+ backend->iahwc_get_display_configs(iahwc_device, 0, &num_configs, NULL);
+ printf("Number of configs %d\n", num_configs);
+ configs = new uint32_t[num_configs];
+ backend->iahwc_get_display_configs(iahwc_device, 0, &num_configs, configs);
+ backend->iahwc_get_display_config(iahwc_device, 0, &preferred_config);
+
+ printf("Preferred config is %d\n", preferred_config);
+
+ for (i = 0; i < num_configs; i++) {
+ int width, height, refresh_rate, dpix, dpiy;
+ backend->iahwc_get_display_info(iahwc_device, 0, configs[i],
+ IAHWC_CONFIG_WIDTH, &width);
+ backend->iahwc_get_display_info(iahwc_device, 0, configs[i],
+ IAHWC_CONFIG_HEIGHT, &height);
+ backend->iahwc_get_display_info(iahwc_device, 0, configs[i],
+ IAHWC_CONFIG_REFRESHRATE, &refresh_rate);
+ backend->iahwc_get_display_info(iahwc_device, 0, configs[i],
+ IAHWC_CONFIG_DPIX, &dpix);
+ backend->iahwc_get_display_info(iahwc_device, 0, configs[i],
+ IAHWC_CONFIG_DPIY, &dpiy);
+
+ printf(
+ "Config %d: width %d, height %d, refresh rate %d, dpix %d, dpiy %d\n",
+ configs[i], width, height, refresh_rate, dpix, dpiy);
+
+ if (configs[i] == preferred_config) {
+ primary_width = width;
+ primary_height = height;
+ }
+ }
+
+ printf("Width of primary display is %d height of the primary display is %d\n",
+ primary_width, primary_height);
+
+ init_frames(primary_width, primary_height);
+
+ int64_t gpu_fence_fd = -1; /* out-fence from gpu, in-fence to kms */
+ uint32_t frame_total = 0;
+
+ for (uint64_t i = 0; arg_frames == 0 || i < arg_frames; ++i) {
+ struct frame *frame = &frames[i % ARRAY_SIZE(frames)];
+ if (kms_fence != -1) {
+ sync_wait(kms_fence, -1);
+ close(kms_fence);
+ kms_fence = -1;
+ }
+
+ for (uint32_t j = 0; j < frame->layers.size(); j++) {
+ frame->layers_fences[j].clear();
+ frame->layer_renderers[j]->Draw(&gpu_fence_fd);
+ backend->iahwc_layer_set_acquire_fence(iahwc_device, 0, frame->layers[j],
+ gpu_fence_fd);
+ iahwc_region_t damage_region;
+ damage_region.numRects = 1;
+ iahwc_rect_t *rect = new iahwc_rect_t[1];
+ rect[0] = {layer_parameter.frame_x, layer_parameter.frame_y,
+ layer_parameter.frame_width, layer_parameter.frame_height};
+ damage_region.rects = rect;
+ backend->iahwc_layer_set_surface_damage(iahwc_device, 0, frame->layers[j],
+ damage_region);
+ backend->iahwc_layer_set_bo(iahwc_device, 0, frame->layers[j],
+ frame->layer_bos[j]);
+ }
+
+ backend->iahwc_present_display(iahwc_device, 0, &kms_fence);
+ frame_total++;
+ }
+
+ reset_vt();
+ return 0;
+}