Merge "Allow specifying ANGLE in manifest via meta-data"
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 5a8d8db..2b0a461 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -77,6 +77,9 @@
output.writeBool(false);
}
+ memcpy(output.writeInplace(16 * sizeof(float)),
+ colorTransform.asArray(), 16 * sizeof(float));
+
return NO_ERROR;
}
@@ -130,6 +133,8 @@
sidebandStream = NativeHandle::create(input.readNativeHandle(), true);
}
+ colorTransform = mat4(static_cast<const float*>(input.readInplace(16 * sizeof(float))));
+
return NO_ERROR;
}
@@ -314,6 +319,10 @@
what |= eSidebandStreamChanged;
sidebandStream = other.sidebandStream;
}
+ if (other.what & eColorTransformChanged) {
+ what |= eColorTransformChanged;
+ colorTransform = other.colorTransform;
+ }
if ((other.what & what) != other.what) {
ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? "
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 09ea0f6..1ac9609 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -602,6 +602,18 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColorTransform(
+ const sp<SurfaceControl>& sc, const mat3& matrix, const vec3& translation) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eColorTransformChanged;
+ s->colorTransform = mat4(matrix, translation);
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 9a9f633..e06e2b1 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -23,6 +23,7 @@
#include <utils/Errors.h>
#include <gui/IGraphicBufferProducer.h>
+#include <math/mat4.h>
#include <math/vec3.h>
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
@@ -72,6 +73,7 @@
eSurfaceDamageRegionChanged = 0x02000000,
eApiChanged = 0x04000000,
eSidebandStreamChanged = 0x08000000,
+ eColorTransformChanged = 0x10000000,
};
layer_state_t()
@@ -94,7 +96,8 @@
crop(Rect::INVALID_RECT),
dataspace(ui::Dataspace::UNKNOWN),
surfaceDamageRegion(),
- api(-1) {
+ api(-1),
+ colorTransform(mat4()) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
hdrMetadata.validTypes = 0;
@@ -150,6 +153,7 @@
Region surfaceDamageRegion;
int32_t api;
sp<NativeHandle> sidebandStream;
+ mat4 colorTransform;
};
struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 314b118..69a759f 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -269,6 +269,10 @@
Transaction& destroySurface(const sp<SurfaceControl>& sc);
+ // Set a color transform matrix on the given layer on the built-in display.
+ Transaction& setColorTransform(const sp<SurfaceControl>& sc, const mat3& matrix,
+ const vec3& translation);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 69b6422..edc9131 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -13,10 +13,13 @@
// limitations under the License.
sourceFiles = [
+ "buffer_hub_base.cpp",
"buffer_hub_client.cpp",
"buffer_hub_rpc.cpp",
+ "consumer_buffer.cpp",
"detached_buffer.cpp",
"ion_buffer.cpp",
+ "producer_buffer.cpp",
]
localIncludeFiles = [
diff --git a/libs/vr/libbufferhub/buffer_hub_base.cpp b/libs/vr/libbufferhub/buffer_hub_base.cpp
new file mode 100644
index 0000000..b2bcda7
--- /dev/null
+++ b/libs/vr/libbufferhub/buffer_hub_base.cpp
@@ -0,0 +1,224 @@
+#include <poll.h>
+#include <sys/epoll.h>
+
+#include <pdx/default_transport/client_channel.h>
+#include <pdx/default_transport/client_channel_factory.h>
+#include <private/dvr/buffer_hub_base.h>
+
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+using android::pdx::default_transport::ClientChannel;
+using android::pdx::default_transport::ClientChannelFactory;
+
+namespace android {
+namespace dvr {
+
+BufferHubBase::BufferHubBase(LocalChannelHandle channel_handle)
+ : Client{pdx::default_transport::ClientChannel::Create(
+ std::move(channel_handle))},
+ id_(-1),
+ cid_(-1) {}
+BufferHubBase::BufferHubBase(const std::string& endpoint_path)
+ : Client{pdx::default_transport::ClientChannelFactory::Create(
+ endpoint_path)},
+ id_(-1),
+ cid_(-1) {}
+
+BufferHubBase::~BufferHubBase() {
+ if (metadata_header_ != nullptr) {
+ metadata_buffer_.Unlock();
+ }
+}
+
+Status<LocalChannelHandle> BufferHubBase::CreateConsumer() {
+ Status<LocalChannelHandle> status =
+ InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
+ ALOGE_IF(!status,
+ "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
+ status.GetErrorMessage().c_str());
+ return status;
+}
+
+int BufferHubBase::ImportBuffer() {
+ ATRACE_NAME("BufferHubBase::ImportBuffer");
+
+ Status<BufferDescription<LocalHandle>> status =
+ InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
+ if (!status) {
+ ALOGE("BufferHubBase::ImportBuffer: Failed to get buffer: %s",
+ status.GetErrorMessage().c_str());
+ return -status.error();
+ } else if (status.get().id() < 0) {
+ ALOGE("BufferHubBase::ImportBuffer: Received an invalid id!");
+ return -EIO;
+ }
+
+ auto buffer_desc = status.take();
+
+ // Stash the buffer id to replace the value in id_.
+ const int new_id = buffer_desc.id();
+
+ // Import the buffer.
+ IonBuffer ion_buffer;
+ ALOGD_IF(TRACE, "BufferHubBase::ImportBuffer: id=%d.", buffer_desc.id());
+
+ if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
+ return ret;
+
+ // Import the metadata.
+ IonBuffer metadata_buffer;
+ if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
+ ALOGE("Failed to import metadata buffer, error=%d", ret);
+ return ret;
+ }
+ size_t metadata_buf_size = metadata_buffer.width();
+ if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
+ ALOGE("BufferHubBase::ImportBuffer: metadata buffer too small: %zu",
+ metadata_buf_size);
+ return -ENOMEM;
+ }
+
+ // If all imports succee, replace the previous buffer and id.
+ buffer_ = std::move(ion_buffer);
+ metadata_buffer_ = std::move(metadata_buffer);
+ metadata_buf_size_ = metadata_buf_size;
+ user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
+
+ void* metadata_ptr = nullptr;
+ if (const int ret =
+ metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
+ /*y=*/0, metadata_buf_size_,
+ /*height=*/1, &metadata_ptr)) {
+ ALOGE("BufferHubBase::ImportBuffer: Failed to lock metadata.");
+ return ret;
+ }
+
+ // Set up shared fences.
+ shared_acquire_fence_ = buffer_desc.take_acquire_fence();
+ shared_release_fence_ = buffer_desc.take_release_fence();
+ if (!shared_acquire_fence_ || !shared_release_fence_) {
+ ALOGE("BufferHubBase::ImportBuffer: Failed to import shared fences.");
+ return -EIO;
+ }
+
+ metadata_header_ =
+ reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
+ if (user_metadata_size_) {
+ user_metadata_ptr_ =
+ reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
+ BufferHubDefs::kMetadataHeaderSize);
+ } else {
+ user_metadata_ptr_ = nullptr;
+ }
+
+ id_ = new_id;
+ cid_ = buffer_desc.buffer_cid();
+ buffer_state_bit_ = buffer_desc.buffer_state_bit();
+
+ // Note that here the buffer state is mapped from shared memory as an atomic
+ // object. The std::atomic's constructor will not be called so that the
+ // original value stored in the memory region will be preserved.
+ buffer_state_ = &metadata_header_->buffer_state;
+ ALOGD_IF(TRACE,
+ "BufferHubBase::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
+ id(), buffer_state_->load());
+ fence_state_ = &metadata_header_->fence_state;
+ ALOGD_IF(TRACE,
+ "BufferHubBase::ImportBuffer: id=%d, fence_state=%" PRIx64 ".", id(),
+ fence_state_->load());
+
+ return 0;
+}
+
+int BufferHubBase::CheckMetadata(size_t user_metadata_size) const {
+ if (user_metadata_size && !user_metadata_ptr_) {
+ ALOGE("BufferHubBase::CheckMetadata: doesn't support custom metadata.");
+ return -EINVAL;
+ }
+ if (user_metadata_size > user_metadata_size_) {
+ ALOGE("BufferHubBase::CheckMetadata: too big: %zu, maximum: %zu.",
+ user_metadata_size, user_metadata_size_);
+ return -E2BIG;
+ }
+ return 0;
+}
+
+int BufferHubBase::UpdateSharedFence(const LocalHandle& new_fence,
+ const LocalHandle& shared_fence) {
+ if (pending_fence_fd_.Get() != new_fence.Get()) {
+ // First, replace the old fd if there was already one. Skipping if the new
+ // one is the same as the old.
+ if (pending_fence_fd_.IsValid()) {
+ const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
+ pending_fence_fd_.Get(), nullptr);
+ ALOGW_IF(ret,
+ "BufferHubBase::UpdateSharedFence: failed to remove old fence "
+ "fd from epoll set, error: %s.",
+ strerror(errno));
+ }
+
+ if (new_fence.IsValid()) {
+ // If ready fence is valid, we put that into the epoll set.
+ epoll_event event;
+ event.events = EPOLLIN;
+ event.data.u64 = buffer_state_bit();
+ pending_fence_fd_ = new_fence.Duplicate();
+ if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
+ &event) < 0) {
+ const int error = errno;
+ ALOGE(
+ "BufferHubBase::UpdateSharedFence: failed to add new fence fd "
+ "into epoll set, error: %s.",
+ strerror(error));
+ return -error;
+ }
+ // Set bit in fence state to indicate that there is a fence from this
+ // producer or consumer.
+ fence_state_->fetch_or(buffer_state_bit());
+ } else {
+ // Unset bit in fence state to indicate that there is no fence, so that
+ // when consumer to acquire or producer to acquire, it knows no need to
+ // check fence for this buffer.
+ fence_state_->fetch_and(~buffer_state_bit());
+ }
+ }
+
+ return 0;
+}
+
+int BufferHubBase::Poll(int timeout_ms) {
+ ATRACE_NAME("BufferHubBase::Poll");
+ pollfd p = {event_fd(), POLLIN, 0};
+ return poll(&p, 1, timeout_ms);
+}
+
+int BufferHubBase::Lock(int usage, int x, int y, int width, int height,
+ void** address) {
+ return buffer_.Lock(usage, x, y, width, height, address);
+}
+
+int BufferHubBase::Unlock() { return buffer_.Unlock(); }
+
+int BufferHubBase::GetBlobReadWritePointer(size_t size, void** addr) {
+ int width = static_cast<int>(size);
+ int height = 1;
+ int ret = Lock(usage(), 0, 0, width, height, addr);
+ if (ret == 0)
+ Unlock();
+ return ret;
+}
+
+int BufferHubBase::GetBlobReadOnlyPointer(size_t size, void** addr) {
+ return GetBlobReadWritePointer(size, addr);
+}
+
+void BufferHubBase::GetBlobFds(int* fds, size_t* fds_count,
+ size_t max_fds_count) const {
+ size_t numFds = static_cast<size_t>(native_handle()->numFds);
+ *fds_count = std::min(max_fds_count, numFds);
+ std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/buffer_hub_client.cpp b/libs/vr/libbufferhub/buffer_hub_client.cpp
index 577cba9..3f20024 100644
--- a/libs/vr/libbufferhub/buffer_hub_client.cpp
+++ b/libs/vr/libbufferhub/buffer_hub_client.cpp
@@ -1,20 +1,12 @@
-#include <private/dvr/buffer_hub_client.h>
-
-#include <log/log.h>
-#include <poll.h>
-#include <sys/epoll.h>
-#include <utils/Trace.h>
-
#include <mutex>
+#include <log/log.h>
#include <pdx/default_transport/client_channel.h>
#include <pdx/default_transport/client_channel_factory.h>
-
-#include "include/private/dvr/bufferhub_rpc.h"
+#include <private/dvr/buffer_hub_client.h>
+#include <utils/Trace.h>
using android::pdx::LocalChannelHandle;
-using android::pdx::LocalHandle;
-using android::pdx::Status;
using android::pdx::default_transport::ClientChannel;
using android::pdx::default_transport::ClientChannelFactory;
@@ -39,615 +31,5 @@
}
}
-BufferHubBuffer::BufferHubBuffer(LocalChannelHandle channel_handle)
- : Client{pdx::default_transport::ClientChannel::Create(
- std::move(channel_handle))},
- id_(-1),
- cid_(-1) {}
-BufferHubBuffer::BufferHubBuffer(const std::string& endpoint_path)
- : Client{pdx::default_transport::ClientChannelFactory::Create(
- endpoint_path)},
- id_(-1),
- cid_(-1) {}
-
-BufferHubBuffer::~BufferHubBuffer() {
- if (metadata_header_ != nullptr) {
- metadata_buffer_.Unlock();
- }
-}
-
-Status<LocalChannelHandle> BufferHubBuffer::CreateConsumer() {
- Status<LocalChannelHandle> status =
- InvokeRemoteMethod<BufferHubRPC::NewConsumer>();
- ALOGE_IF(!status,
- "BufferHub::CreateConsumer: Failed to create consumer channel: %s",
- status.GetErrorMessage().c_str());
- return status;
-}
-
-int BufferHubBuffer::ImportBuffer() {
- ATRACE_NAME("BufferHubBuffer::ImportBuffer");
-
- Status<BufferDescription<LocalHandle>> status =
- InvokeRemoteMethod<BufferHubRPC::GetBuffer>();
- if (!status) {
- ALOGE("BufferHubBuffer::ImportBuffer: Failed to get buffer: %s",
- status.GetErrorMessage().c_str());
- return -status.error();
- } else if (status.get().id() < 0) {
- ALOGE("BufferHubBuffer::ImportBuffer: Received an invalid id!");
- return -EIO;
- }
-
- auto buffer_desc = status.take();
-
- // Stash the buffer id to replace the value in id_.
- const int new_id = buffer_desc.id();
-
- // Import the buffer.
- IonBuffer ion_buffer;
- ALOGD_IF(TRACE, "BufferHubBuffer::ImportBuffer: id=%d.", buffer_desc.id());
-
- if (const int ret = buffer_desc.ImportBuffer(&ion_buffer))
- return ret;
-
- // Import the metadata.
- IonBuffer metadata_buffer;
- if (const int ret = buffer_desc.ImportMetadata(&metadata_buffer)) {
- ALOGE("Failed to import metadata buffer, error=%d", ret);
- return ret;
- }
- size_t metadata_buf_size = metadata_buffer.width();
- if (metadata_buf_size < BufferHubDefs::kMetadataHeaderSize) {
- ALOGE("BufferHubBuffer::ImportBuffer: metadata buffer too small: %zu",
- metadata_buf_size);
- return -ENOMEM;
- }
-
- // If all imports succee, replace the previous buffer and id.
- buffer_ = std::move(ion_buffer);
- metadata_buffer_ = std::move(metadata_buffer);
- metadata_buf_size_ = metadata_buf_size;
- user_metadata_size_ = metadata_buf_size_ - BufferHubDefs::kMetadataHeaderSize;
-
- void* metadata_ptr = nullptr;
- if (const int ret =
- metadata_buffer_.Lock(BufferHubDefs::kMetadataUsage, /*x=*/0,
- /*y=*/0, metadata_buf_size_,
- /*height=*/1, &metadata_ptr)) {
- ALOGE("BufferHubBuffer::ImportBuffer: Failed to lock metadata.");
- return ret;
- }
-
- // Set up shared fences.
- shared_acquire_fence_ = buffer_desc.take_acquire_fence();
- shared_release_fence_ = buffer_desc.take_release_fence();
- if (!shared_acquire_fence_ || !shared_release_fence_) {
- ALOGE("BufferHubBuffer::ImportBuffer: Failed to import shared fences.");
- return -EIO;
- }
-
- metadata_header_ =
- reinterpret_cast<BufferHubDefs::MetadataHeader*>(metadata_ptr);
- if (user_metadata_size_) {
- user_metadata_ptr_ =
- reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(metadata_ptr) +
- BufferHubDefs::kMetadataHeaderSize);
- } else {
- user_metadata_ptr_ = nullptr;
- }
-
- id_ = new_id;
- cid_ = buffer_desc.buffer_cid();
- buffer_state_bit_ = buffer_desc.buffer_state_bit();
-
- // Note that here the buffer state is mapped from shared memory as an atomic
- // object. The std::atomic's constructor will not be called so that the
- // original value stored in the memory region will be preserved.
- buffer_state_ = &metadata_header_->buffer_state;
- ALOGD_IF(TRACE,
- "BufferHubBuffer::ImportBuffer: id=%d, buffer_state=%" PRIx64 ".",
- id(), buffer_state_->load());
- fence_state_ = &metadata_header_->fence_state;
- ALOGD_IF(TRACE,
- "BufferHubBuffer::ImportBuffer: id=%d, fence_state=%" PRIx64 ".",
- id(), fence_state_->load());
-
- return 0;
-}
-
-inline int BufferHubBuffer::CheckMetadata(size_t user_metadata_size) const {
- if (user_metadata_size && !user_metadata_ptr_) {
- ALOGE("BufferHubBuffer::CheckMetadata: doesn't support custom metadata.");
- return -EINVAL;
- }
- if (user_metadata_size > user_metadata_size_) {
- ALOGE("BufferHubBuffer::CheckMetadata: too big: %zu, maximum: %zu.",
- user_metadata_size, user_metadata_size_);
- return -E2BIG;
- }
- return 0;
-}
-
-int BufferHubBuffer::UpdateSharedFence(const LocalHandle& new_fence,
- const LocalHandle& shared_fence) {
- if (pending_fence_fd_.Get() != new_fence.Get()) {
- // First, replace the old fd if there was already one. Skipping if the new
- // one is the same as the old.
- if (pending_fence_fd_.IsValid()) {
- const int ret = epoll_ctl(shared_fence.Get(), EPOLL_CTL_DEL,
- pending_fence_fd_.Get(), nullptr);
- ALOGW_IF(ret,
- "BufferHubBuffer::UpdateSharedFence: failed to remove old fence "
- "fd from epoll set, error: %s.",
- strerror(errno));
- }
-
- if (new_fence.IsValid()) {
- // If ready fence is valid, we put that into the epoll set.
- epoll_event event;
- event.events = EPOLLIN;
- event.data.u64 = buffer_state_bit();
- pending_fence_fd_ = new_fence.Duplicate();
- if (epoll_ctl(shared_fence.Get(), EPOLL_CTL_ADD, pending_fence_fd_.Get(),
- &event) < 0) {
- const int error = errno;
- ALOGE(
- "BufferHubBuffer::UpdateSharedFence: failed to add new fence fd "
- "into epoll set, error: %s.",
- strerror(error));
- return -error;
- }
- // Set bit in fence state to indicate that there is a fence from this
- // producer or consumer.
- fence_state_->fetch_or(buffer_state_bit());
- } else {
- // Unset bit in fence state to indicate that there is no fence, so that
- // when consumer to acquire or producer to acquire, it knows no need to
- // check fence for this buffer.
- fence_state_->fetch_and(~buffer_state_bit());
- }
- }
-
- return 0;
-}
-
-int BufferHubBuffer::Poll(int timeout_ms) {
- ATRACE_NAME("BufferHubBuffer::Poll");
- pollfd p = {event_fd(), POLLIN, 0};
- return poll(&p, 1, timeout_ms);
-}
-
-int BufferHubBuffer::Lock(int usage, int x, int y, int width, int height,
- void** address) {
- return buffer_.Lock(usage, x, y, width, height, address);
-}
-
-int BufferHubBuffer::Unlock() { return buffer_.Unlock(); }
-
-int BufferHubBuffer::GetBlobReadWritePointer(size_t size, void** addr) {
- int width = static_cast<int>(size);
- int height = 1;
- int ret = Lock(usage(), 0, 0, width, height, addr);
- if (ret == 0)
- Unlock();
- return ret;
-}
-
-int BufferHubBuffer::GetBlobReadOnlyPointer(size_t size, void** addr) {
- return GetBlobReadWritePointer(size, addr);
-}
-
-void BufferHubBuffer::GetBlobFds(int* fds, size_t* fds_count,
- size_t max_fds_count) const {
- size_t numFds = static_cast<size_t>(native_handle()->numFds);
- *fds_count = std::min(max_fds_count, numFds);
- std::copy(native_handle()->data, native_handle()->data + *fds_count, fds);
-}
-
-BufferConsumer::BufferConsumer(LocalChannelHandle channel)
- : BASE(std::move(channel)) {
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE("BufferConsumer::BufferConsumer: Failed to import buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-std::unique_ptr<BufferConsumer> BufferConsumer::Import(
- LocalChannelHandle channel) {
- ATRACE_NAME("BufferConsumer::Import");
- ALOGD_IF(TRACE, "BufferConsumer::Import: channel=%d", channel.value());
- return BufferConsumer::Create(std::move(channel));
-}
-
-std::unique_ptr<BufferConsumer> BufferConsumer::Import(
- Status<LocalChannelHandle> status) {
- return Import(status ? status.take()
- : LocalChannelHandle{nullptr, -status.error()});
-}
-
-int BufferConsumer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
- LocalHandle* out_fence) {
- if (!out_meta)
- return -EINVAL;
-
- // Only check producer bit and this consumer buffer's particular consumer bit.
- // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
- // is not set.
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
- ALOGE("BufferConsumer::LocalAcquire: not posted, id=%d state=%" PRIx64
- " buffer_state_bit=%" PRIx64 ".",
- id(), buffer_state, buffer_state_bit());
- return -EBUSY;
- }
-
- // Copy the canonical metadata.
- void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
- memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
- // Fill in the user_metadata_ptr in address space of the local process.
- if (out_meta->user_metadata_size) {
- out_meta->user_metadata_ptr =
- reinterpret_cast<uint64_t>(user_metadata_ptr_);
- } else {
- out_meta->user_metadata_ptr = 0;
- }
-
- uint64_t fence_state = fence_state_->load();
- // If there is an acquire fence from producer, we need to return it.
- if (fence_state & BufferHubDefs::kProducerStateBit) {
- *out_fence = shared_acquire_fence_.Duplicate();
- }
-
- // Set the consumer bit unique to this consumer.
- BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
- return 0;
-}
-
-int BufferConsumer::Acquire(LocalHandle* ready_fence) {
- return Acquire(ready_fence, nullptr, 0);
-}
-
-int BufferConsumer::Acquire(LocalHandle* ready_fence, void* meta,
- size_t user_metadata_size) {
- ATRACE_NAME("BufferConsumer::Acquire");
-
- if (const int error = CheckMetadata(user_metadata_size))
- return error;
-
- DvrNativeBufferMetadata canonical_meta;
- if (const int error = LocalAcquire(&canonical_meta, ready_fence))
- return error;
-
- if (meta && user_metadata_size) {
- void* metadata_src =
- reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
- if (metadata_src) {
- memcpy(meta, metadata_src, user_metadata_size);
- } else {
- ALOGW("BufferConsumer::Acquire: no user-defined metadata.");
- }
- }
-
- auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
- if (!status)
- return -status.error();
- return 0;
-}
-
-int BufferConsumer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
- LocalHandle* out_fence) {
- ATRACE_NAME("BufferConsumer::AcquireAsync");
-
- if (const int error = LocalAcquire(out_meta, out_fence))
- return error;
-
- auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
- if (!status)
- return -status.error();
- return 0;
-}
-
-int BufferConsumer::LocalRelease(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence) {
- if (const int error = CheckMetadata(meta->user_metadata_size))
- return error;
-
- // Check invalid state transition.
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
- ALOGE("BufferConsumer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
- id(), buffer_state);
- return -EBUSY;
- }
-
- // On release, only the user requested metadata is copied back into the shared
- // memory for metadata. Since there are multiple consumers, it doesn't make
- // sense to send the canonical metadata back to the producer. However, one of
- // the consumer can still choose to write up to user_metadata_size bytes of
- // data into user_metadata_ptr.
- if (meta->user_metadata_ptr && meta->user_metadata_size) {
- void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
- memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
- }
-
- // Send out the release fence through the shared epoll fd. Note that during
- // releasing the producer is not expected to be polling on the fence.
- if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
- return error;
-
- // For release operation, the client don't need to change the state as it's
- // bufferhubd's job to flip the produer bit once all consumers are released.
- return 0;
-}
-
-int BufferConsumer::Release(const LocalHandle& release_fence) {
- ATRACE_NAME("BufferConsumer::Release");
-
- DvrNativeBufferMetadata meta;
- if (const int error = LocalRelease(&meta, release_fence))
- return error;
-
- return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
- BorrowedFence(release_fence.Borrow())));
-}
-
-int BufferConsumer::ReleaseAsync() {
- DvrNativeBufferMetadata meta;
- return ReleaseAsync(&meta, LocalHandle());
-}
-
-int BufferConsumer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence) {
- ATRACE_NAME("BufferConsumer::ReleaseAsync");
-
- if (const int error = LocalRelease(meta, release_fence))
- return error;
-
- return ReturnStatusOrError(
- SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
-}
-
-int BufferConsumer::Discard() { return Release(LocalHandle()); }
-
-int BufferConsumer::SetIgnore(bool ignore) {
- return ReturnStatusOrError(
- InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
-}
-
-BufferProducer::BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t usage, size_t user_metadata_size)
- : BASE(BufferHubRPC::kClientPath) {
- ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE,
- "BufferProducer::BufferProducer: fd=%d width=%u height=%u format=%u "
- "usage=%" PRIx64 " user_metadata_size=%zu",
- event_fd(), width, height, format, usage, user_metadata_size);
-
- auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, user_metadata_size);
- if (!status) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to create producer buffer: %s",
- status.GetErrorMessage().c_str());
- Close(-status.error());
- return;
- }
-
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-BufferProducer::BufferProducer(uint64_t usage, size_t size)
- : BASE(BufferHubRPC::kClientPath) {
- ATRACE_NAME("BufferProducer::BufferProducer");
- ALOGD_IF(TRACE, "BufferProducer::BufferProducer: usage=%" PRIx64 " size=%zu",
- usage, size);
- const int width = static_cast<int>(size);
- const int height = 1;
- const int format = HAL_PIXEL_FORMAT_BLOB;
- const size_t user_metadata_size = 0;
-
- auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
- width, height, format, usage, user_metadata_size);
- if (!status) {
- ALOGE("BufferProducer::BufferProducer: Failed to create blob: %s",
- status.GetErrorMessage().c_str());
- Close(-status.error());
- return;
- }
-
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-BufferProducer::BufferProducer(LocalChannelHandle channel)
- : BASE(std::move(channel)) {
- const int ret = ImportBuffer();
- if (ret < 0) {
- ALOGE(
- "BufferProducer::BufferProducer: Failed to import producer buffer: %s",
- strerror(-ret));
- Close(ret);
- }
-}
-
-int BufferProducer::LocalPost(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence) {
- if (const int error = CheckMetadata(meta->user_metadata_size))
- return error;
-
- // Check invalid state transition.
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferGained(buffer_state)) {
- ALOGE("BufferProducer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
- id(), buffer_state);
- return -EBUSY;
- }
-
- // Copy the canonical metadata.
- void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
- memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
- // Copy extra user requested metadata.
- if (meta->user_metadata_ptr && meta->user_metadata_size) {
- void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
- memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
- }
-
- // Send out the acquire fence through the shared epoll fd. Note that during
- // posting no consumer is not expected to be polling on the fence.
- if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
- return error;
-
- // Set the producer bit atomically to transit into posted state.
- BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
- BufferHubDefs::kProducerStateBit);
- return 0;
-}
-
-int BufferProducer::Post(const LocalHandle& ready_fence, const void* meta,
- size_t user_metadata_size) {
- ATRACE_NAME("BufferProducer::Post");
-
- // Populate cononical metadata for posting.
- DvrNativeBufferMetadata canonical_meta;
- canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
- canonical_meta.user_metadata_size = user_metadata_size;
-
- if (const int error = LocalPost(&canonical_meta, ready_fence))
- return error;
-
- return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
- BorrowedFence(ready_fence.Borrow())));
-}
-
-int BufferProducer::PostAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence) {
- ATRACE_NAME("BufferProducer::PostAsync");
-
- if (const int error = LocalPost(meta, ready_fence))
- return error;
-
- return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
-}
-
-int BufferProducer::LocalGain(DvrNativeBufferMetadata* out_meta,
- LocalHandle* out_fence) {
- uint64_t buffer_state = buffer_state_->load();
- ALOGD_IF(TRACE, "BufferProducer::LocalGain: buffer=%d, state=%" PRIx64 ".",
- id(), buffer_state);
-
- if (!out_meta)
- return -EINVAL;
-
- if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
- if (BufferHubDefs::IsBufferGained(buffer_state)) {
- // We don't want to log error when gaining a newly allocated
- // buffer.
- ALOGI("BufferProducer::LocalGain: already gained id=%d.", id());
- return -EALREADY;
- }
- ALOGE("BufferProducer::LocalGain: not released id=%d state=%" PRIx64 ".",
- id(), buffer_state);
- return -EBUSY;
- }
-
- // Canonical metadata is undefined on Gain. Except for user_metadata and
- // release_fence_mask. Fill in the user_metadata_ptr in address space of the
- // local process.
- if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
- out_meta->user_metadata_size =
- metadata_header_->metadata.user_metadata_size;
- out_meta->user_metadata_ptr =
- reinterpret_cast<uint64_t>(user_metadata_ptr_);
- } else {
- out_meta->user_metadata_size = 0;
- out_meta->user_metadata_ptr = 0;
- }
-
- uint64_t fence_state = fence_state_->load();
- // If there is an release fence from consumer, we need to return it.
- if (fence_state & BufferHubDefs::kConsumerStateMask) {
- *out_fence = shared_release_fence_.Duplicate();
- out_meta->release_fence_mask =
- fence_state & BufferHubDefs::kConsumerStateMask;
- }
-
- // Clear out all bits and the buffer is now back to gained state.
- buffer_state_->store(0ULL);
- return 0;
-}
-
-int BufferProducer::Gain(LocalHandle* release_fence) {
- ATRACE_NAME("BufferProducer::Gain");
-
- DvrNativeBufferMetadata meta;
- if (const int error = LocalGain(&meta, release_fence))
- return error;
-
- auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
- if (!status)
- return -status.error();
- return 0;
-}
-
-int BufferProducer::GainAsync(DvrNativeBufferMetadata* out_meta,
- LocalHandle* release_fence) {
- ATRACE_NAME("BufferProducer::GainAsync");
-
- if (const int error = LocalGain(out_meta, release_fence))
- return error;
-
- return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
-}
-
-int BufferProducer::GainAsync() {
- DvrNativeBufferMetadata meta;
- LocalHandle fence;
- return GainAsync(&meta, &fence);
-}
-
-std::unique_ptr<BufferProducer> BufferProducer::Import(
- LocalChannelHandle channel) {
- ALOGD_IF(TRACE, "BufferProducer::Import: channel=%d", channel.value());
- return BufferProducer::Create(std::move(channel));
-}
-
-std::unique_ptr<BufferProducer> BufferProducer::Import(
- Status<LocalChannelHandle> status) {
- return Import(status ? status.take()
- : LocalChannelHandle{nullptr, -status.error()});
-}
-
-Status<LocalChannelHandle> BufferProducer::Detach() {
- uint64_t buffer_state = buffer_state_->load();
- if (!BufferHubDefs::IsBufferGained(buffer_state)) {
- // Can only detach a BufferProducer when it's in gained state.
- ALOGW("BufferProducer::Detach: The buffer (id=%d, state=0x%" PRIx64
- ") is not in gained state.",
- id(), buffer_state);
- return {};
- }
-
- Status<LocalChannelHandle> status =
- InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
- ALOGE_IF(!status,
- "BufferProducer::Detach: Failed to detach buffer (id=%d): %s.", id(),
- status.GetErrorMessage().c_str());
- return status;
-}
-
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
new file mode 100644
index 0000000..4e8c36b
--- /dev/null
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -0,0 +1,183 @@
+#include <private/dvr/consumer_buffer.h>
+
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+ConsumerBuffer::ConsumerBuffer(LocalChannelHandle channel)
+ : BASE(std::move(channel)) {
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE("ConsumerBuffer::ConsumerBuffer: Failed to import buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import(
+ LocalChannelHandle channel) {
+ ATRACE_NAME("ConsumerBuffer::Import");
+ ALOGD_IF(TRACE, "ConsumerBuffer::Import: channel=%d", channel.value());
+ return ConsumerBuffer::Create(std::move(channel));
+}
+
+std::unique_ptr<ConsumerBuffer> ConsumerBuffer::Import(
+ Status<LocalChannelHandle> status) {
+ return Import(status ? status.take()
+ : LocalChannelHandle{nullptr, -status.error()});
+}
+
+int ConsumerBuffer::LocalAcquire(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* out_fence) {
+ if (!out_meta)
+ return -EINVAL;
+
+ // Only check producer bit and this consumer buffer's particular consumer bit.
+ // The buffer is can be acquired iff: 1) producer bit is set; 2) consumer bit
+ // is not set.
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferPosted(buffer_state, buffer_state_bit())) {
+ ALOGE("ConsumerBuffer::LocalAcquire: not posted, id=%d state=%" PRIx64
+ " buffer_state_bit=%" PRIx64 ".",
+ id(), buffer_state, buffer_state_bit());
+ return -EBUSY;
+ }
+
+ // Copy the canonical metadata.
+ void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
+ memcpy(out_meta, metadata_ptr, sizeof(DvrNativeBufferMetadata));
+ // Fill in the user_metadata_ptr in address space of the local process.
+ if (out_meta->user_metadata_size) {
+ out_meta->user_metadata_ptr =
+ reinterpret_cast<uint64_t>(user_metadata_ptr_);
+ } else {
+ out_meta->user_metadata_ptr = 0;
+ }
+
+ uint64_t fence_state = fence_state_->load();
+ // If there is an acquire fence from producer, we need to return it.
+ if (fence_state & BufferHubDefs::kProducerStateBit) {
+ *out_fence = shared_acquire_fence_.Duplicate();
+ }
+
+ // Set the consumer bit unique to this consumer.
+ BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL, buffer_state_bit());
+ return 0;
+}
+
+int ConsumerBuffer::Acquire(LocalHandle* ready_fence) {
+ return Acquire(ready_fence, nullptr, 0);
+}
+
+int ConsumerBuffer::Acquire(LocalHandle* ready_fence, void* meta,
+ size_t user_metadata_size) {
+ ATRACE_NAME("ConsumerBuffer::Acquire");
+
+ if (const int error = CheckMetadata(user_metadata_size))
+ return error;
+
+ DvrNativeBufferMetadata canonical_meta;
+ if (const int error = LocalAcquire(&canonical_meta, ready_fence))
+ return error;
+
+ if (meta && user_metadata_size) {
+ void* metadata_src =
+ reinterpret_cast<void*>(canonical_meta.user_metadata_ptr);
+ if (metadata_src) {
+ memcpy(meta, metadata_src, user_metadata_size);
+ } else {
+ ALOGW("ConsumerBuffer::Acquire: no user-defined metadata.");
+ }
+ }
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::ConsumerAcquire>();
+ if (!status)
+ return -status.error();
+ return 0;
+}
+
+int ConsumerBuffer::AcquireAsync(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* out_fence) {
+ ATRACE_NAME("ConsumerBuffer::AcquireAsync");
+
+ if (const int error = LocalAcquire(out_meta, out_fence))
+ return error;
+
+ auto status = SendImpulse(BufferHubRPC::ConsumerAcquire::Opcode);
+ if (!status)
+ return -status.error();
+ return 0;
+}
+
+int ConsumerBuffer::LocalRelease(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence) {
+ if (const int error = CheckMetadata(meta->user_metadata_size))
+ return error;
+
+ // Check invalid state transition.
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferAcquired(buffer_state)) {
+ ALOGE("ConsumerBuffer::LocalRelease: not acquired id=%d state=%" PRIx64 ".",
+ id(), buffer_state);
+ return -EBUSY;
+ }
+
+ // On release, only the user requested metadata is copied back into the shared
+ // memory for metadata. Since there are multiple consumers, it doesn't make
+ // sense to send the canonical metadata back to the producer. However, one of
+ // the consumer can still choose to write up to user_metadata_size bytes of
+ // data into user_metadata_ptr.
+ if (meta->user_metadata_ptr && meta->user_metadata_size) {
+ void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
+ memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
+ }
+
+ // Send out the release fence through the shared epoll fd. Note that during
+ // releasing the producer is not expected to be polling on the fence.
+ if (const int error = UpdateSharedFence(release_fence, shared_release_fence_))
+ return error;
+
+ // For release operation, the client don't need to change the state as it's
+ // bufferhubd's job to flip the produer bit once all consumers are released.
+ return 0;
+}
+
+int ConsumerBuffer::Release(const LocalHandle& release_fence) {
+ ATRACE_NAME("ConsumerBuffer::Release");
+
+ DvrNativeBufferMetadata meta;
+ if (const int error = LocalRelease(&meta, release_fence))
+ return error;
+
+ return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ConsumerRelease>(
+ BorrowedFence(release_fence.Borrow())));
+}
+
+int ConsumerBuffer::ReleaseAsync() {
+ DvrNativeBufferMetadata meta;
+ return ReleaseAsync(&meta, LocalHandle());
+}
+
+int ConsumerBuffer::ReleaseAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence) {
+ ATRACE_NAME("ConsumerBuffer::ReleaseAsync");
+
+ if (const int error = LocalRelease(meta, release_fence))
+ return error;
+
+ return ReturnStatusOrError(
+ SendImpulse(BufferHubRPC::ConsumerRelease::Opcode));
+}
+
+int ConsumerBuffer::Discard() { return Release(LocalHandle()); }
+
+int ConsumerBuffer::SetIgnore(bool ignore) {
+ return ReturnStatusOrError(
+ InvokeRemoteMethod<BufferHubRPC::ConsumerSetIgnore>(ignore));
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
new file mode 100644
index 0000000..b75fd61
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_base.h
@@ -0,0 +1,167 @@
+#ifndef ANDROID_DVR_BUFFER_HUB_BASE_H_
+#define ANDROID_DVR_BUFFER_HUB_BASE_H_
+
+#include <vector>
+
+#include <private/dvr/bufferhub_rpc.h>
+
+namespace android {
+namespace dvr {
+
+// Base class of two types of BufferHub clients: dvr::ProducerBuffer and
+// dvr::ConsumerBuffer.
+class BufferHubBase : public pdx::Client {
+ public:
+ using LocalHandle = pdx::LocalHandle;
+ using LocalChannelHandle = pdx::LocalChannelHandle;
+ template <typename T>
+ using Status = pdx::Status<T>;
+
+ // Create a new consumer channel that is attached to the producer. Returns
+ // a file descriptor for the new channel or a negative error code.
+ Status<LocalChannelHandle> CreateConsumer();
+
+ // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
+ int Poll(int timeout_ms);
+
+ // Locks the area specified by (x, y, width, height) for a specific usage. If
+ // the usage is software then |addr| will be updated to point to the address
+ // of the buffer in virtual memory. The caller should only access/modify the
+ // pixels in the specified area. anything else is undefined behavior.
+ int Lock(int usage, int x, int y, int width, int height, void** addr);
+
+ // Must be called after Lock() when the caller has finished changing the
+ // buffer.
+ int Unlock();
+
+ // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
+ // Locking and Unlocking is handled internally. There's no need to Unlock
+ // after calling this method.
+ int GetBlobReadWritePointer(size_t size, void** addr);
+
+ // Gets a blob buffer that was created with ProducerBuffer::CreateBlob.
+ // Locking and Unlocking is handled internally. There's no need to Unlock
+ // after calling this method.
+ int GetBlobReadOnlyPointer(size_t size, void** addr);
+
+ // Returns a dup'd file descriptor for accessing the blob shared memory. The
+ // caller takes ownership of the file descriptor and must close it or pass on
+ // ownership. Some GPU API extensions can take file descriptors to bind shared
+ // memory gralloc buffers to GPU buffer objects.
+ LocalHandle GetBlobFd() const {
+ // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
+ // vendors and this is the wrong fd, late-latching and EDS will very clearly
+ // stop working and we will need to correct this. The alternative is to use
+ // a GL context in the pose service to allocate this buffer or to use the
+ // ION API directly instead of gralloc.
+ return LocalHandle(dup(native_handle()->data[0]));
+ }
+
+ // Get up to |max_fds_count| file descriptors for accessing the blob shared
+ // memory. |fds_count| will contain the actual number of file descriptors.
+ void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
+
+ using Client::event_fd;
+
+ Status<int> GetEventMask(int events) {
+ if (auto* client_channel = GetChannel()) {
+ return client_channel->GetEventMask(events);
+ } else {
+ return pdx::ErrorStatus(EINVAL);
+ }
+ }
+
+ std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
+ if (auto* client_channel = GetChannel()) {
+ return client_channel->GetEventSources();
+ } else {
+ return {};
+ }
+ }
+
+ native_handle_t* native_handle() const {
+ return const_cast<native_handle_t*>(buffer_.handle());
+ }
+
+ IonBuffer* buffer() { return &buffer_; }
+ const IonBuffer* buffer() const { return &buffer_; }
+
+ // Gets ID of the buffer client. All BufferHub clients derived from the same
+ // buffer in bufferhubd share the same buffer id.
+ int id() const { return id_; }
+
+ // Gets the channel id of the buffer client. Each BufferHub client has its
+ // system unique channel id.
+ int cid() const { return cid_; }
+
+ // Returns the buffer buffer state.
+ uint64_t buffer_state() { return buffer_state_->load(); };
+
+ // A state mask which is unique to a buffer hub client among all its siblings
+ // sharing the same concrete graphic buffer.
+ uint64_t buffer_state_bit() const { return buffer_state_bit_; }
+
+ // The following methods return settings of the first buffer. Currently,
+ // it is only possible to create multi-buffer BufferHubBases with the same
+ // settings.
+ uint32_t width() const { return buffer_.width(); }
+ uint32_t height() const { return buffer_.height(); }
+ uint32_t stride() const { return buffer_.stride(); }
+ uint32_t format() const { return buffer_.format(); }
+ uint32_t usage() const { return buffer_.usage(); }
+ uint32_t layer_count() const { return buffer_.layer_count(); }
+
+ uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
+ void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
+
+ protected:
+ explicit BufferHubBase(LocalChannelHandle channel);
+ explicit BufferHubBase(const std::string& endpoint_path);
+ virtual ~BufferHubBase();
+
+ // Initialization helper.
+ int ImportBuffer();
+
+ // Check invalid metadata operation. Returns 0 if requested metadata is valid.
+ int CheckMetadata(size_t user_metadata_size) const;
+
+ // Send out the new fence by updating the shared fence (shared_release_fence
+ // for producer and shared_acquire_fence for consumer). Note that during this
+ // should only be used in LocalPost() or LocalRelease, and the shared fence
+ // shouldn't be poll'ed by the other end.
+ int UpdateSharedFence(const LocalHandle& new_fence,
+ const LocalHandle& shared_fence);
+
+ // IonBuffer that is shared between bufferhubd, producer, and consumers.
+ size_t metadata_buf_size_{0};
+ size_t user_metadata_size_{0};
+ BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
+ void* user_metadata_ptr_{nullptr};
+ std::atomic<uint64_t>* buffer_state_{nullptr};
+ std::atomic<uint64_t>* fence_state_{nullptr};
+
+ LocalHandle shared_acquire_fence_;
+ LocalHandle shared_release_fence_;
+
+ // A local fence fd that holds the ownership of the fence fd on Post (for
+ // producer) and Release (for consumer).
+ LocalHandle pending_fence_fd_;
+
+ private:
+ BufferHubBase(const BufferHubBase&) = delete;
+ void operator=(const BufferHubBase&) = delete;
+
+ // Global id for the buffer that is consistent across processes. It is meant
+ // for logging and debugging purposes only and should not be used for lookup
+ // or any other functional purpose as a security precaution.
+ int id_;
+ int cid_;
+ uint64_t buffer_state_bit_{0ULL};
+ IonBuffer buffer_;
+ IonBuffer metadata_buffer_;
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_BUFFER_HUB_BASE_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
index 0b2666a..7b317d1 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_client.h
@@ -1,17 +1,10 @@
#ifndef ANDROID_DVR_BUFFER_HUB_CLIENT_H_
#define ANDROID_DVR_BUFFER_HUB_CLIENT_H_
-#include <hardware/gralloc.h>
#include <pdx/channel_handle.h>
#include <pdx/client.h>
-#include <pdx/file_handle.h>
-#include <pdx/status.h>
-
-#include <vector>
-
-#include <private/dvr/ion_buffer.h>
-
-#include "bufferhub_rpc.h"
+#include <private/dvr/consumer_buffer.h>
+#include <private/dvr/producer_buffer.h>
namespace android {
namespace dvr {
@@ -31,322 +24,6 @@
using pdx::Client::event_fd;
};
-class BufferHubBuffer : public pdx::Client {
- public:
- using LocalHandle = pdx::LocalHandle;
- using LocalChannelHandle = pdx::LocalChannelHandle;
- template <typename T>
- using Status = pdx::Status<T>;
-
- // Create a new consumer channel that is attached to the producer. Returns
- // a file descriptor for the new channel or a negative error code.
- Status<LocalChannelHandle> CreateConsumer();
-
- // Polls the fd for |timeout_ms| milliseconds (-1 for infinity).
- int Poll(int timeout_ms);
-
- // Locks the area specified by (x, y, width, height) for a specific usage. If
- // the usage is software then |addr| will be updated to point to the address
- // of the buffer in virtual memory. The caller should only access/modify the
- // pixels in the specified area. anything else is undefined behavior.
- int Lock(int usage, int x, int y, int width, int height, void** addr);
-
- // Must be called after Lock() when the caller has finished changing the
- // buffer.
- int Unlock();
-
- // Gets a blob buffer that was created with BufferProducer::CreateBlob.
- // Locking and Unlocking is handled internally. There's no need to Unlock
- // after calling this method.
- int GetBlobReadWritePointer(size_t size, void** addr);
-
- // Gets a blob buffer that was created with BufferProducer::CreateBlob.
- // Locking and Unlocking is handled internally. There's no need to Unlock
- // after calling this method.
- int GetBlobReadOnlyPointer(size_t size, void** addr);
-
- // Returns a dup'd file descriptor for accessing the blob shared memory. The
- // caller takes ownership of the file descriptor and must close it or pass on
- // ownership. Some GPU API extensions can take file descriptors to bind shared
- // memory gralloc buffers to GPU buffer objects.
- LocalHandle GetBlobFd() const {
- // Current GPU vendor puts the buffer allocation in one FD. If we change GPU
- // vendors and this is the wrong fd, late-latching and EDS will very clearly
- // stop working and we will need to correct this. The alternative is to use
- // a GL context in the pose service to allocate this buffer or to use the
- // ION API directly instead of gralloc.
- return LocalHandle(dup(native_handle()->data[0]));
- }
-
- // Get up to |max_fds_count| file descriptors for accessing the blob shared
- // memory. |fds_count| will contain the actual number of file descriptors.
- void GetBlobFds(int* fds, size_t* fds_count, size_t max_fds_count) const;
-
- using Client::event_fd;
-
- Status<int> GetEventMask(int events) {
- if (auto* client_channel = GetChannel()) {
- return client_channel->GetEventMask(events);
- } else {
- return pdx::ErrorStatus(EINVAL);
- }
- }
-
- std::vector<pdx::ClientChannel::EventSource> GetEventSources() const {
- if (auto* client_channel = GetChannel()) {
- return client_channel->GetEventSources();
- } else {
- return {};
- }
- }
-
- native_handle_t* native_handle() const {
- return const_cast<native_handle_t*>(buffer_.handle());
- }
-
- IonBuffer* buffer() { return &buffer_; }
- const IonBuffer* buffer() const { return &buffer_; }
-
- // Gets ID of the buffer client. All BufferHubBuffer clients derived from the
- // same buffer in bufferhubd share the same buffer id.
- int id() const { return id_; }
-
- // Gets the channel id of the buffer client. Each BufferHubBuffer client has
- // its system unique channel id.
- int cid() const { return cid_; }
-
- // Returns the buffer buffer state.
- uint64_t buffer_state() { return buffer_state_->load(); };
-
- // A state mask which is unique to a buffer hub client among all its siblings
- // sharing the same concrete graphic buffer.
- uint64_t buffer_state_bit() const { return buffer_state_bit_; }
-
- // The following methods return settings of the first buffer. Currently,
- // it is only possible to create multi-buffer BufferHubBuffers with the same
- // settings.
- uint32_t width() const { return buffer_.width(); }
- uint32_t height() const { return buffer_.height(); }
- uint32_t stride() const { return buffer_.stride(); }
- uint32_t format() const { return buffer_.format(); }
- uint32_t usage() const { return buffer_.usage(); }
- uint32_t layer_count() const { return buffer_.layer_count(); }
-
- uint64_t GetQueueIndex() const { return metadata_header_->queue_index; }
- void SetQueueIndex(uint64_t index) { metadata_header_->queue_index = index; }
-
- protected:
- explicit BufferHubBuffer(LocalChannelHandle channel);
- explicit BufferHubBuffer(const std::string& endpoint_path);
- virtual ~BufferHubBuffer();
-
- // Initialization helper.
- int ImportBuffer();
-
- // Check invalid metadata operation. Returns 0 if requested metadata is valid.
- int CheckMetadata(size_t user_metadata_size) const;
-
- // Send out the new fence by updating the shared fence (shared_release_fence
- // for producer and shared_acquire_fence for consumer). Note that during this
- // should only be used in LocalPost() or LocalRelease, and the shared fence
- // shouldn't be poll'ed by the other end.
- int UpdateSharedFence(const LocalHandle& new_fence,
- const LocalHandle& shared_fence);
-
- // IonBuffer that is shared between bufferhubd, producer, and consumers.
- size_t metadata_buf_size_{0};
- size_t user_metadata_size_{0};
- BufferHubDefs::MetadataHeader* metadata_header_{nullptr};
- void* user_metadata_ptr_{nullptr};
- std::atomic<uint64_t>* buffer_state_{nullptr};
- std::atomic<uint64_t>* fence_state_{nullptr};
-
- LocalHandle shared_acquire_fence_;
- LocalHandle shared_release_fence_;
-
- // A local fence fd that holds the ownership of the fence fd on Post (for
- // producer) and Release (for consumer).
- LocalHandle pending_fence_fd_;
-
- private:
- BufferHubBuffer(const BufferHubBuffer&) = delete;
- void operator=(const BufferHubBuffer&) = delete;
-
- // Global id for the buffer that is consistent across processes. It is meant
- // for logging and debugging purposes only and should not be used for lookup
- // or any other functional purpose as a security precaution.
- int id_;
- int cid_;
- uint64_t buffer_state_bit_{0ULL};
- IonBuffer buffer_;
- IonBuffer metadata_buffer_;
-};
-
-// This represents a writable buffer. Calling Post notifies all clients and
-// makes the buffer read-only. Call Gain to acquire write access. A buffer
-// may have many consumers.
-//
-// The user of BufferProducer is responsible with making sure that the Post() is
-// done with the correct metadata type and size. The user is also responsible
-// for making sure that remote ends (BufferConsumers) are also using the correct
-// metadata when acquiring the buffer. The API guarantees that a Post() with a
-// metadata of wrong size will fail. However, it currently does not do any
-// type checking.
-// The API also assumes that metadata is a serializable type (plain old data).
-class BufferProducer : public pdx::ClientBase<BufferProducer, BufferHubBuffer> {
- public:
- // Imports a bufferhub producer channel, assuming ownership of its handle.
- static std::unique_ptr<BufferProducer> Import(LocalChannelHandle channel);
- static std::unique_ptr<BufferProducer> Import(
- Status<LocalChannelHandle> status);
-
- // Asynchronously posts a buffer. The fence and metadata are passed to
- // consumer via shared fd and shared memory.
- int PostAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence);
-
- // Post this buffer, passing |ready_fence| to the consumers. The bytes in
- // |meta| are passed unaltered to the consumers. The producer must not modify
- // the buffer until it is re-gained.
- // This returns zero or a negative unix error code.
- int Post(const LocalHandle& ready_fence, const void* meta,
- size_t user_metadata_size);
-
- int Post(const LocalHandle& ready_fence) {
- return Post(ready_fence, nullptr, 0);
- }
-
- template <typename Meta, typename = typename std::enable_if<
- !std::is_void<Meta>::value>::type>
- int Post(const LocalHandle& ready_fence, const Meta& meta) {
- return Post(ready_fence, &meta, sizeof(meta));
- }
-
- // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
- // must be waited on before using the buffer. If it is not valid then the
- // buffer is free for immediate use. This call will only succeed if the buffer
- // is in the released state.
- // This returns zero or a negative unix error code.
- int Gain(LocalHandle* release_fence);
- int GainAsync();
-
- // Asynchronously marks a released buffer as gained. This method is similar to
- // the synchronous version above, except that it does not wait for BufferHub
- // to acknowledge success or failure. Because of the asynchronous nature of
- // the underlying message, no error is returned if this method is called when
- // the buffer is in an incorrect state. Returns zero if sending the message
- // succeeded, or a negative errno code if local error check fails.
- int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
-
- // Detaches a ProducerBuffer from an existing producer/consumer set. Can only
- // be called when a producer buffer has exclusive access to the buffer (i.e.
- // in the gain'ed state). On the successful return of the IPC call, a new
- // LocalChannelHandle representing a detached buffer will be returned and all
- // existing producer and consumer channels will be closed. Further IPCs
- // towards those channels will return error.
- Status<LocalChannelHandle> Detach();
-
- private:
- friend BASE;
-
- // Constructors are automatically exposed through BufferProducer::Create(...)
- // static template methods inherited from ClientBase, which take the same
- // arguments as the constructors.
-
- // Constructs a buffer with the given geometry and parameters.
- BufferProducer(uint32_t width, uint32_t height, uint32_t format,
- uint64_t usage, size_t metadata_size = 0);
-
- // Constructs a blob (flat) buffer with the given usage flags.
- BufferProducer(uint64_t usage, size_t size);
-
- // Imports the given file handle to a producer channel, taking ownership.
- explicit BufferProducer(LocalChannelHandle channel);
-
- // Local state transition helpers.
- int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
- int LocalPost(const DvrNativeBufferMetadata* meta,
- const LocalHandle& ready_fence);
-};
-
-// This is a connection to a producer buffer, which can be located in another
-// application. When that buffer is Post()ed, this fd will be signaled and
-// Acquire allows read access. The user is responsible for making sure that
-// Acquire is called with the correct metadata structure. The only guarantee the
-// API currently provides is that an Acquire() with metadata of the wrong size
-// will fail.
-class BufferConsumer : public pdx::ClientBase<BufferConsumer, BufferHubBuffer> {
- public:
- // This call assumes ownership of |fd|.
- static std::unique_ptr<BufferConsumer> Import(LocalChannelHandle channel);
- static std::unique_ptr<BufferConsumer> Import(
- Status<LocalChannelHandle> status);
-
- // Attempt to retrieve a post event from buffer hub. If successful,
- // |ready_fence| will be set to a fence to wait on until the buffer is ready.
- // This call will only succeed after the fd is signalled. This call may be
- // performed as an alternative to the Acquire() with metadata. In such cases
- // the metadata is not read.
- //
- // This returns zero or negative unix error code.
- int Acquire(LocalHandle* ready_fence);
-
- // Attempt to retrieve a post event from buffer hub. If successful,
- // |ready_fence| is set to a fence signaling that the contents of the buffer
- // are available. This call will only succeed if the buffer is in the posted
- // state.
- // Returns zero on success, or a negative errno code otherwise.
- int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
-
- // Attempt to retrieve a post event from buffer hub. If successful,
- // |ready_fence| is set to a fence to wait on until the buffer is ready. This
- // call will only succeed after the fd is signaled. This returns zero or a
- // negative unix error code.
- template <typename Meta>
- int Acquire(LocalHandle* ready_fence, Meta* meta) {
- return Acquire(ready_fence, meta, sizeof(*meta));
- }
-
- // Asynchronously acquires a bufer.
- int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
-
- // This should be called after a successful Acquire call. If the fence is
- // valid the fence determines the buffer usage, otherwise the buffer is
- // released immediately.
- // This returns zero or a negative unix error code.
- int Release(const LocalHandle& release_fence);
- int ReleaseAsync();
-
- // Asynchronously releases a buffer. Similar to the synchronous version above,
- // except that it does not wait for BufferHub to reply with success or error.
- // The fence and metadata are passed to consumer via shared fd and shared
- // memory.
- int ReleaseAsync(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence);
-
- // May be called after or instead of Acquire to indicate that the consumer
- // does not need to access the buffer this cycle. This returns zero or a
- // negative unix error code.
- int Discard();
-
- // When set, this consumer is no longer notified when this buffer is
- // available. The system behaves as if Discard() is immediately called
- // whenever the buffer is posted. If ignore is set to true while a buffer is
- // pending, it will act as if Discard() was also called.
- // This returns zero or a negative unix error code.
- int SetIgnore(bool ignore);
-
- private:
- friend BASE;
-
- explicit BufferConsumer(LocalChannelHandle channel);
-
- // Local state transition helpers.
- int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
- int LocalRelease(const DvrNativeBufferMetadata* meta,
- const LocalHandle& release_fence);
-};
-
} // namespace dvr
} // namespace android
diff --git a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
index e163216..225914a 100644
--- a/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
+++ b/libs/vr/libbufferhub/include/private/dvr/bufferhub_rpc.h
@@ -113,13 +113,15 @@
BufferDescription(BufferDescription&& other) = default;
BufferDescription& operator=(BufferDescription&& other) = default;
- // ID of the buffer client. All BufferHubBuffer clients derived from the same
- // buffer in bufferhubd share the same buffer id.
+ // ID of the buffer client. All BufferHub clients derived from the same buffer
+ // in bufferhubd share the same buffer id.
int id() const { return id_; }
- // Channel ID of the buffer client. Each BufferHubBuffer client has its system
+
+ // Channel ID of the buffer client. Each BufferHub client has its system
// unique channel id.
int buffer_cid() const { return buffer_cid_; }
- // State mask of the buffer client. Each BufferHubBuffer client backed by the
+
+ // State mask of the buffer client. Each BufferHub client backed by the
// same buffer channel has uniqued state bit among its siblings. For a
// producer buffer the bit must be kProducerStateBit; for a consumer the bit
// must be one of the kConsumerStateMask.
diff --git a/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
new file mode 100644
index 0000000..089eff8
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/consumer_buffer.h
@@ -0,0 +1,100 @@
+#ifndef ANDROID_DVR_CONSUMER_BUFFER_H_
+#define ANDROID_DVR_CONSUMER_BUFFER_H_
+
+#include <private/dvr/buffer_hub_base.h>
+
+namespace android {
+namespace dvr {
+
+// BufferConsumer was originally poorly named and gets easily confused with
+// IGraphicBufferConsumer. Actually, BufferConsumer is a single buffer that can
+// consume (i.e. read) data from a buffer, but it doesn't consume buffer. On
+// the other hand, IGraphicBufferConsumer is the consumer end of a BufferQueue
+// and it is used to consume buffers.
+//
+// TODO(b/116855254): Remove this typedef once rename is complete in other
+// projects and/or branches.
+typedef class ConsumerBuffer BufferConsumer;
+
+// This is a connection to a producer buffer, which can be located in another
+// application. When that buffer is Post()ed, this fd will be signaled and
+// Acquire allows read access. The user is responsible for making sure that
+// Acquire is called with the correct metadata structure. The only guarantee the
+// API currently provides is that an Acquire() with metadata of the wrong size
+// will fail.
+class ConsumerBuffer : public pdx::ClientBase<ConsumerBuffer, BufferHubBase> {
+ public:
+ // This call assumes ownership of |fd|.
+ static std::unique_ptr<ConsumerBuffer> Import(LocalChannelHandle channel);
+ static std::unique_ptr<ConsumerBuffer> Import(
+ Status<LocalChannelHandle> status);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| will be set to a fence to wait on until the buffer is ready.
+ // This call will only succeed after the fd is signalled. This call may be
+ // performed as an alternative to the Acquire() with metadata. In such cases
+ // the metadata is not read.
+ //
+ // This returns zero or negative unix error code.
+ int Acquire(LocalHandle* ready_fence);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| is set to a fence signaling that the contents of the buffer
+ // are available. This call will only succeed if the buffer is in the posted
+ // state.
+ // Returns zero on success, or a negative errno code otherwise.
+ int Acquire(LocalHandle* ready_fence, void* meta, size_t user_metadata_size);
+
+ // Attempt to retrieve a post event from buffer hub. If successful,
+ // |ready_fence| is set to a fence to wait on until the buffer is ready. This
+ // call will only succeed after the fd is signaled. This returns zero or a
+ // negative unix error code.
+ template <typename Meta>
+ int Acquire(LocalHandle* ready_fence, Meta* meta) {
+ return Acquire(ready_fence, meta, sizeof(*meta));
+ }
+
+ // Asynchronously acquires a bufer.
+ int AcquireAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+
+ // This should be called after a successful Acquire call. If the fence is
+ // valid the fence determines the buffer usage, otherwise the buffer is
+ // released immediately.
+ // This returns zero or a negative unix error code.
+ int Release(const LocalHandle& release_fence);
+ int ReleaseAsync();
+
+ // Asynchronously releases a buffer. Similar to the synchronous version above,
+ // except that it does not wait for BufferHub to reply with success or error.
+ // The fence and metadata are passed to consumer via shared fd and shared
+ // memory.
+ int ReleaseAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence);
+
+ // May be called after or instead of Acquire to indicate that the consumer
+ // does not need to access the buffer this cycle. This returns zero or a
+ // negative unix error code.
+ int Discard();
+
+ // When set, this consumer is no longer notified when this buffer is
+ // available. The system behaves as if Discard() is immediately called
+ // whenever the buffer is posted. If ignore is set to true while a buffer is
+ // pending, it will act as if Discard() was also called.
+ // This returns zero or a negative unix error code.
+ int SetIgnore(bool ignore);
+
+ private:
+ friend BASE;
+
+ explicit ConsumerBuffer(LocalChannelHandle channel);
+
+ // Local state transition helpers.
+ int LocalAcquire(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+ int LocalRelease(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& release_fence);
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_CONSUMER_BUFFER_H_
diff --git a/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
new file mode 100644
index 0000000..b5e1c5b
--- /dev/null
+++ b/libs/vr/libbufferhub/include/private/dvr/producer_buffer.h
@@ -0,0 +1,109 @@
+#ifndef ANDROID_DVR_PRODUCER_BUFFER_H_
+#define ANDROID_DVR_PRODUCER_BUFFER_H_
+
+#include <private/dvr/buffer_hub_base.h>
+
+namespace android {
+namespace dvr {
+
+// BufferProducer was originally poorly named and gets easily confused with
+// IGraphicBufferProducer. Actually, BufferProducer is a single buffer that can
+// produce (i.e. write) data into a buffer, but it doesn't produce buffer. On
+// the other hand, IGraphicBufferProducer is the producer end of a BufferQueue
+// and it is used to produce buffers.
+//
+// TODO(b/116855254): Remove this typedef once rename is complete in other
+// projects and/or branches.
+typedef class ProducerBuffer BufferProducer;
+
+// This represents a writable buffer. Calling Post notifies all clients and
+// makes the buffer read-only. Call Gain to acquire write access. A buffer
+// may have many consumers.
+//
+// The user of ProducerBuffer is responsible with making sure that the Post() is
+// done with the correct metadata type and size. The user is also responsible
+// for making sure that remote ends (BufferConsumers) are also using the correct
+// metadata when acquiring the buffer. The API guarantees that a Post() with a
+// metadata of wrong size will fail. However, it currently does not do any
+// type checking.
+// The API also assumes that metadata is a serializable type (plain old data).
+class ProducerBuffer : public pdx::ClientBase<ProducerBuffer, BufferHubBase> {
+ public:
+ // Imports a bufferhub producer channel, assuming ownership of its handle.
+ static std::unique_ptr<ProducerBuffer> Import(LocalChannelHandle channel);
+ static std::unique_ptr<ProducerBuffer> Import(
+ Status<LocalChannelHandle> status);
+
+ // Asynchronously posts a buffer. The fence and metadata are passed to
+ // consumer via shared fd and shared memory.
+ int PostAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence);
+
+ // Post this buffer, passing |ready_fence| to the consumers. The bytes in
+ // |meta| are passed unaltered to the consumers. The producer must not modify
+ // the buffer until it is re-gained.
+ // This returns zero or a negative unix error code.
+ int Post(const LocalHandle& ready_fence, const void* meta,
+ size_t user_metadata_size);
+
+ int Post(const LocalHandle& ready_fence) {
+ return Post(ready_fence, nullptr, 0);
+ }
+
+ template <typename Meta, typename = typename std::enable_if<
+ !std::is_void<Meta>::value>::type>
+ int Post(const LocalHandle& ready_fence, const Meta& meta) {
+ return Post(ready_fence, &meta, sizeof(meta));
+ }
+
+ // Attempt to re-gain the buffer for writing. If |release_fence| is valid, it
+ // must be waited on before using the buffer. If it is not valid then the
+ // buffer is free for immediate use. This call will only succeed if the buffer
+ // is in the released state.
+ // This returns zero or a negative unix error code.
+ int Gain(LocalHandle* release_fence);
+ int GainAsync();
+
+ // Asynchronously marks a released buffer as gained. This method is similar to
+ // the synchronous version above, except that it does not wait for BufferHub
+ // to acknowledge success or failure. Because of the asynchronous nature of
+ // the underlying message, no error is returned if this method is called when
+ // the buffer is in an incorrect state. Returns zero if sending the message
+ // succeeded, or a negative errno code if local error check fails.
+ int GainAsync(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+
+ // Detaches a ProducerBuffer from an existing producer/consumer set. Can only
+ // be called when a producer buffer has exclusive access to the buffer (i.e.
+ // in the gain'ed state). On the successful return of the IPC call, a new
+ // LocalChannelHandle representing a detached buffer will be returned and all
+ // existing producer and consumer channels will be closed. Further IPCs
+ // towards those channels will return error.
+ Status<LocalChannelHandle> Detach();
+
+ private:
+ friend BASE;
+
+ // Constructors are automatically exposed through ProducerBuffer::Create(...)
+ // static template methods inherited from ClientBase, which take the same
+ // arguments as the constructors.
+
+ // Constructs a buffer with the given geometry and parameters.
+ ProducerBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t usage, size_t metadata_size = 0);
+
+ // Constructs a blob (flat) buffer with the given usage flags.
+ ProducerBuffer(uint64_t usage, size_t size);
+
+ // Imports the given file handle to a producer channel, taking ownership.
+ explicit ProducerBuffer(LocalChannelHandle channel);
+
+ // Local state transition helpers.
+ int LocalGain(DvrNativeBufferMetadata* out_meta, LocalHandle* out_fence);
+ int LocalPost(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence);
+};
+
+} // namespace dvr
+} // namespace android
+
+#endif // ANDROID_DVR_PRODUCER_BUFFER_H_
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
new file mode 100644
index 0000000..c4f1a3b
--- /dev/null
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -0,0 +1,243 @@
+#include <private/dvr/producer_buffer.h>
+
+using android::pdx::LocalChannelHandle;
+using android::pdx::LocalHandle;
+using android::pdx::Status;
+
+namespace android {
+namespace dvr {
+
+ProducerBuffer::ProducerBuffer(uint32_t width, uint32_t height, uint32_t format,
+ uint64_t usage, size_t user_metadata_size)
+ : BASE(BufferHubRPC::kClientPath) {
+ ATRACE_NAME("ProducerBuffer::ProducerBuffer");
+ ALOGD_IF(TRACE,
+ "ProducerBuffer::ProducerBuffer: fd=%d width=%u height=%u format=%u "
+ "usage=%" PRIx64 " user_metadata_size=%zu",
+ event_fd(), width, height, format, usage, user_metadata_size);
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
+ width, height, format, usage, user_metadata_size);
+ if (!status) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to create producer buffer: %s",
+ status.GetErrorMessage().c_str());
+ Close(-status.error());
+ return;
+ }
+
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+ProducerBuffer::ProducerBuffer(uint64_t usage, size_t size)
+ : BASE(BufferHubRPC::kClientPath) {
+ ATRACE_NAME("ProducerBuffer::ProducerBuffer");
+ ALOGD_IF(TRACE, "ProducerBuffer::ProducerBuffer: usage=%" PRIx64 " size=%zu",
+ usage, size);
+ const int width = static_cast<int>(size);
+ const int height = 1;
+ const int format = HAL_PIXEL_FORMAT_BLOB;
+ const size_t user_metadata_size = 0;
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::CreateBuffer>(
+ width, height, format, usage, user_metadata_size);
+ if (!status) {
+ ALOGE("ProducerBuffer::ProducerBuffer: Failed to create blob: %s",
+ status.GetErrorMessage().c_str());
+ Close(-status.error());
+ return;
+ }
+
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+ProducerBuffer::ProducerBuffer(LocalChannelHandle channel)
+ : BASE(std::move(channel)) {
+ const int ret = ImportBuffer();
+ if (ret < 0) {
+ ALOGE(
+ "ProducerBuffer::ProducerBuffer: Failed to import producer buffer: %s",
+ strerror(-ret));
+ Close(ret);
+ }
+}
+
+int ProducerBuffer::LocalPost(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence) {
+ if (const int error = CheckMetadata(meta->user_metadata_size))
+ return error;
+
+ // Check invalid state transition.
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferGained(buffer_state)) {
+ ALOGE("ProducerBuffer::LocalPost: not gained, id=%d state=%" PRIx64 ".",
+ id(), buffer_state);
+ return -EBUSY;
+ }
+
+ // Copy the canonical metadata.
+ void* metadata_ptr = reinterpret_cast<void*>(&metadata_header_->metadata);
+ memcpy(metadata_ptr, meta, sizeof(DvrNativeBufferMetadata));
+ // Copy extra user requested metadata.
+ if (meta->user_metadata_ptr && meta->user_metadata_size) {
+ void* metadata_src = reinterpret_cast<void*>(meta->user_metadata_ptr);
+ memcpy(user_metadata_ptr_, metadata_src, meta->user_metadata_size);
+ }
+
+ // Send out the acquire fence through the shared epoll fd. Note that during
+ // posting no consumer is not expected to be polling on the fence.
+ if (const int error = UpdateSharedFence(ready_fence, shared_acquire_fence_))
+ return error;
+
+ // Set the producer bit atomically to transit into posted state.
+ BufferHubDefs::ModifyBufferState(buffer_state_, 0ULL,
+ BufferHubDefs::kProducerStateBit);
+ return 0;
+}
+
+int ProducerBuffer::Post(const LocalHandle& ready_fence, const void* meta,
+ size_t user_metadata_size) {
+ ATRACE_NAME("ProducerBuffer::Post");
+
+ // Populate cononical metadata for posting.
+ DvrNativeBufferMetadata canonical_meta;
+ canonical_meta.user_metadata_ptr = reinterpret_cast<uint64_t>(meta);
+ canonical_meta.user_metadata_size = user_metadata_size;
+
+ if (const int error = LocalPost(&canonical_meta, ready_fence))
+ return error;
+
+ return ReturnStatusOrError(InvokeRemoteMethod<BufferHubRPC::ProducerPost>(
+ BorrowedFence(ready_fence.Borrow())));
+}
+
+int ProducerBuffer::PostAsync(const DvrNativeBufferMetadata* meta,
+ const LocalHandle& ready_fence) {
+ ATRACE_NAME("ProducerBuffer::PostAsync");
+
+ if (const int error = LocalPost(meta, ready_fence))
+ return error;
+
+ return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerPost::Opcode));
+}
+
+int ProducerBuffer::LocalGain(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* out_fence) {
+ uint64_t buffer_state = buffer_state_->load();
+ ALOGD_IF(TRACE, "ProducerBuffer::LocalGain: buffer=%d, state=%" PRIx64 ".",
+ id(), buffer_state);
+
+ if (!out_meta)
+ return -EINVAL;
+
+ if (!BufferHubDefs::IsBufferReleased(buffer_state)) {
+ if (BufferHubDefs::IsBufferGained(buffer_state)) {
+ // We don't want to log error when gaining a newly allocated
+ // buffer.
+ ALOGI("ProducerBuffer::LocalGain: already gained id=%d.", id());
+ return -EALREADY;
+ }
+ ALOGE("ProducerBuffer::LocalGain: not released id=%d state=%" PRIx64 ".",
+ id(), buffer_state);
+ return -EBUSY;
+ }
+
+ // Canonical metadata is undefined on Gain. Except for user_metadata and
+ // release_fence_mask. Fill in the user_metadata_ptr in address space of the
+ // local process.
+ if (metadata_header_->metadata.user_metadata_size && user_metadata_ptr_) {
+ out_meta->user_metadata_size =
+ metadata_header_->metadata.user_metadata_size;
+ out_meta->user_metadata_ptr =
+ reinterpret_cast<uint64_t>(user_metadata_ptr_);
+ } else {
+ out_meta->user_metadata_size = 0;
+ out_meta->user_metadata_ptr = 0;
+ }
+
+ uint64_t fence_state = fence_state_->load();
+ // If there is an release fence from consumer, we need to return it.
+ if (fence_state & BufferHubDefs::kConsumerStateMask) {
+ *out_fence = shared_release_fence_.Duplicate();
+ out_meta->release_fence_mask =
+ fence_state & BufferHubDefs::kConsumerStateMask;
+ }
+
+ // Clear out all bits and the buffer is now back to gained state.
+ buffer_state_->store(0ULL);
+ return 0;
+}
+
+int ProducerBuffer::Gain(LocalHandle* release_fence) {
+ ATRACE_NAME("ProducerBuffer::Gain");
+
+ DvrNativeBufferMetadata meta;
+ if (const int error = LocalGain(&meta, release_fence))
+ return error;
+
+ auto status = InvokeRemoteMethod<BufferHubRPC::ProducerGain>();
+ if (!status)
+ return -status.error();
+ return 0;
+}
+
+int ProducerBuffer::GainAsync(DvrNativeBufferMetadata* out_meta,
+ LocalHandle* release_fence) {
+ ATRACE_NAME("ProducerBuffer::GainAsync");
+
+ if (const int error = LocalGain(out_meta, release_fence))
+ return error;
+
+ return ReturnStatusOrError(SendImpulse(BufferHubRPC::ProducerGain::Opcode));
+}
+
+int ProducerBuffer::GainAsync() {
+ DvrNativeBufferMetadata meta;
+ LocalHandle fence;
+ return GainAsync(&meta, &fence);
+}
+
+std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
+ LocalChannelHandle channel) {
+ ALOGD_IF(TRACE, "ProducerBuffer::Import: channel=%d", channel.value());
+ return ProducerBuffer::Create(std::move(channel));
+}
+
+std::unique_ptr<ProducerBuffer> ProducerBuffer::Import(
+ Status<LocalChannelHandle> status) {
+ return Import(status ? status.take()
+ : LocalChannelHandle{nullptr, -status.error()});
+}
+
+Status<LocalChannelHandle> ProducerBuffer::Detach() {
+ uint64_t buffer_state = buffer_state_->load();
+ if (!BufferHubDefs::IsBufferGained(buffer_state)) {
+ // Can only detach a ProducerBuffer when it's in gained state.
+ ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx64
+ ") is not in gained state.",
+ id(), buffer_state);
+ return {};
+ }
+
+ Status<LocalChannelHandle> status =
+ InvokeRemoteMethod<BufferHubRPC::ProducerBufferDetach>();
+ ALOGE_IF(!status,
+ "ProducerBuffer::Detach: Failed to detach buffer (id=%d): %s.", id(),
+ status.GetErrorMessage().c_str());
+ return status;
+}
+
+} // namespace dvr
+} // namespace android
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index 44276ba..e1c1aa9 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -278,7 +278,7 @@
}
Status<void> BufferHubQueue::AddBuffer(
- const std::shared_ptr<BufferHubBuffer>& buffer, size_t slot) {
+ const std::shared_ptr<BufferHubBase>& buffer, size_t slot) {
ALOGD_IF(TRACE, "BufferHubQueue::AddBuffer: buffer_id=%d slot=%zu",
buffer->id(), slot);
@@ -356,8 +356,8 @@
}
}
-Status<std::shared_ptr<BufferHubBuffer>> BufferHubQueue::Dequeue(int timeout,
- size_t* slot) {
+Status<std::shared_ptr<BufferHubBase>> BufferHubQueue::Dequeue(int timeout,
+ size_t* slot) {
ALOGD_IF(TRACE, "BufferHubQueue::Dequeue: count=%zu, timeout=%d", count(),
timeout);
@@ -372,7 +372,7 @@
PDX_TRACE_FORMAT("buffer|buffer_id=%d;slot=%zu|", entry.buffer->id(),
entry.slot);
- std::shared_ptr<BufferHubBuffer> buffer = std::move(entry.buffer);
+ std::shared_ptr<BufferHubBase> buffer = std::move(entry.buffer);
*slot = entry.slot;
available_buffers_.pop();
diff --git a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
index df500b4..c69002d 100644
--- a/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
+++ b/libs/vr/libbufferhubqueue/include/private/dvr/buffer_hub_queue_client.h
@@ -31,13 +31,13 @@
class ConsumerQueue;
-// |BufferHubQueue| manages a queue of |BufferHubBuffer|s. Buffers are
+// |BufferHubQueue| manages a queue of |BufferHubBase|s. Buffers are
// automatically re-requeued when released by the remote side.
class BufferHubQueue : public pdx::Client {
public:
using BufferAvailableCallback = std::function<void()>;
using BufferRemovedCallback =
- std::function<void(const std::shared_ptr<BufferHubBuffer>&)>;
+ std::function<void(const std::shared_ptr<BufferHubBase>&)>;
virtual ~BufferHubQueue() {}
@@ -93,7 +93,7 @@
: -1;
}
- std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
+ std::shared_ptr<BufferHubBase> GetBuffer(size_t slot) const {
return buffers_[slot];
}
@@ -142,7 +142,7 @@
// Register a buffer for management by the queue. Used by subclasses to add a
// buffer to internal bookkeeping.
- pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBuffer>& buffer,
+ pdx::Status<void> AddBuffer(const std::shared_ptr<BufferHubBase>& buffer,
size_t slot);
// Called by ProducerQueue::RemoveBuffer and ConsumerQueue::RemoveBuffer only
@@ -158,8 +158,8 @@
// block. Specifying a timeout of -1 causes Dequeue() to block indefinitely,
// while specifying a timeout equal to zero cause Dequeue() to return
// immediately, even if no buffers are available.
- pdx::Status<std::shared_ptr<BufferHubBuffer>> Dequeue(int timeout,
- size_t* slot);
+ pdx::Status<std::shared_ptr<BufferHubBase>> Dequeue(int timeout,
+ size_t* slot);
// Waits for buffers to become available and adds them to the available queue.
bool WaitForBuffers(int timeout);
@@ -172,10 +172,10 @@
// per-buffer data.
struct Entry {
Entry() : slot(0) {}
- Entry(const std::shared_ptr<BufferHubBuffer>& in_buffer, size_t in_slot,
+ Entry(const std::shared_ptr<BufferHubBase>& in_buffer, size_t in_slot,
uint64_t in_index)
: buffer(in_buffer), slot(in_slot), index(in_index) {}
- Entry(const std::shared_ptr<BufferHubBuffer>& in_buffer,
+ Entry(const std::shared_ptr<BufferHubBase>& in_buffer,
std::unique_ptr<uint8_t[]> in_metadata, pdx::LocalHandle in_fence,
size_t in_slot)
: buffer(in_buffer),
@@ -185,7 +185,7 @@
Entry(Entry&&) = default;
Entry& operator=(Entry&&) = default;
- std::shared_ptr<BufferHubBuffer> buffer;
+ std::shared_ptr<BufferHubBase> buffer;
std::unique_ptr<uint8_t[]> metadata;
pdx::LocalHandle fence;
size_t slot;
@@ -250,7 +250,7 @@
// Tracks the buffers belonging to this queue. Buffers are stored according to
// "slot" in this vector. Each slot is a logical id of the buffer within this
// queue regardless of its queue position or presence in the ring buffer.
- std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;
+ std::array<std::shared_ptr<BufferHubBase>, kMaxQueueCapacity> buffers_;
// Buffers and related data that are available for dequeue.
std::priority_queue<Entry, std::vector<Entry>, EntryComparator>
diff --git a/libs/vr/libdvr/dvr_buffer_queue.cpp b/libs/vr/libdvr/dvr_buffer_queue.cpp
index 571558a..f4c6600 100644
--- a/libs/vr/libdvr/dvr_buffer_queue.cpp
+++ b/libs/vr/libdvr/dvr_buffer_queue.cpp
@@ -9,7 +9,7 @@
using namespace android;
using android::dvr::BufferConsumer;
-using android::dvr::BufferHubBuffer;
+using android::dvr::BufferHubBase;
using android::dvr::BufferProducer;
using android::dvr::ConsumerQueue;
using android::dvr::ProducerQueue;
@@ -439,7 +439,7 @@
consumer_queue_->SetBufferRemovedCallback(nullptr);
} else {
consumer_queue_->SetBufferRemovedCallback(
- [callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) {
+ [callback, context](const std::shared_ptr<BufferHubBase>& buffer) {
// When buffer is removed from the queue, the slot is already invalid.
auto read_buffer = std::make_unique<DvrReadBuffer>();
read_buffer->read_buffer =
diff --git a/libs/vr/libdvr/dvr_internal.h b/libs/vr/libdvr/dvr_internal.h
index de8bb96..df8125a 100644
--- a/libs/vr/libdvr/dvr_internal.h
+++ b/libs/vr/libdvr/dvr_internal.h
@@ -16,8 +16,11 @@
namespace android {
namespace dvr {
-class BufferProducer;
-class BufferConsumer;
+// TODO(b/116855254): Remove this typedef once rename is complete in libdvr.
+// Note that the dvr::BufferProducer and dvr::BufferConsumer were poorly named,
+// they should really be named as ProducerBuffer and ConsumerBuffer.
+typedef class ProducerBuffer BufferProducer;
+typedef class ConsumerBuffer BufferConsumer;
class IonBuffer;
DvrBuffer* CreateDvrBufferFromIonBuffer(
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 642ed2f..cafe26b 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -258,6 +258,7 @@
getBE().compositionInfo.hwc.dataspace = mCurrentDataSpace;
getBE().compositionInfo.hwc.hdrMetadata = getDrawingHdrMetadata();
getBE().compositionInfo.hwc.supportedPerFrameMetadata = display->getSupportedPerFrameMetadata();
+ getBE().compositionInfo.hwc.colorTransform = getColorTransform();
setHwcLayerBuffer(display);
}
@@ -319,7 +320,8 @@
return true;
}
-Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
ATRACE_CALL();
std::optional<Region> sidebandStreamDirtyRegion = latchSidebandStream(recomputeVisibleRegions);
@@ -360,7 +362,7 @@
return dirtyRegion;
}
- status_t err = updateTexImage(recomputeVisibleRegions, latchTime);
+ status_t err = updateTexImage(recomputeVisibleRegions, latchTime, releaseFence);
if (err != NO_ERROR) {
return dirtyRegion;
}
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 92bf132..a294793 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -91,7 +91,11 @@
// the visible regions need to be recomputed (this is a fairly heavy
// operation, so this should be set only if needed). Typically this is used
// to figure out if the content or size of a surface has changed.
- Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ // If there was a GL composition step rendering the previous frame, then
+ // releaseFence will be populated with a native fence that fires when
+ // composition has completed.
+ Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
bool isBufferLatched() const override { return mRefreshPending; }
@@ -135,7 +139,8 @@
virtual void setFilteringEnabled(bool enabled) = 0;
virtual status_t bindTextureImage() const = 0;
- virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
+ virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& flushFence) = 0;
virtual status_t updateActiveBuffer() = 0;
virtual status_t updateFrameNumber(nsecs_t latchTime) = 0;
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index fa181ad..f499f06 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -147,7 +147,8 @@
status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
bool* autoRefresh, bool* queuedBuffer,
- uint64_t maxFrameNumber) {
+ uint64_t maxFrameNumber,
+ const sp<Fence>& releaseFence) {
ATRACE_CALL();
BLC_LOGV("updateTexImage");
Mutex::Autolock lock(mMutex);
@@ -198,12 +199,12 @@
}
// Release the previous buffer.
- err = updateAndReleaseLocked(item, &mPendingRelease);
+ err = updateAndReleaseLocked(item, &mPendingRelease, releaseFence);
if (err != NO_ERROR) {
return err;
}
- if (mRE.useNativeFenceSync()) {
+ if (!mRE.useNativeFenceSync()) {
// Bind the new buffer to the GL texture.
//
// Older devices require the "implicit" synchronization provided
@@ -278,14 +279,15 @@
}
status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease) {
+ PendingRelease* pendingRelease,
+ const sp<Fence>& releaseFence) {
status_t err = NO_ERROR;
int slot = item.mSlot;
// Do whatever sync ops we need to do before releasing the old slot.
if (slot != mCurrentTexture) {
- err = syncForReleaseLocked();
+ err = syncForReleaseLocked(releaseFence);
if (err != NO_ERROR) {
// Release the buffer we just acquired. It's not safe to
// release the old buffer, so instead we just drop the new frame.
@@ -367,19 +369,19 @@
return doFenceWaitLocked();
}
-status_t BufferLayerConsumer::syncForReleaseLocked() {
+status_t BufferLayerConsumer::syncForReleaseLocked(const sp<Fence>& releaseFence) {
BLC_LOGV("syncForReleaseLocked");
if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- if (mRE.useNativeFenceSync()) {
- base::unique_fd fenceFd = mRE.flush();
- if (fenceFd == -1) {
+ if (mRE.useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
+ // TODO(alecmouri): fail further upstream if the fence is invalid
+ if (!releaseFence->isValid()) {
BLC_LOGE("syncForReleaseLocked: failed to flush RenderEngine");
return UNKNOWN_ERROR;
}
- sp<Fence> fence(new Fence(std::move(fenceFd)));
- status_t err = addReleaseFenceLocked(mCurrentTexture,
- mCurrentTextureImage->graphicBuffer(), fence);
+ status_t err =
+ addReleaseFenceLocked(mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
+ releaseFence);
if (err != OK) {
BLC_LOGE("syncForReleaseLocked: error adding release fence: "
"%s (%d)",
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index 257a4e5..dc00487 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -94,7 +94,8 @@
// used to reject the newly acquired buffer. It also does not bind the
// RenderEngine texture until bindTextureImage is called.
status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, bool* autoRefresh,
- bool* queuedBuffer, uint64_t maxFrameNumber);
+ bool* queuedBuffer, uint64_t maxFrameNumber,
+ const sp<Fence>& releaseFence);
// See BufferLayerConsumer::bindTextureImageLocked().
status_t bindTextureImage();
@@ -208,7 +209,8 @@
// completion of the method will instead be returned to the caller, so that
// it may call releaseBufferLocked itself later.
status_t updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease = nullptr);
+ PendingRelease* pendingRelease = nullptr,
+ const sp<Fence>& releaseFence = Fence::NO_FENCE);
// Binds mTexName and the current buffer to TEXTURE_EXTERNAL target. Uses
// mCurrentTexture if it's set, mCurrentTextureImage if not. If the
@@ -282,7 +284,7 @@
// current slot from RenderEngine. If needed it will set the current
// slot's fence to guard against a producer accessing the buffer before
// the outstanding accesses have completed.
- status_t syncForReleaseLocked();
+ status_t syncForReleaseLocked(const sp<Fence>& releaseFence);
// The default consumer usage flags that BufferLayerConsumer always sets on its
// BufferQueue instance; these will be OR:d with any additional flags passed
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 17706b5..6822298 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -221,7 +221,8 @@
return mConsumer->bindTextureImage();
}
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) {
+status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
// This boolean is used to make sure that SurfaceFlinger's shadow copy
// of the buffer queue isn't modified when the buffer queue is returning
// BufferItem's that weren't actually queued. This can happen in shared
@@ -232,7 +233,7 @@
getTransformToDisplayInverse(), mFreezeGeometryUpdates);
status_t updateResult =
mConsumer->updateTexImage(&r, *mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived);
+ mLastFrameNumberReceived, releaseFence);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 051b15d..dcf39ee 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -90,7 +90,8 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() const override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 9c10868..2ecf71c 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -377,7 +377,8 @@
return NO_ERROR;
}
-status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
const State& s(getDrawingState());
if (!s.buffer) {
@@ -419,16 +420,13 @@
}
// Handle sync fences
- if (SyncFeatures::getInstance().useNativeFenceSync()) {
- base::unique_fd fenceFd = engine.flush();
- if (fenceFd == -1) {
- ALOGE("failed to flush RenderEngine");
+ if (SyncFeatures::getInstance().useNativeFenceSync() && releaseFence != Fence::NO_FENCE) {
+ // TODO(alecmouri): Fail somewhere upstream if the fence is invalid.
+ if (!releaseFence->isValid()) {
mTimeStats.clearLayerRecord(getName().c_str());
return UNKNOWN_ERROR;
}
- sp<Fence> fence(new Fence(std::move(fenceFd)));
-
// Check status of fences first because merging is expensive.
// Merging an invalid fence with any other fence results in an
// invalid fence.
@@ -439,10 +437,10 @@
return BAD_VALUE;
}
- auto incomingStatus = fence->getStatus();
+ auto incomingStatus = releaseFence->getStatus();
if (incomingStatus == Fence::Status::Invalid) {
ALOGE("New fence has invalid state");
- mDrawingState.acquireFence = fence;
+ mDrawingState.acquireFence = releaseFence;
mTimeStats.clearLayerRecord(getName().c_str());
return BAD_VALUE;
}
@@ -452,12 +450,13 @@
if (currentStatus == incomingStatus) {
char fenceName[32] = {};
snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
- sp<Fence> mergedFence = Fence::merge(fenceName, mDrawingState.acquireFence, fence);
+ sp<Fence> mergedFence =
+ Fence::merge(fenceName, mDrawingState.acquireFence, releaseFence);
if (!mergedFence.get()) {
ALOGE("failed to merge release fences");
// synchronization is broken, the best we can do is hope fences
// signal in order so the new fence will act like a union
- mDrawingState.acquireFence = fence;
+ mDrawingState.acquireFence = releaseFence;
mTimeStats.clearLayerRecord(getName().c_str());
return BAD_VALUE;
}
@@ -470,7 +469,7 @@
// by this point, they will have both signaled and only the timestamp
// will be slightly off; any dependencies after this point will
// already have been met.
- mDrawingState.acquireFence = fence;
+ mDrawingState.acquireFence = releaseFence;
}
} else {
// Bind the new buffer to the GL texture.
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index b662b96..db11110 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -115,7 +115,8 @@
void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() const override;
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index b02c16c..3a554c9 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -75,6 +75,7 @@
// Clear out the transform, because it doesn't make sense absent a source buffer
getBE().compositionInfo.hwc.transform = HWC2::Transform::None;
+ getBE().compositionInfo.hwc.colorTransform = getColorTransform();
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f9bc1e7..8afd3b3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1546,6 +1546,25 @@
return true;
}
+bool Layer::setColorTransform(const mat4& matrix) {
+ if (mCurrentState.colorTransform == matrix) {
+ return false;
+ }
+ ++mCurrentState.sequence;
+ mCurrentState.colorTransform = matrix;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+const mat4& Layer::getColorTransform() const {
+ return getDrawingState().colorTransform;
+}
+
+bool Layer::hasColorTransform() const {
+ static const mat4 identityMatrix = mat4();
+ return getDrawingState().colorTransform != identityMatrix;
+}
+
bool Layer::isLegacyDataSpace() const {
// return true when no higher bits are set
return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK |
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 874b551..3eb8327 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -181,6 +181,7 @@
int32_t api;
sp<NativeHandle> sidebandStream;
+ mat4 colorTransform;
};
explicit Layer(const LayerCreationArgs& args);
@@ -255,6 +256,9 @@
virtual void setChildrenDrawingParent(const sp<Layer>& layer);
virtual bool reparent(const sp<IBinder>& newParentHandle);
virtual bool detachChildren();
+ virtual bool setColorTransform(const mat4& matrix);
+ virtual const mat4& getColorTransform() const;
+ virtual bool hasColorTransform() const;
// Used only to set BufferStateLayer state
virtual bool setTransform(uint32_t /*transform*/) { return false; };
@@ -457,7 +461,8 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) {
+ virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
+ const sp<Fence>& /*releaseFence*/) {
return {};
}
diff --git a/services/surfaceflinger/LayerBE.cpp b/services/surfaceflinger/LayerBE.cpp
index ef017aa..c9b7933 100644
--- a/services/surfaceflinger/LayerBE.cpp
+++ b/services/surfaceflinger/LayerBE.cpp
@@ -112,6 +112,20 @@
hwc.surfaceDamage.dump(regionString, "surfaceDamage");
result += regionString.string();
}
+
+ result += base::StringPrintf("\tcolor transform matrix:\n"
+ "\t\t[%f, %f, %f, %f,\n"
+ "\t\t %f, %f, %f, %f,\n"
+ "\t\t %f, %f, %f, %f,\n"
+ "\t\t %f, %f, %f, %f]\n",
+ hwc.colorTransform[0][0], hwc.colorTransform[1][0],
+ hwc.colorTransform[2][0], hwc.colorTransform[3][0],
+ hwc.colorTransform[0][1], hwc.colorTransform[1][1],
+ hwc.colorTransform[2][1], hwc.colorTransform[3][1],
+ hwc.colorTransform[0][2], hwc.colorTransform[1][2],
+ hwc.colorTransform[2][2], hwc.colorTransform[3][2],
+ hwc.colorTransform[0][3], hwc.colorTransform[1][3],
+ hwc.colorTransform[2][3], hwc.colorTransform[3][3]);
}
void CompositionInfo::dumpRe(std::string& result, const char* tag) const {
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 2722b01..d63d16f 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -60,6 +60,7 @@
bool clearClientTarget = false;
bool supportedPerFrameMetadata = false;
HdrMetadata hdrMetadata;
+ mat4 colorTransform;
} hwc;
struct {
bool blackoutLayer = false;
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
index 813c9e6..1b0a539 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.cpp
@@ -743,7 +743,7 @@
mState.textureEnabled = true;
}
-void GLES20RenderEngine::setupColorTransform(const mat4& colorTransform) {
+void GLES20RenderEngine::setColorTransform(const mat4& colorTransform) {
mState.colorMatrix = colorTransform;
}
diff --git a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
index fa01410..4f03a90 100644
--- a/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/gl/GLES20RenderEngine.h
@@ -86,7 +86,7 @@
void setupLayerTexturing(const Texture& texture) override;
void setupLayerBlackedOut() override;
void setupFillWithColor(float r, float g, float b, float a) override;
- void setupColorTransform(const mat4& colorTransform) override;
+ void setColorTransform(const mat4& colorTransform) override;
void disableTexturing() override;
void disableBlending() override;
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
index 05668f8..122271f 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/RenderEngine.h
@@ -115,7 +115,9 @@
virtual void setupLayerTexturing(const Texture& texture) = 0;
virtual void setupLayerBlackedOut() = 0;
virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
- virtual void setupColorTransform(const mat4& /* colorTransform */) = 0;
+
+ // Set a color transform matrix that is applied in linear space right before OETF.
+ virtual void setColorTransform(const mat4& /* colorTransform */) = 0;
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
@@ -163,7 +165,6 @@
bool useNativeFenceSync() const override;
bool useWaitSync() const override;
- void setupColorTransform(const mat4& /* colorTransform */) override {}
protected:
RenderEngine(uint32_t featureFlags);
diff --git a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
index efab8ff..911bb7a 100644
--- a/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
+++ b/services/surfaceflinger/RenderEngine/include/renderengine/private/Description.h
@@ -68,6 +68,8 @@
// projection matrix
mat4 projectionMatrix;
+
+ // The color matrix will be applied in linear space right before OETF.
mat4 colorMatrix;
mat4 inputTransformMatrix;
mat4 outputTransformMatrix;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 9410cdb..37b32ed 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1528,6 +1528,18 @@
getBE().mHwc->hasClientComposition(display->getId());
}
+ // Setup RenderEngine sync fences if native sync is supported.
+ if (getBE().mRenderEngine->useNativeFenceSync()) {
+ if (mHadClientComposition) {
+ base::unique_fd flushFence(getRenderEngine().flush());
+ ALOGE_IF(flushFence < 0, "Failed to flush RenderEngine!");
+ getBE().flushFence = new Fence(std::move(flushFence));
+ } else {
+ // Cleanup for hygiene.
+ getBE().flushFence = Fence::NO_FENCE;
+ }
+ }
+
mVsyncModulator.onRefreshed(mHadClientComposition);
getBE().mEndOfFrameCompositionInfo = std::move(getBE().mCompositionInfo);
@@ -1604,6 +1616,11 @@
layer->forceClientComposition(displayId);
}
+ // TODO(b/111562338) remove when composer 2.3 is shipped.
+ if (layer->hasColorTransform()) {
+ layer->forceClientComposition(displayId);
+ }
+
if (layer->getForceClientComposition(displayId)) {
ALOGV("[%s] Requesting Client composition", layer->getName().string());
layer->setCompositionType(displayId, HWC2::Composition::Client);
@@ -2141,6 +2158,8 @@
ALOGE_IF(error != HWC2::Error::None,
"[SF] Failed to set surface damage: %s (%d)",
to_string(error).c_str(), static_cast<int32_t>(error));
+
+ error = (compositionInfo.hwc.hwcLayer)->setColorTransform(compositionInfo.hwc.colorTransform);
}
void SurfaceFlinger::configureDeviceComposition(const CompositionInfo& compositionInfo) const
@@ -3031,7 +3050,7 @@
});
for (auto& layer : mLayersWithQueuedFrames) {
- const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
+ const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
layer->useSurfaceDamage();
invalidateLayerStack(layer, dirty);
if (layer->isBufferLatched()) {
@@ -3039,6 +3058,11 @@
}
}
+ // Clear the renderengine fence here...
+ // downstream code assumes that a cleared fence == NO_FENCE, so reassign to
+ // clear instead of sp::clear.
+ getBE().flushFence = Fence::NO_FENCE;
+
mVisibleRegionsDirty |= visibleRegions;
// If we will need to wake up at some time in the future to deal with a
@@ -3091,6 +3115,7 @@
const bool hasClientComposition = getBE().mHwc->hasClientComposition(displayId);
ATRACE_INT("hasClientComposition", hasClientComposition);
+ mat4 colorMatrix;
bool applyColorMatrix = false;
bool needsEnhancedColorMatrix = false;
@@ -3109,7 +3134,7 @@
const bool skipClientColorTransform = getBE().mHwc->hasCapability(
HWC2::Capability::SkipClientColorTransform);
- mat4 colorMatrix;
+ // Compute the global color transform matrix.
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
colorMatrix = mDrawingState.colorMatrix;
@@ -3125,8 +3150,6 @@
colorMatrix *= mEnhancedSaturationMatrix;
}
- getRenderEngine().setupColorTransform(colorMatrix);
-
if (!display->makeCurrent()) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
display->getDisplayName().c_str());
@@ -3205,6 +3228,19 @@
break;
}
case HWC2::Composition::Client: {
+ if (layer->hasColorTransform()) {
+ mat4 tmpMatrix;
+ if (applyColorMatrix) {
+ tmpMatrix = mDrawingState.colorMatrix;
+ }
+ tmpMatrix *= layer->getColorTransform();
+ if (needsEnhancedColorMatrix) {
+ tmpMatrix *= mEnhancedSaturationMatrix;
+ }
+ getRenderEngine().setColorTransform(tmpMatrix);
+ } else {
+ getRenderEngine().setColorTransform(colorMatrix);
+ }
layer->draw(renderArea, clip);
break;
}
@@ -3217,9 +3253,8 @@
firstLayer = false;
}
- if (applyColorMatrix || needsEnhancedColorMatrix) {
- getRenderEngine().setupColorTransform(mat4());
- }
+ // Clear color transform matrix at the end of the frame.
+ getRenderEngine().setColorTransform(mat4());
// disable scissor at the end of the frame
getBE().mRenderEngine->disableScissor();
@@ -3596,6 +3631,11 @@
if (layer->setColor(s.color))
flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eColorTransformChanged) {
+ if (layer->setColorTransform(s.colorTransform)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eMatrixChanged) {
// TODO: b/109894387
//
@@ -5441,7 +5481,9 @@
engine.clearWithColor(0, 0, 0, alpha);
traverseLayers([&](Layer* layer) {
+ engine.setColorTransform(layer->getColorTransform());
layer->draw(renderArea, useIdentityTransform);
+ engine.setColorTransform(mat4());
});
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b77bf48..a0f7c75 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -191,6 +191,9 @@
nsecs_t mTotalTime;
std::atomic<nsecs_t> mLastSwapTime;
+ // Synchronization fence from a GL composition.
+ sp<Fence> flushFence = Fence::NO_FENCE;
+
// Double- vs. triple-buffering stats
struct BufferingStats {
BufferingStats()
@@ -454,7 +457,6 @@
status_t getCompositionPreference(ui::Dataspace* outDataSpace,
ui::PixelFormat* outPixelFormat) const override;
-
/* ------------------------------------------------------------------------
* DeathRecipient interface
*/
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3af98e5..3166a8c 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -2064,6 +2064,34 @@
Transaction().setSidebandStream(layer, nullptr).apply();
}
+TEST_F(LayerTransactionTest, SetColorTransformBasic) {
+ sp<SurfaceControl> colorLayer;
+ ASSERT_NO_FATAL_FAILURE(
+ colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
+
+ Transaction().setLayer(colorLayer, mLayerZBase + 1).apply();
+ {
+ SCOPED_TRACE("default color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f);
+ const Color expected = {90, 90, 90, 255};
+ // this is handwavy, but the precison loss scaled by 255 (8-bit per
+ // channel) should be less than one
+ const uint8_t tolerance = 1;
+ mat3 matrix;
+ matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11;
+ matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11;
+ matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11;
+ Transaction().setColor(colorLayer, color)
+ .setColorTransform(colorLayer, matrix, vec3()).apply();
+ {
+ SCOPED_TRACE("new color");
+ screenshot()->expectColor(Rect(0, 0, 32, 32), expected, tolerance);
+ }
+}
+
class LayerUpdateTest : public LayerTransactionTest {
protected:
virtual void SetUp() {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 52e64d8..7b79fbd 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -325,7 +325,7 @@
EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE))
.Times(1);
- EXPECT_CALL(*test->mRenderEngine, setupColorTransform(_)).Times(2);
+ EXPECT_CALL(*test->mRenderEngine, setColorTransform(_)).Times(2);
// These expectations retire on saturation as the code path these
// expectations are for appears to make an extra call to them.
// TODO: Investigate this extra call
@@ -478,11 +478,8 @@
EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
EXPECT_CALL(*test->mRenderEngine, createImage())
.WillOnce(Return(ByMove(std::unique_ptr<renderengine::Image>(test->mReImage))));
- EXPECT_CALL(*test->mRenderEngine, bindExternalTextureImage(DEFAULT_TEXTURE_ID, _)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, checkErrors()).Times(1);
- EXPECT_CALL(*test->mReImage, setNativeWindowBuffer(_, false)).WillOnce(Return(true));
bool ignoredRecomputeVisibleRegions;
- layer->latchBuffer(ignoredRecomputeVisibleRegions, 0);
+ layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, Fence::NO_FENCE);
Mock::VerifyAndClear(test->mRenderEngine);
Mock::VerifyAndClear(test->mReImage);
}
diff --git a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
index c29452c..6813cda 100644
--- a/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
+++ b/services/surfaceflinger/tests/unittests/mock/RenderEngine/MockRenderEngine.h
@@ -62,7 +62,7 @@
MOCK_METHOD1(setupLayerTexturing, void(const Texture&));
MOCK_METHOD0(setupLayerBlackedOut, void());
MOCK_METHOD4(setupFillWithColor, void(float, float, float, float));
- MOCK_METHOD1(setupColorTransform, void(const mat4&));
+ MOCK_METHOD1(setColorTransform, void(const mat4&));
MOCK_METHOD1(setSaturationMatrix, void(const mat4&));
MOCK_METHOD0(disableTexturing, void());
MOCK_METHOD0(disableBlending, void());