mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 22:04:26 +00:00
Merge "graphics: rework IComposer"
This commit is contained in:
@@ -8,11 +8,13 @@ genrule {
|
||||
"types.hal",
|
||||
"IComposer.hal",
|
||||
"IComposerCallback.hal",
|
||||
"IComposerClient.hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/graphics/composer/2.1/types.cpp",
|
||||
"android/hardware/graphics/composer/2.1/ComposerAll.cpp",
|
||||
"android/hardware/graphics/composer/2.1/ComposerCallbackAll.cpp",
|
||||
"android/hardware/graphics/composer/2.1/ComposerClientAll.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -24,6 +26,7 @@ genrule {
|
||||
"types.hal",
|
||||
"IComposer.hal",
|
||||
"IComposerCallback.hal",
|
||||
"IComposerClient.hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/graphics/composer/2.1/types.h",
|
||||
@@ -37,6 +40,11 @@ genrule {
|
||||
"android/hardware/graphics/composer/2.1/BnComposerCallback.h",
|
||||
"android/hardware/graphics/composer/2.1/BpComposerCallback.h",
|
||||
"android/hardware/graphics/composer/2.1/BsComposerCallback.h",
|
||||
"android/hardware/graphics/composer/2.1/IComposerClient.h",
|
||||
"android/hardware/graphics/composer/2.1/IHwComposerClient.h",
|
||||
"android/hardware/graphics/composer/2.1/BnComposerClient.h",
|
||||
"android/hardware/graphics/composer/2.1/BpComposerClient.h",
|
||||
"android/hardware/graphics/composer/2.1/BsComposerClient.h",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1118
graphics/composer/2.1/IComposerClient.hal
Normal file
1118
graphics/composer/2.1/IComposerClient.hal
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,19 @@
|
||||
cc_library_shared {
|
||||
name: "android.hardware.graphics.composer@2.1-impl",
|
||||
relative_install_path: "hw",
|
||||
srcs: ["Hwc.cpp"],
|
||||
srcs: ["Hwc.cpp", "HwcClient.cpp"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.allocator@2.0",
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libsync",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
@@ -19,7 +21,7 @@ cc_library_shared {
|
||||
cc_binary {
|
||||
name: "android.hardware.graphics.composer@2.1-service",
|
||||
relative_install_path: "hw",
|
||||
srcs: ["service.cpp", "Hwc.cpp"],
|
||||
srcs: ["service.cpp", "Hwc.cpp", "HwcClient.cpp"],
|
||||
cppflags: ["-DBINDERIZED"],
|
||||
init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
|
||||
|
||||
@@ -29,11 +31,19 @@ cc_binary {
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libsync",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libhwcomposer-command-buffer",
|
||||
shared_libs: ["android.hardware.graphics.composer@2.1"],
|
||||
export_include_dirs: ["."],
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,12 @@
|
||||
#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposer.h>
|
||||
#include <hardware/hwcomposer2.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
@@ -26,6 +31,172 @@ namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
using android::hardware::graphics::common::V1_0::PixelFormat;
|
||||
using android::hardware::graphics::common::V1_0::Transform;
|
||||
using android::hardware::graphics::common::V1_0::Dataspace;
|
||||
using android::hardware::graphics::common::V1_0::ColorMode;
|
||||
using android::hardware::graphics::common::V1_0::ColorTransform;
|
||||
using android::hardware::graphics::common::V1_0::Hdr;
|
||||
|
||||
class HwcClient;
|
||||
|
||||
class HwcHal : public IComposer {
|
||||
public:
|
||||
HwcHal(const hw_module_t* module);
|
||||
virtual ~HwcHal();
|
||||
|
||||
// IComposer interface
|
||||
Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
|
||||
Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
|
||||
Return<void> createClient(createClient_cb hidl_cb) override;
|
||||
|
||||
bool hasCapability(Capability capability) const;
|
||||
|
||||
void removeClient();
|
||||
|
||||
void enableCallback(bool enable);
|
||||
|
||||
uint32_t getMaxVirtualDisplayCount();
|
||||
Error createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat& format, Display& display);
|
||||
Error destroyVirtualDisplay(Display display);
|
||||
|
||||
Error createLayer(Display display, Layer& layer);
|
||||
Error destroyLayer(Display display, Layer layer);
|
||||
|
||||
Error getActiveConfig(Display display, Config& config);
|
||||
Error getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace);
|
||||
Error getColorModes(Display display, hidl_vec<ColorMode>& modes);
|
||||
Error getDisplayAttribute(Display display, Config config,
|
||||
IComposerClient::Attribute attribute, int32_t& value);
|
||||
Error getDisplayConfigs(Display display, hidl_vec<Config>& configs);
|
||||
Error getDisplayName(Display display, hidl_string& name);
|
||||
Error getDisplayType(Display display, IComposerClient::DisplayType& type);
|
||||
Error getDozeSupport(Display display, bool& support);
|
||||
Error getHdrCapabilities(Display display, hidl_vec<Hdr>& types,
|
||||
float& maxLuminance, float& maxAverageLuminance,
|
||||
float& minLuminance);
|
||||
|
||||
Error setActiveConfig(Display display, Config config);
|
||||
Error setColorMode(Display display, ColorMode mode);
|
||||
Error setPowerMode(Display display, IComposerClient::PowerMode mode);
|
||||
Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled);
|
||||
|
||||
Error setColorTransform(Display display, const float* matrix,
|
||||
int32_t hint);
|
||||
Error setClientTarget(Display display, buffer_handle_t target,
|
||||
int32_t acquireFence, int32_t dataspace,
|
||||
const std::vector<hwc_rect_t>& damage);
|
||||
Error setOutputBuffer(Display display, buffer_handle_t buffer,
|
||||
int32_t releaseFence);
|
||||
Error validateDisplay(Display display,
|
||||
std::vector<Layer>& changedLayers,
|
||||
std::vector<IComposerClient::Composition>& compositionTypes,
|
||||
uint32_t& displayRequestMask,
|
||||
std::vector<Layer>& requestedLayers,
|
||||
std::vector<uint32_t>& requestMasks);
|
||||
Error acceptDisplayChanges(Display display);
|
||||
Error presentDisplay(Display display, int32_t& presentFence,
|
||||
std::vector<Layer>& layers, std::vector<int32_t>& releaseFences);
|
||||
|
||||
Error setLayerCursorPosition(Display display, Layer layer,
|
||||
int32_t x, int32_t y);
|
||||
Error setLayerBuffer(Display display, Layer layer,
|
||||
buffer_handle_t buffer, int32_t acquireFence);
|
||||
Error setLayerSurfaceDamage(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& damage);
|
||||
Error setLayerBlendMode(Display display, Layer layer, int32_t mode);
|
||||
Error setLayerColor(Display display, Layer layer,
|
||||
IComposerClient::Color color);
|
||||
Error setLayerCompositionType(Display display, Layer layer,
|
||||
int32_t type);
|
||||
Error setLayerDataspace(Display display, Layer layer,
|
||||
int32_t dataspace);
|
||||
Error setLayerDisplayFrame(Display display, Layer layer,
|
||||
const hwc_rect_t& frame);
|
||||
Error setLayerPlaneAlpha(Display display, Layer layer, float alpha);
|
||||
Error setLayerSidebandStream(Display display, Layer layer,
|
||||
buffer_handle_t stream);
|
||||
Error setLayerSourceCrop(Display display, Layer layer,
|
||||
const hwc_frect_t& crop);
|
||||
Error setLayerTransform(Display display, Layer layer,
|
||||
int32_t transform);
|
||||
Error setLayerVisibleRegion(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& visible);
|
||||
Error setLayerZOrder(Display display, Layer layer, uint32_t z);
|
||||
|
||||
private:
|
||||
void initCapabilities();
|
||||
|
||||
template<typename T>
|
||||
void initDispatch(T& func, hwc2_function_descriptor_t desc);
|
||||
void initDispatch();
|
||||
|
||||
sp<HwcClient> getClient();
|
||||
|
||||
static void hotplugHook(hwc2_callback_data_t callbackData,
|
||||
hwc2_display_t display, int32_t connected);
|
||||
static void refreshHook(hwc2_callback_data_t callbackData,
|
||||
hwc2_display_t display);
|
||||
static void vsyncHook(hwc2_callback_data_t callbackData,
|
||||
hwc2_display_t display, int64_t timestamp);
|
||||
|
||||
hwc2_device_t* mDevice;
|
||||
|
||||
std::unordered_set<Capability> mCapabilities;
|
||||
|
||||
struct {
|
||||
HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
|
||||
HWC2_PFN_CREATE_LAYER createLayer;
|
||||
HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
|
||||
HWC2_PFN_DESTROY_LAYER destroyLayer;
|
||||
HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
|
||||
HWC2_PFN_DUMP dump;
|
||||
HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
|
||||
HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
|
||||
HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
|
||||
HWC2_PFN_GET_COLOR_MODES getColorModes;
|
||||
HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
|
||||
HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
|
||||
HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
|
||||
HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
|
||||
HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
|
||||
HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
|
||||
HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
|
||||
HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
|
||||
HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
|
||||
HWC2_PFN_PRESENT_DISPLAY presentDisplay;
|
||||
HWC2_PFN_REGISTER_CALLBACK registerCallback;
|
||||
HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
|
||||
HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
|
||||
HWC2_PFN_SET_COLOR_MODE setColorMode;
|
||||
HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
|
||||
HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
|
||||
HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
|
||||
HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
|
||||
HWC2_PFN_SET_LAYER_COLOR setLayerColor;
|
||||
HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
|
||||
HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
|
||||
HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
|
||||
HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
|
||||
HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
|
||||
HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
|
||||
HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
|
||||
HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
|
||||
HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
|
||||
HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
|
||||
HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
|
||||
HWC2_PFN_SET_POWER_MODE setPowerMode;
|
||||
HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
|
||||
HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
|
||||
} mDispatch;
|
||||
|
||||
std::mutex mClientMutex;
|
||||
wp<HwcClient> mClient;
|
||||
};
|
||||
|
||||
extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
1126
graphics/composer/2.1/default/HwcClient.cpp
Normal file
1126
graphics/composer/2.1/default/HwcClient.cpp
Normal file
File diff suppressed because it is too large
Load Diff
202
graphics/composer/2.1/default/HwcClient.h
Normal file
202
graphics/composer/2.1/default/HwcClient.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "Hwc.h"
|
||||
#include "IComposerCommandBuffer.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
class BufferClone {
|
||||
public:
|
||||
BufferClone();
|
||||
BufferClone(BufferClone&& other);
|
||||
|
||||
BufferClone(const BufferClone& other) = delete;
|
||||
BufferClone& operator=(const BufferClone& other) = delete;
|
||||
|
||||
BufferClone& operator=(buffer_handle_t handle);
|
||||
~BufferClone();
|
||||
|
||||
operator buffer_handle_t() const { return mHandle; }
|
||||
|
||||
private:
|
||||
void clear();
|
||||
|
||||
buffer_handle_t mHandle;
|
||||
};
|
||||
|
||||
class HwcClient : public IComposerClient {
|
||||
public:
|
||||
HwcClient(HwcHal& hal);
|
||||
virtual ~HwcClient();
|
||||
|
||||
void onHotplug(Display display, IComposerCallback::Connection connected);
|
||||
void onRefresh(Display display);
|
||||
void onVsync(Display display, int64_t timestamp);
|
||||
|
||||
// IComposerClient interface
|
||||
Return<void> registerCallback(
|
||||
const sp<IComposerCallback>& callback) override;
|
||||
Return<uint32_t> getMaxVirtualDisplayCount() override;
|
||||
Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat formatHint, uint32_t outputBufferSlotCount,
|
||||
createVirtualDisplay_cb hidl_cb) override;
|
||||
Return<Error> destroyVirtualDisplay(Display display) override;
|
||||
Return<void> createLayer(Display display, uint32_t bufferSlotCount,
|
||||
createLayer_cb hidl_cb) override;
|
||||
Return<Error> destroyLayer(Display display, Layer layer) override;
|
||||
Return<void> getActiveConfig(Display display,
|
||||
getActiveConfig_cb hidl_cb) override;
|
||||
Return<Error> getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace) override;
|
||||
Return<void> getColorModes(Display display,
|
||||
getColorModes_cb hidl_cb) override;
|
||||
Return<void> getDisplayAttribute(Display display,
|
||||
Config config, Attribute attribute,
|
||||
getDisplayAttribute_cb hidl_cb) override;
|
||||
Return<void> getDisplayConfigs(Display display,
|
||||
getDisplayConfigs_cb hidl_cb) override;
|
||||
Return<void> getDisplayName(Display display,
|
||||
getDisplayName_cb hidl_cb) override;
|
||||
Return<void> getDisplayType(Display display,
|
||||
getDisplayType_cb hidl_cb) override;
|
||||
Return<void> getDozeSupport(Display display,
|
||||
getDozeSupport_cb hidl_cb) override;
|
||||
Return<void> getHdrCapabilities(Display display,
|
||||
getHdrCapabilities_cb hidl_cb) override;
|
||||
Return<Error> setActiveConfig(Display display, Config config) override;
|
||||
Return<Error> setColorMode(Display display, ColorMode mode) override;
|
||||
Return<Error> setPowerMode(Display display, PowerMode mode) override;
|
||||
Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
|
||||
Return<Error> setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount) override;
|
||||
Return<Error> setInputCommandQueue(
|
||||
const MQDescriptorSync& descriptor) override;
|
||||
Return<void> getOutputCommandQueue(
|
||||
getOutputCommandQueue_cb hidl_cb) override;
|
||||
Return<void> executeCommands(uint32_t inLength,
|
||||
const hidl_vec<hidl_handle>& inHandles,
|
||||
executeCommands_cb hidl_cb) override;
|
||||
|
||||
private:
|
||||
struct LayerBuffers {
|
||||
std::vector<BufferClone> Buffers;
|
||||
BufferClone SidebandStream;
|
||||
};
|
||||
|
||||
struct DisplayData {
|
||||
bool IsVirtual;
|
||||
|
||||
std::vector<BufferClone> ClientTargets;
|
||||
std::vector<BufferClone> OutputBuffers;
|
||||
|
||||
std::unordered_map<Layer, LayerBuffers> Layers;
|
||||
|
||||
DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
|
||||
};
|
||||
|
||||
class CommandReader : public CommandReaderBase {
|
||||
public:
|
||||
CommandReader(HwcClient& client);
|
||||
Error parse();
|
||||
|
||||
private:
|
||||
bool parseSelectDisplay(uint16_t length);
|
||||
bool parseSelectLayer(uint16_t length);
|
||||
bool parseSetColorTransform(uint16_t length);
|
||||
bool parseSetClientTarget(uint16_t length);
|
||||
bool parseSetOutputBuffer(uint16_t length);
|
||||
bool parseValidateDisplay(uint16_t length);
|
||||
bool parseAcceptDisplayChanges(uint16_t length);
|
||||
bool parsePresentDisplay(uint16_t length);
|
||||
bool parseSetLayerCursorPosition(uint16_t length);
|
||||
bool parseSetLayerBuffer(uint16_t length);
|
||||
bool parseSetLayerSurfaceDamage(uint16_t length);
|
||||
bool parseSetLayerBlendMode(uint16_t length);
|
||||
bool parseSetLayerColor(uint16_t length);
|
||||
bool parseSetLayerCompositionType(uint16_t length);
|
||||
bool parseSetLayerDataspace(uint16_t length);
|
||||
bool parseSetLayerDisplayFrame(uint16_t length);
|
||||
bool parseSetLayerPlaneAlpha(uint16_t length);
|
||||
bool parseSetLayerSidebandStream(uint16_t length);
|
||||
bool parseSetLayerSourceCrop(uint16_t length);
|
||||
bool parseSetLayerTransform(uint16_t length);
|
||||
bool parseSetLayerVisibleRegion(uint16_t length);
|
||||
bool parseSetLayerZOrder(uint16_t length);
|
||||
|
||||
hwc_rect_t readRect();
|
||||
std::vector<hwc_rect_t> readRegion(size_t count);
|
||||
hwc_frect_t readFRect();
|
||||
|
||||
enum class BufferCache {
|
||||
CLIENT_TARGETS,
|
||||
OUTPUT_BUFFERS,
|
||||
LAYER_BUFFERS,
|
||||
LAYER_SIDEBAND_STREAMS,
|
||||
};
|
||||
Error lookupBuffer(BufferCache cache, uint32_t slot,
|
||||
bool useCache, buffer_handle_t& handle);
|
||||
|
||||
Error lookupLayerSidebandStream(buffer_handle_t& handle)
|
||||
{
|
||||
return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
|
||||
0, false, handle);
|
||||
}
|
||||
|
||||
HwcClient& mClient;
|
||||
HwcHal& mHal;
|
||||
CommandWriter& mWriter;
|
||||
|
||||
Display mDisplay;
|
||||
Layer mLayer;
|
||||
};
|
||||
|
||||
HwcHal& mHal;
|
||||
|
||||
// 64KiB minus a small space for metadata such as read/write pointers
|
||||
static constexpr size_t kWriterInitialSize =
|
||||
64 * 1024 / sizeof(uint32_t) - 16;
|
||||
std::mutex mCommandMutex;
|
||||
CommandReader mReader;
|
||||
CommandWriter mWriter;
|
||||
|
||||
sp<IComposerCallback> mCallback;
|
||||
|
||||
std::mutex mDisplayDataMutex;
|
||||
std::unordered_map<Display, DisplayData> mDisplayData;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H
|
||||
848
graphics/composer/2.1/default/IComposerCommandBuffer.h
Normal file
848
graphics/composer/2.1/default/IComposerCommandBuffer.h
Normal file
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#warn "IComposerCommandBuffer.h included without LOG_TAG"
|
||||
#endif
|
||||
|
||||
#undef LOG_NDEBUG
|
||||
#define LOG_NDEBUG 0
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposer.h>
|
||||
#include <log/log.h>
|
||||
#include <sync/sync.h>
|
||||
#include <MessageQueue.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
|
||||
using android::hardware::graphics::common::V1_0::ColorTransform;
|
||||
using android::hardware::graphics::common::V1_0::Dataspace;
|
||||
using android::hardware::graphics::common::V1_0::Transform;
|
||||
using android::hardware::MessageQueue;
|
||||
|
||||
using CommandQueueType = MessageQueue<uint32_t, kSynchronizedReadWrite>;
|
||||
|
||||
// This class helps build a command queue. Note that all sizes/lengths are in
|
||||
// units of uint32_t's.
|
||||
class CommandWriter {
|
||||
public:
|
||||
CommandWriter(uint32_t initialMaxSize)
|
||||
: mDataMaxSize(initialMaxSize)
|
||||
{
|
||||
mData = std::make_unique<uint32_t[]>(mDataMaxSize);
|
||||
reset();
|
||||
}
|
||||
|
||||
~CommandWriter()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
mDataWritten = 0;
|
||||
mCommandEnd = 0;
|
||||
|
||||
// handles in mDataHandles are owned by the caller
|
||||
mDataHandles.clear();
|
||||
|
||||
// handles in mTemporaryHandles are owned by the writer
|
||||
for (auto handle : mTemporaryHandles) {
|
||||
native_handle_close(handle);
|
||||
native_handle_delete(handle);
|
||||
}
|
||||
mTemporaryHandles.clear();
|
||||
}
|
||||
|
||||
IComposerClient::Command getCommand(uint32_t offset)
|
||||
{
|
||||
uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
|
||||
return static_cast<IComposerClient::Command>(val &
|
||||
static_cast<uint32_t>(IComposerClient::Command::OPCODE_MASK));
|
||||
}
|
||||
|
||||
bool writeQueue(bool& queueChanged, uint32_t& commandLength,
|
||||
hidl_vec<hidl_handle>& commandHandles)
|
||||
{
|
||||
// write data to queue, optionally resizing it
|
||||
if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
|
||||
if (!mQueue->write(mData.get(), mDataWritten)) {
|
||||
ALOGE("failed to write commands to message queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
queueChanged = false;
|
||||
} else {
|
||||
auto newQueue = std::make_unique<CommandQueueType>(mDataMaxSize);
|
||||
if (!newQueue->isValid() ||
|
||||
!newQueue->write(mData.get(), mDataWritten)) {
|
||||
ALOGE("failed to prepare a new message queue ");
|
||||
return false;
|
||||
}
|
||||
|
||||
mQueue = std::move(newQueue);
|
||||
queueChanged = true;
|
||||
}
|
||||
|
||||
commandLength = mDataWritten;
|
||||
commandHandles.setToExternal(
|
||||
const_cast<hidl_handle*>(mDataHandles.data()),
|
||||
mDataHandles.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const MQDescriptorSync* getMQDescriptor() const
|
||||
{
|
||||
return (mQueue) ? mQueue->getDesc() : nullptr;
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSelectDisplayLength = 2;
|
||||
void selectDisplay(Display display)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SELECT_DISPLAY,
|
||||
kSelectDisplayLength);
|
||||
write64(display);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSelectLayerLength = 2;
|
||||
void selectLayer(Layer layer)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SELECT_LAYER,
|
||||
kSelectLayerLength);
|
||||
write64(layer);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetErrorLength = 2;
|
||||
void setError(uint32_t location, Error error)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_ERROR, kSetErrorLength);
|
||||
write(location);
|
||||
writeSigned(static_cast<int32_t>(error));
|
||||
endCommand();
|
||||
}
|
||||
|
||||
void setChangedCompositionTypes(const std::vector<Layer>& layers,
|
||||
const std::vector<IComposerClient::Composition>& types)
|
||||
{
|
||||
size_t totalLayers = std::min(layers.size(), types.size());
|
||||
size_t currentLayer = 0;
|
||||
|
||||
while (currentLayer < totalLayers) {
|
||||
size_t count = std::min(totalLayers - currentLayer,
|
||||
static_cast<size_t>(kMaxLength) / 3);
|
||||
|
||||
beginCommand(
|
||||
IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES,
|
||||
count * 3);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
write64(layers[currentLayer + i]);
|
||||
writeSigned(static_cast<int32_t>(types[currentLayer + i]));
|
||||
}
|
||||
endCommand();
|
||||
|
||||
currentLayer += count;
|
||||
}
|
||||
}
|
||||
|
||||
void setDisplayRequests(uint32_t displayRequestMask,
|
||||
const std::vector<Layer>& layers,
|
||||
const std::vector<uint32_t>& layerRequestMasks)
|
||||
{
|
||||
size_t totalLayers = std::min(layers.size(),
|
||||
layerRequestMasks.size());
|
||||
size_t currentLayer = 0;
|
||||
|
||||
while (currentLayer < totalLayers) {
|
||||
size_t count = std::min(totalLayers - currentLayer,
|
||||
static_cast<size_t>(kMaxLength - 1) / 3);
|
||||
|
||||
beginCommand(IComposerClient::Command::SET_DISPLAY_REQUESTS,
|
||||
1 + count * 3);
|
||||
write(displayRequestMask);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
write64(layers[currentLayer + i]);
|
||||
write(static_cast<int32_t>(layerRequestMasks[currentLayer + i]));
|
||||
}
|
||||
endCommand();
|
||||
|
||||
currentLayer += count;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetPresentFenceLength = 1;
|
||||
void setPresentFence(int presentFence)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_PRESENT_FENCE,
|
||||
kSetPresentFenceLength);
|
||||
writeFence(presentFence);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
void setReleaseFences(const std::vector<Layer>& layers,
|
||||
const std::vector<int>& releaseFences)
|
||||
{
|
||||
size_t totalLayers = std::min(layers.size(), releaseFences.size());
|
||||
size_t currentLayer = 0;
|
||||
|
||||
while (currentLayer < totalLayers) {
|
||||
size_t count = std::min(totalLayers - currentLayer,
|
||||
static_cast<size_t>(kMaxLength) / 3);
|
||||
|
||||
beginCommand(IComposerClient::Command::SET_RELEASE_FENCES,
|
||||
count * 3);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
write64(layers[currentLayer + i]);
|
||||
writeFence(releaseFences[currentLayer + i]);
|
||||
}
|
||||
endCommand();
|
||||
|
||||
currentLayer += count;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetColorTransformLength = 17;
|
||||
void setColorTransform(const float* matrix, ColorTransform hint)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_COLOR_TRANSFORM,
|
||||
kSetColorTransformLength);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
writeFloat(matrix[i]);
|
||||
}
|
||||
writeSigned(static_cast<int32_t>(hint));
|
||||
endCommand();
|
||||
}
|
||||
|
||||
void setClientTarget(uint32_t slot, const native_handle_t* target,
|
||||
int acquireFence, Dataspace dataspace,
|
||||
const std::vector<IComposerClient::Rect>& damage)
|
||||
{
|
||||
bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
|
||||
size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
|
||||
|
||||
beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
|
||||
write(slot);
|
||||
writeHandle(target, true);
|
||||
writeFence(acquireFence);
|
||||
writeSigned(static_cast<int32_t>(dataspace));
|
||||
// When there are too many rectangles in the damage region and doWrite
|
||||
// is false, we write no rectangle at all which means the entire
|
||||
// client target is damaged.
|
||||
if (doWrite) {
|
||||
writeRegion(damage);
|
||||
}
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetOutputBufferLength = 3;
|
||||
void setOutputBuffer(uint32_t slot, const native_handle_t* buffer,
|
||||
int releaseFence)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_OUTPUT_BUFFER,
|
||||
kSetOutputBufferLength);
|
||||
write(slot);
|
||||
writeHandle(buffer, true);
|
||||
writeFence(releaseFence);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kValidateDisplayLength = 0;
|
||||
void validateDisplay()
|
||||
{
|
||||
beginCommand(IComposerClient::Command::VALIDATE_DISPLAY,
|
||||
kValidateDisplayLength);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kAcceptDisplayChangesLength = 0;
|
||||
void acceptDisplayChanges()
|
||||
{
|
||||
beginCommand(IComposerClient::Command::ACCEPT_DISPLAY_CHANGES,
|
||||
kAcceptDisplayChangesLength);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kPresentDisplayLength = 0;
|
||||
void presentDisplay()
|
||||
{
|
||||
beginCommand(IComposerClient::Command::PRESENT_DISPLAY,
|
||||
kPresentDisplayLength);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerCursorPositionLength = 2;
|
||||
void setLayerCursorPosition(int32_t x, int32_t y)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_CURSOR_POSITION,
|
||||
kSetLayerCursorPositionLength);
|
||||
writeSigned(x);
|
||||
writeSigned(y);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerBufferLength = 3;
|
||||
void setLayerBuffer(uint32_t slot, const native_handle_t* buffer,
|
||||
int acquireFence)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_BUFFER,
|
||||
kSetLayerBufferLength);
|
||||
write(slot);
|
||||
writeHandle(buffer, true);
|
||||
writeFence(acquireFence);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
void setLayerSurfaceDamage(
|
||||
const std::vector<IComposerClient::Rect>& damage)
|
||||
{
|
||||
bool doWrite = (damage.size() <= kMaxLength / 4);
|
||||
size_t length = (doWrite) ? damage.size() * 4 : 0;
|
||||
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE,
|
||||
length);
|
||||
// When there are too many rectangles in the damage region and doWrite
|
||||
// is false, we write no rectangle at all which means the entire
|
||||
// layer is damaged.
|
||||
if (doWrite) {
|
||||
writeRegion(damage);
|
||||
}
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerBlendModeLength = 1;
|
||||
void setLayerBlendMode(IComposerClient::BlendMode mode)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_BLEND_MODE,
|
||||
kSetLayerBlendModeLength);
|
||||
writeSigned(static_cast<int32_t>(mode));
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerColorLength = 1;
|
||||
void setLayerColor(IComposerClient::Color color)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_COLOR,
|
||||
kSetLayerColorLength);
|
||||
writeColor(color);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerCompositionTypeLength = 1;
|
||||
void setLayerCompositionType(IComposerClient::Composition type)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE,
|
||||
kSetLayerCompositionTypeLength);
|
||||
writeSigned(static_cast<int32_t>(type));
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerDataspaceLength = 1;
|
||||
void setLayerDataspace(Dataspace dataspace)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE,
|
||||
kSetLayerDataspaceLength);
|
||||
writeSigned(static_cast<int32_t>(dataspace));
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
|
||||
void setLayerDisplayFrame(const IComposerClient::Rect& frame)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_DISPLAY_FRAME,
|
||||
kSetLayerDisplayFrameLength);
|
||||
writeRect(frame);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerPlaneAlphaLength = 1;
|
||||
void setLayerPlaneAlpha(float alpha)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_PLANE_ALPHA,
|
||||
kSetLayerPlaneAlphaLength);
|
||||
writeFloat(alpha);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerSidebandStreamLength = 1;
|
||||
void setLayerSidebandStream(const native_handle_t* stream)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM,
|
||||
kSetLayerSidebandStreamLength);
|
||||
writeHandle(stream);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerSourceCropLength = 4;
|
||||
void setLayerSourceCrop(const IComposerClient::FRect& crop)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_SOURCE_CROP,
|
||||
kSetLayerSourceCropLength);
|
||||
writeFRect(crop);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerTransformLength = 1;
|
||||
void setLayerTransform(Transform transform)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_TRANSFORM,
|
||||
kSetLayerTransformLength);
|
||||
writeSigned(static_cast<int32_t>(transform));
|
||||
endCommand();
|
||||
}
|
||||
|
||||
void setLayerVisibleRegion(
|
||||
const std::vector<IComposerClient::Rect>& visible)
|
||||
{
|
||||
bool doWrite = (visible.size() <= kMaxLength / 4);
|
||||
size_t length = (doWrite) ? visible.size() * 4 : 0;
|
||||
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_VISIBLE_REGION,
|
||||
length);
|
||||
// When there are too many rectangles in the visible region and
|
||||
// doWrite is false, we write no rectangle at all which means the
|
||||
// entire layer is visible.
|
||||
if (doWrite) {
|
||||
writeRegion(visible);
|
||||
}
|
||||
endCommand();
|
||||
}
|
||||
|
||||
static constexpr uint16_t kSetLayerZOrderLength = 1;
|
||||
void setLayerZOrder(uint32_t z)
|
||||
{
|
||||
beginCommand(IComposerClient::Command::SET_LAYER_Z_ORDER,
|
||||
kSetLayerZOrderLength);
|
||||
write(z);
|
||||
endCommand();
|
||||
}
|
||||
|
||||
protected:
|
||||
void beginCommand(IComposerClient::Command command, uint16_t length)
|
||||
{
|
||||
if (mCommandEnd) {
|
||||
LOG_FATAL("endCommand was not called before command 0x%x",
|
||||
command);
|
||||
}
|
||||
|
||||
growData(1 + length);
|
||||
write(static_cast<uint32_t>(command) | length);
|
||||
|
||||
mCommandEnd = mDataWritten + length;
|
||||
}
|
||||
|
||||
void endCommand()
|
||||
{
|
||||
if (!mCommandEnd) {
|
||||
LOG_FATAL("beginCommand was not called");
|
||||
} else if (mDataWritten > mCommandEnd) {
|
||||
LOG_FATAL("too much data written");
|
||||
mDataWritten = mCommandEnd;
|
||||
} else if (mDataWritten < mCommandEnd) {
|
||||
LOG_FATAL("too little data written");
|
||||
while (mDataWritten < mCommandEnd) {
|
||||
write(0);
|
||||
}
|
||||
}
|
||||
|
||||
mCommandEnd = 0;
|
||||
}
|
||||
|
||||
void write(uint32_t val)
|
||||
{
|
||||
mData[mDataWritten++] = val;
|
||||
}
|
||||
|
||||
void writeSigned(int32_t val)
|
||||
{
|
||||
memcpy(&mData[mDataWritten++], &val, sizeof(val));
|
||||
}
|
||||
|
||||
void writeFloat(float val)
|
||||
{
|
||||
memcpy(&mData[mDataWritten++], &val, sizeof(val));
|
||||
}
|
||||
|
||||
void write64(uint64_t val)
|
||||
{
|
||||
uint32_t lo = static_cast<uint32_t>(val & 0xffffffff);
|
||||
uint32_t hi = static_cast<uint32_t>(val >> 32);
|
||||
write(lo);
|
||||
write(hi);
|
||||
}
|
||||
|
||||
void writeRect(const IComposerClient::Rect& rect)
|
||||
{
|
||||
writeSigned(rect.left);
|
||||
writeSigned(rect.top);
|
||||
writeSigned(rect.right);
|
||||
writeSigned(rect.bottom);
|
||||
}
|
||||
|
||||
void writeRegion(const std::vector<IComposerClient::Rect>& region)
|
||||
{
|
||||
for (const auto& rect : region) {
|
||||
writeRect(rect);
|
||||
}
|
||||
}
|
||||
|
||||
void writeFRect(const IComposerClient::FRect& rect)
|
||||
{
|
||||
writeFloat(rect.left);
|
||||
writeFloat(rect.top);
|
||||
writeFloat(rect.right);
|
||||
writeFloat(rect.bottom);
|
||||
}
|
||||
|
||||
void writeColor(const IComposerClient::Color& color)
|
||||
{
|
||||
write((color.r << 0) |
|
||||
(color.g << 8) |
|
||||
(color.b << 16) |
|
||||
(color.a << 24));
|
||||
}
|
||||
|
||||
// ownership of handle is not transferred
|
||||
void writeHandle(const native_handle_t* handle, bool useCache)
|
||||
{
|
||||
if (!handle) {
|
||||
writeSigned(static_cast<int32_t>((useCache) ?
|
||||
IComposerClient::HandleIndex::CACHED :
|
||||
IComposerClient::HandleIndex::EMPTY));
|
||||
return;
|
||||
}
|
||||
|
||||
mDataHandles.push_back(handle);
|
||||
writeSigned(mDataHandles.size() - 1);
|
||||
}
|
||||
|
||||
void writeHandle(const native_handle_t* handle)
|
||||
{
|
||||
writeHandle(handle, false);
|
||||
}
|
||||
|
||||
// ownership of fence is transferred
|
||||
void writeFence(int fence)
|
||||
{
|
||||
native_handle_t* handle = nullptr;
|
||||
if (fence >= 0) {
|
||||
handle = getTemporaryHandle(1, 0);
|
||||
if (handle) {
|
||||
handle->data[0] = fence;
|
||||
} else {
|
||||
ALOGW("failed to get temporary handle for fence %d", fence);
|
||||
sync_wait(fence, -1);
|
||||
close(fence);
|
||||
}
|
||||
}
|
||||
|
||||
writeHandle(handle);
|
||||
}
|
||||
|
||||
native_handle_t* getTemporaryHandle(int numFds, int numInts)
|
||||
{
|
||||
native_handle_t* handle = native_handle_create(numFds, numInts);
|
||||
if (handle) {
|
||||
mTemporaryHandles.push_back(handle);
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
static constexpr uint16_t kMaxLength =
|
||||
std::numeric_limits<uint16_t>::max();
|
||||
|
||||
private:
|
||||
void growData(uint32_t grow)
|
||||
{
|
||||
uint32_t newWritten = mDataWritten + grow;
|
||||
if (newWritten < mDataWritten) {
|
||||
LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32
|
||||
", growing by %" PRIu32, mDataWritten, grow);
|
||||
}
|
||||
|
||||
if (newWritten <= mDataMaxSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t newMaxSize = mDataMaxSize << 1;
|
||||
if (newMaxSize < newWritten) {
|
||||
newMaxSize = newWritten;
|
||||
}
|
||||
|
||||
auto newData = std::make_unique<uint32_t[]>(newMaxSize);
|
||||
std::copy_n(mData.get(), mDataWritten, newData.get());
|
||||
mDataMaxSize = newMaxSize;
|
||||
mData = std::move(newData);
|
||||
}
|
||||
|
||||
uint32_t mDataMaxSize;
|
||||
std::unique_ptr<uint32_t[]> mData;
|
||||
|
||||
uint32_t mDataWritten;
|
||||
// end offset of the current command
|
||||
uint32_t mCommandEnd;
|
||||
|
||||
std::vector<hidl_handle> mDataHandles;
|
||||
std::vector<native_handle_t *> mTemporaryHandles;
|
||||
|
||||
std::unique_ptr<CommandQueueType> mQueue;
|
||||
};
|
||||
|
||||
// This class helps parse a command queue. Note that all sizes/lengths are in
|
||||
// units of uint32_t's.
|
||||
class CommandReaderBase {
|
||||
public:
|
||||
CommandReaderBase() : mDataMaxSize(0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
bool setMQDescriptor(const MQDescriptorSync& descriptor)
|
||||
{
|
||||
mQueue = std::make_unique<CommandQueueType>(descriptor, false);
|
||||
if (mQueue->isValid()) {
|
||||
return true;
|
||||
} else {
|
||||
mQueue = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool readQueue(uint32_t commandLength,
|
||||
const hidl_vec<hidl_handle>& commandHandles)
|
||||
{
|
||||
if (!mQueue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto quantumCount = mQueue->getQuantumCount();
|
||||
if (mDataMaxSize < quantumCount) {
|
||||
mDataMaxSize = quantumCount;
|
||||
mData = std::make_unique<uint32_t[]>(mDataMaxSize);
|
||||
}
|
||||
|
||||
if (commandLength > mDataMaxSize ||
|
||||
!mQueue->read(mData.get(), commandLength)) {
|
||||
ALOGE("failed to read commands from message queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
mDataSize = commandLength;
|
||||
mDataRead = 0;
|
||||
mCommandBegin = 0;
|
||||
mCommandEnd = 0;
|
||||
mDataHandles.setToExternal(
|
||||
const_cast<hidl_handle*>(commandHandles.data()),
|
||||
commandHandles.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
mDataSize = 0;
|
||||
mDataRead = 0;
|
||||
mCommandBegin = 0;
|
||||
mCommandEnd = 0;
|
||||
mDataHandles.setToExternal(nullptr, 0);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool isEmpty() const
|
||||
{
|
||||
return (mDataRead >= mDataSize);
|
||||
}
|
||||
|
||||
bool beginCommand(IComposerClient::Command& command, uint16_t& length)
|
||||
{
|
||||
if (mCommandEnd) {
|
||||
LOG_FATAL("endCommand was not called before command 0x%x",
|
||||
command);
|
||||
}
|
||||
|
||||
constexpr uint32_t opcode_mask =
|
||||
static_cast<uint32_t>(IComposerClient::Command::OPCODE_MASK);
|
||||
constexpr uint32_t length_mask =
|
||||
static_cast<uint32_t>(IComposerClient::Command::LENGTH_MASK);
|
||||
|
||||
uint32_t val = read();
|
||||
command = static_cast<IComposerClient::Command>(val & opcode_mask);
|
||||
length = static_cast<uint16_t>(val & length_mask);
|
||||
|
||||
if (mDataRead + length > mDataSize) {
|
||||
ALOGE("command 0x%x has invalid command length %" PRIu16,
|
||||
command, length);
|
||||
// undo the read() above
|
||||
mDataRead--;
|
||||
return false;
|
||||
}
|
||||
|
||||
mCommandEnd = mDataRead + length;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void endCommand()
|
||||
{
|
||||
if (!mCommandEnd) {
|
||||
LOG_FATAL("beginCommand was not called");
|
||||
} else if (mDataRead > mCommandEnd) {
|
||||
LOG_FATAL("too much data read");
|
||||
mDataRead = mCommandEnd;
|
||||
} else if (mDataRead < mCommandEnd) {
|
||||
LOG_FATAL("too little data read");
|
||||
mDataRead = mCommandEnd;
|
||||
}
|
||||
|
||||
mCommandBegin = mCommandEnd;
|
||||
mCommandEnd = 0;
|
||||
}
|
||||
|
||||
uint32_t getCommandLoc() const
|
||||
{
|
||||
return mCommandBegin;
|
||||
}
|
||||
|
||||
uint32_t read()
|
||||
{
|
||||
return mData[mDataRead++];
|
||||
}
|
||||
|
||||
int32_t readSigned()
|
||||
{
|
||||
int32_t val;
|
||||
memcpy(&val, &mData[mDataRead++], sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
float readFloat()
|
||||
{
|
||||
float val;
|
||||
memcpy(&val, &mData[mDataRead++], sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
uint64_t read64()
|
||||
{
|
||||
uint32_t lo = read();
|
||||
uint32_t hi = read();
|
||||
return (static_cast<uint64_t>(hi) << 32) | lo;
|
||||
}
|
||||
|
||||
IComposerClient::Color readColor()
|
||||
{
|
||||
uint32_t val = read();
|
||||
return IComposerClient::Color{
|
||||
static_cast<uint8_t>((val >> 0) & 0xff),
|
||||
static_cast<uint8_t>((val >> 8) & 0xff),
|
||||
static_cast<uint8_t>((val >> 16) & 0xff),
|
||||
static_cast<uint8_t>((val >> 24) & 0xff),
|
||||
};
|
||||
}
|
||||
|
||||
// ownership of handle is not transferred
|
||||
const native_handle_t* readHandle(bool& useCache)
|
||||
{
|
||||
const native_handle_t* handle = nullptr;
|
||||
|
||||
int32_t index = readSigned();
|
||||
switch (index) {
|
||||
case static_cast<int32_t>(IComposerClient::HandleIndex::EMPTY):
|
||||
useCache = false;
|
||||
break;
|
||||
case static_cast<int32_t>(IComposerClient::HandleIndex::CACHED):
|
||||
useCache = true;
|
||||
break;
|
||||
default:
|
||||
if (static_cast<size_t>(index) < mDataHandles.size()) {
|
||||
handle = mDataHandles[index].getNativeHandle();
|
||||
} else {
|
||||
ALOGE("invalid handle index %zu", static_cast<size_t>(index));
|
||||
}
|
||||
useCache = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
const native_handle_t* readHandle()
|
||||
{
|
||||
bool useCache;
|
||||
return readHandle(useCache);
|
||||
}
|
||||
|
||||
// ownership of fence is transferred
|
||||
int readFence()
|
||||
{
|
||||
auto handle = readHandle();
|
||||
if (!handle || handle->numFds == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (handle->numFds != 1) {
|
||||
ALOGE("invalid fence handle with %d fds", handle->numFds);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = dup(handle->data[0]);
|
||||
if (fd < 0) {
|
||||
ALOGW("failed to dup fence %d", handle->data[0]);
|
||||
sync_wait(handle->data[0], -1);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<CommandQueueType> mQueue;
|
||||
uint32_t mDataMaxSize;
|
||||
std::unique_ptr<uint32_t[]> mData;
|
||||
|
||||
uint32_t mDataSize;
|
||||
uint32_t mDataRead;
|
||||
|
||||
// begin/end offsets of the current command
|
||||
uint32_t mCommandBegin;
|
||||
uint32_t mCommandEnd;
|
||||
|
||||
hidl_vec<hidl_handle> mDataHandles;
|
||||
};
|
||||
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
|
||||
@@ -23,7 +23,7 @@ enum Error : int32_t {
|
||||
BAD_DISPLAY = 2, /* invalid Display */
|
||||
BAD_LAYER = 3, /* invalid Layer */
|
||||
BAD_PARAMETER = 4, /* invalid width, height, etc. */
|
||||
HAS_CHANGES = 5,
|
||||
/* 5 is reserved */
|
||||
NO_RESOURCES = 6, /* temporary failure due to resource contention */
|
||||
NOT_VALIDATED = 7, /* validateDisplay has not been called */
|
||||
UNSUPPORTED = 8, /* permanent failure */
|
||||
|
||||
Reference in New Issue
Block a user