upload android base code part4
This commit is contained in:
parent
b9e30e05b1
commit
78ea2404cd
23455 changed files with 5250148 additions and 0 deletions
82
android/hardware/interfaces/graphics/composer/2.1/Android.bp
Normal file
82
android/hardware/interfaces/graphics/composer/2.1/Android.bp
Normal file
|
@ -0,0 +1,82 @@
|
|||
// This file is autogenerated by hidl-gen. Do not edit manually.
|
||||
|
||||
filegroup {
|
||||
name: "android.hardware.graphics.composer@2.1_hal",
|
||||
srcs: [
|
||||
"types.hal",
|
||||
"IComposer.hal",
|
||||
"IComposerCallback.hal",
|
||||
"IComposerClient.hal",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.graphics.composer@2.1_genc++",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.composer@2.1",
|
||||
srcs: [
|
||||
":android.hardware.graphics.composer@2.1_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",
|
||||
],
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "android.hardware.graphics.composer@2.1_genc++_headers",
|
||||
tools: ["hidl-gen"],
|
||||
cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.composer@2.1",
|
||||
srcs: [
|
||||
":android.hardware.graphics.composer@2.1_hal",
|
||||
],
|
||||
out: [
|
||||
"android/hardware/graphics/composer/2.1/types.h",
|
||||
"android/hardware/graphics/composer/2.1/hwtypes.h",
|
||||
"android/hardware/graphics/composer/2.1/IComposer.h",
|
||||
"android/hardware/graphics/composer/2.1/IHwComposer.h",
|
||||
"android/hardware/graphics/composer/2.1/BnHwComposer.h",
|
||||
"android/hardware/graphics/composer/2.1/BpHwComposer.h",
|
||||
"android/hardware/graphics/composer/2.1/BsComposer.h",
|
||||
"android/hardware/graphics/composer/2.1/IComposerCallback.h",
|
||||
"android/hardware/graphics/composer/2.1/IHwComposerCallback.h",
|
||||
"android/hardware/graphics/composer/2.1/BnHwComposerCallback.h",
|
||||
"android/hardware/graphics/composer/2.1/BpHwComposerCallback.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/BnHwComposerClient.h",
|
||||
"android/hardware/graphics/composer/2.1/BpHwComposerClient.h",
|
||||
"android/hardware/graphics/composer/2.1/BsComposerClient.h",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "android.hardware.graphics.composer@2.1",
|
||||
defaults: ["hidl-module-defaults"],
|
||||
generated_sources: ["android.hardware.graphics.composer@2.1_genc++"],
|
||||
generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
|
||||
export_generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
|
||||
vendor_available: true,
|
||||
vndk: {
|
||||
enabled: true,
|
||||
},
|
||||
shared_libs: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"libcutils",
|
||||
"android.hardware.graphics.common@1.0",
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"libhwbinder",
|
||||
"libutils",
|
||||
"android.hardware.graphics.common@1.0",
|
||||
],
|
||||
}
|
19
android/hardware/interfaces/graphics/composer/2.1/Android.mk
Normal file
19
android/hardware/interfaces/graphics/composer/2.1/Android.mk
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (C) 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(call all-subdir-makefiles)
|
97
android/hardware/interfaces/graphics/composer/2.1/IComposer.hal
Executable file
97
android/hardware/interfaces/graphics/composer/2.1/IComposer.hal
Executable file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package android.hardware.graphics.composer@2.1;
|
||||
|
||||
import IComposerClient;
|
||||
|
||||
interface IComposer {
|
||||
/**
|
||||
* Optional capabilities which may be supported by some devices. The
|
||||
* particular set of supported capabilities for a given device may be
|
||||
* retrieved using getCapabilities.
|
||||
*/
|
||||
enum Capability : int32_t {
|
||||
INVALID = 0,
|
||||
|
||||
/**
|
||||
* Specifies that the device supports sideband stream layers, for
|
||||
* which buffer content updates and other synchronization will not be
|
||||
* provided through the usual validate/present cycle and must be
|
||||
* handled by an external implementation-defined mechanism. Only
|
||||
* changes to layer state (such as position, size, etc.) need to be
|
||||
* performed through the validate/present cycle.
|
||||
*/
|
||||
SIDEBAND_STREAM = 1,
|
||||
|
||||
/**
|
||||
* Specifies that the device will apply a color transform even when
|
||||
* either the client or the device has chosen that all layers should
|
||||
* be composed by the client. This will prevent the client from
|
||||
* applying the color transform during its composition step.
|
||||
*/
|
||||
SKIP_CLIENT_COLOR_TRANSFORM = 2,
|
||||
|
||||
/**
|
||||
* Specifies that the present fence must not be used as an accurate
|
||||
* representation of the actual present time of a frame.
|
||||
*/
|
||||
PRESENT_FENCE_IS_NOT_RELIABLE = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides a list of supported capabilities (as described in the
|
||||
* definition of Capability above). This list must not change after
|
||||
* initialization.
|
||||
*
|
||||
* @return capabilities is a list of supported capabilities.
|
||||
*/
|
||||
@entry
|
||||
@exit
|
||||
@callflow(next="*")
|
||||
getCapabilities() generates (vec<Capability> capabilities);
|
||||
|
||||
/**
|
||||
* Retrieves implementation-defined debug information, which will be
|
||||
* displayed during, for example, `dumpsys SurfaceFlinger`.
|
||||
*
|
||||
* @return debugInfo is a string of debug information.
|
||||
*/
|
||||
@entry
|
||||
@exit
|
||||
@callflow(next="*")
|
||||
dumpDebugInfo() generates (string debugInfo);
|
||||
|
||||
/**
|
||||
* Creates a client of the composer. All resources created by the client
|
||||
* are owned by the client and are only visible to the client.
|
||||
*
|
||||
* There can only be one client at any time.
|
||||
*
|
||||
* @return error is NONE upon success. Otherwise,
|
||||
* NO_RESOURCES when no more client can be created currently.
|
||||
* @return client is the newly created client.
|
||||
*/
|
||||
@entry
|
||||
@callflow(next="*")
|
||||
createClient() generates (Error error, IComposerClient client);
|
||||
@entry
|
||||
@callflow(next="*")
|
||||
setDisplayArg(int32_t disp,
|
||||
int32_t cmd1,
|
||||
int32_t cmd2,
|
||||
int32_t data)generates (Error error);
|
||||
};
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package android.hardware.graphics.composer@2.1;
|
||||
|
||||
interface IComposerCallback {
|
||||
enum Connection : int32_t {
|
||||
INVALID = 0,
|
||||
|
||||
/** The display has been connected */
|
||||
CONNECTED = 1,
|
||||
/** The display has been disconnected */
|
||||
DISCONNECTED = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Notifies the client that the given display has either been connected or
|
||||
* disconnected. Every active display (even a built-in physical display)
|
||||
* must trigger at least one hotplug notification, even if it only occurs
|
||||
* immediately after callback registration.
|
||||
*
|
||||
* Displays which have been connected are assumed to be in PowerMode::OFF,
|
||||
* and the onVsync callback should not be called for a display until vsync
|
||||
* has been enabled with setVsyncEnabled.
|
||||
*
|
||||
* The client may call back into the device while the callback is in
|
||||
* progress. The device must serialize calls to this callback such that
|
||||
* only one thread is calling it at a time.
|
||||
*
|
||||
* @param display is the display that triggers the hotplug event.
|
||||
* @param connected indicates whether the display is connected or
|
||||
* disconnected.
|
||||
*/
|
||||
@callflow(next="*")
|
||||
onHotplug(Display display, Connection connected);
|
||||
|
||||
/**
|
||||
* Notifies the client to trigger a screen refresh. This forces all layer
|
||||
* state for this display to be resent, and the display to be validated
|
||||
* and presented, even if there have been no changes.
|
||||
|
||||
* This refresh will occur some time after the callback is initiated, but
|
||||
* not necessarily before it returns. It is safe to trigger this callback
|
||||
* from other functions which call into the device.
|
||||
*
|
||||
* @param display is the display to refresh.
|
||||
*/
|
||||
@callflow(next="*")
|
||||
oneway onRefresh(Display display);
|
||||
|
||||
/**
|
||||
* Notifies the client that a vsync event has occurred. This callback must
|
||||
* only be triggered when vsync is enabled for this display (through
|
||||
* setVsyncEnabled).
|
||||
*
|
||||
* @param display is the display which has received a vsync event
|
||||
* @param timestamp is the CLOCK_MONOTONIC time at which the vsync event
|
||||
* occurred, in nanoseconds.
|
||||
*/
|
||||
@callflow(next="*")
|
||||
oneway onVsync(Display display, int64_t timestamp);
|
||||
};
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,73 @@
|
|||
cc_library_static {
|
||||
name: "libhwcomposer-client",
|
||||
vendor_available: true,
|
||||
defaults: ["hidl_defaults"],
|
||||
export_include_dirs: ["."],
|
||||
srcs: ["ComposerClient.cpp"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libsync",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "android.hardware.graphics.composer@2.1-impl",
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["Hwc.cpp"],
|
||||
static_libs: ["libhwcomposer-client"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libsync",
|
||||
"libutils",
|
||||
"libhwc2on1adapter"
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.graphics.composer@2.1-service",
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["service.cpp"],
|
||||
init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
|
||||
static_libs: ["libhwcomposer-client"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"libbase",
|
||||
"libbinder",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libsync",
|
||||
"libutils",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libhwcomposer-command-buffer",
|
||||
defaults: ["hidl_defaults"],
|
||||
shared_libs: ["android.hardware.graphics.composer@2.1"],
|
||||
export_include_dirs: ["."],
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright 2017 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_COMPOSER_BASE_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposer.h>
|
||||
#include <hardware/hwcomposer2.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
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 ComposerBase {
|
||||
public:
|
||||
virtual ~ComposerBase() {};
|
||||
|
||||
virtual void removeClient() = 0;
|
||||
virtual void enableCallback(bool enable) = 0;
|
||||
virtual uint32_t getMaxVirtualDisplayCount() = 0;
|
||||
virtual Error createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat* format, Display* outDisplay) = 0;
|
||||
virtual Error destroyVirtualDisplay(Display display) = 0;
|
||||
virtual Error createLayer(Display display, Layer* outLayer) = 0;
|
||||
virtual Error destroyLayer(Display display, Layer layer) = 0;
|
||||
|
||||
virtual Error getActiveConfig(Display display, Config* outConfig) = 0;
|
||||
virtual Error getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace) = 0;
|
||||
virtual Error getColorModes(Display display,
|
||||
hidl_vec<ColorMode>* outModes) = 0;
|
||||
virtual Error getDisplayAttribute(Display display, Config config,
|
||||
IComposerClient::Attribute attribute, int32_t* outValue) = 0;
|
||||
virtual Error getDisplayConfigs(Display display,
|
||||
hidl_vec<Config>* outConfigs) = 0;
|
||||
virtual Error getDisplayName(Display display, hidl_string* outName) = 0;
|
||||
virtual Error getDisplayType(Display display,
|
||||
IComposerClient::DisplayType* outType) = 0;
|
||||
virtual Error getDozeSupport(Display display, bool* outSupport) = 0;
|
||||
virtual Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
|
||||
float* outMaxLuminance, float* outMaxAverageLuminance,
|
||||
float* outMinLuminance) = 0;
|
||||
|
||||
virtual Error setActiveConfig(Display display, Config config) = 0;
|
||||
virtual Error setColorMode(Display display, ColorMode mode) = 0;
|
||||
virtual Error setPowerMode(Display display,
|
||||
IComposerClient::PowerMode mode) = 0;
|
||||
virtual Error setVsyncEnabled(Display display,
|
||||
IComposerClient::Vsync enabled) = 0;
|
||||
|
||||
virtual Error setColorTransform(Display display, const float* matrix,
|
||||
int32_t hint) = 0;
|
||||
virtual Error setClientTarget(Display display, buffer_handle_t target,
|
||||
int32_t acquireFence, int32_t dataspace,
|
||||
const std::vector<hwc_rect_t>& damage) = 0;
|
||||
virtual Error setOutputBuffer(Display display, buffer_handle_t buffer,
|
||||
int32_t releaseFence) = 0;
|
||||
virtual Error validateDisplay(Display display,
|
||||
std::vector<Layer>* outChangedLayers,
|
||||
std::vector<IComposerClient::Composition>* outCompositionTypes,
|
||||
uint32_t* outDisplayRequestMask,
|
||||
std::vector<Layer>* outRequestedLayers,
|
||||
std::vector<uint32_t>* outRequestMasks) = 0;
|
||||
virtual Error acceptDisplayChanges(Display display) = 0;
|
||||
virtual Error presentDisplay(Display display, int32_t* outPresentFence,
|
||||
std::vector<Layer>* outLayers,
|
||||
std::vector<int32_t>* outReleaseFences) = 0;
|
||||
|
||||
virtual Error setLayerCursorPosition(Display display, Layer layer,
|
||||
int32_t x, int32_t y) = 0;
|
||||
virtual Error setLayerBuffer(Display display, Layer layer,
|
||||
buffer_handle_t buffer, int32_t acquireFence) = 0;
|
||||
virtual Error setLayerSurfaceDamage(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& damage) = 0;
|
||||
virtual Error setLayerBlendMode(Display display, Layer layer,
|
||||
int32_t mode) = 0;
|
||||
virtual Error setLayerColor(Display display, Layer layer,
|
||||
IComposerClient::Color color) = 0;
|
||||
virtual Error setLayerCompositionType(Display display, Layer layer,
|
||||
int32_t type) = 0;
|
||||
virtual Error setLayerDataspace(Display display, Layer layer,
|
||||
int32_t dataspace) = 0;
|
||||
virtual Error setLayerDisplayFrame(Display display, Layer layer,
|
||||
const hwc_rect_t& frame) = 0;
|
||||
virtual Error setLayerPlaneAlpha(Display display, Layer layer,
|
||||
float alpha) = 0;
|
||||
virtual Error setLayerSidebandStream(Display display, Layer layer,
|
||||
buffer_handle_t stream) = 0;
|
||||
virtual Error setLayerSourceCrop(Display display, Layer layer,
|
||||
const hwc_frect_t& crop) = 0;
|
||||
virtual Error setLayerTransform(Display display, Layer layer,
|
||||
int32_t transform) = 0;
|
||||
virtual Error setLayerVisibleRegion(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& visible) = 0;
|
||||
virtual Error setLayerZOrder(Display display, Layer layer,
|
||||
uint32_t z) = 0;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_BASE_H
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* 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_COMPOSER_CLIENT_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <hardware/hwcomposer2.h>
|
||||
#include "IComposerCommandBuffer.h"
|
||||
#include "ComposerBase.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
class BufferCacheEntry {
|
||||
public:
|
||||
BufferCacheEntry();
|
||||
BufferCacheEntry(BufferCacheEntry&& other);
|
||||
|
||||
BufferCacheEntry(const BufferCacheEntry& other) = delete;
|
||||
BufferCacheEntry& operator=(const BufferCacheEntry& other) = delete;
|
||||
|
||||
BufferCacheEntry& operator=(buffer_handle_t handle);
|
||||
~BufferCacheEntry();
|
||||
|
||||
buffer_handle_t getHandle() const { return mHandle; }
|
||||
|
||||
private:
|
||||
void clear();
|
||||
|
||||
buffer_handle_t mHandle;
|
||||
};
|
||||
|
||||
class ComposerClient : public IComposerClient {
|
||||
public:
|
||||
ComposerClient(ComposerBase& hal);
|
||||
virtual ~ComposerClient();
|
||||
|
||||
void initialize();
|
||||
|
||||
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<uint32_t>& 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;
|
||||
|
||||
protected:
|
||||
struct LayerBuffers {
|
||||
std::vector<BufferCacheEntry> Buffers;
|
||||
// the handle is a sideband stream handle, not a buffer handle
|
||||
BufferCacheEntry SidebandStream;
|
||||
};
|
||||
|
||||
struct DisplayData {
|
||||
bool IsVirtual;
|
||||
|
||||
std::vector<BufferCacheEntry> ClientTargets;
|
||||
std::vector<BufferCacheEntry> OutputBuffers;
|
||||
|
||||
std::unordered_map<Layer, LayerBuffers> Layers;
|
||||
|
||||
DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
|
||||
};
|
||||
|
||||
class CommandReader : public CommandReaderBase {
|
||||
public:
|
||||
CommandReader(ComposerClient& client);
|
||||
virtual ~CommandReader();
|
||||
|
||||
Error parse();
|
||||
|
||||
protected:
|
||||
virtual bool parseCommand(IComposerClient::Command command,
|
||||
uint16_t length);
|
||||
|
||||
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 parsePresentOrValidateDisplay(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 lookupBufferCacheEntryLocked(BufferCache cache, uint32_t slot,
|
||||
BufferCacheEntry** outEntry);
|
||||
Error lookupBuffer(BufferCache cache, uint32_t slot,
|
||||
bool useCache, buffer_handle_t handle,
|
||||
buffer_handle_t* outHandle);
|
||||
Error updateBuffer(BufferCache cache, uint32_t slot,
|
||||
bool useCache, buffer_handle_t handle);
|
||||
|
||||
Error lookupLayerSidebandStream(buffer_handle_t handle,
|
||||
buffer_handle_t* outHandle)
|
||||
{
|
||||
return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
|
||||
0, false, handle, outHandle);
|
||||
}
|
||||
Error updateLayerSidebandStream(buffer_handle_t handle)
|
||||
{
|
||||
return updateBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
|
||||
0, false, handle);
|
||||
}
|
||||
|
||||
ComposerClient& mClient;
|
||||
ComposerBase& mHal;
|
||||
CommandWriterBase& mWriter;
|
||||
|
||||
Display mDisplay;
|
||||
Layer mLayer;
|
||||
};
|
||||
|
||||
virtual std::unique_ptr<CommandReader> createCommandReader();
|
||||
|
||||
ComposerBase& 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;
|
||||
std::unique_ptr<CommandReader> mReader;
|
||||
CommandWriterBase 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_COMPOSER_CLIENT_H
|
773
android/hardware/interfaces/graphics/composer/2.1/default/Hwc.cpp
Executable file
773
android/hardware/interfaces/graphics/composer/2.1/default/Hwc.cpp
Executable file
|
@ -0,0 +1,773 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "HwcPassthrough"
|
||||
|
||||
#include "Hwc.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <type_traits>
|
||||
#include <log/log.h>
|
||||
|
||||
#include "ComposerClient.h"
|
||||
#include "hardware/hwcomposer.h"
|
||||
#include "hwc2on1adapter/HWC2On1Adapter.h"
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
|
||||
HwcHal::HwcHal(const hw_module_t* module)
|
||||
: mDevice(nullptr), mDispatch(), mAdapter()
|
||||
{
|
||||
// Determine what kind of module is available (HWC2 vs HWC1.X).
|
||||
hw_device_t* device = nullptr;
|
||||
int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
|
||||
if (error != 0) {
|
||||
ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
|
||||
abort();
|
||||
}
|
||||
uint32_t majorVersion = (device->version >> 24) & 0xF;
|
||||
|
||||
// If we don't have a HWC2, we need to wrap whatever we have in an adapter.
|
||||
if (majorVersion != 2) {
|
||||
uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
|
||||
minorVersion = (minorVersion >> 16) & 0xF;
|
||||
ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion);
|
||||
if (minorVersion < 1) {
|
||||
ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1",
|
||||
majorVersion, minorVersion);
|
||||
abort();
|
||||
}
|
||||
mAdapter = std::make_unique<HWC2On1Adapter>(
|
||||
reinterpret_cast<hwc_composer_device_1*>(device));
|
||||
|
||||
// Place the adapter in front of the device module.
|
||||
mDevice = mAdapter.get();
|
||||
} else {
|
||||
mDevice = reinterpret_cast<hwc2_device_t*>(device);
|
||||
}
|
||||
|
||||
initCapabilities();
|
||||
if (majorVersion >= 2 &&
|
||||
hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {
|
||||
ALOGE("Present fence must be reliable from HWC2 on.");
|
||||
abort();
|
||||
}
|
||||
|
||||
initDispatch();
|
||||
}
|
||||
|
||||
HwcHal::~HwcHal()
|
||||
{
|
||||
hwc2_close(mDevice);
|
||||
}
|
||||
|
||||
void HwcHal::initCapabilities()
|
||||
{
|
||||
uint32_t count = 0;
|
||||
mDevice->getCapabilities(mDevice, &count, nullptr);
|
||||
|
||||
std::vector<Capability> caps(count);
|
||||
mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
|
||||
std::underlying_type<Capability>::type*>(caps.data()));
|
||||
caps.resize(count);
|
||||
|
||||
mCapabilities.insert(caps.cbegin(), caps.cend());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void HwcHal::initDispatch(hwc2_function_descriptor_t desc, T* outPfn)
|
||||
{
|
||||
auto pfn = mDevice->getFunction(mDevice, desc);
|
||||
if (!pfn) {
|
||||
LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc);
|
||||
}
|
||||
|
||||
*outPfn = reinterpret_cast<T>(pfn);
|
||||
}
|
||||
|
||||
void HwcHal::initDispatch()
|
||||
{
|
||||
initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
|
||||
&mDispatch.acceptDisplayChanges);
|
||||
initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer);
|
||||
initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
|
||||
&mDispatch.createVirtualDisplay);
|
||||
initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer);
|
||||
initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
|
||||
&mDispatch.destroyVirtualDisplay);
|
||||
initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump);
|
||||
initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig);
|
||||
initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
|
||||
&mDispatch.getChangedCompositionTypes);
|
||||
initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
|
||||
&mDispatch.getClientTargetSupport);
|
||||
initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes);
|
||||
initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
|
||||
&mDispatch.getDisplayAttribute);
|
||||
initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
|
||||
&mDispatch.getDisplayConfigs);
|
||||
initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName);
|
||||
initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
|
||||
&mDispatch.getDisplayRequests);
|
||||
initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType);
|
||||
initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport);
|
||||
initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES,
|
||||
&mDispatch.getHdrCapabilities);
|
||||
initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
|
||||
&mDispatch.getMaxVirtualDisplayCount);
|
||||
initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES,
|
||||
&mDispatch.getReleaseFences);
|
||||
initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay);
|
||||
initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK,
|
||||
&mDispatch.registerCallback);
|
||||
initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig);
|
||||
initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget);
|
||||
initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode);
|
||||
initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM,
|
||||
&mDispatch.setColorTransform);
|
||||
initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION,
|
||||
&mDispatch.setCursorPosition);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
|
||||
&mDispatch.setLayerBlendMode);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
|
||||
&mDispatch.setLayerCompositionType);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE,
|
||||
&mDispatch.setLayerDataspace);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
|
||||
&mDispatch.setLayerDisplayFrame);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
|
||||
&mDispatch.setLayerPlaneAlpha);
|
||||
|
||||
if (hasCapability(Capability::SIDEBAND_STREAM)) {
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
|
||||
&mDispatch.setLayerSidebandStream);
|
||||
}
|
||||
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
|
||||
&mDispatch.setLayerSourceCrop);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
|
||||
&mDispatch.setLayerSurfaceDamage);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM,
|
||||
&mDispatch.setLayerTransform);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
|
||||
&mDispatch.setLayerVisibleRegion);
|
||||
initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder);
|
||||
initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer);
|
||||
initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode);
|
||||
initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled);
|
||||
initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay);
|
||||
initDispatch(HWC2_FUNCTION_SUNXI_SET_DISPLY, &mDispatch.sunxisetdisplay);
|
||||
}
|
||||
|
||||
bool HwcHal::hasCapability(Capability capability) const
|
||||
{
|
||||
return (mCapabilities.count(capability) > 0);
|
||||
}
|
||||
|
||||
Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb)
|
||||
{
|
||||
std::vector<Capability> caps(
|
||||
mCapabilities.cbegin(), mCapabilities.cend());
|
||||
|
||||
hidl_vec<Capability> caps_reply;
|
||||
caps_reply.setToExternal(caps.data(), caps.size());
|
||||
hidl_cb(caps_reply);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
mDispatch.dump(mDevice, &len, nullptr);
|
||||
|
||||
std::vector<char> buf(len + 1);
|
||||
mDispatch.dump(mDevice, &len, buf.data());
|
||||
buf.resize(len + 1);
|
||||
buf[len] = '\0';
|
||||
|
||||
hidl_string buf_reply;
|
||||
buf_reply.setToExternal(buf.data(), len);
|
||||
hidl_cb(buf_reply);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> HwcHal::createClient(createClient_cb hidl_cb)
|
||||
{
|
||||
Error err = Error::NONE;
|
||||
sp<ComposerClient> client;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mClientMutex);
|
||||
|
||||
if (mClient != nullptr) {
|
||||
// In surface flinger we delete a composer client on one thread and
|
||||
// then create a new client on another thread. Although surface
|
||||
// flinger ensures the calls are made in that sequence (destroy and
|
||||
// then create), sometimes the calls land in the composer service
|
||||
// inverted (create and then destroy). Wait for a brief period to
|
||||
// see if the existing client is destroyed.
|
||||
ALOGI("HwcHal::createClient: Client already exists. Waiting for"
|
||||
" it to be destroyed.");
|
||||
mClientDestroyedWait.wait_for(lock, 1s,
|
||||
[this] { return mClient == nullptr; });
|
||||
std::string doneMsg = mClient == nullptr ?
|
||||
"Existing client was destroyed." :
|
||||
"Existing client was never destroyed!";
|
||||
ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
|
||||
}
|
||||
|
||||
// only one client is allowed
|
||||
if (mClient == nullptr) {
|
||||
client = new ComposerClient(*this);
|
||||
client->initialize();
|
||||
mClient = client;
|
||||
} else {
|
||||
err = Error::NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
hidl_cb(err, client);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
sp<ComposerClient> HwcHal::getClient()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mClientMutex);
|
||||
return (mClient != nullptr) ? mClient.promote() : nullptr;
|
||||
}
|
||||
|
||||
void HwcHal::removeClient()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mClientMutex);
|
||||
mClient = nullptr;
|
||||
mClientDestroyedWait.notify_all();
|
||||
}
|
||||
|
||||
void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
|
||||
hwc2_display_t display, int32_t connected)
|
||||
{
|
||||
auto hal = reinterpret_cast<HwcHal*>(callbackData);
|
||||
auto client = hal->getClient();
|
||||
if (client != nullptr) {
|
||||
client->onHotplug(display,
|
||||
static_cast<IComposerCallback::Connection>(connected));
|
||||
}
|
||||
}
|
||||
|
||||
void HwcHal::refreshHook(hwc2_callback_data_t callbackData,
|
||||
hwc2_display_t display)
|
||||
{
|
||||
auto hal = reinterpret_cast<HwcHal*>(callbackData);
|
||||
auto client = hal->getClient();
|
||||
if (client != nullptr) {
|
||||
client->onRefresh(display);
|
||||
}
|
||||
}
|
||||
|
||||
void HwcHal::vsyncHook(hwc2_callback_data_t callbackData,
|
||||
hwc2_display_t display, int64_t timestamp)
|
||||
{
|
||||
auto hal = reinterpret_cast<HwcHal*>(callbackData);
|
||||
auto client = hal->getClient();
|
||||
if (client != nullptr) {
|
||||
client->onVsync(display, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void HwcHal::enableCallback(bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
|
||||
reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
|
||||
mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
|
||||
reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
|
||||
mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
|
||||
reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
|
||||
} else {
|
||||
mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
|
||||
nullptr);
|
||||
mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
|
||||
nullptr);
|
||||
mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
|
||||
nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HwcHal::getMaxVirtualDisplayCount()
|
||||
{
|
||||
return mDispatch.getMaxVirtualDisplayCount(mDevice);
|
||||
}
|
||||
|
||||
Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat* format, Display* outDisplay)
|
||||
{
|
||||
int32_t hwc_format = static_cast<int32_t>(*format);
|
||||
int32_t err = mDispatch.createVirtualDisplay(mDevice, width, height,
|
||||
&hwc_format, outDisplay);
|
||||
*format = static_cast<PixelFormat>(hwc_format);
|
||||
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::destroyVirtualDisplay(Display display)
|
||||
{
|
||||
int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::createLayer(Display display, Layer* outLayer)
|
||||
{
|
||||
int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::destroyLayer(Display display, Layer layer)
|
||||
{
|
||||
int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::getActiveConfig(Display display, Config* outConfig)
|
||||
{
|
||||
int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace)
|
||||
{
|
||||
int32_t err = mDispatch.getClientTargetSupport(mDevice, display,
|
||||
width, height, static_cast<int32_t>(format),
|
||||
static_cast<int32_t>(dataspace));
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::getColorModes(Display display, hidl_vec<ColorMode>* outModes)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
outModes->resize(count);
|
||||
err = mDispatch.getColorModes(mDevice, display, &count,
|
||||
reinterpret_cast<std::underlying_type<ColorMode>::type*>(
|
||||
outModes->data()));
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
*outModes = hidl_vec<ColorMode>();
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error HwcHal::getDisplayAttribute(Display display, Config config,
|
||||
IComposerClient::Attribute attribute, int32_t* outValue)
|
||||
{
|
||||
int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
|
||||
static_cast<int32_t>(attribute), outValue);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
int32_t err = mDispatch.getDisplayConfigs(mDevice, display,
|
||||
&count, nullptr);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
outConfigs->resize(count);
|
||||
err = mDispatch.getDisplayConfigs(mDevice, display,
|
||||
&count, outConfigs->data());
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
*outConfigs = hidl_vec<Config>();
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error HwcHal::getDisplayName(Display display, hidl_string* outName)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
std::vector<char> buf(count + 1);
|
||||
err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
buf.resize(count + 1);
|
||||
buf[count] = '\0';
|
||||
|
||||
*outName = buf.data();
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error HwcHal::getDisplayType(Display display,
|
||||
IComposerClient::DisplayType* outType)
|
||||
{
|
||||
int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
|
||||
int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
|
||||
*outType = static_cast<IComposerClient::DisplayType>(hwc_type);
|
||||
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::getDozeSupport(Display display, bool* outSupport)
|
||||
{
|
||||
int32_t hwc_support = 0;
|
||||
int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
|
||||
*outSupport = hwc_support;
|
||||
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
|
||||
float* outMaxLuminance, float* outMaxAverageLuminance,
|
||||
float* outMinLuminance)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
int32_t err = mDispatch.getHdrCapabilities(mDevice, display, &count,
|
||||
nullptr, outMaxLuminance, outMaxAverageLuminance,
|
||||
outMinLuminance);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
outTypes->resize(count);
|
||||
err = mDispatch.getHdrCapabilities(mDevice, display, &count,
|
||||
reinterpret_cast<std::underlying_type<Hdr>::type*>(
|
||||
outTypes->data()), outMaxLuminance,
|
||||
outMaxAverageLuminance, outMinLuminance);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
*outTypes = hidl_vec<Hdr>();
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error HwcHal::setActiveConfig(Display display, Config config)
|
||||
{
|
||||
int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setColorMode(Display display, ColorMode mode)
|
||||
{
|
||||
int32_t err = mDispatch.setColorMode(mDevice, display,
|
||||
static_cast<int32_t>(mode));
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode)
|
||||
{
|
||||
int32_t err = mDispatch.setPowerMode(mDevice, display,
|
||||
static_cast<int32_t>(mode));
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
|
||||
{
|
||||
int32_t err = mDispatch.setVsyncEnabled(mDevice, display,
|
||||
static_cast<int32_t>(enabled));
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setColorTransform(Display display, const float* matrix,
|
||||
int32_t hint)
|
||||
{
|
||||
int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setClientTarget(Display display, buffer_handle_t target,
|
||||
int32_t acquireFence, int32_t dataspace,
|
||||
const std::vector<hwc_rect_t>& damage)
|
||||
{
|
||||
hwc_region region = { damage.size(), damage.data() };
|
||||
int32_t err = mDispatch.setClientTarget(mDevice, display, target,
|
||||
acquireFence, dataspace, region);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer,
|
||||
int32_t releaseFence)
|
||||
{
|
||||
int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer,
|
||||
releaseFence);
|
||||
// unlike in setClientTarget, releaseFence is owned by us
|
||||
if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
|
||||
close(releaseFence);
|
||||
}
|
||||
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::validateDisplay(Display display,
|
||||
std::vector<Layer>* outChangedLayers,
|
||||
std::vector<IComposerClient::Composition>* outCompositionTypes,
|
||||
uint32_t* outDisplayRequestMask,
|
||||
std::vector<Layer>* outRequestedLayers,
|
||||
std::vector<uint32_t>* outRequestMasks)
|
||||
{
|
||||
uint32_t types_count = 0;
|
||||
uint32_t reqs_count = 0;
|
||||
int32_t err = mDispatch.validateDisplay(mDevice, display,
|
||||
&types_count, &reqs_count);
|
||||
if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
err = mDispatch.getChangedCompositionTypes(mDevice, display,
|
||||
&types_count, nullptr, nullptr);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
outChangedLayers->resize(types_count);
|
||||
outCompositionTypes->resize(types_count);
|
||||
err = mDispatch.getChangedCompositionTypes(mDevice, display,
|
||||
&types_count, outChangedLayers->data(),
|
||||
reinterpret_cast<
|
||||
std::underlying_type<IComposerClient::Composition>::type*>(
|
||||
outCompositionTypes->data()));
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
outChangedLayers->clear();
|
||||
outCompositionTypes->clear();
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
int32_t display_reqs = 0;
|
||||
err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
|
||||
&reqs_count, nullptr, nullptr);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
outChangedLayers->clear();
|
||||
outCompositionTypes->clear();
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
outRequestedLayers->resize(reqs_count);
|
||||
outRequestMasks->resize(reqs_count);
|
||||
err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
|
||||
&reqs_count, outRequestedLayers->data(),
|
||||
reinterpret_cast<int32_t*>(outRequestMasks->data()));
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
outChangedLayers->clear();
|
||||
outCompositionTypes->clear();
|
||||
|
||||
outRequestedLayers->clear();
|
||||
outRequestMasks->clear();
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
*outDisplayRequestMask = display_reqs;
|
||||
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::acceptDisplayChanges(Display display)
|
||||
{
|
||||
int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::presentDisplay(Display display, int32_t* outPresentFence,
|
||||
std::vector<Layer>* outLayers, std::vector<int32_t>* outReleaseFences)
|
||||
{
|
||||
*outPresentFence = -1;
|
||||
int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
uint32_t count = 0;
|
||||
err = mDispatch.getReleaseFences(mDevice, display, &count,
|
||||
nullptr, nullptr);
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
ALOGW("failed to get release fences");
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
outLayers->resize(count);
|
||||
outReleaseFences->resize(count);
|
||||
err = mDispatch.getReleaseFences(mDevice, display, &count,
|
||||
outLayers->data(), outReleaseFences->data());
|
||||
if (err != HWC2_ERROR_NONE) {
|
||||
ALOGW("failed to get release fences");
|
||||
outLayers->clear();
|
||||
outReleaseFences->clear();
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerCursorPosition(Display display, Layer layer,
|
||||
int32_t x, int32_t y)
|
||||
{
|
||||
int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerBuffer(Display display, Layer layer,
|
||||
buffer_handle_t buffer, int32_t acquireFence)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer,
|
||||
buffer, acquireFence);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& damage)
|
||||
{
|
||||
hwc_region region = { damage.size(), damage.data() };
|
||||
int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer,
|
||||
region);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerColor(Display display, Layer layer,
|
||||
IComposerClient::Color color)
|
||||
{
|
||||
hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
|
||||
int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerCompositionType(Display display, Layer layer,
|
||||
int32_t type)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer,
|
||||
type);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerDataspace(Display display, Layer layer,
|
||||
int32_t dataspace)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer,
|
||||
dataspace);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerDisplayFrame(Display display, Layer layer,
|
||||
const hwc_rect_t& frame)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer,
|
||||
frame);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer,
|
||||
alpha);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerSidebandStream(Display display, Layer layer,
|
||||
buffer_handle_t stream)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer,
|
||||
stream);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerSourceCrop(Display display, Layer layer,
|
||||
const hwc_frect_t& crop)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerTransform(Display display, Layer layer,
|
||||
int32_t transform)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerTransform(mDevice, display, layer,
|
||||
transform);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerVisibleRegion(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& visible)
|
||||
{
|
||||
hwc_region_t region = { visible.size(), visible.data() };
|
||||
int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer,
|
||||
region);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z)
|
||||
{
|
||||
int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
Return<Error> HwcHal::setDisplayArg(int32_t disp, int32_t cmd1, int32_t cmd2, int32_t data)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = mDispatch.sunxisetdisplay(disp, cmd1, cmd2, data);
|
||||
return static_cast<Error>(err);
|
||||
}
|
||||
|
||||
IComposer* HIDL_FETCH_IComposer(const char*)
|
||||
{
|
||||
const hw_module_t* module = nullptr;
|
||||
int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
|
||||
if (err) {
|
||||
ALOGE("failed to get hwcomposer module");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new HwcHal(module);
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
235
android/hardware/interfaces/graphics/composer/2.1/default/Hwc.h
Executable file
235
android/hardware/interfaces/graphics/composer/2.1/default/Hwc.h
Executable file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* 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_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposer.h>
|
||||
#define HWC2_INCLUDE_STRINGIFICATION
|
||||
#define HWC2_USE_CPP11
|
||||
#include <hardware/hwcomposer2.h>
|
||||
#undef HWC2_INCLUDE_STRINGIFICATION
|
||||
#undef HWC2_USE_CPP11
|
||||
#include "ComposerBase.h"
|
||||
|
||||
namespace android {
|
||||
class HWC2On1Adapter;
|
||||
}
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
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 ComposerClient;
|
||||
|
||||
class HwcHal : public IComposer, public ComposerBase {
|
||||
public:
|
||||
HwcHal(const hw_module_t* module);
|
||||
virtual ~HwcHal();
|
||||
|
||||
bool hasCapability(Capability capability) const;
|
||||
|
||||
// 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;
|
||||
Return<Error> setDisplayArg(int32_t disp, int32_t cmd1, int32_t cmd2, int32_t data) override;
|
||||
|
||||
// ComposerBase interface
|
||||
void removeClient() override;
|
||||
void enableCallback(bool enable) override;
|
||||
uint32_t getMaxVirtualDisplayCount() override;
|
||||
Error createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat* format, Display* outDisplay) override;
|
||||
Error destroyVirtualDisplay(Display display) override;
|
||||
|
||||
Error createLayer(Display display, Layer* outLayer) override;
|
||||
Error destroyLayer(Display display, Layer layer) override;
|
||||
|
||||
Error getActiveConfig(Display display, Config* outConfig) override;
|
||||
Error getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace) override;
|
||||
Error getColorModes(Display display,
|
||||
hidl_vec<ColorMode>* outModes) override;
|
||||
Error getDisplayAttribute(Display display, Config config,
|
||||
IComposerClient::Attribute attribute, int32_t* outValue) override;
|
||||
Error getDisplayConfigs(Display display,
|
||||
hidl_vec<Config>* outConfigs) override;
|
||||
Error getDisplayName(Display display, hidl_string* outName) override;
|
||||
Error getDisplayType(Display display,
|
||||
IComposerClient::DisplayType* outType) override;
|
||||
Error getDozeSupport(Display display, bool* outSupport) override;
|
||||
Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
|
||||
float* outMaxLuminance, float* outMaxAverageLuminance,
|
||||
float* outMinLuminance) override;
|
||||
|
||||
Error setActiveConfig(Display display, Config config) override;
|
||||
Error setColorMode(Display display, ColorMode mode) override;
|
||||
Error setPowerMode(Display display,
|
||||
IComposerClient::PowerMode mode) override;
|
||||
Error setVsyncEnabled(Display display,
|
||||
IComposerClient::Vsync enabled) override;
|
||||
|
||||
Error setColorTransform(Display display, const float* matrix,
|
||||
int32_t hint) override;
|
||||
Error setClientTarget(Display display, buffer_handle_t target,
|
||||
int32_t acquireFence, int32_t dataspace,
|
||||
const std::vector<hwc_rect_t>& damage) override;
|
||||
Error setOutputBuffer(Display display, buffer_handle_t buffer,
|
||||
int32_t releaseFence) override;
|
||||
Error validateDisplay(Display display,
|
||||
std::vector<Layer>* outChangedLayers,
|
||||
std::vector<IComposerClient::Composition>* outCompositionTypes,
|
||||
uint32_t* outDisplayRequestMask,
|
||||
std::vector<Layer>* outRequestedLayers,
|
||||
std::vector<uint32_t>* outRequestMasks) override;
|
||||
Error acceptDisplayChanges(Display display) override;
|
||||
Error presentDisplay(Display display, int32_t* outPresentFence,
|
||||
std::vector<Layer>* outLayers,
|
||||
std::vector<int32_t>* outReleaseFences) override;
|
||||
|
||||
Error setLayerCursorPosition(Display display, Layer layer,
|
||||
int32_t x, int32_t y) override;
|
||||
Error setLayerBuffer(Display display, Layer layer,
|
||||
buffer_handle_t buffer, int32_t acquireFence) override;
|
||||
Error setLayerSurfaceDamage(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& damage) override;
|
||||
Error setLayerBlendMode(Display display, Layer layer,
|
||||
int32_t mode) override;
|
||||
Error setLayerColor(Display display, Layer layer,
|
||||
IComposerClient::Color color) override;
|
||||
Error setLayerCompositionType(Display display, Layer layer,
|
||||
int32_t type) override;
|
||||
Error setLayerDataspace(Display display, Layer layer,
|
||||
int32_t dataspace) override;
|
||||
Error setLayerDisplayFrame(Display display, Layer layer,
|
||||
const hwc_rect_t& frame) override;
|
||||
Error setLayerPlaneAlpha(Display display, Layer layer,
|
||||
float alpha) override;
|
||||
Error setLayerSidebandStream(Display display, Layer layer,
|
||||
buffer_handle_t stream) override;
|
||||
Error setLayerSourceCrop(Display display, Layer layer,
|
||||
const hwc_frect_t& crop) override;
|
||||
Error setLayerTransform(Display display, Layer layer,
|
||||
int32_t transform) override;
|
||||
Error setLayerVisibleRegion(Display display, Layer layer,
|
||||
const std::vector<hwc_rect_t>& visible) override;
|
||||
Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
|
||||
|
||||
private:
|
||||
void initCapabilities();
|
||||
|
||||
template<typename T>
|
||||
void initDispatch(hwc2_function_descriptor_t desc, T* outPfn);
|
||||
void initDispatch();
|
||||
|
||||
sp<ComposerClient> 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;
|
||||
typedef int (*SUNXI_SET_DISPLY_COMMAND)(int display, int cmd1, int cmd2, int data);
|
||||
|
||||
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;
|
||||
SUNXI_SET_DISPLY_COMMAND sunxisetdisplay;
|
||||
} mDispatch;
|
||||
|
||||
std::mutex mClientMutex;
|
||||
std::condition_variable mClientDestroyedWait;
|
||||
wp<ComposerClient> mClient;
|
||||
|
||||
// If the HWC implementation version is < 2.0, use an adapter to interface
|
||||
// between HWC 2.0 <-> HWC 1.X.
|
||||
std::unique_ptr<HWC2On1Adapter> mAdapter;
|
||||
};
|
||||
|
||||
extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
|
|
@ -0,0 +1,881 @@
|
|||
/*
|
||||
* 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 <fmq/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 CommandWriterBase {
|
||||
public:
|
||||
CommandWriterBase(uint32_t initialMaxSize)
|
||||
: mDataMaxSize(initialMaxSize)
|
||||
{
|
||||
mData = std::make_unique<uint32_t[]>(mDataMaxSize);
|
||||
reset();
|
||||
}
|
||||
|
||||
virtual ~CommandWriterBase()
|
||||
{
|
||||
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* outQueueChanged, uint32_t* outCommandLength,
|
||||
hidl_vec<hidl_handle>* outCommandHandles)
|
||||
{
|
||||
// After data are written to the queue, it may not be read by the
|
||||
// remote reader when
|
||||
//
|
||||
// - the writer does not send them (because of other errors)
|
||||
// - the hwbinder transaction fails
|
||||
// - the reader does not read them (because of other errors)
|
||||
//
|
||||
// Discard the stale data here.
|
||||
size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
|
||||
if (staleDataSize > 0) {
|
||||
ALOGW("discarding stale data from message queue");
|
||||
CommandQueueType::MemTransaction tx;
|
||||
if (mQueue->beginRead(staleDataSize, &tx)) {
|
||||
mQueue->commitRead(staleDataSize);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
*outQueueChanged = 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);
|
||||
*outQueueChanged = true;
|
||||
}
|
||||
|
||||
*outCommandLength = mDataWritten;
|
||||
outCommandHandles->setToExternal(
|
||||
const_cast<hidl_handle*>(mDataHandles.data()),
|
||||
mDataHandles.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const MQDescriptorSync<uint32_t>* 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();
|
||||
}
|
||||
|
||||
static constexpr uint32_t kPresentOrValidateDisplayResultLength = 1;
|
||||
void setPresentOrValidateResult(uint32_t state) {
|
||||
beginCommand(IComposerClient::Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT, kPresentOrValidateDisplayResultLength);
|
||||
write(state);
|
||||
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 kPresentOrValidateDisplayLength = 0;
|
||||
void presentOrvalidateDisplay()
|
||||
{
|
||||
beginCommand(IComposerClient::Command::PRESENT_OR_VALIDATE_DISPLAY,
|
||||
kPresentOrValidateDisplayLength);
|
||||
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<uint32_t>& 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* outCommand,
|
||||
uint16_t* outLength)
|
||||
{
|
||||
if (mCommandEnd) {
|
||||
LOG_FATAL("endCommand was not called for last 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();
|
||||
*outCommand = static_cast<IComposerClient::Command>(
|
||||
val & opcode_mask);
|
||||
*outLength = static_cast<uint16_t>(val & length_mask);
|
||||
|
||||
if (mDataRead + *outLength > mDataSize) {
|
||||
ALOGE("command 0x%x has invalid command length %" PRIu16,
|
||||
*outCommand, *outLength);
|
||||
// undo the read() above
|
||||
mDataRead--;
|
||||
return false;
|
||||
}
|
||||
|
||||
mCommandEnd = mDataRead + *outLength;
|
||||
|
||||
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* outUseCache)
|
||||
{
|
||||
const native_handle_t* handle = nullptr;
|
||||
|
||||
int32_t index = readSigned();
|
||||
switch (index) {
|
||||
case static_cast<int32_t>(IComposerClient::HandleIndex::EMPTY):
|
||||
*outUseCache = false;
|
||||
break;
|
||||
case static_cast<int32_t>(IComposerClient::HandleIndex::CACHED):
|
||||
*outUseCache = 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));
|
||||
}
|
||||
*outUseCache = 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
|
|
@ -0,0 +1,6 @@
|
|||
service hwcomposer-2-1 /vendor/bin/hw/android.hardware.graphics.composer@2.1-service
|
||||
class hal animation
|
||||
user system
|
||||
group graphics drmrpc
|
||||
capabilities SYS_NICE
|
||||
onrestart restart surfaceflinger
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "android.hardware.graphics.composer@2.1-service"
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposer.h>
|
||||
|
||||
#include <binder/ProcessState.h>
|
||||
#include <hidl/LegacySupport.h>
|
||||
|
||||
using android::hardware::graphics::composer::V2_1::IComposer;
|
||||
using android::hardware::defaultPassthroughServiceImplementation;
|
||||
|
||||
int main() {
|
||||
// the conventional HAL might start binder services
|
||||
android::ProcessState::initWithDriver("/dev/vndbinder");
|
||||
android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
|
||||
android::ProcessState::self()->startThreadPool();
|
||||
|
||||
// same as SF main thread
|
||||
struct sched_param param = {0};
|
||||
param.sched_priority = 2;
|
||||
if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK,
|
||||
¶m) != 0) {
|
||||
ALOGE("Couldn't set SCHED_FIFO: %d", errno);
|
||||
}
|
||||
|
||||
return defaultPassthroughServiceImplementation<IComposer>(4);
|
||||
}
|
34
android/hardware/interfaces/graphics/composer/2.1/types.hal
Normal file
34
android/hardware/interfaces/graphics/composer/2.1/types.hal
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package android.hardware.graphics.composer@2.1;
|
||||
|
||||
/** Return codes from all functions. */
|
||||
enum Error : int32_t {
|
||||
NONE = 0, /** no error */
|
||||
BAD_CONFIG = 1, /** invalid Config */
|
||||
BAD_DISPLAY = 2, /** invalid Display */
|
||||
BAD_LAYER = 3, /** invalid Layer */
|
||||
BAD_PARAMETER = 4, /** invalid width, height, etc. */
|
||||
/** 5 is reserved */
|
||||
NO_RESOURCES = 6, /** temporary failure due to resource contention */
|
||||
NOT_VALIDATED = 7, /** validateDisplay has not been called */
|
||||
UNSUPPORTED = 8, /** permanent failure */
|
||||
};
|
||||
|
||||
typedef uint32_t Config;
|
||||
typedef uint64_t Display;
|
||||
typedef uint64_t Layer;
|
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// Copyright (C) 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.
|
||||
//
|
||||
|
||||
cc_library_static {
|
||||
name: "libVtsHalGraphicsComposerTestUtils",
|
||||
defaults: ["hidl_defaults"],
|
||||
srcs: [
|
||||
"GraphicsComposerCallback.cpp",
|
||||
"TestCommandReader.cpp",
|
||||
"VtsHalGraphicsComposerTestUtils.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"libfmq",
|
||||
"libsync",
|
||||
],
|
||||
static_libs: [
|
||||
"libhwcomposer-command-buffer",
|
||||
"VtsHalHidlTargetTestBase",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-O0",
|
||||
"-g",
|
||||
"-DLOG_TAG=\"GraphicsComposerTestUtils\"",
|
||||
],
|
||||
export_include_dirs: ["."],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalGraphicsComposerV2_1TargetTest",
|
||||
defaults: ["VtsHalTargetTestDefaults"],
|
||||
srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
|
||||
|
||||
// TODO(b/64437680): Assume these libs are always available on the device.
|
||||
shared_libs: [
|
||||
"libfmq",
|
||||
"libsync",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.graphics.allocator@2.0",
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"libVtsHalGraphicsComposerTestUtils",
|
||||
"libVtsHalGraphicsMapperTestUtils",
|
||||
"libhwcomposer-command-buffer",
|
||||
"libnativehelper",
|
||||
],
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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 "GraphicsComposerCallback.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
|
||||
void GraphicsComposerCallback::setVsyncAllowed(bool allowed) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
mVsyncAllowed = allowed;
|
||||
}
|
||||
|
||||
std::vector<Display> GraphicsComposerCallback::getDisplays() const {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return std::vector<Display>(mDisplays.begin(), mDisplays.end());
|
||||
}
|
||||
|
||||
int GraphicsComposerCallback::getInvalidHotplugCount() const {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mInvalidHotplugCount;
|
||||
}
|
||||
|
||||
int GraphicsComposerCallback::getInvalidRefreshCount() const {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mInvalidRefreshCount;
|
||||
}
|
||||
|
||||
int GraphicsComposerCallback::getInvalidVsyncCount() const {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
return mInvalidVsyncCount;
|
||||
}
|
||||
|
||||
Return<void> GraphicsComposerCallback::onHotplug(Display display,
|
||||
Connection connection) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
if (connection == Connection::CONNECTED) {
|
||||
if (!mDisplays.insert(display).second) {
|
||||
mInvalidHotplugCount++;
|
||||
}
|
||||
} else if (connection == Connection::DISCONNECTED) {
|
||||
if (!mDisplays.erase(display)) {
|
||||
mInvalidHotplugCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> GraphicsComposerCallback::onRefresh(Display display) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
if (mDisplays.count(display) == 0) {
|
||||
mInvalidRefreshCount++;
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> GraphicsComposerCallback::onVsync(Display display, int64_t) {
|
||||
std::lock_guard<std::mutex> lock(mMutex);
|
||||
|
||||
if (!mVsyncAllowed || mDisplays.count(display) == 0) {
|
||||
mInvalidVsyncCount++;
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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 GRAPHICS_COMPOSER_CALLBACK_H
|
||||
#define GRAPHICS_COMPOSER_CALLBACK_H
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposerCallback.h>
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
|
||||
// IComposerCallback to be installed with IComposerClient::registerCallback.
|
||||
class GraphicsComposerCallback : public IComposerCallback {
|
||||
public:
|
||||
void setVsyncAllowed(bool allowed);
|
||||
|
||||
std::vector<Display> getDisplays() const;
|
||||
|
||||
int getInvalidHotplugCount() const;
|
||||
|
||||
int getInvalidRefreshCount() const;
|
||||
|
||||
int getInvalidVsyncCount() const;
|
||||
|
||||
private:
|
||||
Return<void> onHotplug(Display display, Connection connection) override;
|
||||
Return<void> onRefresh(Display display) override;
|
||||
Return<void> onVsync(Display display, int64_t) override;
|
||||
|
||||
mutable std::mutex mMutex;
|
||||
// the set of all currently connected displays
|
||||
std::unordered_set<Display> mDisplays;
|
||||
// true only when vsync is enabled
|
||||
bool mVsyncAllowed = true;
|
||||
|
||||
// track invalid callbacks
|
||||
int mInvalidHotplugCount = 0;
|
||||
int mInvalidRefreshCount = 0;
|
||||
int mInvalidVsyncCount = 0;
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // GRAPHICS_COMPOSER_CALLBACK_H
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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 "TestCommandReader.h"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
|
||||
void TestCommandReader::parse() {
|
||||
while (!isEmpty()) {
|
||||
IComposerClient::Command command;
|
||||
uint16_t length;
|
||||
ASSERT_TRUE(beginCommand(&command, &length));
|
||||
|
||||
switch (command) {
|
||||
case IComposerClient::Command::SET_ERROR: {
|
||||
ASSERT_EQ(2, length);
|
||||
auto loc = read();
|
||||
auto err = readSigned();
|
||||
GTEST_FAIL() << "unexpected error " << err << " at location " << loc;
|
||||
} break;
|
||||
case IComposerClient::Command::SELECT_DISPLAY:
|
||||
case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
|
||||
case IComposerClient::Command::SET_DISPLAY_REQUESTS:
|
||||
case IComposerClient::Command::SET_PRESENT_FENCE:
|
||||
case IComposerClient::Command::SET_RELEASE_FENCES:
|
||||
break;
|
||||
default:
|
||||
GTEST_FAIL() << "unexpected return command " << std::hex
|
||||
<< static_cast<int>(command);
|
||||
break;
|
||||
}
|
||||
|
||||
endCommand();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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 TEST_COMMAND_READER_H
|
||||
#define TEST_COMMAND_READER_H
|
||||
|
||||
#include <IComposerCommandBuffer.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
|
||||
// A command parser that checks that no error nor unexpected commands are
|
||||
// returned.
|
||||
class TestCommandReader : public CommandReaderBase {
|
||||
public:
|
||||
// Parse all commands in the return command queue. Call GTEST_FAIL() for
|
||||
// unexpected errors or commands.
|
||||
void parse();
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // TEST_COMMAND_READER_H
|
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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 <VtsHalHidlTargetTestBase.h>
|
||||
|
||||
#include "VtsHalGraphicsComposerTestUtils.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
|
||||
Composer::Composer() {
|
||||
mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>();
|
||||
init();
|
||||
}
|
||||
|
||||
Composer::Composer(const std::string& name) {
|
||||
mComposer = ::testing::VtsHalHidlTargetTestBase::getService<IComposer>(name);
|
||||
init();
|
||||
}
|
||||
|
||||
void Composer::init() {
|
||||
ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service";
|
||||
|
||||
std::vector<IComposer::Capability> capabilities = getCapabilities();
|
||||
mCapabilities.insert(capabilities.begin(), capabilities.end());
|
||||
}
|
||||
|
||||
sp<IComposer> Composer::getRaw() const { return mComposer; }
|
||||
|
||||
bool Composer::hasCapability(IComposer::Capability capability) const {
|
||||
return mCapabilities.count(capability) > 0;
|
||||
}
|
||||
|
||||
std::vector<IComposer::Capability> Composer::getCapabilities() {
|
||||
std::vector<IComposer::Capability> capabilities;
|
||||
mComposer->getCapabilities(
|
||||
[&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; });
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
std::string Composer::dumpDebugInfo() {
|
||||
std::string debugInfo;
|
||||
mComposer->dumpDebugInfo(
|
||||
[&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
|
||||
|
||||
return debugInfo;
|
||||
}
|
||||
|
||||
std::unique_ptr<ComposerClient> Composer::createClient() {
|
||||
std::unique_ptr<ComposerClient> client;
|
||||
mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
|
||||
client = std::make_unique<ComposerClient>(tmpClient);
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
ComposerClient::ComposerClient(const sp<IComposerClient>& client)
|
||||
: mClient(client) {}
|
||||
|
||||
ComposerClient::~ComposerClient() {
|
||||
for (auto it : mDisplayResources) {
|
||||
Display display = it.first;
|
||||
DisplayResource& resource = it.second;
|
||||
|
||||
for (auto layer : resource.layers) {
|
||||
EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer))
|
||||
<< "failed to destroy layer " << layer;
|
||||
}
|
||||
|
||||
if (resource.isVirtual) {
|
||||
EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display))
|
||||
<< "failed to destroy virtual display " << display;
|
||||
}
|
||||
}
|
||||
mDisplayResources.clear();
|
||||
}
|
||||
|
||||
sp<IComposerClient> ComposerClient::getRaw() const { return mClient; }
|
||||
|
||||
void ComposerClient::registerCallback(const sp<IComposerCallback>& callback) {
|
||||
mClient->registerCallback(callback);
|
||||
}
|
||||
|
||||
uint32_t ComposerClient::getMaxVirtualDisplayCount() {
|
||||
return mClient->getMaxVirtualDisplayCount();
|
||||
}
|
||||
|
||||
Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat formatHint,
|
||||
uint32_t outputBufferSlotCount,
|
||||
PixelFormat* outFormat) {
|
||||
Display display = 0;
|
||||
mClient->createVirtualDisplay(
|
||||
width, height, formatHint, outputBufferSlotCount,
|
||||
[&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display";
|
||||
display = tmpDisplay;
|
||||
*outFormat = tmpFormat;
|
||||
|
||||
ASSERT_TRUE(
|
||||
mDisplayResources.insert({display, DisplayResource(true)}).second)
|
||||
<< "duplicated virtual display id " << display;
|
||||
});
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void ComposerClient::destroyVirtualDisplay(Display display) {
|
||||
Error error = mClient->destroyVirtualDisplay(display);
|
||||
ASSERT_EQ(Error::NONE, error)
|
||||
<< "failed to destroy virtual display " << display;
|
||||
|
||||
mDisplayResources.erase(display);
|
||||
}
|
||||
|
||||
Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) {
|
||||
Layer layer = 0;
|
||||
mClient->createLayer(
|
||||
display, bufferSlotCount,
|
||||
[&](const auto& tmpError, const auto& tmpLayer) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer";
|
||||
layer = tmpLayer;
|
||||
|
||||
auto resourceIt = mDisplayResources.find(display);
|
||||
if (resourceIt == mDisplayResources.end()) {
|
||||
resourceIt =
|
||||
mDisplayResources.insert({display, DisplayResource(false)}).first;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(resourceIt->second.layers.insert(layer).second)
|
||||
<< "duplicated layer id " << layer;
|
||||
});
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
void ComposerClient::destroyLayer(Display display, Layer layer) {
|
||||
Error error = mClient->destroyLayer(display, layer);
|
||||
ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer;
|
||||
|
||||
auto resourceIt = mDisplayResources.find(display);
|
||||
ASSERT_NE(mDisplayResources.end(), resourceIt);
|
||||
resourceIt->second.layers.erase(layer);
|
||||
}
|
||||
|
||||
Config ComposerClient::getActiveConfig(Display display) {
|
||||
Config config = 0;
|
||||
mClient->getActiveConfig(
|
||||
display, [&](const auto& tmpError, const auto& tmpConfig) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config";
|
||||
config = tmpConfig;
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
bool ComposerClient::getClientTargetSupport(Display display, uint32_t width,
|
||||
uint32_t height, PixelFormat format,
|
||||
Dataspace dataspace) {
|
||||
Error error = mClient->getClientTargetSupport(display, width, height, format,
|
||||
dataspace);
|
||||
return error == Error::NONE;
|
||||
}
|
||||
|
||||
std::vector<ColorMode> ComposerClient::getColorModes(Display display) {
|
||||
std::vector<ColorMode> modes;
|
||||
mClient->getColorModes(
|
||||
display, [&](const auto& tmpError, const auto& tmpMode) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode";
|
||||
modes = tmpMode;
|
||||
});
|
||||
|
||||
return modes;
|
||||
}
|
||||
|
||||
int32_t ComposerClient::getDisplayAttribute(
|
||||
Display display, Config config, IComposerClient::Attribute attribute) {
|
||||
int32_t value = 0;
|
||||
mClient->getDisplayAttribute(display, config, attribute,
|
||||
[&](const auto& tmpError, const auto& tmpValue) {
|
||||
ASSERT_EQ(Error::NONE, tmpError)
|
||||
<< "failed to get display attribute";
|
||||
value = tmpValue;
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<Config> ComposerClient::getDisplayConfigs(Display display) {
|
||||
std::vector<Config> configs;
|
||||
mClient->getDisplayConfigs(
|
||||
display, [&](const auto& tmpError, const auto& tmpConfigs) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs";
|
||||
configs = tmpConfigs;
|
||||
});
|
||||
|
||||
return configs;
|
||||
}
|
||||
|
||||
std::string ComposerClient::getDisplayName(Display display) {
|
||||
std::string name;
|
||||
mClient->getDisplayName(
|
||||
display, [&](const auto& tmpError, const auto& tmpName) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name";
|
||||
name = tmpName.c_str();
|
||||
});
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) {
|
||||
IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
|
||||
mClient->getDisplayType(
|
||||
display, [&](const auto& tmpError, const auto& tmpType) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type";
|
||||
type = tmpType;
|
||||
});
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
bool ComposerClient::getDozeSupport(Display display) {
|
||||
bool support = false;
|
||||
mClient->getDozeSupport(
|
||||
display, [&](const auto& tmpError, const auto& tmpSupport) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support";
|
||||
support = tmpSupport;
|
||||
});
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
std::vector<Hdr> ComposerClient::getHdrCapabilities(
|
||||
Display display, float* outMaxLuminance, float* outMaxAverageLuminance,
|
||||
float* outMinLuminance) {
|
||||
std::vector<Hdr> types;
|
||||
mClient->getHdrCapabilities(
|
||||
display,
|
||||
[&](const auto& tmpError, const auto& tmpTypes,
|
||||
const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance,
|
||||
const auto& tmpMinLuminance) {
|
||||
ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities";
|
||||
types = tmpTypes;
|
||||
*outMaxLuminance = tmpMaxLuminance;
|
||||
*outMaxAverageLuminance = tmpMaxAverageLuminance;
|
||||
*outMinLuminance = tmpMinLuminance;
|
||||
});
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
void ComposerClient::setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount) {
|
||||
Error error =
|
||||
mClient->setClientTargetSlotCount(display, clientTargetSlotCount);
|
||||
ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count";
|
||||
}
|
||||
|
||||
void ComposerClient::setActiveConfig(Display display, Config config) {
|
||||
Error error = mClient->setActiveConfig(display, config);
|
||||
ASSERT_EQ(Error::NONE, error) << "failed to set active config";
|
||||
}
|
||||
|
||||
void ComposerClient::setColorMode(Display display, ColorMode mode) {
|
||||
Error error = mClient->setColorMode(display, mode);
|
||||
ASSERT_EQ(Error::NONE, error) << "failed to set color mode";
|
||||
}
|
||||
|
||||
void ComposerClient::setPowerMode(Display display,
|
||||
IComposerClient::PowerMode mode) {
|
||||
Error error = mClient->setPowerMode(display, mode);
|
||||
ASSERT_EQ(Error::NONE, error) << "failed to set power mode";
|
||||
}
|
||||
|
||||
void ComposerClient::setVsyncEnabled(Display display, bool enabled) {
|
||||
IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE
|
||||
: IComposerClient::Vsync::DISABLE;
|
||||
Error error = mClient->setVsyncEnabled(display, vsync);
|
||||
ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode";
|
||||
|
||||
// give the hwbinder thread some time to handle any pending vsync callback
|
||||
if (!enabled) {
|
||||
usleep(5 * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void ComposerClient::execute(TestCommandReader* reader,
|
||||
CommandWriterBase* writer) {
|
||||
bool queueChanged = false;
|
||||
uint32_t commandLength = 0;
|
||||
hidl_vec<hidl_handle> commandHandles;
|
||||
ASSERT_TRUE(
|
||||
writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
|
||||
|
||||
if (queueChanged) {
|
||||
auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
|
||||
ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
mClient->executeCommands(
|
||||
commandLength, commandHandles,
|
||||
[&](const auto& tmpError, const auto& tmpOutQueueChanged,
|
||||
const auto& tmpOutLength, const auto& tmpOutHandles) {
|
||||
ASSERT_EQ(Error::NONE, tmpError);
|
||||
|
||||
if (tmpOutQueueChanged) {
|
||||
mClient->getOutputCommandQueue(
|
||||
[&](const auto& tmpError, const auto& tmpDescriptor) {
|
||||
ASSERT_EQ(Error::NONE, tmpError);
|
||||
reader->setMQDescriptor(tmpDescriptor);
|
||||
});
|
||||
}
|
||||
|
||||
ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
|
||||
reader->parse();
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (C) 2017 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 VTS_HAL_GRAPHICS_COMPOSER_UTILS
|
||||
#define VTS_HAL_GRAPHICS_COMPOSER_UTILS
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <IComposerCommandBuffer.h>
|
||||
#include <android/hardware/graphics/composer/2.1/IComposer.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
|
||||
#include "TestCommandReader.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
|
||||
using android::hardware::graphics::common::V1_0::ColorMode;
|
||||
using android::hardware::graphics::common::V1_0::Dataspace;
|
||||
using android::hardware::graphics::common::V1_0::Hdr;
|
||||
using android::hardware::graphics::common::V1_0::PixelFormat;
|
||||
|
||||
class ComposerClient;
|
||||
|
||||
// A wrapper to IComposer.
|
||||
class Composer {
|
||||
public:
|
||||
Composer();
|
||||
explicit Composer(const std::string& name);
|
||||
|
||||
sp<IComposer> getRaw() const;
|
||||
|
||||
// Returns true when the composer supports the specified capability.
|
||||
bool hasCapability(IComposer::Capability capability) const;
|
||||
|
||||
std::vector<IComposer::Capability> getCapabilities();
|
||||
std::string dumpDebugInfo();
|
||||
std::unique_ptr<ComposerClient> createClient();
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
sp<IComposer> mComposer;
|
||||
std::unordered_set<IComposer::Capability> mCapabilities;
|
||||
};
|
||||
|
||||
// A wrapper to IComposerClient.
|
||||
class ComposerClient {
|
||||
public:
|
||||
ComposerClient(const sp<IComposerClient>& client);
|
||||
~ComposerClient();
|
||||
|
||||
sp<IComposerClient> getRaw() const;
|
||||
|
||||
void registerCallback(const sp<IComposerCallback>& callback);
|
||||
uint32_t getMaxVirtualDisplayCount();
|
||||
|
||||
Display createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat formatHint,
|
||||
uint32_t outputBufferSlotCount,
|
||||
PixelFormat* outFormat);
|
||||
void destroyVirtualDisplay(Display display);
|
||||
|
||||
Layer createLayer(Display display, uint32_t bufferSlotCount);
|
||||
void destroyLayer(Display display, Layer layer);
|
||||
|
||||
Config getActiveConfig(Display display);
|
||||
bool getClientTargetSupport(Display display, uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace);
|
||||
std::vector<ColorMode> getColorModes(Display display);
|
||||
int32_t getDisplayAttribute(Display display, Config config,
|
||||
IComposerClient::Attribute attribute);
|
||||
std::vector<Config> getDisplayConfigs(Display display);
|
||||
std::string getDisplayName(Display display);
|
||||
IComposerClient::DisplayType getDisplayType(Display display);
|
||||
bool getDozeSupport(Display display);
|
||||
std::vector<Hdr> getHdrCapabilities(Display display, float* outMaxLuminance,
|
||||
float* outMaxAverageLuminance,
|
||||
float* outMinLuminance);
|
||||
|
||||
void setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount);
|
||||
void setActiveConfig(Display display, Config config);
|
||||
void setColorMode(Display display, ColorMode mode);
|
||||
void setPowerMode(Display display, IComposerClient::PowerMode mode);
|
||||
void setVsyncEnabled(Display display, bool enabled);
|
||||
|
||||
void execute(TestCommandReader* reader, CommandWriterBase* writer);
|
||||
|
||||
private:
|
||||
sp<IComposerClient> mClient;
|
||||
|
||||
// Keep track of all virtual displays and layers. When a test fails with
|
||||
// ASSERT_*, the destructor will clean up the resources for the test.
|
||||
struct DisplayResource {
|
||||
DisplayResource(bool isVirtual_) : isVirtual(isVirtual_) {}
|
||||
|
||||
bool isVirtual;
|
||||
std::unordered_set<Layer> layers;
|
||||
};
|
||||
std::unordered_map<Display, DisplayResource> mDisplayResources;
|
||||
};
|
||||
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // VTS_HAL_GRAPHICS_COMPOSER_UTILS
|
|
@ -0,0 +1,714 @@
|
|||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "graphics_composer_hidl_hal_test"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include "GraphicsComposerCallback.h"
|
||||
#include "TestCommandReader.h"
|
||||
#include "VtsHalGraphicsComposerTestUtils.h"
|
||||
#include "VtsHalGraphicsMapperTestUtils.h"
|
||||
|
||||
#include <VtsHalHidlTargetTestBase.h>
|
||||
#include <VtsHalHidlTargetTestEnvBase.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace tests {
|
||||
namespace {
|
||||
|
||||
using android::hardware::graphics::common::V1_0::BufferUsage;
|
||||
using android::hardware::graphics::common::V1_0::ColorMode;
|
||||
using android::hardware::graphics::common::V1_0::ColorTransform;
|
||||
using android::hardware::graphics::common::V1_0::Dataspace;
|
||||
using android::hardware::graphics::common::V1_0::PixelFormat;
|
||||
using android::hardware::graphics::common::V1_0::Transform;
|
||||
using android::hardware::graphics::mapper::V2_0::IMapper;
|
||||
using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
|
||||
using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
|
||||
|
||||
// Test environment for graphics.composer
|
||||
class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
|
||||
public:
|
||||
// get the test environment singleton
|
||||
static GraphicsComposerHidlEnvironment* Instance() {
|
||||
static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
|
||||
return instance;
|
||||
}
|
||||
|
||||
virtual void registerTestServices() override { registerTestService<IComposer>(); }
|
||||
|
||||
private:
|
||||
GraphicsComposerHidlEnvironment() {}
|
||||
|
||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
|
||||
};
|
||||
|
||||
class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
mComposer = std::make_unique<Composer>(
|
||||
GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
|
||||
ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
|
||||
|
||||
mComposerCallback = new GraphicsComposerCallback;
|
||||
mComposerClient->registerCallback(mComposerCallback);
|
||||
|
||||
// assume the first display is primary and is never removed
|
||||
mPrimaryDisplay = waitForFirstDisplay();
|
||||
|
||||
// explicitly disable vsync
|
||||
mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
|
||||
mComposerCallback->setVsyncAllowed(false);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
if (mComposerCallback != nullptr) {
|
||||
EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
|
||||
EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
|
||||
EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
|
||||
}
|
||||
}
|
||||
|
||||
// use the slot count usually set by SF
|
||||
static constexpr uint32_t kBufferSlotCount = 64;
|
||||
|
||||
std::unique_ptr<Composer> mComposer;
|
||||
std::unique_ptr<ComposerClient> mComposerClient;
|
||||
sp<GraphicsComposerCallback> mComposerCallback;
|
||||
// the first display and is assumed never to be removed
|
||||
Display mPrimaryDisplay;
|
||||
|
||||
private:
|
||||
Display waitForFirstDisplay() {
|
||||
while (true) {
|
||||
std::vector<Display> displays = mComposerCallback->getDisplays();
|
||||
if (displays.empty()) {
|
||||
usleep(5 * 1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
return displays[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test IComposer::getCapabilities.
|
||||
*
|
||||
* Test that IComposer::getCapabilities returns no invalid capabilities.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, GetCapabilities) {
|
||||
auto capabilities = mComposer->getCapabilities();
|
||||
ASSERT_EQ(capabilities.end(),
|
||||
std::find(capabilities.begin(), capabilities.end(),
|
||||
IComposer::Capability::INVALID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposer::dumpDebugInfo.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, DumpDebugInfo) { mComposer->dumpDebugInfo(); }
|
||||
|
||||
/**
|
||||
* Test IComposer::createClient.
|
||||
*
|
||||
* Test that IComposerClient is a singleton.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, CreateClientSingleton) {
|
||||
mComposer->getRaw()->createClient([&](const auto& tmpError, const auto&) {
|
||||
EXPECT_EQ(Error::NO_RESOURCES, tmpError);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::createVirtualDisplay and
|
||||
* IComposerClient::destroyVirtualDisplay.
|
||||
*
|
||||
* Test that virtual displays can be created and has the correct display type.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, CreateVirtualDisplay) {
|
||||
if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
|
||||
GTEST_SUCCEED() << "no virtual display support";
|
||||
return;
|
||||
}
|
||||
|
||||
Display display;
|
||||
PixelFormat format;
|
||||
ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
|
||||
64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
|
||||
kBufferSlotCount, &format));
|
||||
|
||||
// test display type
|
||||
IComposerClient::DisplayType type = mComposerClient->getDisplayType(display);
|
||||
EXPECT_EQ(IComposerClient::DisplayType::VIRTUAL, type);
|
||||
|
||||
mComposerClient->destroyVirtualDisplay(display);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::createLayer and IComposerClient::destroyLayer.
|
||||
*
|
||||
* Test that layers can be created and destroyed.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, CreateLayer) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mComposerClient->destroyLayer(mPrimaryDisplay, layer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::getDisplayName.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, GetDisplayName) {
|
||||
mComposerClient->getDisplayName(mPrimaryDisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::getDisplayType.
|
||||
*
|
||||
* Test that IComposerClient::getDisplayType returns the correct display type
|
||||
* for the primary display.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, GetDisplayType) {
|
||||
ASSERT_EQ(IComposerClient::DisplayType::PHYSICAL,
|
||||
mComposerClient->getDisplayType(mPrimaryDisplay));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::getClientTargetSupport.
|
||||
*
|
||||
* Test that IComposerClient::getClientTargetSupport returns true for the
|
||||
* required client targets.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport) {
|
||||
std::vector<Config> configs =
|
||||
mComposerClient->getDisplayConfigs(mPrimaryDisplay);
|
||||
for (auto config : configs) {
|
||||
int32_t width = mComposerClient->getDisplayAttribute(
|
||||
mPrimaryDisplay, config, IComposerClient::Attribute::WIDTH);
|
||||
int32_t height = mComposerClient->getDisplayAttribute(
|
||||
mPrimaryDisplay, config, IComposerClient::Attribute::HEIGHT);
|
||||
ASSERT_LT(0, width);
|
||||
ASSERT_LT(0, height);
|
||||
|
||||
mComposerClient->setActiveConfig(mPrimaryDisplay, config);
|
||||
|
||||
ASSERT_TRUE(mComposerClient->getClientTargetSupport(
|
||||
mPrimaryDisplay, width, height, PixelFormat::RGBA_8888,
|
||||
Dataspace::UNKNOWN));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::getDisplayAttribute.
|
||||
*
|
||||
* Test that IComposerClient::getDisplayAttribute succeeds for the required
|
||||
* formats, and succeeds or fails correctly for optional attributes.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, GetDisplayAttribute) {
|
||||
std::vector<Config> configs =
|
||||
mComposerClient->getDisplayConfigs(mPrimaryDisplay);
|
||||
for (auto config : configs) {
|
||||
const std::array<IComposerClient::Attribute, 3> requiredAttributes = {{
|
||||
IComposerClient::Attribute::WIDTH, IComposerClient::Attribute::HEIGHT,
|
||||
IComposerClient::Attribute::VSYNC_PERIOD,
|
||||
}};
|
||||
for (auto attribute : requiredAttributes) {
|
||||
mComposerClient->getDisplayAttribute(mPrimaryDisplay, config, attribute);
|
||||
}
|
||||
|
||||
const std::array<IComposerClient::Attribute, 2> optionalAttributes = {{
|
||||
IComposerClient::Attribute::DPI_X, IComposerClient::Attribute::DPI_Y,
|
||||
}};
|
||||
for (auto attribute : optionalAttributes) {
|
||||
mComposerClient->getRaw()->getDisplayAttribute(
|
||||
mPrimaryDisplay, config, attribute,
|
||||
[&](const auto& tmpError, const auto&) {
|
||||
EXPECT_TRUE(tmpError == Error::NONE ||
|
||||
tmpError == Error::UNSUPPORTED);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::getHdrCapabilities.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, GetHdrCapabilities) {
|
||||
float maxLuminance;
|
||||
float maxAverageLuminance;
|
||||
float minLuminance;
|
||||
mComposerClient->getHdrCapabilities(mPrimaryDisplay, &maxLuminance,
|
||||
&maxAverageLuminance, &minLuminance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::setClientTargetSlotCount.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, SetClientTargetSlotCount) {
|
||||
mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::setActiveConfig.
|
||||
*
|
||||
* Test that IComposerClient::setActiveConfig succeeds for all display
|
||||
* configs.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, SetActiveConfig) {
|
||||
std::vector<Config> configs =
|
||||
mComposerClient->getDisplayConfigs(mPrimaryDisplay);
|
||||
for (auto config : configs) {
|
||||
mComposerClient->setActiveConfig(mPrimaryDisplay, config);
|
||||
ASSERT_EQ(config, mComposerClient->getActiveConfig(mPrimaryDisplay));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::setColorMode.
|
||||
*
|
||||
* Test that IComposerClient::setColorMode succeeds for all color modes.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, SetColorMode) {
|
||||
std::vector<ColorMode> modes =
|
||||
mComposerClient->getColorModes(mPrimaryDisplay);
|
||||
for (auto mode : modes) {
|
||||
mComposerClient->setColorMode(mPrimaryDisplay, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::setPowerMode.
|
||||
*
|
||||
* Test that IComposerClient::setPowerMode succeeds for all power modes.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, SetPowerMode) {
|
||||
std::vector<IComposerClient::PowerMode> modes;
|
||||
modes.push_back(IComposerClient::PowerMode::OFF);
|
||||
|
||||
if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
|
||||
modes.push_back(IComposerClient::PowerMode::DOZE);
|
||||
modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
|
||||
}
|
||||
|
||||
// push ON last
|
||||
modes.push_back(IComposerClient::PowerMode::ON);
|
||||
|
||||
for (auto mode : modes) {
|
||||
mComposerClient->setPowerMode(mPrimaryDisplay, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::setVsyncEnabled.
|
||||
*
|
||||
* Test that IComposerClient::setVsyncEnabled succeeds and there is no
|
||||
* spurious vsync events.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlTest, SetVsyncEnabled) {
|
||||
mComposerCallback->setVsyncAllowed(true);
|
||||
|
||||
mComposerClient->setVsyncEnabled(mPrimaryDisplay, true);
|
||||
usleep(60 * 1000);
|
||||
mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
|
||||
|
||||
mComposerCallback->setVsyncAllowed(false);
|
||||
}
|
||||
|
||||
// Tests for IComposerClient::Command.
|
||||
class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
|
||||
|
||||
mWriter = std::make_unique<CommandWriterBase>(1024);
|
||||
mReader = std::make_unique<TestCommandReader>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown());
|
||||
}
|
||||
|
||||
const native_handle_t* allocate() {
|
||||
IMapper::BufferDescriptorInfo info{};
|
||||
info.width = 64;
|
||||
info.height = 64;
|
||||
info.layerCount = 1;
|
||||
info.format = PixelFormat::RGBA_8888;
|
||||
info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN |
|
||||
BufferUsage::CPU_READ_OFTEN);
|
||||
|
||||
return mGralloc->allocate(info);
|
||||
}
|
||||
|
||||
void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
|
||||
|
||||
std::unique_ptr<CommandWriterBase> mWriter;
|
||||
std::unique_ptr<TestCommandReader> mReader;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Gralloc> mGralloc;
|
||||
};
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_COLOR_TRANSFORM.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_COLOR_TRANSFORM) {
|
||||
const std::array<float, 16> identity = {{
|
||||
1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
}};
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->setColorTransform(identity.data(), ColorTransform::IDENTITY);
|
||||
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_CLIENT_TARGET.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_CLIENT_TARGET) {
|
||||
mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount);
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->setClientTarget(0, nullptr, -1, Dataspace::UNKNOWN,
|
||||
std::vector<IComposerClient::Rect>());
|
||||
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_OUTPUT_BUFFER.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_OUTPUT_BUFFER) {
|
||||
if (mComposerClient->getMaxVirtualDisplayCount() == 0) {
|
||||
GTEST_SUCCEED() << "no virtual display support";
|
||||
return;
|
||||
}
|
||||
|
||||
Display display;
|
||||
PixelFormat format;
|
||||
ASSERT_NO_FATAL_FAILURE(display = mComposerClient->createVirtualDisplay(
|
||||
64, 64, PixelFormat::IMPLEMENTATION_DEFINED,
|
||||
kBufferSlotCount, &format));
|
||||
|
||||
const native_handle_t* handle;
|
||||
ASSERT_NO_FATAL_FAILURE(handle = allocate());
|
||||
|
||||
mWriter->selectDisplay(display);
|
||||
mWriter->setOutputBuffer(0, handle, -1);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::VALIDATE_DISPLAY.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, VALIDATE_DISPLAY) {
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->validateDisplay();
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::ACCEPT_DISPLAY_CHANGES.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, ACCEPT_DISPLAY_CHANGES) {
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->validateDisplay();
|
||||
mWriter->acceptDisplayChanges();
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::PRESENT_DISPLAY.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY) {
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->validateDisplay();
|
||||
mWriter->presentDisplay();
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerCursorPosition(1, 1);
|
||||
mWriter->setLayerCursorPosition(0, 0);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_BUFFER.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BUFFER) {
|
||||
auto handle = allocate();
|
||||
ASSERT_NE(nullptr, handle);
|
||||
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerBuffer(0, handle, -1);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SURFACE_DAMAGE) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
IComposerClient::Rect empty{0, 0, 0, 0};
|
||||
IComposerClient::Rect unit{0, 0, 1, 1};
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, empty));
|
||||
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, unit));
|
||||
mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>());
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_BLEND_MODE.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_BLEND_MODE) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
|
||||
mWriter->setLayerBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
|
||||
mWriter->setLayerBlendMode(IComposerClient::BlendMode::COVERAGE);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_COLOR.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COLOR) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerColor(IComposerClient::Color{0xff, 0xff, 0xff, 0xff});
|
||||
mWriter->setLayerColor(IComposerClient::Color{0, 0, 0, 0});
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_COMPOSITION_TYPE) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
|
||||
mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
|
||||
mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
|
||||
mWriter->setLayerCompositionType(IComposerClient::Composition::CURSOR);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_DATASPACE.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DATASPACE) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerDataspace(Dataspace::UNKNOWN);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_DISPLAY_FRAME.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_DISPLAY_FRAME) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerDisplayFrame(IComposerClient::Rect{0, 0, 1, 1});
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_PLANE_ALPHA.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_PLANE_ALPHA) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerPlaneAlpha(0.0f);
|
||||
mWriter->setLayerPlaneAlpha(1.0f);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SIDEBAND_STREAM) {
|
||||
if (!mComposer->hasCapability(IComposer::Capability::SIDEBAND_STREAM)) {
|
||||
GTEST_SUCCEED() << "no sideband stream support";
|
||||
return;
|
||||
}
|
||||
|
||||
auto handle = allocate();
|
||||
ASSERT_NE(nullptr, handle);
|
||||
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerSidebandStream(handle);
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_SOURCE_CROP.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_SOURCE_CROP) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerSourceCrop(IComposerClient::FRect{0.0f, 0.0f, 1.0f, 1.0f});
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_TRANSFORM.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_TRANSFORM) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerTransform(static_cast<Transform>(0));
|
||||
mWriter->setLayerTransform(Transform::FLIP_H);
|
||||
mWriter->setLayerTransform(Transform::FLIP_V);
|
||||
mWriter->setLayerTransform(Transform::ROT_90);
|
||||
mWriter->setLayerTransform(Transform::ROT_180);
|
||||
mWriter->setLayerTransform(Transform::ROT_270);
|
||||
mWriter->setLayerTransform(
|
||||
static_cast<Transform>(Transform::FLIP_H | Transform::ROT_90));
|
||||
mWriter->setLayerTransform(
|
||||
static_cast<Transform>(Transform::FLIP_V | Transform::ROT_90));
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_VISIBLE_REGION.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_VISIBLE_REGION) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
IComposerClient::Rect empty{0, 0, 0, 0};
|
||||
IComposerClient::Rect unit{0, 0, 1, 1};
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, empty));
|
||||
mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, unit));
|
||||
mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>());
|
||||
execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IComposerClient::Command::SET_LAYER_Z_ORDER.
|
||||
*/
|
||||
TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_Z_ORDER) {
|
||||
Layer layer;
|
||||
ASSERT_NO_FATAL_FAILURE(
|
||||
layer = mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
|
||||
|
||||
mWriter->selectDisplay(mPrimaryDisplay);
|
||||
mWriter->selectLayer(layer);
|
||||
mWriter->setLayerZOrder(10);
|
||||
mWriter->setLayerZOrder(0);
|
||||
execute();
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
} // namespace tests
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
|
||||
::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
|
||||
int status = RUN_ALL_TESTS();
|
||||
ALOGI("Test result = %d", status);
|
||||
return status;
|
||||
}
|
19
android/hardware/interfaces/graphics/composer/Android.mk
Normal file
19
android/hardware/interfaces/graphics/composer/Android.mk
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (C) 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(call all-subdir-makefiles)
|
Loading…
Add table
Add a link
Reference in a new issue