| /* | |
| * Copyright 2024 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 <apex/display.h> | |
| #include <utils/Errors.h> | |
| #include <stdlib.h> | |
| #include <type_traits> | |
| namespace android::display::impl { | |
| /** | |
| * Implementation of ADisplayConfig | |
| */ | |
| struct DisplayConfigImpl { | |
| /** | |
| * The width in pixels of the display configuration. | |
| */ | |
| int32_t width{1080}; | |
| /** | |
| * The height in pixels of the display configuration. | |
| */ | |
| int32_t height{1920}; | |
| /** | |
| * The refresh rate of the display configuration, in frames per second. | |
| */ | |
| float fps{60.0}; | |
| /** | |
| * The vsync offset at which surfaceflinger runs, in nanoseconds. | |
| */ | |
| int64_t sfOffset{0}; | |
| /** | |
| * The vsync offset at which applications run, in nanoseconds. | |
| */ | |
| int64_t appOffset{0}; | |
| }; | |
| // DisplayConfigImpl allocation is not managed through C++ memory apis, so | |
| // preventing calling the destructor here. | |
| static_assert(std::is_trivially_destructible<DisplayConfigImpl>::value); | |
| /** | |
| * Implementation of ADisplay | |
| */ | |
| struct DisplayImpl { | |
| /** | |
| * The type of the display, i.e. whether it is an internal or external | |
| * display. | |
| */ | |
| ADisplayType type; | |
| /** | |
| * The preferred WCG dataspace | |
| */ | |
| ADataSpace wcgDataspace; | |
| /** | |
| * The preferred WCG pixel format | |
| */ | |
| AHardwareBuffer_Format wcgPixelFormat; | |
| /** | |
| * The config for this display. | |
| */ | |
| DisplayConfigImpl config; | |
| }; | |
| // DisplayImpl allocation is not managed through C++ memory apis, so | |
| // preventing calling the destructor here. | |
| static_assert(std::is_trivially_destructible<DisplayImpl>::value); | |
| } // namespace android::display::impl | |
| using namespace android; | |
| using namespace android::display::impl; | |
| namespace android { | |
| int ADisplay_acquirePhysicalDisplays(ADisplay*** outDisplays) { | |
| // This is running on host, so there are no physical displays available. | |
| // Create 1 fake display instead. | |
| DisplayImpl** const impls = | |
| reinterpret_cast<DisplayImpl**>(malloc(sizeof(DisplayImpl*) + sizeof(DisplayImpl))); | |
| DisplayImpl* const displayData = reinterpret_cast<DisplayImpl*>(impls + 1); | |
| displayData[0] = | |
| DisplayImpl{ADisplayType::DISPLAY_TYPE_INTERNAL, ADataSpace::ADATASPACE_UNKNOWN, | |
| AHardwareBuffer_Format::AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, | |
| DisplayConfigImpl()}; | |
| impls[0] = displayData; | |
| *outDisplays = reinterpret_cast<ADisplay**>(impls); | |
| return 1; | |
| } | |
| void ADisplay_release(ADisplay** displays) { | |
| if (displays == nullptr) { | |
| return; | |
| } | |
| free(displays); | |
| } | |
| float ADisplay_getMaxSupportedFps(ADisplay* display) { | |
| DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display); | |
| return impl->config.fps; | |
| } | |
| ADisplayType ADisplay_getDisplayType(ADisplay* display) { | |
| return reinterpret_cast<DisplayImpl*>(display)->type; | |
| } | |
| void ADisplay_getPreferredWideColorFormat(ADisplay* display, ADataSpace* outDataspace, | |
| AHardwareBuffer_Format* outPixelFormat) { | |
| DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display); | |
| *outDataspace = impl->wcgDataspace; | |
| *outPixelFormat = impl->wcgPixelFormat; | |
| } | |
| int ADisplay_getCurrentConfig(ADisplay* display, ADisplayConfig** outConfig) { | |
| DisplayImpl* impl = reinterpret_cast<DisplayImpl*>(display); | |
| *outConfig = reinterpret_cast<ADisplayConfig*>(&impl->config); | |
| return OK; | |
| } | |
| int32_t ADisplayConfig_getWidth(ADisplayConfig* config) { | |
| return reinterpret_cast<DisplayConfigImpl*>(config)->width; | |
| } | |
| int32_t ADisplayConfig_getHeight(ADisplayConfig* config) { | |
| return reinterpret_cast<DisplayConfigImpl*>(config)->height; | |
| } | |
| float ADisplayConfig_getFps(ADisplayConfig* config) { | |
| return reinterpret_cast<DisplayConfigImpl*>(config)->fps; | |
| } | |
| int64_t ADisplayConfig_getCompositorOffsetNanos(ADisplayConfig* config) { | |
| return reinterpret_cast<DisplayConfigImpl*>(config)->sfOffset; | |
| } | |
| int64_t ADisplayConfig_getAppVsyncOffsetNanos(ADisplayConfig* config) { | |
| return reinterpret_cast<DisplayConfigImpl*>(config)->appOffset; | |
| } | |
| } // namespace android |