graphics: add ComposerResources
Add ComposerResources to the HAL support library to replace HandleImporter, DisplayData, and BufferCache in ComposerClient. ComposerResources tracks the current displays and layers, as well as managing buffer caches for them. This is more than refactoring. HandleImporter used to be a static object, but we want ComposerResources to be self-contained rather than depending on a static object. This needs to be fixed. It also becomes obvious that we used to treat sideband streams as buffers in BufferCacheEntry destructor incorrectly. That needs to be fixed as well (as a trivial consequence of making HandleImporter non-static). Test: boots and VTS Change-Id: I8e3014cb233e2a6d1a71cc244eff80f126c58a94
This commit is contained in:
parent
bbd9545732
commit
2d894af0c7
4 changed files with 610 additions and 372 deletions
|
@ -28,117 +28,23 @@ namespace composer {
|
|||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
namespace {
|
||||
|
||||
using MapperError = android::hardware::graphics::mapper::V2_0::Error;
|
||||
using android::hardware::graphics::mapper::V2_0::IMapper;
|
||||
|
||||
class HandleImporter {
|
||||
public:
|
||||
bool initialize()
|
||||
{
|
||||
// allow only one client
|
||||
if (mInitialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mMapper = IMapper::getService();
|
||||
|
||||
mInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
mMapper.clear();
|
||||
mInitialized = false;
|
||||
}
|
||||
|
||||
// In IComposer, any buffer_handle_t is owned by the caller and we need to
|
||||
// make a clone for hwcomposer2. We also need to translate empty handle
|
||||
// to nullptr. This function does that, in-place.
|
||||
bool importBuffer(buffer_handle_t& handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!handle->numFds && !handle->numInts) {
|
||||
handle = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
MapperError error;
|
||||
buffer_handle_t importedHandle;
|
||||
mMapper->importBuffer(
|
||||
hidl_handle(handle),
|
||||
[&](const auto& tmpError, const auto& tmpBufferHandle) {
|
||||
error = tmpError;
|
||||
importedHandle = static_cast<buffer_handle_t>(tmpBufferHandle);
|
||||
});
|
||||
if (error != MapperError::NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
handle = importedHandle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void freeBuffer(buffer_handle_t handle)
|
||||
{
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
|
||||
mMapper->freeBuffer(const_cast<native_handle_t*>(handle));
|
||||
}
|
||||
|
||||
private:
|
||||
bool mInitialized = false;
|
||||
sp<IMapper> mMapper;
|
||||
};
|
||||
|
||||
HandleImporter sHandleImporter;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
BufferCacheEntry::BufferCacheEntry()
|
||||
: mHandle(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
BufferCacheEntry::BufferCacheEntry(BufferCacheEntry&& other)
|
||||
{
|
||||
mHandle = other.mHandle;
|
||||
other.mHandle = nullptr;
|
||||
}
|
||||
|
||||
BufferCacheEntry& BufferCacheEntry::operator=(buffer_handle_t handle)
|
||||
{
|
||||
clear();
|
||||
mHandle = handle;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BufferCacheEntry::~BufferCacheEntry()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void BufferCacheEntry::clear()
|
||||
{
|
||||
if (mHandle) {
|
||||
sHandleImporter.freeBuffer(mHandle);
|
||||
}
|
||||
}
|
||||
|
||||
ComposerClient::ComposerClient(ComposerHal& hal)
|
||||
: mHal(hal), mWriter(kWriterInitialSize)
|
||||
{
|
||||
}
|
||||
|
||||
ComposerClient::~ComposerClient()
|
||||
{
|
||||
ALOGD("destroying composer client");
|
||||
|
||||
mHal.enableCallback(false);
|
||||
destroyResources();
|
||||
mHal.removeClient();
|
||||
|
||||
ALOGD("removed composer client");
|
||||
}
|
||||
|
||||
void ComposerClient::destroyResources()
|
||||
{
|
||||
// We want to call hwc2_close here (and move hwc2_open to the
|
||||
// constructor), with the assumption that hwc2_close would
|
||||
|
@ -153,21 +59,15 @@ ComposerClient::~ComposerClient()
|
|||
//
|
||||
// Below we manually clean all resources (layers and virtual
|
||||
// displays), and perform a presentDisplay afterwards.
|
||||
ALOGW("destroying composer client");
|
||||
mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
|
||||
ALOGW("destroying client resources for display %" PRIu64, display);
|
||||
|
||||
mHal.enableCallback(false);
|
||||
|
||||
// no need to grab the mutex as any in-flight hwbinder call would have
|
||||
// kept the client alive
|
||||
for (const auto& dpy : mDisplayData) {
|
||||
ALOGW("destroying client resources for display %" PRIu64, dpy.first);
|
||||
|
||||
for (const auto& ly : dpy.second.Layers) {
|
||||
mHal.destroyLayer(dpy.first, ly.first);
|
||||
for (auto layer : layers) {
|
||||
mHal.destroyLayer(display, layer);
|
||||
}
|
||||
|
||||
if (dpy.second.IsVirtual) {
|
||||
mHal.destroyVirtualDisplay(dpy.first);
|
||||
if (isVirtual) {
|
||||
mHal.destroyVirtualDisplay(display);
|
||||
} else {
|
||||
ALOGW("performing a final presentDisplay");
|
||||
|
||||
|
@ -176,15 +76,15 @@ ComposerClient::~ComposerClient()
|
|||
uint32_t displayRequestMask = 0;
|
||||
std::vector<Layer> requestedLayers;
|
||||
std::vector<uint32_t> requestMasks;
|
||||
mHal.validateDisplay(dpy.first, &changedLayers, &compositionTypes,
|
||||
&displayRequestMask, &requestedLayers, &requestMasks);
|
||||
mHal.validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask,
|
||||
&requestedLayers, &requestMasks);
|
||||
|
||||
mHal.acceptDisplayChanges(dpy.first);
|
||||
mHal.acceptDisplayChanges(display);
|
||||
|
||||
int32_t presentFence = -1;
|
||||
std::vector<Layer> releasedLayers;
|
||||
std::vector<int32_t> releaseFences;
|
||||
mHal.presentDisplay(dpy.first, &presentFence, &releasedLayers, &releaseFences);
|
||||
mHal.presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
|
||||
if (presentFence >= 0) {
|
||||
close(presentFence);
|
||||
}
|
||||
|
@ -194,36 +94,28 @@ ComposerClient::~ComposerClient()
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mDisplayData.clear();
|
||||
|
||||
sHandleImporter.cleanup();
|
||||
|
||||
mHal.removeClient();
|
||||
|
||||
ALOGW("removed composer client");
|
||||
mResources.reset();
|
||||
}
|
||||
|
||||
void ComposerClient::initialize()
|
||||
{
|
||||
mReader = createCommandReader();
|
||||
if (!sHandleImporter.initialize()) {
|
||||
LOG_ALWAYS_FATAL("failed to initialize handle importer");
|
||||
mResources = createResources();
|
||||
if (!mResources) {
|
||||
LOG_ALWAYS_FATAL("failed to create resources");
|
||||
}
|
||||
|
||||
mReader = createCommandReader();
|
||||
}
|
||||
|
||||
void ComposerClient::onHotplug(Display display,
|
||||
IComposerCallback::Connection connected)
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mDisplayDataMutex);
|
||||
|
||||
if (connected == IComposerCallback::Connection::CONNECTED) {
|
||||
mDisplayData.emplace(display, DisplayData(false));
|
||||
} else if (connected == IComposerCallback::Connection::DISCONNECTED) {
|
||||
mDisplayData.erase(display);
|
||||
}
|
||||
if (connected == IComposerCallback::Connection::CONNECTED) {
|
||||
mResources->addPhysicalDisplay(display);
|
||||
} else if (connected == IComposerCallback::Connection::DISCONNECTED) {
|
||||
mResources->removeDisplay(display);
|
||||
}
|
||||
|
||||
auto ret = mCallback->onHotplug(display, connected);
|
||||
|
@ -268,10 +160,7 @@ Return<void> ComposerClient::createVirtualDisplay(uint32_t width,
|
|||
Error err = mHal.createVirtualDisplay(width, height,
|
||||
&formatHint, &display);
|
||||
if (err == Error::NONE) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayDataMutex);
|
||||
|
||||
auto dpy = mDisplayData.emplace(display, DisplayData(true)).first;
|
||||
dpy->second.OutputBuffers.resize(outputBufferSlotCount);
|
||||
mResources->addVirtualDisplay(display, outputBufferSlotCount);
|
||||
}
|
||||
|
||||
hidl_cb(err, display, formatHint);
|
||||
|
@ -282,9 +171,7 @@ Return<Error> ComposerClient::destroyVirtualDisplay(Display display)
|
|||
{
|
||||
Error err = mHal.destroyVirtualDisplay(display);
|
||||
if (err == Error::NONE) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayDataMutex);
|
||||
|
||||
mDisplayData.erase(display);
|
||||
mResources->removeDisplay(display);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -296,14 +183,9 @@ Return<void> ComposerClient::createLayer(Display display,
|
|||
Layer layer = 0;
|
||||
Error err = mHal.createLayer(display, &layer);
|
||||
if (err == Error::NONE) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayDataMutex);
|
||||
auto dpy = mDisplayData.find(display);
|
||||
// The display entry may have already been removed by onHotplug.
|
||||
if (dpy != mDisplayData.end()) {
|
||||
auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
|
||||
ly->second.Buffers.resize(bufferSlotCount);
|
||||
} else {
|
||||
err = Error::BAD_DISPLAY;
|
||||
err = mResources->addLayer(display, layer, bufferSlotCount);
|
||||
if (err != Error::NONE) {
|
||||
// The display entry may have already been removed by onHotplug.
|
||||
// Note: We do not destroy the layer on this error as the hotplug
|
||||
// disconnect invalidates the display id. The implementation should
|
||||
// ensure all layers for the display are destroyed.
|
||||
|
@ -318,13 +200,7 @@ Return<Error> ComposerClient::destroyLayer(Display display, Layer layer)
|
|||
{
|
||||
Error err = mHal.destroyLayer(display, layer);
|
||||
if (err == Error::NONE) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayDataMutex);
|
||||
|
||||
auto dpy = mDisplayData.find(display);
|
||||
// The display entry may have already been removed by onHotplug.
|
||||
if (dpy != mDisplayData.end()) {
|
||||
dpy->second.Layers.erase(layer);
|
||||
}
|
||||
mResources->removeLayer(display, layer);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -427,16 +303,7 @@ Return<void> ComposerClient::getHdrCapabilities(Display display,
|
|||
Return<Error> ComposerClient::setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mDisplayDataMutex);
|
||||
|
||||
auto dpy = mDisplayData.find(display);
|
||||
if (dpy == mDisplayData.end()) {
|
||||
return Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
dpy->second.ClientTargets.resize(clientTargetSlotCount);
|
||||
|
||||
return Error::NONE;
|
||||
return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setActiveConfig(Display display, Config config)
|
||||
|
@ -516,6 +383,11 @@ Return<void> ComposerClient::executeCommands(uint32_t inLength,
|
|||
return Void();
|
||||
}
|
||||
|
||||
std::unique_ptr<ComposerResources> ComposerClient::createResources()
|
||||
{
|
||||
return ComposerResources::create();
|
||||
}
|
||||
|
||||
std::unique_ptr<ComposerClient::CommandReader>
|
||||
ComposerClient::createCommandReader()
|
||||
{
|
||||
|
@ -524,7 +396,7 @@ ComposerClient::createCommandReader()
|
|||
}
|
||||
|
||||
ComposerClient::CommandReader::CommandReader(ComposerClient& client)
|
||||
: mClient(client), mHal(client.mHal), mWriter(client.mWriter)
|
||||
: mHal(client.mHal), mResources(client.mResources.get()), mWriter(client.mWriter)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -661,22 +533,21 @@ bool ComposerClient::CommandReader::parseSetClientTarget(uint16_t length)
|
|||
|
||||
bool useCache = false;
|
||||
auto slot = read();
|
||||
auto clientTarget = readHandle(&useCache);
|
||||
auto rawHandle = readHandle(&useCache);
|
||||
auto fence = readFence();
|
||||
auto dataspace = readSigned();
|
||||
auto damage = readRegion((length - 4) / 4);
|
||||
bool closeFence = true;
|
||||
|
||||
auto err = lookupBuffer(BufferCache::CLIENT_TARGETS,
|
||||
slot, useCache, clientTarget, &clientTarget);
|
||||
const native_handle_t* clientTarget;
|
||||
ComposerResources::ReplacedBufferHandle replacedClientTarget;
|
||||
auto err = mResources->getDisplayClientTarget(mDisplay,
|
||||
slot, useCache, rawHandle, &clientTarget, &replacedClientTarget);
|
||||
if (err == Error::NONE) {
|
||||
err = mHal.setClientTarget(mDisplay, clientTarget, fence,
|
||||
dataspace, damage);
|
||||
auto updateBufErr = updateBuffer(BufferCache::CLIENT_TARGETS, slot,
|
||||
useCache, clientTarget);
|
||||
if (err == Error::NONE) {
|
||||
closeFence = false;
|
||||
err = updateBufErr;
|
||||
}
|
||||
}
|
||||
if (closeFence) {
|
||||
|
@ -697,19 +568,18 @@ bool ComposerClient::CommandReader::parseSetOutputBuffer(uint16_t length)
|
|||
|
||||
bool useCache = false;
|
||||
auto slot = read();
|
||||
auto outputBuffer = readHandle(&useCache);
|
||||
auto rawhandle = readHandle(&useCache);
|
||||
auto fence = readFence();
|
||||
bool closeFence = true;
|
||||
|
||||
auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS,
|
||||
slot, useCache, outputBuffer, &outputBuffer);
|
||||
const native_handle_t* outputBuffer;
|
||||
ComposerResources::ReplacedBufferHandle replacedOutputBuffer;
|
||||
auto err = mResources->getDisplayOutputBuffer(mDisplay,
|
||||
slot, useCache, rawhandle, &outputBuffer, &replacedOutputBuffer);
|
||||
if (err == Error::NONE) {
|
||||
err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
|
||||
auto updateBufErr = updateBuffer(BufferCache::OUTPUT_BUFFERS,
|
||||
slot, useCache, outputBuffer);
|
||||
if (err == Error::NONE) {
|
||||
closeFence = false;
|
||||
err = updateBufErr;
|
||||
}
|
||||
}
|
||||
if (closeFence) {
|
||||
|
@ -848,19 +718,18 @@ bool ComposerClient::CommandReader::parseSetLayerBuffer(uint16_t length)
|
|||
|
||||
bool useCache = false;
|
||||
auto slot = read();
|
||||
auto buffer = readHandle(&useCache);
|
||||
auto rawHandle = readHandle(&useCache);
|
||||
auto fence = readFence();
|
||||
bool closeFence = true;
|
||||
|
||||
auto err = lookupBuffer(BufferCache::LAYER_BUFFERS,
|
||||
slot, useCache, buffer, &buffer);
|
||||
const native_handle_t* buffer;
|
||||
ComposerResources::ReplacedBufferHandle replacedBuffer;
|
||||
auto err = mResources->getLayerBuffer(mDisplay, mLayer,
|
||||
slot, useCache, rawHandle, &buffer, &replacedBuffer);
|
||||
if (err == Error::NONE) {
|
||||
err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
|
||||
auto updateBufErr = updateBuffer(BufferCache::LAYER_BUFFERS, slot,
|
||||
useCache, buffer);
|
||||
if (err == Error::NONE) {
|
||||
closeFence = false;
|
||||
err = updateBufErr;
|
||||
}
|
||||
}
|
||||
if (closeFence) {
|
||||
|
@ -980,15 +849,14 @@ bool ComposerClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
|
|||
return false;
|
||||
}
|
||||
|
||||
auto stream = readHandle();
|
||||
auto rawHandle = readHandle();
|
||||
|
||||
auto err = lookupLayerSidebandStream(stream, &stream);
|
||||
const native_handle_t* stream;
|
||||
ComposerResources::ReplacedStreamHandle replacedStream;
|
||||
auto err = mResources->getLayerSidebandStream(mDisplay, mLayer,
|
||||
rawHandle, &stream, &replacedStream);
|
||||
if (err == Error::NONE) {
|
||||
err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
|
||||
auto updateErr = updateLayerSidebandStream(stream);
|
||||
if (err == Error::NONE) {
|
||||
err = updateErr;
|
||||
}
|
||||
}
|
||||
if (err != Error::NONE) {
|
||||
mWriter.setError(getCommandLoc(), err);
|
||||
|
@ -1087,115 +955,6 @@ hwc_frect_t ComposerClient::CommandReader::readFRect()
|
|||
};
|
||||
}
|
||||
|
||||
Error ComposerClient::CommandReader::lookupBufferCacheEntryLocked(
|
||||
BufferCache cache, uint32_t slot, BufferCacheEntry** outEntry)
|
||||
{
|
||||
auto dpy = mClient.mDisplayData.find(mDisplay);
|
||||
if (dpy == mClient.mDisplayData.end()) {
|
||||
return Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
BufferCacheEntry* entry = nullptr;
|
||||
switch (cache) {
|
||||
case BufferCache::CLIENT_TARGETS:
|
||||
if (slot < dpy->second.ClientTargets.size()) {
|
||||
entry = &dpy->second.ClientTargets[slot];
|
||||
}
|
||||
break;
|
||||
case BufferCache::OUTPUT_BUFFERS:
|
||||
if (slot < dpy->second.OutputBuffers.size()) {
|
||||
entry = &dpy->second.OutputBuffers[slot];
|
||||
}
|
||||
break;
|
||||
case BufferCache::LAYER_BUFFERS:
|
||||
{
|
||||
auto ly = dpy->second.Layers.find(mLayer);
|
||||
if (ly == dpy->second.Layers.end()) {
|
||||
return Error::BAD_LAYER;
|
||||
}
|
||||
if (slot < ly->second.Buffers.size()) {
|
||||
entry = &ly->second.Buffers[slot];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BufferCache::LAYER_SIDEBAND_STREAMS:
|
||||
{
|
||||
auto ly = dpy->second.Layers.find(mLayer);
|
||||
if (ly == dpy->second.Layers.end()) {
|
||||
return Error::BAD_LAYER;
|
||||
}
|
||||
if (slot == 0) {
|
||||
entry = &ly->second.SidebandStream;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
ALOGW("invalid buffer slot %" PRIu32, slot);
|
||||
return Error::BAD_PARAMETER;
|
||||
}
|
||||
|
||||
*outEntry = entry;
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error ComposerClient::CommandReader::lookupBuffer(BufferCache cache,
|
||||
uint32_t slot, bool useCache, buffer_handle_t handle,
|
||||
buffer_handle_t* outHandle)
|
||||
{
|
||||
if (useCache) {
|
||||
std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
|
||||
|
||||
BufferCacheEntry* entry;
|
||||
Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
|
||||
if (error != Error::NONE) {
|
||||
return error;
|
||||
}
|
||||
|
||||
// input handle is ignored
|
||||
*outHandle = entry->getHandle();
|
||||
} else if (cache == BufferCache::LAYER_SIDEBAND_STREAMS) {
|
||||
if (handle) {
|
||||
*outHandle = native_handle_clone(handle);
|
||||
if (*outHandle == nullptr) {
|
||||
return Error::NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!sHandleImporter.importBuffer(handle)) {
|
||||
return Error::NO_RESOURCES;
|
||||
}
|
||||
|
||||
*outHandle = handle;
|
||||
}
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
Error ComposerClient::CommandReader::updateBuffer(BufferCache cache,
|
||||
uint32_t slot, bool useCache, buffer_handle_t handle)
|
||||
{
|
||||
// handle was looked up from cache
|
||||
if (useCache) {
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
|
||||
|
||||
BufferCacheEntry* entry = nullptr;
|
||||
Error error = lookupBufferCacheEntryLocked(cache, slot, &entry);
|
||||
if (error != Error::NONE) {
|
||||
return error;
|
||||
}
|
||||
|
||||
*entry = handle;
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
|
||||
#include <composer-hal/2.1/ComposerHal.h>
|
||||
#include <composer-hal/2.1/ComposerResources.h>
|
||||
#include <hardware/hwcomposer2.h>
|
||||
|
||||
namespace android {
|
||||
|
@ -34,25 +35,6 @@ namespace implementation {
|
|||
|
||||
using namespace hal;
|
||||
|
||||
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(ComposerHal& hal);
|
||||
|
@ -110,23 +92,6 @@ public:
|
|||
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);
|
||||
|
@ -166,44 +131,23 @@ protected:
|
|||
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;
|
||||
ComposerHal& mHal;
|
||||
ComposerResources* mResources;
|
||||
CommandWriterBase& mWriter;
|
||||
|
||||
Display mDisplay;
|
||||
Layer mLayer;
|
||||
};
|
||||
|
||||
void destroyResources();
|
||||
|
||||
virtual std::unique_ptr<ComposerResources> createResources();
|
||||
virtual std::unique_ptr<CommandReader> createCommandReader();
|
||||
|
||||
ComposerHal& mHal;
|
||||
|
||||
std::unique_ptr<ComposerResources> mResources;
|
||||
|
||||
// 64KiB minus a small space for metadata such as read/write pointers
|
||||
static constexpr size_t kWriterInitialSize =
|
||||
64 * 1024 / sizeof(uint32_t) - 16;
|
||||
|
@ -212,9 +156,6 @@ protected:
|
|||
CommandWriterBase mWriter;
|
||||
|
||||
sp<IComposerCallback> mCallback;
|
||||
|
||||
std::mutex mDisplayDataMutex;
|
||||
std::unordered_map<Display, DisplayData> mDisplayData;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
|
|
@ -19,10 +19,12 @@ cc_library_headers {
|
|||
vendor_available: true,
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"libhardware", // TODO remove hwcomposer2.h dependency
|
||||
],
|
||||
export_shared_lib_headers: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"libhardware",
|
||||
],
|
||||
export_include_dirs: ["include"],
|
||||
|
|
|
@ -0,0 +1,536 @@
|
|||
/*
|
||||
* Copyright 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#warning "ComposerResources.h included without LOG_TAG"
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace hal {
|
||||
|
||||
// wrapper for IMapper to import buffers and sideband streams
|
||||
class ComposerHandleImporter {
|
||||
public:
|
||||
bool init() {
|
||||
mMapper = mapper::V2_0::IMapper::getService();
|
||||
ALOGE_IF(!mMapper, "failed to get mapper service");
|
||||
return mMapper != nullptr;
|
||||
}
|
||||
|
||||
Error importBuffer(const native_handle_t* rawHandle, const native_handle_t** outBufferHandle) {
|
||||
if (!rawHandle || (!rawHandle->numFds && !rawHandle->numInts)) {
|
||||
*outBufferHandle = nullptr;
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
mapper::V2_0::Error error;
|
||||
const native_handle_t* bufferHandle;
|
||||
mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBufferHandle) {
|
||||
error = tmpError;
|
||||
bufferHandle = static_cast<const native_handle_t*>(tmpBufferHandle);
|
||||
});
|
||||
if (error != mapper::V2_0::Error::NONE) {
|
||||
return Error::NO_RESOURCES;
|
||||
}
|
||||
|
||||
*outBufferHandle = bufferHandle;
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
void freeBuffer(const native_handle_t* bufferHandle) {
|
||||
if (bufferHandle) {
|
||||
mMapper->freeBuffer(static_cast<void*>(const_cast<native_handle_t*>(bufferHandle)));
|
||||
}
|
||||
}
|
||||
|
||||
Error importStream(const native_handle_t* rawHandle, const native_handle_t** outStreamHandle) {
|
||||
const native_handle_t* streamHandle = nullptr;
|
||||
if (rawHandle) {
|
||||
streamHandle = native_handle_clone(rawHandle);
|
||||
if (!streamHandle) {
|
||||
return Error::NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
|
||||
*outStreamHandle = streamHandle;
|
||||
return Error::NONE;
|
||||
}
|
||||
|
||||
void freeStream(const native_handle_t* streamHandle) {
|
||||
if (streamHandle) {
|
||||
native_handle_close(streamHandle);
|
||||
native_handle_delete(const_cast<native_handle_t*>(streamHandle));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
sp<mapper::V2_0::IMapper> mMapper;
|
||||
};
|
||||
|
||||
class ComposerHandleCache {
|
||||
public:
|
||||
enum class HandleType {
|
||||
INVALID,
|
||||
BUFFER,
|
||||
STREAM,
|
||||
};
|
||||
|
||||
ComposerHandleCache(ComposerHandleImporter& importer, HandleType type, uint32_t cacheSize)
|
||||
: mImporter(importer), mHandleType(type), mHandles(cacheSize, nullptr) {}
|
||||
|
||||
// must be initialized later with initCache
|
||||
ComposerHandleCache(ComposerHandleImporter& importer) : mImporter(importer) {}
|
||||
|
||||
~ComposerHandleCache() {
|
||||
switch (mHandleType) {
|
||||
case HandleType::BUFFER:
|
||||
for (auto handle : mHandles) {
|
||||
mImporter.freeBuffer(handle);
|
||||
}
|
||||
break;
|
||||
case HandleType::STREAM:
|
||||
for (auto handle : mHandles) {
|
||||
mImporter.freeStream(handle);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ComposerHandleCache(const ComposerHandleCache&) = delete;
|
||||
ComposerHandleCache& operator=(const ComposerHandleCache&) = delete;
|
||||
|
||||
bool initCache(HandleType type, uint32_t cacheSize) {
|
||||
// already initialized
|
||||
if (mHandleType != HandleType::INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mHandleType = type;
|
||||
mHandles.resize(cacheSize, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Error lookupCache(uint32_t slot, const native_handle_t** outHandle) {
|
||||
if (slot < mHandles.size()) {
|
||||
*outHandle = mHandles[slot];
|
||||
return Error::NONE;
|
||||
} else {
|
||||
return Error::BAD_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
Error updateCache(uint32_t slot, const native_handle_t* handle,
|
||||
const native_handle** outReplacedHandle) {
|
||||
if (slot < mHandles.size()) {
|
||||
auto& cachedHandle = mHandles[slot];
|
||||
*outReplacedHandle = cachedHandle;
|
||||
cachedHandle = handle;
|
||||
return Error::NONE;
|
||||
} else {
|
||||
return Error::BAD_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
// when fromCache is true, look up in the cache; otherwise, update the cache
|
||||
Error getHandle(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
|
||||
const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
|
||||
if (fromCache) {
|
||||
*outReplacedHandle = nullptr;
|
||||
return lookupCache(slot, outHandle);
|
||||
} else {
|
||||
*outHandle = inHandle;
|
||||
return updateCache(slot, inHandle, outReplacedHandle);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ComposerHandleImporter& mImporter;
|
||||
HandleType mHandleType = HandleType::INVALID;
|
||||
std::vector<const native_handle_t*> mHandles;
|
||||
};
|
||||
|
||||
// layer resource
|
||||
class ComposerLayerResource {
|
||||
public:
|
||||
ComposerLayerResource(ComposerHandleImporter& importer, uint32_t bufferCacheSize)
|
||||
: mBufferCache(importer, ComposerHandleCache::HandleType::BUFFER, bufferCacheSize),
|
||||
mSidebandStreamCache(importer, ComposerHandleCache::HandleType::STREAM, 1) {}
|
||||
|
||||
Error getBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
|
||||
const native_handle_t** outHandle, const native_handle** outReplacedHandle) {
|
||||
return mBufferCache.getHandle(slot, fromCache, inHandle, outHandle, outReplacedHandle);
|
||||
}
|
||||
|
||||
Error getSidebandStream(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
|
||||
const native_handle_t** outHandle,
|
||||
const native_handle** outReplacedHandle) {
|
||||
return mSidebandStreamCache.getHandle(slot, fromCache, inHandle, outHandle,
|
||||
outReplacedHandle);
|
||||
}
|
||||
|
||||
protected:
|
||||
ComposerHandleCache mBufferCache;
|
||||
ComposerHandleCache mSidebandStreamCache;
|
||||
};
|
||||
|
||||
// display resource
|
||||
class ComposerDisplayResource {
|
||||
public:
|
||||
enum class DisplayType {
|
||||
PHYSICAL,
|
||||
VIRTUAL,
|
||||
};
|
||||
|
||||
ComposerDisplayResource(DisplayType type, ComposerHandleImporter& importer,
|
||||
uint32_t outputBufferCacheSize)
|
||||
: mType(type),
|
||||
mClientTargetCache(importer),
|
||||
mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
|
||||
outputBufferCacheSize) {}
|
||||
|
||||
bool initClientTargetCache(uint32_t cacheSize) {
|
||||
return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
|
||||
}
|
||||
|
||||
bool isVirtual() const { return mType == DisplayType::VIRTUAL; }
|
||||
|
||||
Error getClientTarget(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
|
||||
const native_handle_t** outHandle,
|
||||
const native_handle** outReplacedHandle) {
|
||||
return mClientTargetCache.getHandle(slot, fromCache, inHandle, outHandle,
|
||||
outReplacedHandle);
|
||||
}
|
||||
|
||||
Error getOutputBuffer(uint32_t slot, bool fromCache, const native_handle_t* inHandle,
|
||||
const native_handle_t** outHandle,
|
||||
const native_handle** outReplacedHandle) {
|
||||
return mOutputBufferCache.getHandle(slot, fromCache, inHandle, outHandle,
|
||||
outReplacedHandle);
|
||||
}
|
||||
|
||||
bool addLayer(Layer layer, std::unique_ptr<ComposerLayerResource> layerResource) {
|
||||
auto result = mLayerResources.emplace(layer, std::move(layerResource));
|
||||
return result.second;
|
||||
}
|
||||
|
||||
bool removeLayer(Layer layer) { return mLayerResources.erase(layer) > 0; }
|
||||
|
||||
ComposerLayerResource* findLayerResource(Layer layer) {
|
||||
auto layerIter = mLayerResources.find(layer);
|
||||
if (layerIter == mLayerResources.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return layerIter->second.get();
|
||||
}
|
||||
|
||||
std::vector<Layer> getLayers() const {
|
||||
std::vector<Layer> layers;
|
||||
layers.reserve(mLayerResources.size());
|
||||
for (const auto& layerKey : mLayerResources) {
|
||||
layers.push_back(layerKey.first);
|
||||
}
|
||||
return layers;
|
||||
}
|
||||
|
||||
protected:
|
||||
const DisplayType mType;
|
||||
ComposerHandleCache mClientTargetCache;
|
||||
ComposerHandleCache mOutputBufferCache;
|
||||
|
||||
std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
|
||||
};
|
||||
|
||||
class ComposerResources {
|
||||
private:
|
||||
template <bool isBuffer>
|
||||
class ReplacedHandle;
|
||||
|
||||
public:
|
||||
static std::unique_ptr<ComposerResources> create() {
|
||||
auto resources = std::make_unique<ComposerResources>();
|
||||
return resources->init() ? std::move(resources) : nullptr;
|
||||
}
|
||||
|
||||
ComposerResources() = default;
|
||||
virtual ~ComposerResources() = default;
|
||||
|
||||
bool init() { return mImporter.init(); }
|
||||
|
||||
using RemoveDisplay =
|
||||
std::function<void(Display display, bool isVirtual, const std::vector<Layer>& layers)>;
|
||||
void clear(RemoveDisplay removeDisplay) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
for (const auto& displayKey : mDisplayResources) {
|
||||
Display display = displayKey.first;
|
||||
const ComposerDisplayResource& displayResource = *displayKey.second;
|
||||
removeDisplay(display, displayResource.isVirtual(), displayResource.getLayers());
|
||||
}
|
||||
mDisplayResources.clear();
|
||||
}
|
||||
|
||||
Error addPhysicalDisplay(Display display) {
|
||||
auto displayResource =
|
||||
createDisplayResource(ComposerDisplayResource::DisplayType::PHYSICAL, 0);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
auto result = mDisplayResources.emplace(display, std::move(displayResource));
|
||||
return result.second ? Error::NONE : Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
Error addVirtualDisplay(Display display, uint32_t outputBufferCacheSize) {
|
||||
auto displayResource = createDisplayResource(ComposerDisplayResource::DisplayType::VIRTUAL,
|
||||
outputBufferCacheSize);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
auto result = mDisplayResources.emplace(display, std::move(displayResource));
|
||||
return result.second ? Error::NONE : Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
Error removeDisplay(Display display) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
return mDisplayResources.erase(display) > 0 ? Error::NONE : Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
Error setDisplayClientTargetCacheSize(Display display, uint32_t clientTargetCacheSize) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
|
||||
if (!displayResource) {
|
||||
return Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
return displayResource->initClientTargetCache(clientTargetCacheSize) ? Error::NONE
|
||||
: Error::BAD_PARAMETER;
|
||||
}
|
||||
|
||||
Error addLayer(Display display, Layer layer, uint32_t bufferCacheSize) {
|
||||
auto layerResource = createLayerResource(bufferCacheSize);
|
||||
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
|
||||
if (!displayResource) {
|
||||
return Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
return displayResource->addLayer(layer, std::move(layerResource)) ? Error::NONE
|
||||
: Error::BAD_LAYER;
|
||||
}
|
||||
|
||||
Error removeLayer(Display display, Layer layer) {
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
|
||||
if (!displayResource) {
|
||||
return Error::BAD_DISPLAY;
|
||||
}
|
||||
|
||||
return displayResource->removeLayer(layer) ? Error::NONE : Error::BAD_LAYER;
|
||||
}
|
||||
|
||||
using ReplacedBufferHandle = ReplacedHandle<true>;
|
||||
using ReplacedStreamHandle = ReplacedHandle<false>;
|
||||
|
||||
Error getDisplayClientTarget(Display display, uint32_t slot, bool fromCache,
|
||||
const native_handle_t* rawHandle,
|
||||
const native_handle_t** outBufferHandle,
|
||||
ReplacedBufferHandle* outReplacedBuffer) {
|
||||
return getHandle<Cache::CLIENT_TARGET>(display, 0, slot, fromCache, rawHandle,
|
||||
outBufferHandle, outReplacedBuffer);
|
||||
}
|
||||
|
||||
Error getDisplayOutputBuffer(Display display, uint32_t slot, bool fromCache,
|
||||
const native_handle_t* rawHandle,
|
||||
const native_handle_t** outBufferHandle,
|
||||
ReplacedBufferHandle* outReplacedBuffer) {
|
||||
return getHandle<Cache::OUTPUT_BUFFER>(display, 0, slot, fromCache, rawHandle,
|
||||
outBufferHandle, outReplacedBuffer);
|
||||
}
|
||||
|
||||
Error getLayerBuffer(Display display, Layer layer, uint32_t slot, bool fromCache,
|
||||
const native_handle_t* rawHandle, const native_handle_t** outBufferHandle,
|
||||
ReplacedBufferHandle* outReplacedBuffer) {
|
||||
return getHandle<Cache::LAYER_BUFFER>(display, layer, slot, fromCache, rawHandle,
|
||||
outBufferHandle, outReplacedBuffer);
|
||||
}
|
||||
|
||||
Error getLayerSidebandStream(Display display, Layer layer, const native_handle_t* rawHandle,
|
||||
const native_handle_t** outStreamHandle,
|
||||
ReplacedStreamHandle* outReplacedStream) {
|
||||
return getHandle<Cache::LAYER_SIDEBAND_STREAM>(display, layer, 0, false, rawHandle,
|
||||
outStreamHandle, outReplacedStream);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
|
||||
ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
|
||||
return std::make_unique<ComposerDisplayResource>(type, mImporter, outputBufferCacheSize);
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<ComposerLayerResource> createLayerResource(uint32_t bufferCacheSize) {
|
||||
return std::make_unique<ComposerLayerResource>(mImporter, bufferCacheSize);
|
||||
}
|
||||
|
||||
ComposerDisplayResource* findDisplayResourceLocked(Display display) {
|
||||
auto iter = mDisplayResources.find(display);
|
||||
if (iter == mDisplayResources.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second.get();
|
||||
}
|
||||
|
||||
ComposerHandleImporter mImporter;
|
||||
|
||||
std::mutex mDisplayResourcesMutex;
|
||||
std::unordered_map<Display, std::unique_ptr<ComposerDisplayResource>> mDisplayResources;
|
||||
|
||||
private:
|
||||
enum class Cache {
|
||||
CLIENT_TARGET,
|
||||
OUTPUT_BUFFER,
|
||||
LAYER_BUFFER,
|
||||
LAYER_SIDEBAND_STREAM,
|
||||
};
|
||||
|
||||
// When a buffer in the cache is replaced by a new one, we must keep it
|
||||
// alive until it has been replaced in ComposerHal.
|
||||
template <bool isBuffer>
|
||||
class ReplacedHandle {
|
||||
public:
|
||||
ReplacedHandle() = default;
|
||||
ReplacedHandle(const ReplacedHandle&) = delete;
|
||||
ReplacedHandle& operator=(const ReplacedHandle&) = delete;
|
||||
|
||||
~ReplacedHandle() { reset(); }
|
||||
|
||||
void reset(ComposerHandleImporter* importer = nullptr,
|
||||
const native_handle_t* handle = nullptr) {
|
||||
if (mHandle) {
|
||||
if (isBuffer) {
|
||||
mImporter->freeBuffer(mHandle);
|
||||
} else {
|
||||
mImporter->freeStream(mHandle);
|
||||
}
|
||||
}
|
||||
|
||||
mImporter = importer;
|
||||
mHandle = handle;
|
||||
}
|
||||
|
||||
private:
|
||||
ComposerHandleImporter* mImporter = nullptr;
|
||||
const native_handle_t* mHandle = nullptr;
|
||||
};
|
||||
|
||||
template <Cache cache, bool isBuffer>
|
||||
Error getHandle(Display display, Layer layer, uint32_t slot, bool fromCache,
|
||||
const native_handle_t* rawHandle, const native_handle_t** outHandle,
|
||||
ReplacedHandle<isBuffer>* outReplacedHandle) {
|
||||
Error error;
|
||||
|
||||
// import the raw handle (or ignore raw handle when fromCache is true)
|
||||
const native_handle_t* importedHandle = nullptr;
|
||||
if (!fromCache) {
|
||||
error = (isBuffer) ? mImporter.importBuffer(rawHandle, &importedHandle)
|
||||
: mImporter.importStream(rawHandle, &importedHandle);
|
||||
if (error != Error::NONE) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
|
||||
|
||||
// find display/layer resource
|
||||
const bool needLayerResource =
|
||||
(cache == Cache::LAYER_BUFFER || cache == Cache::LAYER_SIDEBAND_STREAM);
|
||||
ComposerDisplayResource* displayResource = findDisplayResourceLocked(display);
|
||||
ComposerLayerResource* layerResource = (displayResource && needLayerResource)
|
||||
? displayResource->findLayerResource(layer)
|
||||
: nullptr;
|
||||
|
||||
// lookup or update cache
|
||||
const native_handle_t* replacedHandle = nullptr;
|
||||
if (displayResource && (!needLayerResource || layerResource)) {
|
||||
switch (cache) {
|
||||
case Cache::CLIENT_TARGET:
|
||||
error = displayResource->getClientTarget(slot, fromCache, importedHandle,
|
||||
outHandle, &replacedHandle);
|
||||
break;
|
||||
case Cache::OUTPUT_BUFFER:
|
||||
error = displayResource->getOutputBuffer(slot, fromCache, importedHandle,
|
||||
outHandle, &replacedHandle);
|
||||
break;
|
||||
case Cache::LAYER_BUFFER:
|
||||
error = layerResource->getBuffer(slot, fromCache, importedHandle, outHandle,
|
||||
&replacedHandle);
|
||||
break;
|
||||
case Cache::LAYER_SIDEBAND_STREAM:
|
||||
error = layerResource->getSidebandStream(slot, fromCache, importedHandle,
|
||||
outHandle, &replacedHandle);
|
||||
break;
|
||||
default:
|
||||
error = Error::BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error != Error::NONE) {
|
||||
ALOGW("invalid cache %d slot %d", int(cache), int(slot));
|
||||
}
|
||||
} else if (!displayResource) {
|
||||
error = Error::BAD_DISPLAY;
|
||||
} else {
|
||||
error = Error::BAD_LAYER;
|
||||
}
|
||||
|
||||
// clean up on errors
|
||||
if (error != Error::NONE) {
|
||||
if (!fromCache) {
|
||||
if (isBuffer) {
|
||||
mImporter.freeBuffer(importedHandle);
|
||||
} else {
|
||||
mImporter.freeStream(importedHandle);
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
outReplacedHandle->reset(&mImporter, replacedHandle);
|
||||
|
||||
return Error::NONE;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace hal
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
Loading…
Reference in a new issue