/* * 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 "ComposerCommandEngine.h" #include "Util.h" /// The command engine interface is not 'pure' aidl. Conversion to aidl // structure is done within this class. Don't mix it with impl/translate. // Expect to have an AIDL command interface in the future. // // The initial implementation is a combination of asop ComposerCommandEngine 2.1 to 2.4 // and adapt to aidl structures. 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_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) bool ComposerCommandEngine::init() { mWriter = std::make_unique(); return (mWriter != nullptr); } int32_t ComposerCommandEngine::execute(const std::vector& commands, std::vector* result) { mCommandIndex = 0; for (const auto& command : commands) { dispatchDisplayCommand(command); ++mCommandIndex; } *result = mWriter->getPendingCommandResults(); return 0; } void ComposerCommandEngine::dispatchDisplayCommand(const DisplayCommand& command) { for (const auto& layerCmd : command.layers) { dispatchLayerCommand(command.display, layerCmd); } DISPATCH_DISPLAY_COMMAND(command, colorTransform, SetColorTransform); DISPATCH_DISPLAY_COMMAND(command, clientTarget, SetClientTarget); DISPATCH_DISPLAY_COMMAND(command, virtualDisplayOutputBuffer, SetOutputBuffer); // TODO: (b/196171661) SDR & HDR blending // DISPATCH_DISPLAY_COMMAND(command, displayBrightness, SetDisplayBrightness); DISPATCH_DISPLAY_BOOL_COMMAND(command, validateDisplay, ValidateDisplay); DISPATCH_DISPLAY_BOOL_COMMAND(command, acceptDisplayChanges, AcceptDisplayChanges); DISPATCH_DISPLAY_BOOL_COMMAND(command, presentDisplay, PresentDisplay); DISPATCH_DISPLAY_BOOL_COMMAND(command, presentOrValidateDisplay, 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, floatColor, FloatColor); 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); // TODO: (b/196171661) add support for mixed composition // DISPATCH_LAYER_COMMAND(display, command, whitePointNits, WhitePointNits); DISPATCH_LAYER_COMMAND(display, command, genericMetadata, GenericMetadata); DISPATCH_LAYER_COMMAND(display, command, perFrameMetadata, PerFrameMetadata); DISPATCH_LAYER_COMMAND(display, command, perFrameMetadataBlob, PerFrameMetadataBlobs); } 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}; auto err = mHal->validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask, &requestedLayers, &requestMasks, &clientTargetProperty); mResources->setDisplayMustValidateState(display, false); if (!err) { mWriter->setChangedCompositionTypes(display, changedLayers, compositionTypes); mWriter->setDisplayRequests(display, displayRequestMask, requestedLayers, requestMasks); // TODO: (b/196171661) sdr/hdr composition, use 1.0 mWriter->setClientTargetProperty(display, clientTargetProperty, 1.0f); } else { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } return err; } void ComposerCommandEngine::executeSetColorTransform(int64_t display, const ColorTransformPayload& command) { auto err = mHal->setColorTransform(display, command.matrix, command.hint); 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::executeValidateDisplay(int64_t display) { executeValidateDisplayInternal(display); } void ComposerCommandEngine::executePresentOrValidateDisplay(int64_t display) { int err; // First try to Present as is. if (mHal->hasCapability(Capability::SKIP_VALIDATE)) { err = 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 = mResources->mustValidateDisplay(display) ? IComposerClient::EX_NOT_VALIDATED : 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::executeSetLayerFloatColor(int64_t display, int64_t layer, const FloatColor& floatColor) { auto err = mHal->setLayerFloatColor(display, layer, floatColor); 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::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); } } void ComposerCommandEngine::executeSetLayerGenericMetadata(int64_t display, int64_t layer, const GenericMetadata& metadata) { auto err = mHal->setLayerGenericMetadata(display, layer, metadata); if (err) { LOG(ERROR) << __func__ << ": err " << err; mWriter->setError(mCommandIndex, err); } } } // namespace aidl::android::hardware::graphics::composer3::impl