graphics: add ComposerCommandEngine
Add ComposerCommandEngine to the HAL support library to replace
ComposerClient::CommandReader and ComposerClient::mWriter.
Test: boots and VTS
Change-Id: I2d1281d37180497cbd5c623ef005cee44bce377e
diff --git a/graphics/composer/2.1/utils/hal/Android.bp b/graphics/composer/2.1/utils/hal/Android.bp
index a8ff59d..f24e768 100644
--- a/graphics/composer/2.1/utils/hal/Android.bp
+++ b/graphics/composer/2.1/utils/hal/Android.bp
@@ -27,5 +27,11 @@
"android.hardware.graphics.mapper@2.0",
"libhardware",
],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ export_header_lib_headers: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
export_include_dirs: ["include"],
}
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
new file mode 100644
index 0000000..36aa64e
--- /dev/null
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -0,0 +1,594 @@
+/*
+ * Copyright 2018 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <vector>
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerHal.h>
+#include <composer-hal/2.1/ComposerResources.h>
+// TODO remove hwcomposer_defs.h dependency
+#include <hardware/hwcomposer_defs.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace hal {
+
+// TODO own a CommandReaderBase rather than subclassing
+class ComposerCommandEngine : protected CommandReaderBase {
+ public:
+ ComposerCommandEngine(ComposerHal* hal, ComposerResources* resources)
+ : mHal(hal), mResources(resources) {}
+
+ virtual ~ComposerCommandEngine() = default;
+
+ bool setInputMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor) {
+ return setMQDescriptor(descriptor);
+ }
+
+ Error execute(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles, bool* outQueueChanged,
+ uint32_t* outCommandLength, hidl_vec<hidl_handle>* outCommandHandles) {
+ if (!readQueue(inLength, inHandles)) {
+ return Error::BAD_PARAMETER;
+ }
+
+ IComposerClient::Command command;
+ uint16_t length = 0;
+ while (!isEmpty()) {
+ if (!beginCommand(&command, &length)) {
+ break;
+ }
+
+ bool parsed = executeCommand(command, length);
+ endCommand();
+
+ if (!parsed) {
+ ALOGE("failed to parse command 0x%x, length %" PRIu16, command, length);
+ break;
+ }
+ }
+
+ if (!isEmpty()) {
+ return Error::BAD_PARAMETER;
+ }
+
+ return mWriter.writeQueue(outQueueChanged, outCommandLength, outCommandHandles)
+ ? Error::NONE
+ : Error::NO_RESOURCES;
+ }
+
+ const MQDescriptorSync<uint32_t>* getOutputMQDescriptor() { return mWriter.getMQDescriptor(); }
+
+ void reset() {
+ CommandReaderBase::reset();
+ mWriter.reset();
+ }
+
+ protected:
+ virtual bool executeCommand(IComposerClient::Command command, uint16_t length) {
+ switch (command) {
+ case IComposerClient::Command::SELECT_DISPLAY:
+ return executeSelectDisplay(length);
+ case IComposerClient::Command::SELECT_LAYER:
+ return executeSelectLayer(length);
+ case IComposerClient::Command::SET_COLOR_TRANSFORM:
+ return executeSetColorTransform(length);
+ case IComposerClient::Command::SET_CLIENT_TARGET:
+ return executeSetClientTarget(length);
+ case IComposerClient::Command::SET_OUTPUT_BUFFER:
+ return executeSetOutputBuffer(length);
+ case IComposerClient::Command::VALIDATE_DISPLAY:
+ return executeValidateDisplay(length);
+ case IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY:
+ return executePresentOrValidateDisplay(length);
+ case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+ return executeAcceptDisplayChanges(length);
+ case IComposerClient::Command::PRESENT_DISPLAY:
+ return executePresentDisplay(length);
+ case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+ return executeSetLayerCursorPosition(length);
+ case IComposerClient::Command::SET_LAYER_BUFFER:
+ return executeSetLayerBuffer(length);
+ case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+ return executeSetLayerSurfaceDamage(length);
+ case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+ return executeSetLayerBlendMode(length);
+ case IComposerClient::Command::SET_LAYER_COLOR:
+ return executeSetLayerColor(length);
+ case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+ return executeSetLayerCompositionType(length);
+ case IComposerClient::Command::SET_LAYER_DATASPACE:
+ return executeSetLayerDataspace(length);
+ case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+ return executeSetLayerDisplayFrame(length);
+ case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+ return executeSetLayerPlaneAlpha(length);
+ case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+ return executeSetLayerSidebandStream(length);
+ case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+ return executeSetLayerSourceCrop(length);
+ case IComposerClient::Command::SET_LAYER_TRANSFORM:
+ return executeSetLayerTransform(length);
+ case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+ return executeSetLayerVisibleRegion(length);
+ case IComposerClient::Command::SET_LAYER_Z_ORDER:
+ return executeSetLayerZOrder(length);
+ default:
+ return false;
+ }
+ }
+
+ bool executeSelectDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kSelectDisplayLength) {
+ return false;
+ }
+
+ mCurrentDisplay = read64();
+ mWriter.selectDisplay(mCurrentDisplay);
+
+ return true;
+ }
+
+ bool executeSelectLayer(uint16_t length) {
+ if (length != CommandWriterBase::kSelectLayerLength) {
+ return false;
+ }
+
+ mCurrentLayer = read64();
+
+ return true;
+ }
+
+ bool executeSetColorTransform(uint16_t length) {
+ if (length != CommandWriterBase::kSetColorTransformLength) {
+ return false;
+ }
+
+ float matrix[16];
+ for (int i = 0; i < 16; i++) {
+ matrix[i] = readFloat();
+ }
+ auto transform = readSigned();
+
+ auto err = mHal->setColorTransform(mCurrentDisplay, matrix, transform);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetClientTarget(uint16_t length) {
+ // 4 parameters followed by N rectangles
+ if ((length - 4) % 4 != 0) {
+ return false;
+ }
+
+ bool useCache = false;
+ auto slot = read();
+ auto rawHandle = readHandle(&useCache);
+ auto fence = readFence();
+ auto dataspace = readSigned();
+ auto damage = readRegion((length - 4) / 4);
+ bool closeFence = true;
+
+ const native_handle_t* clientTarget;
+ ComposerResources::ReplacedBufferHandle replacedClientTarget;
+ auto err = mResources->getDisplayClientTarget(mCurrentDisplay, slot, useCache, rawHandle,
+ &clientTarget, &replacedClientTarget);
+ if (err == Error::NONE) {
+ err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage);
+ if (err == Error::NONE) {
+ closeFence = false;
+ }
+ }
+ if (closeFence) {
+ close(fence);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetOutputBuffer(uint16_t length) {
+ if (length != CommandWriterBase::kSetOutputBufferLength) {
+ return false;
+ }
+
+ bool useCache = false;
+ auto slot = read();
+ auto rawhandle = readHandle(&useCache);
+ auto fence = readFence();
+ bool closeFence = true;
+
+ const native_handle_t* outputBuffer;
+ ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
+ auto err = mResources->getDisplayOutputBuffer(mCurrentDisplay, slot, useCache, rawhandle,
+ &outputBuffer, &replacedOutputBuffer);
+ if (err == Error::NONE) {
+ err = mHal->setOutputBuffer(mCurrentDisplay, outputBuffer, fence);
+ if (err == Error::NONE) {
+ closeFence = false;
+ }
+ }
+ if (closeFence) {
+ close(fence);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeValidateDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kValidateDisplayLength) {
+ return false;
+ }
+
+ std::vector<Layer> changedLayers;
+ std::vector<IComposerClient::Composition> compositionTypes;
+ uint32_t displayRequestMask = 0x0;
+ std::vector<Layer> requestedLayers;
+ std::vector<uint32_t> requestMasks;
+
+ auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+ &displayRequestMask, &requestedLayers, &requestMasks);
+ if (err == Error::NONE) {
+ mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+ mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+ } else {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executePresentOrValidateDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kPresentOrValidateDisplayLength) {
+ return false;
+ }
+
+ // First try to Present as is.
+ if (mHal->hasCapability(HWC2_CAPABILITY_SKIP_VALIDATE)) {
+ int presentFence = -1;
+ std::vector<Layer> layers;
+ std::vector<int> fences;
+ auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+ if (err == Error::NONE) {
+ mWriter.setPresentOrValidateResult(1);
+ mWriter.setPresentFence(presentFence);
+ mWriter.setReleaseFences(layers, fences);
+ return true;
+ }
+ }
+
+ // Present has failed. We need to fallback to validate
+ std::vector<Layer> changedLayers;
+ std::vector<IComposerClient::Composition> compositionTypes;
+ uint32_t displayRequestMask = 0x0;
+ std::vector<Layer> requestedLayers;
+ std::vector<uint32_t> requestMasks;
+
+ auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
+ &displayRequestMask, &requestedLayers, &requestMasks);
+ if (err == Error::NONE) {
+ mWriter.setPresentOrValidateResult(0);
+ mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
+ mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
+ } else {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeAcceptDisplayChanges(uint16_t length) {
+ if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
+ return false;
+ }
+
+ auto err = mHal->acceptDisplayChanges(mCurrentDisplay);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executePresentDisplay(uint16_t length) {
+ if (length != CommandWriterBase::kPresentDisplayLength) {
+ return false;
+ }
+
+ int presentFence = -1;
+ std::vector<Layer> layers;
+ std::vector<int> fences;
+ auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+ if (err == Error::NONE) {
+ mWriter.setPresentFence(presentFence);
+ mWriter.setReleaseFences(layers, fences);
+ } else {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerCursorPosition(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerCursorPosition(mCurrentDisplay, mCurrentLayer, readSigned(),
+ readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerBuffer(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerBufferLength) {
+ return false;
+ }
+
+ bool useCache = false;
+ auto slot = read();
+ auto rawHandle = readHandle(&useCache);
+ auto fence = readFence();
+ bool closeFence = true;
+
+ const native_handle_t* buffer;
+ ComposerResources::ReplacedBufferHandle replacedBuffer;
+ auto err = mResources->getLayerBuffer(mCurrentDisplay, mCurrentLayer, slot, useCache,
+ rawHandle, &buffer, &replacedBuffer);
+ if (err == Error::NONE) {
+ err = mHal->setLayerBuffer(mCurrentDisplay, mCurrentLayer, buffer, fence);
+ if (err == Error::NONE) {
+ closeFence = false;
+ }
+ }
+ if (closeFence) {
+ close(fence);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerSurfaceDamage(uint16_t length) {
+ // N rectangles
+ if (length % 4 != 0) {
+ return false;
+ }
+
+ auto damage = readRegion(length / 4);
+ auto err = mHal->setLayerSurfaceDamage(mCurrentDisplay, mCurrentLayer, damage);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerBlendMode(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerBlendModeLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerBlendMode(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerColor(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerColorLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerColor(mCurrentDisplay, mCurrentLayer, readColor());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerCompositionType(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerCompositionType(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerDataspace(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerDataspaceLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerDataspace(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerDisplayFrame(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerDisplayFrame(mCurrentDisplay, mCurrentLayer, readRect());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerPlaneAlpha(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerPlaneAlpha(mCurrentDisplay, mCurrentLayer, readFloat());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerSidebandStream(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
+ return false;
+ }
+
+ auto rawHandle = readHandle();
+
+ const native_handle_t* stream;
+ ComposerResources::ReplacedStreamHandle replacedStream;
+ auto err = mResources->getLayerSidebandStream(mCurrentDisplay, mCurrentLayer, rawHandle,
+ &stream, &replacedStream);
+ if (err == Error::NONE) {
+ err = mHal->setLayerSidebandStream(mCurrentDisplay, mCurrentLayer, stream);
+ }
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerSourceCrop(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerSourceCropLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerSourceCrop(mCurrentDisplay, mCurrentLayer, readFRect());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerTransform(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerTransformLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerTransform(mCurrentDisplay, mCurrentLayer, readSigned());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerVisibleRegion(uint16_t length) {
+ // N rectangles
+ if (length % 4 != 0) {
+ return false;
+ }
+
+ auto region = readRegion(length / 4);
+ auto err = mHal->setLayerVisibleRegion(mCurrentDisplay, mCurrentLayer, region);
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ bool executeSetLayerZOrder(uint16_t length) {
+ if (length != CommandWriterBase::kSetLayerZOrderLength) {
+ return false;
+ }
+
+ auto err = mHal->setLayerZOrder(mCurrentDisplay, mCurrentLayer, read());
+ if (err != Error::NONE) {
+ mWriter.setError(getCommandLoc(), err);
+ }
+
+ return true;
+ }
+
+ hwc_rect_t readRect() {
+ return hwc_rect_t{
+ readSigned(), readSigned(), readSigned(), readSigned(),
+ };
+ }
+
+ std::vector<hwc_rect_t> readRegion(size_t count) {
+ std::vector<hwc_rect_t> region;
+ region.reserve(count);
+ while (count > 0) {
+ region.emplace_back(readRect());
+ count--;
+ }
+
+ return region;
+ }
+
+ hwc_frect_t readFRect() {
+ return hwc_frect_t{
+ readFloat(), readFloat(), readFloat(), readFloat(),
+ };
+ }
+
+ ComposerHal* mHal;
+ ComposerResources* mResources;
+
+ // 64KiB minus a small space for metadata such as read/write pointers
+ static constexpr size_t kWriterInitialSize = 64 * 1024 / sizeof(uint32_t) - 16;
+ CommandWriterBase mWriter{kWriterInitialSize};
+
+ Display mCurrentDisplay = 0;
+ Layer mCurrentLayer = 0;
+};
+
+} // namespace hal
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android