/* * Copyright (C) 2021 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 #include "ComposerCommandEngine.h" #include "Util.h" namespace aidl::android::hardware::graphics::composer3::impl { #define DISPATCH_LAYER_COMMAND(display, layerCmd, field, funcName) \ do { \ if (layerCmd.field) { \ executeSetLayer##funcName(display, layerCmd.layer, *layerCmd.field); \ } \ } while (0) #define DISPATCH_LAYER_COMMAND_SIMPLE(display, layerCmd, field, funcName) \ do { \ dispatchLayerCommand(display, layerCmd.layer, #field, layerCmd.field, \ &IComposerHal::setLayer##funcName); \ } while (0) #define DISPATCH_DISPLAY_COMMAND(displayCmd, field, funcName) \ do { \ if (displayCmd.field) { \ execute##funcName(displayCmd.display, *displayCmd.field); \ } \ } while (0) #define DISPATCH_DISPLAY_BOOL_COMMAND(displayCmd, field, funcName) \ do { \ if (displayCmd.field) { \ execute##funcName(displayCmd.display); \ } \ } while (0) #define DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(displayCmd, field, data, funcName) \ do { \ if (displayCmd.field) { \ execute##funcName(displayCmd.display, displayCmd.data); \ } \ } while (0) bool ComposerCommandEngine::init() { mWriter = std::make_unique(); return (mWriter != nullptr); } int32_t ComposerCommandEngine::execute(const std::vector& commands, std::vector* result) { std::set displaysPendingBrightenssChange; mCommandIndex = 0; for (const auto& command : commands) { dispatchDisplayCommand(command); ++mCommandIndex; // The input commands could have 2+ commands for the same display. // If the first has pending brightness change, the second presentDisplay will apply it. if (command.validateDisplay || command.presentDisplay || command.presentOrValidateDisplay) { displaysPendingBrightenssChange.erase(command.display); } else if (command.brightness) { displaysPendingBrightenssChange.insert(command.display); } } *result = mWriter->getPendingCommandResults(); mWriter->reset(); // standalone display brightness command shouldn't wait for next present or validate for (auto display : displaysPendingBrightenssChange) { auto err = mHal->flushDisplayBrightnessChange(display); if (err) { return err; } } return ::android::NO_ERROR; } void ComposerCommandEngine::dispatchDisplayCommand(const DisplayCommand& command) { // place SetDisplayBrightness before SetLayerWhitePointNits since current // display brightness is used to validate the layer white point nits. DISPATCH_DISPLAY_COMMAND(command, brightness, SetDisplayBrightness); for (const auto& layerCmd : command.layers) { dispatchLayerCommand(command.display, layerCmd); } DISPATCH_DISPLAY_COMMAND(command, colorTransformMatrix, SetColorTransform); DISPATCH_DISPLAY_COMMAND(command, clientTarget, SetClientTarget); DISPATCH_DISPLAY_COMMAND(command, virtualDisplayOutputBuffer, SetOutputBuffer); DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(command, validateDisplay, expectedPresentTime, ValidateDisplay); DISPATCH_DISPLAY_BOOL_COMMAND(command, acceptDisplayChanges, AcceptDisplayChanges); DISPATCH_DISPLAY_BOOL_COMMAND(command, presentDisplay, PresentDisplay); DISPATCH_DISPLAY_BOOL_COMMAND_AND_DATA(command, presentOrValidateDisplay, expectedPresentTime, PresentOrValidateDisplay); } void ComposerCommandEngine::dispatchLayerCommand(int64_t display, const LayerCommand& command) { DISPATCH_LAYER_COMMAND(display, command, cursorPosition, CursorPosition); DISPATCH_LAYER_COMMAND(display, command, buffer, Buffer); DISPATCH_LAYER_COMMAND(display, command, damage, SurfaceDamage); DISPATCH_LAYER_COMMAND(display, command, blendMode, BlendMode); DISPATCH_LAYER_COMMAND(display, command, color, Color); DISPATCH_LAYER_COMMAND(display, command, composition, Composition); DISPATCH_LAYER_COMMAND(display, command, dataspace, Dataspace); DISPATCH_LAYER_COMMAND(display, command, displayFrame, DisplayFrame); DISPATCH_LAYER_COMMAND(display, command, planeAlpha, PlaneAlpha); DISPATCH_LAYER_COMMAND(display, command, sidebandStream, SidebandStream); DISPATCH_LAYER_COMMAND(display, command, sourceCrop, SourceCrop); DISPATCH_LAYER_COMMAND(display, command, transform, Transform); DISPATCH_LAYER_COMMAND(display, command, visibleRegion, VisibleRegion); DISPATCH_LAYER_COMMAND(display, command, z, ZOrder); DISPATCH_LAYER_COMMAND(display, command, colorTransform, ColorTransform); DISPATCH_LAYER_COMMAND(display, command, brightness, Brightness); DISPATCH_LAYER_COMMAND(display, command, perFrameMetadata, PerFrameMetadata); DISPATCH_LAYER_COMMAND(display, command, perFrameMetadataBlob, PerFrameMetadataBlobs); DISPATCH_LAYER_COMMAND_SIMPLE(display, command, blockingRegion, BlockingRegion); } int32_t ComposerCommandEngine::executeValidateDisplayInternal(int64_t display) { std::vector changedLayers; std::vector compositionTypes; uint32_t displayRequestMask = 0x0; std::vector requestedLayers; std::vector requestMasks; ClientTargetProperty clientTargetProperty{common::PixelFormat::RGBA_8888, common::Dataspace::UNKNOWN}; DimmingStage dimmingStage; auto err = mHal->validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask, &requestedLayers, &requestMasks, &clientTargetProperty, &dimmingStage); mResources->setDisplayMustValidateState(display, false); if (!err) { mWriter->setChangedCompositionTypes(display, changedLayers, compositionTypes); mWriter->setDisplayRequests(display, displayRequestMask, requestedLayers, requestMasks); static constexpr float kBrightness = 1.f; mWriter->setClientTargetProperty(display, clientTargetProperty, kBrightness, dimmingStage); } else { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } return err; } void ComposerCommandEngine::executeSetColorTransform(int64_t display, const std::vector& matrix) { auto err = mHal->setColorTransform(display, matrix); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetClientTarget(int64_t display, const ClientTarget& command) { bool useCache = !command.buffer.handle; buffer_handle_t handle = useCache ? nullptr : ::android::makeFromAidl(*command.buffer.handle); buffer_handle_t clientTarget; auto bufferReleaser = mResources->createReleaser(true); auto err = mResources->getDisplayClientTarget(display, command.buffer.slot, useCache, handle, clientTarget, bufferReleaser.get()); if (!err) { err = mHal->setClientTarget(display, clientTarget, command.buffer.fence, command.dataspace, command.damage); if (err) { LOG(ERROR) << __func__ << " setClientTarget: err " << err; mWriter->setError(mCommandIndex, err); } } else { LOG(ERROR) << __func__ << " getDisplayClientTarget : err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetOutputBuffer(uint64_t display, const Buffer& buffer) { bool useCache = !buffer.handle; buffer_handle_t handle = useCache ? nullptr : ::android::makeFromAidl(*buffer.handle); buffer_handle_t outputBuffer; auto bufferReleaser = mResources->createReleaser(true); auto err = mResources->getDisplayOutputBuffer(display, buffer.slot, useCache, handle, outputBuffer, bufferReleaser.get()); if (!err) { err = mHal->setOutputBuffer(display, outputBuffer, buffer.fence); if (err) { LOG(ERROR) << __func__ << " setOutputBuffer: err " << err; mWriter->setError(mCommandIndex, err); } } else { LOG(ERROR) << __func__ << " getDisplayOutputBuffer: err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetExpectedPresentTimeInternal( int64_t display, const std::optional expectedPresentTime) { mHal->setExpectedPresentTime(display, expectedPresentTime); } void ComposerCommandEngine::executeValidateDisplay( int64_t display, const std::optional expectedPresentTime) { executeSetExpectedPresentTimeInternal(display, expectedPresentTime); executeValidateDisplayInternal(display); } void ComposerCommandEngine::executeSetDisplayBrightness(uint64_t display, const DisplayBrightness& command) { auto err = mHal->setDisplayBrightness(display, command.brightness); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executePresentOrValidateDisplay( int64_t display, const std::optional expectedPresentTime) { executeSetExpectedPresentTimeInternal(display, expectedPresentTime); int err; // First try to Present as is. if (mHal->hasCapability(Capability::SKIP_VALIDATE)) { err = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED : executePresentDisplay(display); if (!err) { mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Presented); return; } } // Fallback to validate err = executeValidateDisplayInternal(display); if (!err) { mWriter->setPresentOrValidateResult(display, PresentOrValidate::Result::Validated); } } void ComposerCommandEngine::executeAcceptDisplayChanges(int64_t display) { auto err = mHal->acceptDisplayChanges(display); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } int ComposerCommandEngine::executePresentDisplay(int64_t display) { ndk::ScopedFileDescriptor presentFence; std::vector layers; std::vector fences; auto err = mHal->presentDisplay(display, presentFence, &layers, &fences); if (!err) { mWriter->setPresentFence(display, std::move(presentFence)); mWriter->setReleaseFences(display, layers, std::move(fences)); } return err; } void ComposerCommandEngine::executeSetLayerCursorPosition(int64_t display, int64_t layer, const common::Point& cursorPosition) { auto err = mHal->setLayerCursorPosition(display, layer, cursorPosition.x, cursorPosition.y); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerBuffer(int64_t display, int64_t layer, const Buffer& buffer) { bool useCache = !buffer.handle; buffer_handle_t handle = useCache ? nullptr : ::android::makeFromAidl(*buffer.handle); buffer_handle_t hwcBuffer; auto bufferReleaser = mResources->createReleaser(true); auto err = mResources->getLayerBuffer(display, layer, buffer.slot, useCache, handle, hwcBuffer, bufferReleaser.get()); if (!err) { err = mHal->setLayerBuffer(display, layer, hwcBuffer, buffer.fence); if (err) { LOG(ERROR) << __func__ << ": setLayerBuffer err " << err; mWriter->setError(mCommandIndex, err); } } else { LOG(ERROR) << __func__ << ": getLayerBuffer err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerSurfaceDamage(int64_t display, int64_t layer, const std::vector>& damage) { auto err = mHal->setLayerSurfaceDamage(display, layer, damage); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerBlendMode(int64_t display, int64_t layer, const ParcelableBlendMode& blendMode) { auto err = mHal->setLayerBlendMode(display, layer, blendMode.blendMode); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerColor(int64_t display, int64_t layer, const Color& color) { auto err = mHal->setLayerColor(display, layer, color); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerComposition(int64_t display, int64_t layer, const ParcelableComposition& composition) { auto err = mHal->setLayerCompositionType(display, layer, composition.composition); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerDataspace(int64_t display, int64_t layer, const ParcelableDataspace& dataspace) { auto err = mHal->setLayerDataspace(display, layer, dataspace.dataspace); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerDisplayFrame(int64_t display, int64_t layer, const common::Rect& rect) { auto err = mHal->setLayerDisplayFrame(display, layer, rect); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerPlaneAlpha(int64_t display, int64_t layer, const PlaneAlpha& planeAlpha) { auto err = mHal->setLayerPlaneAlpha(display, layer, planeAlpha.alpha); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerSidebandStream(int64_t display, int64_t layer, const AidlNativeHandle& sidebandStream) { buffer_handle_t handle = ::android::makeFromAidl(sidebandStream); buffer_handle_t stream; auto bufferReleaser = mResources->createReleaser(false); auto err = mResources->getLayerSidebandStream(display, layer, handle, stream, bufferReleaser.get()); if (err) { err = mHal->setLayerSidebandStream(display, layer, stream); } if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerSourceCrop(int64_t display, int64_t layer, const common::FRect& sourceCrop) { auto err = mHal->setLayerSourceCrop(display, layer, sourceCrop); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerTransform(int64_t display, int64_t layer, const ParcelableTransform& transform) { auto err = mHal->setLayerTransform(display, layer, transform.transform); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerVisibleRegion(int64_t display, int64_t layer, const std::vector>& visibleRegion) { auto err = mHal->setLayerVisibleRegion(display, layer, visibleRegion); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerZOrder(int64_t display, int64_t layer, const ZOrder& zOrder) { auto err = mHal->setLayerZOrder(display, layer, zOrder.z); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerPerFrameMetadata(int64_t display, int64_t layer, const std::vector>& perFrameMetadata) { auto err = mHal->setLayerPerFrameMetadata(display, layer, perFrameMetadata); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerColorTransform(int64_t display, int64_t layer, const std::vector& matrix) { auto err = mHal->setLayerColorTransform(display, layer, matrix); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerBrightness(int64_t display, int64_t layer, const LayerBrightness& brightness) { auto err = mHal->setLayerBrightness(display, layer, brightness.brightness); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } void ComposerCommandEngine::executeSetLayerPerFrameMetadataBlobs(int64_t display, int64_t layer, const std::vector>& metadata) { auto err = mHal->setLayerPerFrameMetadataBlobs(display, layer, metadata); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } } // namespace aidl::android::hardware::graphics::composer3::impl