blast: BufferStateLayer
Adds the initial foundation for supporting buffers on
transactions as well as the other metadata that had been passed
over BufferQueue.
Bug: 80477568
Test: Transaction_test.cpp
Change-Id: I61e44462c66c1a912adbabf62015e66bde44c216
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0be1fd7..3fa1311 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -92,6 +92,7 @@
"BufferLayer.cpp",
"BufferLayerConsumer.cpp",
"BufferQueueLayer.cpp",
+ "BufferStateLayer.cpp",
"Client.cpp",
"ColorLayer.cpp",
"ContainerLayer.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 6484245..e724666 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -136,7 +136,7 @@
* onDraw will draw the current layer onto the presentable buffer
*/
void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const {
+ bool useIdentityTransform) {
ATRACE_CALL();
CompositionInfo& compositionInfo = getBE().compositionInfo;
@@ -232,7 +232,7 @@
engine.disableTexturing();
}
-void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) const {
+void BufferLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) {
CompositionInfo& compositionInfo = getBE().compositionInfo;
auto& engine(mFlinger->getRenderEngine());
@@ -518,7 +518,7 @@
// FIXME: postedRegion should be dirty & bounds
// transform the dirty region to window-manager space
- return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h)));
+ return getTransform().transform(Region(Rect(getActiveWidth(s), getActiveHeight(s))));
}
// transaction
@@ -641,9 +641,10 @@
Transform t = getTransform();
Rect win = bounds;
- if (!s.finalCrop_legacy.isEmpty()) {
+ Rect finalCrop = getFinalCrop(s);
+ if (!finalCrop.isEmpty()) {
win = t.transform(win);
- if (!win.intersect(s.finalCrop_legacy, &win)) {
+ if (!win.intersect(finalCrop, &win)) {
win.clear();
}
win = t.inverse().transform(win);
@@ -652,10 +653,10 @@
}
}
- float left = float(win.left) / float(s.active_legacy.w);
- float top = float(win.top) / float(s.active_legacy.h);
- float right = float(win.right) / float(s.active_legacy.w);
- float bottom = float(win.bottom) / float(s.active_legacy.h);
+ float left = float(win.left) / float(getActiveWidth(s));
+ float top = float(win.top) / float(getActiveHeight(s));
+ float right = float(win.right) / float(getActiveWidth(s));
+ float bottom = float(win.bottom) / float(getActiveHeight(s));
// TODO: we probably want to generate the texture coords with the mesh
// here we assume that we only have 4 vertices
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 6ffcff4..13f4e83 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -78,8 +78,8 @@
// onDraw - draws the surface.
void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const override;
- void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const;
+ bool useIdentityTransform) override;
+ void drawNow(const RenderArea& renderArea, bool useIdentityTransform);
bool isHdrY410() const override;
@@ -102,7 +102,6 @@
bool hasReadyFrame() const override;
-private:
// Returns the current scaling mode, unless mOverrideScalingMode
// is set, in which case, it returns mOverrideScalingMode
uint32_t getEffectiveScalingMode() const override;
@@ -117,7 +116,7 @@
virtual nsecs_t getDesiredPresentTime() = 0;
virtual std::shared_ptr<FenceTime> getCurrentFenceTime() const = 0;
- virtual void getDrawingTransformMatrix(float matrix[16]) const = 0;
+ virtual void getDrawingTransformMatrix(float *matrix) = 0;
virtual uint32_t getDrawingTransform() const = 0;
virtual ui::Dataspace getDrawingDataSpace() const = 0;
virtual Rect getDrawingCrop() const = 0;
@@ -136,7 +135,7 @@
virtual bool hasDrawingBuffer() const = 0;
- virtual void setFilteringEnabled(bool enabled) const = 0;
+ virtual void setFilteringEnabled(bool enabled) = 0;
virtual status_t bindTextureImage() const = 0;
virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 1bf9cf2..0913de4 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -152,7 +152,7 @@
return mConsumer->getCurrentFenceTime();
}
-void BufferQueueLayer::getDrawingTransformMatrix(float matrix[16]) const {
+void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) {
return mConsumer->getTransformMatrix(matrix);
}
@@ -228,7 +228,7 @@
return mQueuedFrames > 0;
}
-void BufferQueueLayer::setFilteringEnabled(bool enabled) const {
+void BufferQueueLayer::setFilteringEnabled(bool enabled) {
return mConsumer->setFilteringEnabled(enabled);
}
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 7454e20..579ed81 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -68,7 +68,7 @@
nsecs_t getDesiredPresentTime() override;
std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
- void getDrawingTransformMatrix(float matrix[16]) const override;
+ void getDrawingTransformMatrix(float *matrix) override;
uint32_t getDrawingTransform() const override;
ui::Dataspace getDrawingDataSpace() const override;
Rect getDrawingCrop() const override;
@@ -87,7 +87,7 @@
bool hasDrawingBuffer() const override;
- void setFilteringEnabled(bool enabled) const override;
+ void setFilteringEnabled(bool enabled) override;
status_t bindTextureImage() const override;
status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
new file mode 100644
index 0000000..2e411f1
--- /dev/null
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "BufferStateLayer"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "BufferStateLayer.h"
+#include "RenderEngine/Image.h"
+#include "clz.h"
+
+#include <private/gui/SyncFeatures.h>
+
+namespace android {
+
+static const std::array<float, 16> IDENTITY_MATRIX{1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1};
+
+BufferStateLayer::BufferStateLayer(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+ : BufferLayer(flinger, client, name, w, h, flags),
+ mSidebandStreamChanged(false),
+ mFrameNumber(0) {
+ mTransformMatrix = IDENTITY_MATRIX;
+}
+
+// -----------------------------------------------------------------------
+// Interface implementation for Layer
+// -----------------------------------------------------------------------
+void BufferStateLayer::onLayerDisplayed(const sp<Fence>& /*releaseFence*/) {
+ // TODO(marissaw): send the release fence back to buffer owner
+ return;
+}
+
+void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const {
+ // TODO(marissaw): send the transform hint to buffer owner
+ return;
+}
+
+void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
+ // TODO(marissaw): use this to signal the buffer owner
+ return;
+}
+
+bool BufferStateLayer::shouldPresentNow(const DispSync& /*dispSync*/) const {
+ if (getSidebandStreamChanged() || getAutoRefresh()) {
+ return true;
+ }
+
+ return hasDrawingBuffer();
+}
+
+bool BufferStateLayer::getTransformToDisplayInverse() const {
+ return mCurrentState.transformToDisplayInverse;
+}
+
+void BufferStateLayer::pushPendingState() {
+ if (!mCurrentState.modified) {
+ return;
+ }
+ mPendingStates.push_back(mCurrentState);
+ ATRACE_INT(mTransactionName.string(), mPendingStates.size());
+}
+
+bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
+ const bool stateUpdateAvailable = !mPendingStates.empty();
+ while (!mPendingStates.empty()) {
+ popPendingState(stateToCommit);
+ }
+ mCurrentState.modified = false;
+ return stateUpdateAvailable;
+}
+
+Rect BufferStateLayer::getCrop(const Layer::State& s) const {
+ return (getEffectiveScalingMode() == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
+ ? GLConsumer::scaleDownCrop(s.crop, s.active.w, s.active.h)
+ : s.crop;
+}
+
+bool BufferStateLayer::setTransform(uint32_t transform) {
+ if (mCurrentState.transform == transform) return false;
+ mCurrentState.sequence++;
+ mCurrentState.transform = transform;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setTransformToDisplayInverse(bool transformToDisplayInverse) {
+ if (mCurrentState.transformToDisplayInverse == transformToDisplayInverse) return false;
+ mCurrentState.sequence++;
+ mCurrentState.transformToDisplayInverse = transformToDisplayInverse;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setCrop(const Rect& crop) {
+ if (mCurrentState.crop == crop) return false;
+ mCurrentState.sequence++;
+ mCurrentState.crop = crop;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setBuffer(sp<GraphicBuffer> buffer) {
+ mCurrentState.sequence++;
+ mCurrentState.buffer = buffer;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setAcquireFence(const sp<Fence>& fence) {
+ mCurrentState.acquireFence = fence;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setDataspace(ui::Dataspace dataspace) {
+ if (mCurrentState.dataspace == dataspace) return false;
+ mCurrentState.sequence++;
+ mCurrentState.dataspace = dataspace;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setHdrMetadata(const HdrMetadata& hdrMetadata) {
+ if (mCurrentState.hdrMetadata == hdrMetadata) return false;
+ mCurrentState.sequence++;
+ mCurrentState.hdrMetadata = hdrMetadata;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setSurfaceDamageRegion(const Region& surfaceDamage) {
+ mCurrentState.sequence++;
+ mCurrentState.surfaceDamageRegion = surfaceDamage;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setApi(int32_t api) {
+ if (mCurrentState.api == api) return false;
+ mCurrentState.sequence++;
+ mCurrentState.api = api;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setSidebandStream(const sp<NativeHandle>& sidebandStream) {
+ if (mCurrentState.sidebandStream == sidebandStream) return false;
+ mCurrentState.sequence++;
+ mCurrentState.sidebandStream = sidebandStream;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+
+ if (!mSidebandStreamChanged.exchange(true)) {
+ // mSidebandStreamChanged was false
+ mFlinger->signalLayerUpdate();
+ }
+ return true;
+}
+
+bool BufferStateLayer::setSize(uint32_t w, uint32_t h) {
+ if (mCurrentState.active.w == w && mCurrentState.active.h == h) return false;
+ mCurrentState.active.w = w;
+ mCurrentState.active.h = h;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setPosition(float x, float y, bool /*immediate*/) {
+ if (mCurrentState.active.transform.tx() == x && mCurrentState.active.transform.ty() == y)
+ return false;
+
+ mCurrentState.active.transform.set(x, y);
+
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
+ mCurrentState.transparentRegionHint = transparent;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+bool BufferStateLayer::setMatrix(const layer_state_t::matrix22_t& matrix,
+ bool allowNonRectPreservingTransforms) {
+ Transform t;
+ t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+
+ if (!allowNonRectPreservingTransforms && !t.preserveRects()) {
+ ALOGW("Attempt to set rotation matrix without permission ACCESS_SURFACE_FLINGER ignored");
+ return false;
+ }
+
+ mCurrentState.sequence++;
+ mCurrentState.active.transform.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+// -----------------------------------------------------------------------
+
+// -----------------------------------------------------------------------
+// Interface implementation for BufferLayer
+// -----------------------------------------------------------------------
+bool BufferStateLayer::fenceHasSignaled() const {
+ if (latchUnsignaledBuffers()) {
+ return true;
+ }
+
+ return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled;
+}
+
+nsecs_t BufferStateLayer::getDesiredPresentTime() {
+ // TODO(marissaw): support an equivalent to desiredPresentTime for timestats metrics
+ return 0;
+}
+
+std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
+ return std::make_shared<FenceTime>(getDrawingState().acquireFence);
+}
+
+void BufferStateLayer::getDrawingTransformMatrix(float *matrix) {
+ std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix);
+}
+
+uint32_t BufferStateLayer::getDrawingTransform() const {
+ return getDrawingState().transform;
+}
+
+ui::Dataspace BufferStateLayer::getDrawingDataSpace() const {
+ return getDrawingState().dataspace;
+}
+
+Rect BufferStateLayer::getDrawingCrop() const {
+ return Rect::INVALID_RECT;
+}
+
+uint32_t BufferStateLayer::getDrawingScalingMode() const {
+ return NATIVE_WINDOW_SCALING_MODE_FREEZE;
+}
+
+Region BufferStateLayer::getDrawingSurfaceDamage() const {
+ return getDrawingState().surfaceDamageRegion;
+}
+
+const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const {
+ return getDrawingState().hdrMetadata;
+}
+
+int BufferStateLayer::getDrawingApi() const {
+ return getDrawingState().api;
+}
+
+PixelFormat BufferStateLayer::getPixelFormat() const {
+ return mActiveBuffer->format;
+}
+
+uint64_t BufferStateLayer::getFrameNumber() const {
+ return mFrameNumber;
+}
+
+bool BufferStateLayer::getAutoRefresh() const {
+ // TODO(marissaw): support shared buffer mode
+ return false;
+}
+
+bool BufferStateLayer::getSidebandStreamChanged() const {
+ return mSidebandStreamChanged.load();
+}
+
+std::optional<Region> BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
+ if (mSidebandStreamChanged.exchange(false)) {
+ const State& s(getDrawingState());
+ // mSidebandStreamChanged was true
+ // replicated in LayerBE until FE/BE is ready to be synchronized
+ getBE().compositionInfo.hwc.sidebandStream = s.sidebandStream;
+ if (getBE().compositionInfo.hwc.sidebandStream != nullptr) {
+ setTransactionFlags(eTransactionNeeded);
+ mFlinger->setTransactionFlags(eTraversalNeeded);
+ }
+ recomputeVisibleRegions = true;
+
+ return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
+ }
+ return {};
+}
+
+bool BufferStateLayer::hasDrawingBuffer() const {
+ return getDrawingState().buffer != nullptr;
+}
+
+void BufferStateLayer::setFilteringEnabled(bool enabled) {
+ GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop,
+ mCurrentTransform, enabled);
+}
+
+status_t BufferStateLayer::bindTextureImage() const {
+ const State& s(getDrawingState());
+ auto& engine(mFlinger->getRenderEngine());
+
+ if (!engine.isCurrent()) {
+ ALOGE("RenderEngine is not current");
+ return INVALID_OPERATION;
+ }
+
+ engine.checkErrors();
+
+ if (!mTextureImage) {
+ ALOGE("no currently-bound texture");
+ engine.bindExternalTextureImage(mTextureName, *engine.createImage());
+ return NO_INIT;
+ }
+
+ bool created =
+ mTextureImage->setNativeWindowBuffer(s.buffer->getNativeBuffer(),
+ s.buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
+ if (!created) {
+ ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
+ s.buffer->getWidth(), s.buffer->getHeight(), s.buffer->getStride(),
+ s.buffer->getUsage(), s.buffer->getPixelFormat());
+ engine.bindExternalTextureImage(mTextureName, *engine.createImage());
+ return NO_INIT;
+ }
+
+ engine.bindExternalTextureImage(mTextureName, *mTextureImage);
+
+ // Wait for the new buffer to be ready.
+ if (s.acquireFence->isValid()) {
+ if (SyncFeatures::getInstance().useWaitSync()) {
+ base::unique_fd fenceFd(s.acquireFence->dup());
+ if (fenceFd == -1) {
+ ALOGE("error dup'ing fence fd: %d", errno);
+ return -errno;
+ }
+ if (!engine.waitFence(std::move(fenceFd))) {
+ ALOGE("failed to wait on fence fd");
+ return UNKNOWN_ERROR;
+ }
+ } else {
+ status_t err = s.acquireFence->waitForever("BufferStateLayer::bindTextureImage");
+ if (err != NO_ERROR) {
+ ALOGE("error waiting for fence: %d", err);
+ return err;
+ }
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) {
+ const State& s(getDrawingState());
+
+ if (!s.buffer) {
+ return NO_ERROR;
+ }
+
+ auto& engine(mFlinger->getRenderEngine());
+ if (!engine.isCurrent()) {
+ ALOGE("RenderEngine is not current");
+ return INVALID_OPERATION;
+ }
+ engine.checkErrors();
+
+ // TODO(marissaw): once buffers are cached, don't create a new image everytime
+ mTextureImage = engine.createImage();
+
+ // Reject if the layer is invalid
+ uint32_t bufferWidth = s.buffer->width;
+ uint32_t bufferHeight = s.buffer->height;
+
+ if (s.transform & Transform::ROT_90) {
+ swap(bufferWidth, bufferHeight);
+ }
+
+ if (s.transformToDisplayInverse) {
+ uint32_t invTransform = DisplayDevice::getPrimaryDisplayOrientationTransform();
+ if (invTransform & Transform::ROT_90) {
+ swap(bufferWidth, bufferHeight);
+ }
+ }
+
+ if (mOverrideScalingMode == NATIVE_WINDOW_SCALING_MODE_FREEZE &&
+ (s.active.w != bufferWidth || s.active.h != bufferHeight)) {
+ ALOGE("[%s] rejecting buffer: "
+ "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}",
+ mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h);
+ mTimeStats.removeTimeRecord(getName().c_str(), getFrameNumber());
+ return BAD_VALUE;
+ }
+
+ // Handle sync fences
+ if (SyncFeatures::getInstance().useNativeFenceSync()) {
+ base::unique_fd fenceFd = engine.flush();
+ if (fenceFd == -1) {
+ ALOGE("failed to flush RenderEngine");
+ 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.
+ auto currentStatus = s.acquireFence->getStatus();
+ if (currentStatus == Fence::Status::Invalid) {
+ ALOGE("Existing fence has invalid state");
+ mTimeStats.clearLayerRecord(getName().c_str());
+ return BAD_VALUE;
+ }
+
+ auto incomingStatus = fence->getStatus();
+ if (incomingStatus == Fence::Status::Invalid) {
+ ALOGE("New fence has invalid state");
+ mDrawingState.acquireFence = fence;
+ mTimeStats.clearLayerRecord(getName().c_str());
+ return BAD_VALUE;
+ }
+
+ // If both fences are signaled or both are unsignaled, we need to merge
+ // them to get an accurate timestamp.
+ if (currentStatus == incomingStatus) {
+ char fenceName[32] = {};
+ snprintf(fenceName, 32, "%.28s:%d", mName.string(), mFrameNumber);
+ sp<Fence> mergedFence = Fence::merge(fenceName, mDrawingState.acquireFence, fence);
+ 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;
+ mTimeStats.clearLayerRecord(getName().c_str());
+ return BAD_VALUE;
+ }
+ mDrawingState.acquireFence = mergedFence;
+ } else if (incomingStatus == Fence::Status::Unsignaled) {
+ // If one fence has signaled and the other hasn't, the unsignaled
+ // fence will approximately correspond with the correct timestamp.
+ // There's a small race if both fences signal at about the same time
+ // and their statuses are retrieved with unfortunate timing. However,
+ // 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;
+ }
+ } else {
+ // Bind the new buffer to the GL texture.
+ //
+ // Older devices require the "implicit" synchronization provided
+ // by glEGLImageTargetTexture2DOES, which this method calls. Newer
+ // devices will either call this in Layer::onDraw, or (if it's not
+ // a GL-composited layer) not at all.
+ status_t err = bindTextureImage();
+ if (err != NO_ERROR) {
+ mTimeStats.clearLayerRecord(getName().c_str());
+ return BAD_VALUE;
+ }
+ }
+
+ // TODO(marissaw): properly support mTimeStats
+ const std::string layerName(getName().c_str());
+ mTimeStats.setPostTime(getName().c_str(), getFrameNumber(), latchTime);
+ mTimeStats.setAcquireFence(layerName, getFrameNumber(), getCurrentFenceTime());
+ mTimeStats.setLatchTime(layerName, getFrameNumber(), latchTime);
+
+ return NO_ERROR;
+}
+
+status_t BufferStateLayer::updateActiveBuffer() {
+ const State& s(getDrawingState());
+
+ if (s.buffer == nullptr) {
+ return BAD_VALUE;
+ }
+
+ mActiveBuffer = s.buffer;
+ getBE().compositionInfo.mBuffer = mActiveBuffer;
+ getBE().compositionInfo.mBufferSlot = 0;
+
+ return NO_ERROR;
+}
+
+status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) {
+ // TODO(marissaw): support frame history events
+ mCurrentFrameNumber = mFrameNumber;
+ return NO_ERROR;
+}
+
+void BufferStateLayer::setHwcLayerBuffer(const sp<const DisplayDevice>& display) {
+ const auto displayId = display->getId();
+ auto& hwcInfo = getBE().mHwcLayers[displayId];
+ auto& hwcLayer = hwcInfo.layer;
+
+ const State& s(getDrawingState());
+
+ // TODO(marissaw): support more than one slot
+ uint32_t hwcSlot = 0;
+
+ auto error = hwcLayer->setBuffer(hwcSlot, s.buffer, s.acquireFence);
+ if (error != HWC2::Error::None) {
+ ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
+ s.buffer->handle, to_string(error).c_str(), static_cast<int32_t>(error));
+ }
+
+ mFrameNumber++;
+}
+
+void BufferStateLayer::onFirstRef() {
+ if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+ updateTransformHint(display);
+ }
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
new file mode 100644
index 0000000..4d7396e
--- /dev/null
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "RenderEngine/Image.h"
+#include "RenderEngine/RenderEngine.h"
+
+#include "BufferLayer.h"
+#include "Layer.h"
+
+#include <gui/GLConsumer.h>
+#include <system/window.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class BufferStateLayer : public BufferLayer {
+public:
+ BufferStateLayer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags);
+
+ // -----------------------------------------------------------------------
+ // Interface implementation for Layer
+ // -----------------------------------------------------------------------
+ void onLayerDisplayed(const sp<Fence>& releaseFence) override;
+ void setTransformHint(uint32_t orientation) const override;
+ void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
+
+ bool shouldPresentNow(const DispSync& dispSync) const override;
+
+ bool getTransformToDisplayInverse() const override;
+
+ uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override {
+ return flags;
+ }
+ void pushPendingState() override;
+ bool applyPendingStates(Layer::State* stateToCommit) override;
+
+ uint32_t getActiveWidth(const Layer::State& s) const override { return s.active.w; }
+ uint32_t getActiveHeight(const Layer::State& s) const override { return s.active.h; }
+ Transform getActiveTransform(const Layer::State& s) const override {
+ return s.active.transform;
+ }
+ Region getActiveTransparentRegion(const Layer::State& s) const override {
+ return s.transparentRegionHint;
+ }
+ Rect getCrop(const Layer::State& s) const;
+ Rect getFinalCrop(const Layer::State& /*s*/) const { return Rect::EMPTY_RECT; }
+
+ bool setTransform(uint32_t transform) override;
+ bool setTransformToDisplayInverse(bool transformToDisplayInverse) override;
+ bool setCrop(const Rect& crop) override;
+ bool setBuffer(sp<GraphicBuffer> buffer) override;
+ bool setAcquireFence(const sp<Fence>& fence) override;
+ bool setDataspace(ui::Dataspace dataspace) override;
+ bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
+ bool setSurfaceDamageRegion(const Region& surfaceDamage) override;
+ bool setApi(int32_t api) override;
+ bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
+
+ bool setSize(uint32_t w, uint32_t h) override;
+ bool setPosition(float x, float y, bool immediate) override;
+ bool setTransparentRegionHint(const Region& transparent) override;
+ bool setMatrix(const layer_state_t::matrix22_t& matrix,
+ bool allowNonRectPreservingTransforms) override;
+
+ // Override to ignore legacy layer state properties that are not used by BufferStateLayer
+ bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; };
+ bool setFinalCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; };
+ void deferTransactionUntil_legacy(const sp<IBinder>& /*barrierHandle*/,
+ uint64_t /*frameNumber*/) override {}
+ void deferTransactionUntil_legacy(const sp<Layer>& /*barrierLayer*/,
+ uint64_t /*frameNumber*/) override {}
+ // -----------------------------------------------------------------------
+
+ // -----------------------------------------------------------------------
+ // Interface implementation for BufferLayer
+ // -----------------------------------------------------------------------
+ bool fenceHasSignaled() const override;
+
+private:
+ nsecs_t getDesiredPresentTime() override;
+ std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
+
+ void getDrawingTransformMatrix(float *matrix) override;
+ uint32_t getDrawingTransform() const override;
+ ui::Dataspace getDrawingDataSpace() const override;
+ Rect getDrawingCrop() const override;
+ uint32_t getDrawingScalingMode() const override;
+ Region getDrawingSurfaceDamage() const override;
+ const HdrMetadata& getDrawingHdrMetadata() const override;
+ int getDrawingApi() const override;
+ PixelFormat getPixelFormat() const override;
+
+ uint64_t getFrameNumber() const override;
+
+ bool getAutoRefresh() const override;
+ bool getSidebandStreamChanged() const override;
+
+ std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
+
+ bool hasDrawingBuffer() const override;
+
+ void setFilteringEnabled(bool enabled) override;
+
+ status_t bindTextureImage() const override;
+ status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override;
+
+ status_t updateActiveBuffer() override;
+ status_t updateFrameNumber(nsecs_t latchTime) override;
+
+ void setHwcLayerBuffer(const sp<const DisplayDevice>& display) override;
+ // -----------------------------------------------------------------------
+private:
+ void onFirstRef() override;
+
+ std::unique_ptr<RE::Image> mTextureImage;
+
+ std::array<float, 16> mTransformMatrix;
+
+ std::atomic<bool> mSidebandStreamChanged;
+
+ uint32_t mFrameNumber;
+
+ // TODO(marissaw): support sticky transform for LEGACY camera mode
+};
+
+} // namespace android
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 10075ae..bac46a3 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -43,7 +43,7 @@
}
void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
- bool useIdentityTransform) const {
+ bool useIdentityTransform) {
half4 color = getColor();
if (color.a > 0) {
computeGeometry(renderArea, getBE().mMesh, useIdentityTransform);
@@ -54,7 +54,7 @@
}
}
-void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) const {
+void ColorLayer::drawNow(const RenderArea& renderArea, bool useIdentityTransform) {
CompositionInfo& compositionInfo = getBE().compositionInfo;
auto& engine(mFlinger->getRenderEngine());
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 8417135..429ad79 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -31,8 +31,8 @@
virtual const char* getTypeId() const { return "ColorLayer"; }
virtual void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const;
- void drawNow(const RenderArea& , bool ) const;
+ bool useIdentityTransform);
+ void drawNow(const RenderArea&, bool);
bool isVisible() const override;
void setPerFrameData(const sp<const DisplayDevice>& display) override;
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 320c0df..5ad5d56 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -28,9 +28,9 @@
mDrawingState = mCurrentState;
}
-void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) const {}
+void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {}
-void ContainerLayer::drawNow(const RenderArea&, bool) const {}
+void ContainerLayer::drawNow(const RenderArea&, bool) {}
bool ContainerLayer::isVisible() const {
return !isHiddenByPolicy();
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 29a5c3a..051e765 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -31,8 +31,8 @@
const char* getTypeId() const override { return "ContainerLayer"; }
void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const override;
- void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const override;
+ bool useIdentityTransform) override;
+ void drawNow(const RenderArea& renderArea, bool useIdentityTransform) override;
bool isVisible() const override;
void setPerFrameData(const sp<const DisplayDevice>& display) override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index eeee0ae..ee9ee78 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -114,6 +114,17 @@
mCurrentState.requested_legacy = mCurrentState.active_legacy;
mCurrentState.appId = 0;
mCurrentState.type = 0;
+ mCurrentState.active.w = 0;
+ mCurrentState.active.h = 0;
+ mCurrentState.active.transform.set(0, 0);
+ mCurrentState.transform = 0;
+ mCurrentState.transformToDisplayInverse = false;
+ mCurrentState.crop.makeInvalid();
+ mCurrentState.acquireFence = new Fence(-1);
+ mCurrentState.dataspace = ui::Dataspace::UNKNOWN;
+ mCurrentState.hdrMetadata.validTypes = 0;
+ mCurrentState.surfaceDamageRegion.clear();
+ mCurrentState.api = -1;
// drawing state & current state are identical
mDrawingState = mCurrentState;
@@ -293,17 +304,19 @@
Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const {
const Layer::State& s(getDrawingState());
- Rect win(s.active_legacy.w, s.active_legacy.h);
+ Rect win(getActiveWidth(s), getActiveHeight(s));
- if (!s.crop_legacy.isEmpty()) {
- win.intersect(s.crop_legacy, &win);
+ Rect crop = getCrop(s);
+ if (!crop.isEmpty()) {
+ win.intersect(crop, &win);
}
Transform t = getTransform();
win = t.transform(win);
- if (!s.finalCrop_legacy.isEmpty()) {
- win.intersect(s.finalCrop_legacy, &win);
+ Rect finalCrop = getFinalCrop(s);
+ if (!finalCrop.isEmpty()) {
+ win.intersect(finalCrop, &win);
}
const sp<Layer>& p = mDrawingParent.promote();
@@ -322,7 +335,7 @@
}
if (reduceTransparentRegion) {
- auto const screenTransparentRegion = t.transform(s.activeTransparentRegion_legacy);
+ auto const screenTransparentRegion = t.transform(getActiveTransparentRegion(s));
win = reduce(win, screenTransparentRegion);
}
@@ -331,15 +344,16 @@
FloatRect Layer::computeBounds() const {
const Layer::State& s(getDrawingState());
- return computeBounds(s.activeTransparentRegion_legacy);
+ return computeBounds(getActiveTransparentRegion(s));
}
FloatRect Layer::computeBounds(const Region& activeTransparentRegion) const {
const Layer::State& s(getDrawingState());
- Rect win(s.active_legacy.w, s.active_legacy.h);
+ Rect win(getActiveWidth(s), getActiveHeight(s));
- if (!s.crop_legacy.isEmpty()) {
- win.intersect(s.crop_legacy, &win);
+ Rect crop = getCrop(s);
+ if (!crop.isEmpty()) {
+ win.intersect(crop, &win);
}
const auto& p = mDrawingParent.promote();
@@ -379,9 +393,10 @@
// FIXME: the 3 lines below can produce slightly incorrect clipping when we have
// a viewport clipping and a window transform. we should use floating point to fix this.
- Rect activeCrop(s.active_legacy.w, s.active_legacy.h);
- if (!s.crop_legacy.isEmpty()) {
- activeCrop.intersect(s.crop_legacy, &activeCrop);
+ Rect activeCrop(getActiveWidth(s), getActiveHeight(s));
+ Rect crop = getCrop(s);
+ if (!crop.isEmpty()) {
+ activeCrop.intersect(crop, &activeCrop);
}
Transform t = getTransform();
@@ -389,8 +404,9 @@
if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
activeCrop.clear();
}
- if (!s.finalCrop_legacy.isEmpty()) {
- if (!activeCrop.intersect(s.finalCrop_legacy, &activeCrop)) {
+ Rect finalCrop = getFinalCrop(s);
+ if (!finalCrop.isEmpty()) {
+ if (!activeCrop.intersect(finalCrop, &activeCrop)) {
activeCrop.clear();
}
}
@@ -424,12 +440,12 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- if (!activeCrop.intersect(Rect(s.active_legacy.w, s.active_legacy.h), &activeCrop)) {
+ if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) {
activeCrop.clear();
}
// subtract the transparent region and snap to the bounds
- activeCrop = reduce(activeCrop, s.activeTransparentRegion_legacy);
+ activeCrop = reduce(activeCrop, getActiveTransparentRegion(s));
// Transform the window crop to match the buffer coordinate system,
// which means using the inverse of the current transform set on the
@@ -449,8 +465,8 @@
invTransform = (Transform(invTransformOrient) * Transform(invTransform)).getOrientation();
}
- int winWidth = s.active_legacy.w;
- int winHeight = s.active_legacy.h;
+ int winWidth = getActiveWidth(s);
+ int winHeight = getActiveHeight(s);
if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
// If the activeCrop has been rotate the ends are rotated but not
// the space itself so when transforming ends back we can't rely on
@@ -462,10 +478,10 @@
if (is_h_flipped == is_v_flipped) {
invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_FLIP_H;
}
- winWidth = s.active_legacy.h;
- winHeight = s.active_legacy.w;
+ winWidth = getActiveHeight(s);
+ winHeight = getActiveWidth(s);
}
- const Rect winCrop = activeCrop.transform(invTransform, s.active_legacy.w, s.active_legacy.h);
+ const Rect winCrop = activeCrop.transform(invTransform, getActiveWidth(s), getActiveHeight(s));
// below, crop is intersected with winCrop expressed in crop's coordinate space
float xScale = crop.getWidth() / float(winWidth);
@@ -518,10 +534,10 @@
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
- Region activeTransparentRegion(s.activeTransparentRegion_legacy);
+ Region activeTransparentRegion(getActiveTransparentRegion(s));
Transform t = getTransform();
- if (!s.crop_legacy.isEmpty()) {
- Rect activeCrop(s.crop_legacy);
+ Rect activeCrop = getCrop(s);
+ if (!activeCrop.isEmpty()) {
activeCrop = t.transform(activeCrop);
if (!activeCrop.intersect(display->getViewport(), &activeCrop)) {
activeCrop.clear();
@@ -533,23 +549,24 @@
// transform.inverse().transform(transform.transform(Rect)) != Rect
// in which case we need to make sure the final rect is clipped to the
// display bounds.
- if (!activeCrop.intersect(Rect(s.active_legacy.w, s.active_legacy.h), &activeCrop)) {
+ if (!activeCrop.intersect(Rect(getActiveWidth(s), getActiveHeight(s)), &activeCrop)) {
activeCrop.clear();
}
// mark regions outside the crop as transparent
- activeTransparentRegion.orSelf(Rect(0, 0, s.active_legacy.w, activeCrop.top));
+ activeTransparentRegion.orSelf(Rect(0, 0, getActiveWidth(s), activeCrop.top));
activeTransparentRegion.orSelf(
- Rect(0, activeCrop.bottom, s.active_legacy.w, s.active_legacy.h));
+ Rect(0, activeCrop.bottom, getActiveWidth(s), getActiveHeight(s)));
activeTransparentRegion.orSelf(Rect(0, activeCrop.top, activeCrop.left, activeCrop.bottom));
activeTransparentRegion.orSelf(
- Rect(activeCrop.right, activeCrop.top, s.active_legacy.w, activeCrop.bottom));
+ Rect(activeCrop.right, activeCrop.top, getActiveWidth(s), activeCrop.bottom));
}
// computeBounds returns a FloatRect to provide more accuracy during the
// transformation. We then round upon constructing 'frame'.
Rect frame{t.transform(computeBounds(activeTransparentRegion))};
- if (!s.finalCrop_legacy.isEmpty()) {
- if (!frame.intersect(s.finalCrop_legacy, &frame)) {
+ Rect finalCrop = getFinalCrop(s);
+ if (!finalCrop.isEmpty()) {
+ if (!frame.intersect(finalCrop, &frame)) {
frame.clear();
}
}
@@ -682,16 +699,18 @@
// Apply the layer's transform, followed by the display's global transform
// Here we're guaranteed that the layer's transform preserves rects
- Rect win(s.active_legacy.w, s.active_legacy.h);
- if (!s.crop_legacy.isEmpty()) {
- win.intersect(s.crop_legacy, &win);
+ Rect win(getActiveWidth(s), getActiveHeight(s));
+ Rect crop = getCrop(s);
+ if (!crop.isEmpty()) {
+ win.intersect(crop, &win);
}
// Subtract the transparent region and snap to the bounds
- Rect bounds = reduce(win, s.activeTransparentRegion_legacy);
+ Rect bounds = reduce(win, getActiveTransparentRegion(s));
Rect frame(getTransform().transform(bounds));
frame.intersect(display->getViewport(), &frame);
- if (!s.finalCrop_legacy.isEmpty()) {
- frame.intersect(s.finalCrop_legacy, &frame);
+ Rect finalCrop = getFinalCrop(s);
+ if (!finalCrop.isEmpty()) {
+ frame.intersect(finalCrop, &frame);
}
auto& displayTransform = display->getTransform();
auto position = displayTransform.transform(frame);
@@ -709,15 +728,15 @@
// drawing...
// ---------------------------------------------------------------------------
-void Layer::draw(const RenderArea& renderArea, const Region& clip) const {
+void Layer::draw(const RenderArea& renderArea, const Region& clip) {
onDraw(renderArea, clip, false);
}
-void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) const {
+void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) {
onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform);
}
-void Layer::draw(const RenderArea& renderArea) const {
+void Layer::draw(const RenderArea& renderArea) {
onDraw(renderArea, Region(renderArea.getBounds()), false);
}
@@ -844,11 +863,12 @@
rt = layerTransform.transform(rt);
}
- if (!s.finalCrop_legacy.isEmpty()) {
- boundPoint(<, s.finalCrop_legacy);
- boundPoint(&lb, s.finalCrop_legacy);
- boundPoint(&rb, s.finalCrop_legacy);
- boundPoint(&rt, s.finalCrop_legacy);
+ Rect finalCrop = getFinalCrop(s);
+ if (!finalCrop.isEmpty()) {
+ boundPoint(<, finalCrop);
+ boundPoint(&lb, finalCrop);
+ boundPoint(&rb, finalCrop);
+ boundPoint(&rt, finalCrop);
}
Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
@@ -984,19 +1004,11 @@
return stateUpdateAvailable;
}
-uint32_t Layer::doTransaction(uint32_t flags) {
- ATRACE_CALL();
-
- pushPendingState();
- Layer::State c = getCurrentState();
- if (!applyPendingStates(&c)) {
- return 0;
- }
-
+uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) {
const Layer::State& s(getDrawingState());
- const bool sizeChanged = (c.requested_legacy.w != s.requested_legacy.w) ||
- (c.requested_legacy.h != s.requested_legacy.h);
+ const bool sizeChanged = (stateToCommit->requested_legacy.w != s.requested_legacy.w) ||
+ (stateToCommit->requested_legacy.h != s.requested_legacy.h);
if (sizeChanged) {
// the size changed, we need to ask our client to request a new buffer
@@ -1007,16 +1019,18 @@
" drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
" requested={ wh={%4u,%4u} }}\n",
this, getName().string(), mCurrentTransform, getEffectiveScalingMode(),
- c.active_legacy.w, c.active_legacy.h, c.crop_legacy.left, c.crop_legacy.top,
- c.crop_legacy.right, c.crop_legacy.bottom, c.crop_legacy.getWidth(),
- c.crop_legacy.getHeight(), c.requested_legacy.w, c.requested_legacy.h,
+ stateToCommit->active_legacy.w, stateToCommit->active_legacy.h,
+ stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top,
+ stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom,
+ stateToCommit->crop_legacy.getWidth(), stateToCommit->crop_legacy.getHeight(),
+ stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h,
s.active_legacy.w, s.active_legacy.h, s.crop_legacy.left, s.crop_legacy.top,
s.crop_legacy.right, s.crop_legacy.bottom, s.crop_legacy.getWidth(),
s.crop_legacy.getHeight(), s.requested_legacy.w, s.requested_legacy.h);
// record the new size, form this point on, when the client request
// a buffer, it'll get the new size.
- setDefaultBufferSize(c.requested_legacy.w, c.requested_legacy.h);
+ setDefaultBufferSize(stateToCommit->requested_legacy.w, stateToCommit->requested_legacy.h);
}
// Don't let Layer::doTransaction update the drawing state
@@ -1037,8 +1051,9 @@
// resizePending state is to avoid applying the state of the new buffer
// to the old buffer. However in the state where we don't have an old buffer
// there is no such concern but we may still be being used as a parent layer.
- const bool resizePending = ((c.requested_legacy.w != c.active_legacy.w) ||
- (c.requested_legacy.h != c.active_legacy.h)) &&
+ const bool resizePending =
+ ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) ||
+ (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) &&
(getBE().compositionInfo.mBuffer != nullptr);
if (!isFixedSize()) {
if (resizePending && getBE().compositionInfo.hwc.sidebandStream == nullptr) {
@@ -1062,21 +1077,37 @@
// being stored in the same data structure while having different latching rules.
// b/38182305
//
- // Careful that "c" and editCurrentState may not begin as equivalent due to
+ // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to
// applyPendingStates in the presence of deferred transactions.
if (mFreezeGeometryUpdates) {
- float tx = c.active_legacy.transform.tx();
- float ty = c.active_legacy.transform.ty();
- c.active_legacy = c.requested_legacy;
- c.active_legacy.transform.set(tx, ty);
- editCurrentState.active_legacy = c.active_legacy;
+ float tx = stateToCommit->active_legacy.transform.tx();
+ float ty = stateToCommit->active_legacy.transform.ty();
+ stateToCommit->active_legacy = stateToCommit->requested_legacy;
+ stateToCommit->active_legacy.transform.set(tx, ty);
+ editCurrentState.active_legacy = stateToCommit->active_legacy;
} else {
editCurrentState.active_legacy = editCurrentState.requested_legacy;
- c.active_legacy = c.requested_legacy;
+ stateToCommit->active_legacy = stateToCommit->requested_legacy;
}
}
- if (s.active_legacy != c.active_legacy) {
+ return flags;
+}
+
+uint32_t Layer::doTransaction(uint32_t flags) {
+ ATRACE_CALL();
+
+ pushPendingState();
+ Layer::State c = getCurrentState();
+ if (!applyPendingStates(&c)) {
+ return 0;
+ }
+
+ flags = doTransactionResize(flags, &c);
+
+ const Layer::State& s(getDrawingState());
+
+ if (getActiveGeometry(c) != getActiveGeometry(s)) {
// invalidate and recompute the visible regions if needed
flags |= Layer::eVisibleRegion;
}
@@ -1087,9 +1118,8 @@
this->contentDirty = true;
// we may use linear filtering, if the matrix scales us
- const uint8_t type = c.active_legacy.transform.getType();
- mNeedsFiltering =
- (!c.active_legacy.transform.preserveRects() || (type >= Transform::SCALE));
+ const uint8_t type = getActiveTransform(c).getType();
+ mNeedsFiltering = (!getActiveTransform(c).preserveRects() || (type >= Transform::SCALE));
}
// If the layer is hidden, signal and clear out all local sync points so
@@ -1278,6 +1308,7 @@
setTransactionFlags(eTransactionNeeded);
return true;
}
+
bool Layer::setTransparentRegionHint(const Region& transparent) {
mCurrentState.requestedTransparentRegion_legacy = transparent;
mCurrentState.modified = true;
@@ -1415,6 +1446,7 @@
// debugging
// ----------------------------------------------------------------------------
+// TODO(marissaw): add new layer state info to layer debugging
LayerDebugInfo Layer::getLayerDebugInfo() const {
LayerDebugInfo info;
const Layer::State& ds = getDrawingState();
@@ -1889,14 +1921,14 @@
bufferHeight = p->getBE().compositionInfo.mBuffer->getWidth();
bufferWidth = p->getBE().compositionInfo.mBuffer->getHeight();
}
- float sx = p->getDrawingState().active_legacy.w / static_cast<float>(bufferWidth);
- float sy = p->getDrawingState().active_legacy.h / static_cast<float>(bufferHeight);
+ float sx = p->getActiveWidth(p->getDrawingState()) / static_cast<float>(bufferWidth);
+ float sy = p->getActiveHeight(p->getDrawingState()) / static_cast<float>(bufferHeight);
Transform extraParentScaling;
extraParentScaling.set(sx, 0, 0, sy);
t = t * extraParentScaling;
}
}
- return t * getDrawingState().active_legacy.transform;
+ return t * getActiveTransform(getDrawingState());
}
half Layer::getAlpha() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 96ec84b..a48cdff 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -156,6 +156,24 @@
SortedVector<wp<Layer>> zOrderRelatives;
half4 color;
+
+ // The fields below this point are only used by BufferStateLayer
+ Geometry active;
+
+ uint32_t transform;
+ bool transformToDisplayInverse;
+
+ Rect crop;
+ Region transparentRegionHint;
+
+ sp<GraphicBuffer> buffer;
+ sp<Fence> acquireFence;
+ ui::Dataspace dataspace;
+ HdrMetadata hdrMetadata;
+ Region surfaceDamageRegion;
+ int32_t api;
+
+ sp<NativeHandle> sidebandStream;
};
Layer(SurfaceFlinger* flinger, const sp<Client>& client, const String8& name, uint32_t w,
@@ -191,11 +209,12 @@
// also the rendered size of the layer prior to any transformations. Parent
// or local matrix transformations will not affect the size of the buffer,
// but may affect it's on-screen size or clipping.
- bool setSize(uint32_t w, uint32_t h);
+ virtual bool setSize(uint32_t w, uint32_t h);
// Set a 2x2 transformation matrix on the layer. This transform
// will be applied after parent transforms, but before any final
// producer specified transform.
- bool setMatrix(const layer_state_t::matrix22_t& matrix, bool allowNonRectPreservingTransforms);
+ virtual bool setMatrix(const layer_state_t::matrix22_t& matrix,
+ bool allowNonRectPreservingTransforms);
// This second set of geometry attributes are controlled by
// setGeometryAppliesWithResize, and their default mode is to be
@@ -205,32 +224,45 @@
// setPosition operates in parent buffer space (pre parent-transform) or display
// space for top-level layers.
- bool setPosition(float x, float y, bool immediate);
+ virtual bool setPosition(float x, float y, bool immediate);
// Buffer space
- bool setCrop_legacy(const Rect& crop, bool immediate);
+ virtual bool setCrop_legacy(const Rect& crop, bool immediate);
// Parent buffer space/display space
- bool setFinalCrop_legacy(const Rect& crop, bool immediate);
+ virtual bool setFinalCrop_legacy(const Rect& crop, bool immediate);
// TODO(b/38182121): Could we eliminate the various latching modes by
// using the layer hierarchy?
// -----------------------------------------------------------------------
- bool setLayer(int32_t z);
- bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
+ virtual bool setLayer(int32_t z);
+ virtual bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ);
- bool setAlpha(float alpha);
- bool setColor(const half3& color);
- bool setTransparentRegionHint(const Region& transparent);
- bool setFlags(uint8_t flags, uint8_t mask);
- bool setLayerStack(uint32_t layerStack);
- uint32_t getLayerStack() const;
- void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle, uint64_t frameNumber);
- void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
- bool setOverrideScalingMode(int32_t overrideScalingMode);
- void setInfo(int32_t type, int32_t appId);
- bool reparentChildren(const sp<IBinder>& layer);
- void setChildrenDrawingParent(const sp<Layer>& layer);
- bool reparent(const sp<IBinder>& newParentHandle);
- bool detachChildren();
+ virtual bool setAlpha(float alpha);
+ virtual bool setColor(const half3& color);
+ virtual bool setTransparentRegionHint(const Region& transparent);
+ virtual bool setFlags(uint8_t flags, uint8_t mask);
+ virtual bool setLayerStack(uint32_t layerStack);
+ virtual uint32_t getLayerStack() const;
+ virtual void deferTransactionUntil_legacy(const sp<IBinder>& barrierHandle,
+ uint64_t frameNumber);
+ virtual void deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber);
+ virtual bool setOverrideScalingMode(int32_t overrideScalingMode);
+ virtual void setInfo(int32_t type, int32_t appId);
+ virtual bool reparentChildren(const sp<IBinder>& layer);
+ virtual void setChildrenDrawingParent(const sp<Layer>& layer);
+ virtual bool reparent(const sp<IBinder>& newParentHandle);
+ virtual bool detachChildren();
+
+ // Used only to set BufferStateLayer state
+ virtual bool setTransform(uint32_t /*transform*/) { return false; };
+ virtual bool setTransformToDisplayInverse(bool /*transformToDisplayInverse*/) { return false; };
+ virtual bool setCrop(const Rect& /*crop*/) { return false; };
+ virtual bool setBuffer(sp<GraphicBuffer> /*buffer*/) { return false; };
+ virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
+ virtual bool setDataspace(ui::Dataspace /*dataspace*/) { return false; };
+ virtual bool setHdrMetadata(const HdrMetadata& /*hdrMetadata*/) { return false; };
+ virtual bool setSurfaceDamageRegion(const Region& /*surfaceDamage*/) { return false; };
+ virtual bool setApi(int32_t /*api*/) { return false; };
+ virtual bool setSidebandStream(const sp<NativeHandle>& /*sidebandStream*/) { return false; };
ui::Dataspace getDataSpace() const { return mCurrentDataSpace; }
@@ -310,12 +342,24 @@
void writeToProto(LayerProto* layerInfo, int32_t displayId);
+ virtual Geometry getActiveGeometry(const Layer::State& s) const { return s.active_legacy; }
+ virtual uint32_t getActiveWidth(const Layer::State& s) const { return s.active_legacy.w; }
+ virtual uint32_t getActiveHeight(const Layer::State& s) const { return s.active_legacy.h; }
+ virtual Transform getActiveTransform(const Layer::State& s) const {
+ return s.active_legacy.transform;
+ }
+ virtual Region getActiveTransparentRegion(const Layer::State& s) const {
+ return s.activeTransparentRegion_legacy;
+ }
+ virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
+ virtual Rect getFinalCrop(const Layer::State& s) const { return s.finalCrop_legacy; }
+
protected:
/*
* onDraw - draws the surface.
*/
virtual void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) const = 0;
+ bool useIdentityTransform) = 0;
public:
virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
@@ -369,9 +413,9 @@
* draw - performs some global clipping optimizations
* and calls onDraw().
*/
- void draw(const RenderArea& renderArea, const Region& clip) const;
- void draw(const RenderArea& renderArea, bool useIdentityTransform) const;
- void draw(const RenderArea& renderArea) const;
+ void draw(const RenderArea& renderArea, const Region& clip);
+ void draw(const RenderArea& renderArea, bool useIdentityTransform);
+ void draw(const RenderArea& renderArea);
/*
* drawNow uses the renderEngine to draw the layer. This is different than the
@@ -381,7 +425,7 @@
* is used for screen captures which happens separately from the frame
* compositing path.
*/
- virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) const = 0;
+ virtual void drawNow(const RenderArea& renderArea, bool useIdentityTransform) = 0;
/*
* doTransaction - process the transaction. This is a good place to figure
@@ -536,7 +580,7 @@
// SurfaceFlinger to complete a transaction.
void commitChildList();
int32_t getZ() const;
- void pushPendingState();
+ virtual void pushPendingState();
protected:
// constant
@@ -620,7 +664,8 @@
bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
void popPendingState(State* stateToCommit);
- bool applyPendingStates(State* stateToCommit);
+ virtual bool applyPendingStates(State* stateToCommit);
+ virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
void clearSyncPoints();
diff --git a/services/surfaceflinger/LayerBE.h b/services/surfaceflinger/LayerBE.h
index 8b37170..b5aceba 100644
--- a/services/surfaceflinger/LayerBE.h
+++ b/services/surfaceflinger/LayerBE.h
@@ -78,6 +78,7 @@
friend class Layer;
friend class BufferLayer;
friend class BufferQueueLayer;
+ friend class BufferStateLayer;
friend class ColorLayer;
friend class SurfaceFlinger;
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
index fd0ca82..70558d4 100644
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ b/services/surfaceflinger/LayerRejecter.cpp
@@ -101,7 +101,8 @@
ALOGD_IF(DEBUG_RESIZE,
"[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
- " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) "
+ " drawing={ active_legacy ={ wh={%4u,%4u} crop_legacy={%4d,%4d,%4d,%4d} "
+ "(%4d,%4d) "
"}\n"
" requested_legacy={ wh={%4u,%4u} }}\n",
mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 64f1eaf..399fbd8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -64,6 +64,7 @@
#include "BufferLayer.h"
#include "BufferQueueLayer.h"
+#include "BufferStateLayer.h"
#include "Client.h"
#include "ColorLayer.h"
#include "Colorizer.h"
@@ -2766,7 +2767,7 @@
if (translucent) {
if (tr.preserveRects()) {
// transform the transparent region
- transparentRegion = tr.transform(s.activeTransparentRegion_legacy);
+ transparentRegion = tr.transform(layer->getActiveTransparentRegion(s));
} else {
// transformation too complex, can't do the
// transparent region optimization.
@@ -3551,6 +3552,37 @@
// We don't trigger a traversal here because if no other state is
// changed, we don't want this to cause any more work
}
+ if (what & layer_state_t::eTransformChanged) {
+ if (layer->setTransform(s.transform)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eTransformToDisplayInverseChanged) {
+ if (layer->setTransformToDisplayInverse(s.transformToDisplayInverse))
+ flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eCropChanged) {
+ if (layer->setCrop(s.crop)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eBufferChanged) {
+ if (layer->setBuffer(s.buffer)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eAcquireFenceChanged) {
+ if (layer->setAcquireFence(s.acquireFence)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eDataspaceChanged) {
+ if (layer->setDataspace(s.dataspace)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eHdrMetadataChanged) {
+ if (layer->setHdrMetadata(s.hdrMetadata)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eSurfaceDamageRegionChanged) {
+ if (layer->setSurfaceDamageRegion(s.surfaceDamageRegion)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eApiChanged) {
+ if (layer->setApi(s.api)) flags |= eTraversalNeeded;
+ }
+ if (what & layer_state_t::eSidebandStreamChanged) {
+ if (layer->setSidebandStream(s.sidebandStream)) flags |= eTraversalNeeded;
+ }
return flags;
}
@@ -3593,11 +3625,14 @@
String8 uniqueName = getUniqueLayerName(name);
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
- case ISurfaceComposerClient::eFXSurfaceNormal:
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
result = createBufferQueueLayer(client, uniqueName, w, h, flags, format, handle, gbp,
&layer);
break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ result = createBufferStateLayer(client, uniqueName, w, h, flags, handle, &layer);
+ break;
case ISurfaceComposerClient::eFXSurfaceColor:
result = createColorLayer(client,
uniqueName, w, h, flags,
@@ -3687,6 +3722,16 @@
return err;
}
+status_t SurfaceFlinger::createBufferStateLayer(const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags,
+ sp<IBinder>* handle, sp<Layer>* outLayer) {
+ sp<BufferStateLayer> layer = new BufferStateLayer(this, client, name, w, h, flags);
+ *handle = layer->getHandle();
+ *outLayer = layer;
+
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::createColorLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags,
sp<IBinder>* handle, sp<Layer>* outLayer)
@@ -4864,10 +4909,12 @@
const Transform& getTransform() const override { return mTransform; }
Rect getBounds() const override {
const Layer::State& layerState(mLayer->getDrawingState());
- return Rect(layerState.active_legacy.w, layerState.active_legacy.h);
+ return Rect(mLayer->getActiveWidth(layerState), mLayer->getActiveHeight(layerState));
}
- int getHeight() const override { return mLayer->getDrawingState().active_legacy.h; }
- int getWidth() const override { return mLayer->getDrawingState().active_legacy.w; }
+ int getHeight() const override {
+ return mLayer->getActiveHeight(mLayer->getDrawingState());
+ }
+ int getWidth() const override { return mLayer->getActiveWidth(mLayer->getDrawingState()); }
bool isSecure() const override { return false; }
bool needsFiltering() const override { return false; }
Rect getSourceCrop() const override {
@@ -4935,12 +4982,12 @@
Rect crop(sourceCrop);
if (sourceCrop.width() <= 0) {
crop.left = 0;
- crop.right = parent->getCurrentState().active_legacy.w;
+ crop.right = parent->getActiveWidth(parent->getCurrentState());
}
if (sourceCrop.height() <= 0) {
crop.top = 0;
- crop.bottom = parent->getCurrentState().active_legacy.h;
+ crop.bottom = parent->getActiveHeight(parent->getCurrentState());
}
int32_t reqWidth = crop.width() * frameScale;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a750636..eaaf742 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -356,6 +356,7 @@
friend class Layer;
friend class BufferLayer;
friend class BufferQueueLayer;
+ friend class BufferStateLayer;
friend class MonitoredProducer;
// For unit tests
@@ -535,6 +536,10 @@
sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
sp<Layer>* outLayer);
+ status_t createBufferStateLayer(const sp<Client>& client, const String8& name, uint32_t w,
+ uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
+ sp<Layer>* outLayer);
+
status_t createColorLayer(const sp<Client>& client, const String8& name,
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index c42213a..f504c13 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -30,6 +30,7 @@
namespace android {
// ----------------------------------------------------------------------------
+// TODO(marissaw): add new layer state values to SurfaceInterceptor
SurfaceInterceptor::~SurfaceInterceptor() = default;
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 2ce32b5..bde6614 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -62,38 +62,28 @@
const Color Color::BLACK{0, 0, 0, 255};
const Color Color::TRANSPARENT{0, 0, 0, 0};
+using android::hardware::graphics::common::V1_1::BufferUsage;
+
std::ostream& operator<<(std::ostream& os, const Color& color) {
os << int(color.r) << ", " << int(color.g) << ", " << int(color.b) << ", " << int(color.a);
return os;
}
// Fill a region with the specified color.
-void fillBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect, const Color& color) {
- int32_t x = rect.left;
- int32_t y = rect.top;
- int32_t width = rect.right - rect.left;
- int32_t height = rect.bottom - rect.top;
-
- if (x < 0) {
- width += x;
- x = 0;
- }
- if (y < 0) {
- height += y;
- y = 0;
- }
- if (x + width > buffer.width) {
- x = std::min(x, buffer.width);
- width = buffer.width - x;
- }
- if (y + height > buffer.height) {
- y = std::min(y, buffer.height);
- height = buffer.height - y;
+void fillANativeWindowBufferColor(const ANativeWindow_Buffer& buffer, const Rect& rect,
+ const Color& color) {
+ Rect r(0, 0, buffer.width, buffer.height);
+ if (!r.intersect(rect, &r)) {
+ return;
}
- for (int32_t j = 0; j < height; j++) {
- uint8_t* dst = static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (y + j) + x) * 4;
- for (int32_t i = 0; i < width; i++) {
+ int32_t width = r.right - r.left;
+ int32_t height = r.bottom - r.top;
+
+ for (int32_t row = 0; row < height; row++) {
+ uint8_t* dst =
+ static_cast<uint8_t*>(buffer.bits) + (buffer.stride * (r.top + row) + r.left) * 4;
+ for (int32_t column = 0; column < width; column++) {
dst[0] = color.r;
dst[1] = color.g;
dst[2] = color.b;
@@ -103,6 +93,33 @@
}
}
+// Fill a region with the specified color.
+void fillGraphicBufferColor(const sp<GraphicBuffer>& buffer, const Rect& rect, const Color& color) {
+ Rect r(0, 0, buffer->width, buffer->height);
+ if (!r.intersect(rect, &r)) {
+ return;
+ }
+
+ int32_t width = r.right - r.left;
+ int32_t height = r.bottom - r.top;
+
+ uint8_t* pixels;
+ buffer->lock(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
+ reinterpret_cast<void**>(&pixels));
+
+ for (int32_t row = 0; row < height; row++) {
+ uint8_t* dst = pixels + (buffer->getStride() * (r.top + row) + r.left) * 4;
+ for (int32_t column = 0; column < width; column++) {
+ dst[0] = color.r;
+ dst[1] = color.g;
+ dst[2] = color.b;
+ dst[3] = color.a;
+ dst += 4;
+ }
+ }
+ buffer->unlock();
+}
+
// Check if a region has the specified color.
void expectBufferColor(const sp<GraphicBuffer>& outBuffer, uint8_t* pixels, const Rect& rect,
const Color& color, uint8_t tolerance) {
@@ -301,8 +318,8 @@
ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
}
- sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
- uint32_t flags = 0) {
+ virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
+ uint32_t flags = 0) {
auto layer =
mClient->createSurface(String8(name), width, height, PIXEL_FORMAT_RGBA_8888, flags);
EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl";
@@ -319,7 +336,7 @@
return layer;
}
- ANativeWindow_Buffer getLayerBuffer(const sp<SurfaceControl>& layer) {
+ ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
// wait for previous transactions (such as setSize) to complete
Transaction().apply(true);
@@ -329,35 +346,103 @@
return buffer;
}
- void postLayerBuffer(const sp<SurfaceControl>& layer) {
+ void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) {
ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost());
// wait for the newly posted buffer to be latched
waitForLayerBuffers();
}
- void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color) {
+ virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
ANativeWindow_Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
- fillBufferColor(buffer, Rect(0, 0, buffer.width, buffer.height), color);
- postLayerBuffer(layer);
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ fillANativeWindowBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color);
+ postBufferQueueLayerBuffer(layer);
}
- void fillLayerQuadrant(const sp<SurfaceControl>& layer, const Color& topLeft,
+ virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color);
+ Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
+ }
+
+ void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
+ switch (mLayerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight);
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight);
+ break;
+ default:
+ ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
+ }
+ }
+
+ void fillLayerQuadrant(uint32_t mLayerType, const sp<SurfaceControl>& layer,
+ int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft,
const Color& topRight, const Color& bottomLeft,
const Color& bottomRight) {
+ switch (mLayerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight,
+ bottomLeft, bottomRight);
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight,
+ bottomLeft, bottomRight);
+ break;
+ default:
+ ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
+ }
+ }
+
+ virtual void fillBufferQueueLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
+ int32_t bufferHeight, const Color& topLeft,
+ const Color& topRight, const Color& bottomLeft,
+ const Color& bottomRight) {
ANativeWindow_Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
- ASSERT_TRUE(buffer.width % 2 == 0 && buffer.height % 2 == 0);
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0);
- const int32_t halfW = buffer.width / 2;
- const int32_t halfH = buffer.height / 2;
- fillBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
- fillBufferColor(buffer, Rect(halfW, 0, buffer.width, halfH), topRight);
- fillBufferColor(buffer, Rect(0, halfH, halfW, buffer.height), bottomLeft);
- fillBufferColor(buffer, Rect(halfW, halfH, buffer.width, buffer.height), bottomRight);
+ const int32_t halfW = bufferWidth / 2;
+ const int32_t halfH = bufferHeight / 2;
+ fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+ fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight);
+ fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft);
+ fillANativeWindowBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight),
+ bottomRight);
- postLayerBuffer(layer);
+ postBufferQueueLayerBuffer(layer);
+ }
+
+ virtual void fillBufferStateLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
+ int32_t bufferHeight, const Color& topLeft,
+ const Color& topRight, const Color& bottomLeft,
+ const Color& bottomRight) {
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+
+ ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0);
+
+ const int32_t halfW = bufferWidth / 2;
+ const int32_t halfH = bufferHeight / 2;
+ fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft);
+ fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), topRight);
+ fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), bottomLeft);
+ fillGraphicBufferColor(buffer, Rect(halfW, halfH, bufferWidth, bufferHeight), bottomRight);
+
+ Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply();
}
sp<ScreenCapture> screenshot() {
@@ -376,6 +461,10 @@
// leave room for ~256 layers
const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256;
+ void setPositionWithResizeHelper(uint32_t layerType);
+ void setSizeBasicHelper(uint32_t layerType);
+ void setMatrixWithResizeHelper(uint32_t layerType);
+
private:
void SetUpDisplay() {
mDisplay = mClient->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain);
@@ -404,10 +493,48 @@
int32_t mBufferPostDelay;
};
-TEST_F(LayerTransactionTest, SetPositionBasic) {
+class LayerTypeTransactionTest : public LayerTransactionTest,
+ public ::testing::WithParamInterface<uint32_t> {
+public:
+ LayerTypeTransactionTest() { mLayerType = GetParam(); }
+
+ sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
+ uint32_t flags = 0) override {
+ // if the flags already have a layer type specified, return an error
+ if (flags & ISurfaceComposerClient::eFXSurfaceMask) {
+ return nullptr;
+ }
+ return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType);
+ }
+
+ void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth,
+ int32_t bufferHeight) {
+ ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color,
+ bufferWidth, bufferHeight));
+ }
+
+ void fillLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth,
+ int32_t bufferHeight, const Color& topLeft, const Color& topRight,
+ const Color& bottomLeft, const Color& bottomRight) {
+ ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer,
+ bufferWidth, bufferHeight,
+ topLeft, topRight,
+ bottomLeft, bottomRight));
+ }
+
+protected:
+ uint32_t mLayerType;
+};
+
+INSTANTIATE_TEST_CASE_P(
+ LayerTypeTransactionTests, LayerTypeTransactionTest,
+ ::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue),
+ static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)));
+
+TEST_P(LayerTypeTransactionTest, SetPositionBasic) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
{
SCOPED_TRACE("default position");
@@ -425,10 +552,10 @@
}
}
-TEST_F(LayerTransactionTest, SetPositionRounding) {
+TEST_P(LayerTypeTransactionTest, SetPositionRounding) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
// GLES requires only 4 bits of subpixel precision during rasterization
// XXX GLES composition does not match HWC composition due to precision
@@ -447,10 +574,10 @@
}
}
-TEST_F(LayerTransactionTest, SetPositionOutOfBounds) {
+TEST_P(LayerTypeTransactionTest, SetPositionOutOfBounds) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
Transaction().setPosition(layer, -32, -32).apply();
{
@@ -465,10 +592,10 @@
}
}
-TEST_F(LayerTransactionTest, SetPositionPartiallyOutOfBounds) {
+TEST_P(LayerTypeTransactionTest, SetPositionPartiallyOutOfBounds) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
// partially out of bounds
Transaction().setPosition(layer, -30, -30).apply();
@@ -486,10 +613,10 @@
}
}
-TEST_F(LayerTransactionTest, SetPositionWithResize) {
+void LayerTransactionTest::setPositionWithResizeHelper(uint32_t layerType) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32));
// setPosition is applied immediately by default, with or without resize
// pending
@@ -497,21 +624,43 @@
{
SCOPED_TRACE("resize pending");
auto shot = screenshot();
- shot->expectColor(Rect(5, 10, 37, 42), Color::RED);
- shot->expectBorder(Rect(5, 10, 37, 42), Color::BLACK);
+ Rect rect;
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ rect = {5, 10, 37, 42};
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ rect = {5, 10, 69, 74};
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64));
{
SCOPED_TRACE("resize applied");
screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
}
}
-TEST_F(LayerTransactionTest, SetPositionWithNextResize) {
+TEST_F(LayerTransactionTest, SetPositionWithResize_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(
+ setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithResize_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(
+ setPositionWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
+TEST_F(LayerTransactionTest, SetPositionWithNextResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// request setPosition to be applied with the next resize
Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply();
@@ -533,17 +682,17 @@
}
// finally resize and latch the buffer
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
{
SCOPED_TRACE("new position applied");
screenshot()->expectColor(Rect(15, 20, 79, 84), Color::RED);
}
}
-TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow) {
+TEST_F(LayerTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setPosition is not immediate even with SCALE_TO_WINDOW override
Transaction()
@@ -557,27 +706,38 @@
screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64));
{
SCOPED_TRACE("new position applied");
screenshot()->expectColor(Rect(5, 10, 69, 74), Color::RED);
}
}
-TEST_F(LayerTransactionTest, SetSizeBasic) {
+void LayerTransactionTest::setSizeBasicHelper(uint32_t layerType) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32));
Transaction().setSize(layer, 64, 64).apply();
{
SCOPED_TRACE("resize pending");
auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ Rect rect;
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ rect = {0, 0, 32, 32};
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ rect = {0, 0, 64, 64};
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64));
{
SCOPED_TRACE("resize applied");
auto shot = screenshot();
@@ -586,14 +746,22 @@
}
}
-TEST_F(LayerTransactionTest, SetSizeInvalid) {
+TEST_F(LayerTransactionTest, SetSizeBasic_BufferQueue) {
+ setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue);
+}
+
+TEST_F(LayerTransactionTest, SetSizeBasic_BufferState) {
+ setSizeBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState);
+}
+
+TEST_P(LayerTypeTransactionTest, SetSizeInvalid) {
// cannot test robustness against invalid sizes (zero or really huge)
}
-TEST_F(LayerTransactionTest, SetSizeWithScaleToWindow) {
+TEST_P(LayerTypeTransactionTest, SetSizeWithScaleToWindow) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
// setSize is immediate with SCALE_TO_WINDOW, unlike setPosition
Transaction()
@@ -603,13 +771,13 @@
screenshot()->expectColor(Rect(0, 0, 64, 64), Color::RED);
}
-TEST_F(LayerTransactionTest, SetZBasic) {
+TEST_P(LayerTypeTransactionTest, SetZBasic) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
Transaction().setLayer(layerR, mLayerZBase + 1).apply();
{
@@ -624,13 +792,13 @@
}
}
-TEST_F(LayerTransactionTest, SetZNegative) {
+TEST_P(LayerTypeTransactionTest, SetZNegative) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply();
{
@@ -649,13 +817,13 @@
}
}
-TEST_F(LayerTransactionTest, SetRelativeZBasic) {
+TEST_P(LayerTypeTransactionTest, SetRelativeZBasic) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
Transaction()
.setPosition(layerG, 16, 16)
@@ -677,16 +845,16 @@
}
}
-TEST_F(LayerTransactionTest, SetRelativeZNegative) {
+TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
sp<SurfaceControl> layerB;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32));
// layerR = mLayerZBase, layerG = layerR - 1, layerB = -2
Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply();
@@ -697,16 +865,16 @@
screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
}
-TEST_F(LayerTransactionTest, SetRelativeZGroup) {
+TEST_P(LayerTypeTransactionTest, SetRelativeZGroup) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
sp<SurfaceControl> layerB;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32));
// layerR = 0, layerG = layerR + 3, layerB = 2
Transaction()
@@ -764,14 +932,14 @@
}
}
-TEST_F(LayerTransactionTest, SetRelativeZBug64572777) {
+TEST_P(LayerTypeTransactionTest, SetRelativeZBug64572777) {
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
Transaction()
.setPosition(layerG, 16, 16)
@@ -783,10 +951,10 @@
screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
-TEST_F(LayerTransactionTest, SetFlagsHidden) {
+TEST_P(LayerTypeTransactionTest, SetFlagsHidden) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply();
{
@@ -801,14 +969,14 @@
}
}
-TEST_F(LayerTransactionTest, SetFlagsOpaque) {
+TEST_P(LayerTypeTransactionTest, SetFlagsOpaque) {
const Color translucentRed = {100, 0, 0, 100};
sp<SurfaceControl> layerR;
sp<SurfaceControl> layerG;
ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32));
ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32));
Transaction()
.setLayer(layerR, mLayerZBase + 1)
@@ -827,10 +995,10 @@
}
}
-TEST_F(LayerTransactionTest, SetFlagsSecure) {
+TEST_P(LayerTypeTransactionTest, SetFlagsSecure) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
sp<ISurfaceComposer> composer = ComposerService::getComposerService();
sp<GraphicBuffer> outBuffer;
@@ -847,19 +1015,19 @@
false));
}
-TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic) {
+TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferQueue) {
const Rect top(0, 0, 32, 16);
const Rect bottom(0, 16, 32, 32);
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
ANativeWindow_Buffer buffer;
- ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
- ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::TRANSPARENT));
- ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::RED));
// setTransparentRegionHint always applies to the following buffer
Transaction().setTransparentRegionHint(layer, Region(top)).apply();
- ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
{
SCOPED_TRACE("top transparent");
auto shot = screenshot();
@@ -875,10 +1043,10 @@
shot->expectColor(bottom, Color::RED);
}
- ASSERT_NO_FATAL_FAILURE(buffer = getLayerBuffer(layer));
- ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, top, Color::RED));
- ASSERT_NO_FATAL_FAILURE(fillBufferColor(buffer, bottom, Color::TRANSPARENT));
- ASSERT_NO_FATAL_FAILURE(postLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer));
+ ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, top, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer));
{
SCOPED_TRACE("bottom transparent");
auto shot = screenshot();
@@ -887,7 +1055,58 @@
}
}
-TEST_F(LayerTransactionTest, SetTransparentRegionHintOutOfBounds) {
+TEST_F(LayerTransactionTest, SetTransparentRegionHintBasic_BufferState) {
+ const Rect top(0, 0, 32, 16);
+ const Rect bottom(0, 16, 32, 32);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+
+ ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::TRANSPARENT));
+ ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::RED));
+ Transaction()
+ .setTransparentRegionHint(layer, Region(top))
+ .setBuffer(layer, buffer)
+ .setSize(layer, 32, 32)
+ .apply();
+ {
+ SCOPED_TRACE("top transparent");
+ auto shot = screenshot();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::RED);
+ }
+
+ Transaction().setTransparentRegionHint(layer, Region(bottom)).apply();
+ {
+ SCOPED_TRACE("transparent region hint intermediate");
+ auto shot = screenshot();
+ shot->expectColor(top, Color::BLACK);
+ shot->expectColor(bottom, Color::BLACK);
+ }
+
+ buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+
+ ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, top, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT));
+ Transaction().setBuffer(layer, buffer).setSize(layer, 32, 32).apply();
+ {
+ SCOPED_TRACE("bottom transparent");
+ auto shot = screenshot();
+ shot->expectColor(top, Color::RED);
+ shot->expectColor(bottom, Color::BLACK);
+ }
+}
+
+TEST_P(LayerTypeTransactionTest, SetTransparentRegionHintOutOfBounds) {
sp<SurfaceControl> layerTransparent;
sp<SurfaceControl> layerR;
ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32));
@@ -900,18 +1119,18 @@
.setPosition(layerR, 16, 16)
.setLayer(layerR, mLayerZBase + 1)
.apply();
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32));
screenshot()->expectColor(Rect(16, 16, 48, 48), Color::RED);
}
-TEST_F(LayerTransactionTest, SetAlphaBasic) {
+TEST_P(LayerTypeTransactionTest, SetAlphaBasic) {
sp<SurfaceControl> layer1;
sp<SurfaceControl> layer2;
ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32));
ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer1, {64, 0, 0, 255}, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer2, {0, 64, 0, 255}, 32, 32));
Transaction()
.setAlpha(layer1, 0.25f)
@@ -931,11 +1150,11 @@
}
}
-TEST_F(LayerTransactionTest, SetAlphaClamped) {
+TEST_P(LayerTypeTransactionTest, SetAlphaClamped) {
const Color color = {64, 0, 0, 255};
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32));
Transaction().setAlpha(layer, 2.0f).apply();
{
@@ -954,7 +1173,7 @@
sp<SurfaceControl> bufferLayer;
sp<SurfaceControl> colorLayer;
ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(
colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
@@ -989,7 +1208,7 @@
sp<SurfaceControl> bufferLayer;
sp<SurfaceControl> colorLayer;
ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(
colorLayer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
@@ -1014,7 +1233,7 @@
sp<SurfaceControl> colorLayer;
ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32));
ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer(
"childWithColor", 32, 32, ISurfaceComposerClient::eFXSurfaceColor));
@@ -1034,20 +1253,20 @@
tolerance);
}
-TEST_F(LayerTransactionTest, SetColorWithBuffer) {
+TEST_P(LayerTypeTransactionTest, SetColorWithBuffer) {
sp<SurfaceControl> bufferLayer;
ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32));
// color is ignored
Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply();
screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
-TEST_F(LayerTransactionTest, SetLayerStackBasic) {
+TEST_P(LayerTypeTransactionTest, SetLayerStackBasic) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply();
{
@@ -1062,11 +1281,11 @@
}
}
-TEST_F(LayerTransactionTest, SetMatrixBasic) {
+TEST_P(LayerTypeTransactionTest, SetMatrixBasic) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
ASSERT_NO_FATAL_FAILURE(
- fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+ fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply();
{
@@ -1104,11 +1323,11 @@
}
}
-TEST_F(LayerTransactionTest, SetMatrixRot45) {
+TEST_P(LayerTypeTransactionTest, SetMatrixRot45) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
ASSERT_NO_FATAL_FAILURE(
- fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+ fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
const float rot = M_SQRT1_2; // 45 degrees
const float trans = M_SQRT2 * 16.0f;
@@ -1127,31 +1346,52 @@
shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE);
}
-TEST_F(LayerTransactionTest, SetMatrixWithResize) {
+void LayerTransactionTest::setMatrixWithResizeHelper(uint32_t layerType) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32, layerType));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 32, 32));
// setMatrix is applied after any pending resize, unlike setPosition
Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply();
{
SCOPED_TRACE("resize pending");
auto shot = screenshot();
- shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
- shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ Rect rect;
+ switch (layerType) {
+ case ISurfaceComposerClient::eFXSurfaceBufferQueue:
+ rect = {0, 0, 32, 32};
+ break;
+ case ISurfaceComposerClient::eFXSurfaceBufferState:
+ rect = {0, 0, 128, 128};
+ break;
+ default:
+ ASSERT_FALSE(true) << "Unsupported layer type";
+ }
+ shot->expectColor(rect, Color::RED);
+ shot->expectBorder(rect, Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer, Color::RED, 64, 64));
{
SCOPED_TRACE("resize applied");
screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
}
}
-TEST_F(LayerTransactionTest, SetMatrixWithScaleToWindow) {
+TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferQueue) {
+ ASSERT_NO_FATAL_FAILURE(
+ setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue));
+}
+
+TEST_F(LayerTransactionTest, SetMatrixWithResize_BufferState) {
+ ASSERT_NO_FATAL_FAILURE(
+ setMatrixWithResizeHelper(ISurfaceComposerClient::eFXSurfaceBufferState));
+}
+
+TEST_P(LayerTypeTransactionTest, SetMatrixWithScaleToWindow) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32));
// setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition
Transaction()
@@ -1162,11 +1402,11 @@
screenshot()->expectColor(Rect(0, 0, 128, 128), Color::RED);
}
-TEST_F(LayerTransactionTest, SetOverrideScalingModeBasic) {
+TEST_P(LayerTypeTransactionTest, SetOverrideScalingModeBasic) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
ASSERT_NO_FATAL_FAILURE(
- fillLayerQuadrant(layer, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
+ fillLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, Color::BLUE, Color::WHITE));
// XXX SCALE_CROP is not respected; calling setSize and
// setOverrideScalingMode in separate transactions does not work
@@ -1182,10 +1422,10 @@
}
}
-TEST_F(LayerTransactionTest, SetCropBasic) {
+TEST_F(LayerTransactionTest, SetCropBasic_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
const Rect crop(8, 8, 24, 24);
Transaction().setCrop_legacy(layer, crop).apply();
@@ -1194,10 +1434,23 @@
shot->expectBorder(crop, Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetCropEmpty) {
+TEST_F(LayerTransactionTest, SetCropBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ const Rect crop(8, 8, 24, 24);
+
+ Transaction().setCrop(layer, crop).apply();
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::RED);
+ shot->expectBorder(crop, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropEmpty_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
{
SCOPED_TRACE("empty rect");
@@ -1212,10 +1465,29 @@
}
}
-TEST_F(LayerTransactionTest, SetCropOutOfBounds) {
+TEST_F(LayerTransactionTest, SetCropEmpty_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("empty rect");
+ Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+
+ {
+ SCOPED_TRACE("negative rect");
+ Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply();
+ screenshot()->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply();
auto shot = screenshot();
@@ -1223,10 +1495,22 @@
shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetCropWithTranslation) {
+TEST_F(LayerTransactionTest, SetCropOutOfBounds_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ Transaction().setCrop(layer, Rect(-128, -64, 128, 64)).apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
const Point position(32, 32);
const Rect crop(8, 8, 24, 24);
@@ -1236,10 +1520,24 @@
shot->expectBorder(crop + position, Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetCropWithScale) {
+TEST_F(LayerTransactionTest, SetCropWithTranslation_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ const Point position(32, 32);
+ const Rect crop(8, 8, 24, 24);
+ Transaction().setPosition(layer, position.x, position.y).setCrop(layer, crop).apply();
+ auto shot = screenshot();
+ shot->expectColor(crop + position, Color::RED);
+ shot->expectBorder(crop + position, Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithScale_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// crop is affected by matrix
Transaction()
@@ -1251,10 +1549,26 @@
shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetCropWithResize) {
+TEST_F(LayerTransactionTest, SetCropWithScale_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ // crop is affected by matrix
+ Transaction()
+ .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f)
+ .setCrop(layer, Rect(8, 8, 24, 24))
+ .apply();
+ auto shot = screenshot();
+ shot->expectColor(Rect(16, 16, 48, 48), Color::RED);
+ shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetCropWithResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setCrop_legacy is applied immediately by default, with or without resize pending
Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
@@ -1265,7 +1579,7 @@
shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
{
SCOPED_TRACE("resize applied");
auto shot = screenshot();
@@ -1274,10 +1588,34 @@
}
}
-TEST_F(LayerTransactionTest, SetCropWithNextResize) {
+TEST_F(LayerTransactionTest, SetCropWithResize_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ // setCrop_legacy is applied immediately by default, with or without resize pending
+ Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("new buffer pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+ shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16));
+ {
+ SCOPED_TRACE("new buffer");
+ auto shot = screenshot();
+ shot->expectColor(Rect(8, 8, 16, 16), Color::RED);
+ shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// request setCrop_legacy to be applied with the next resize
Transaction()
@@ -1302,7 +1640,7 @@
}
// finally resize
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
{
SCOPED_TRACE("new crop applied");
auto shot = screenshot();
@@ -1311,10 +1649,45 @@
}
}
-TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow) {
+TEST_F(LayerTransactionTest, SetCropWithNextResize_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ // request setCrop_legacy to be applied with the next resize
+ Transaction().setCrop(layer, Rect(8, 8, 24, 24)).setGeometryAppliesWithResize(layer).apply();
+ {
+ SCOPED_TRACE("set crop 1");
+ screenshot()->expectColor(Rect(8, 8, 24, 24), Color::RED);
+ }
+
+ Transaction().setCrop(layer, Rect(4, 4, 12, 12)).apply();
+ {
+ SCOPED_TRACE("set crop 2");
+ screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ }
+
+ Transaction().setSize(layer, 16, 16).apply();
+ {
+ SCOPED_TRACE("resize");
+ screenshot()->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ }
+
+ // finally resize
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16));
+ {
+ SCOPED_TRACE("new buffer");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// setCrop_legacy is not immediate even with SCALE_TO_WINDOW override
Transaction()
@@ -1332,7 +1705,7 @@
// XXX crop is never latched without other geometry change (b/69315677)
Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
Transaction().setPosition(layer, 0, 0).apply();
{
SCOPED_TRACE("new crop applied");
@@ -1342,10 +1715,41 @@
}
}
-TEST_F(LayerTransactionTest, SetFinalCropBasic) {
+TEST_F(LayerTransactionTest, SetCropWithNextResizeScaleToWindow_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ // all properties are applied immediate so setGeometryAppliesWithResize has no effect
+ Transaction()
+ .setCrop(layer, Rect(4, 4, 12, 12))
+ .setSize(layer, 16, 16)
+ .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)
+ .setGeometryAppliesWithResize(layer)
+ .apply();
+ {
+ SCOPED_TRACE("new crop pending");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+
+ Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 16, 16));
+ Transaction().setPosition(layer, 0, 0).apply();
+ {
+ SCOPED_TRACE("new crop applied");
+ auto shot = screenshot();
+ shot->expectColor(Rect(4, 4, 12, 12), Color::RED);
+ shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetFinalCropBasic_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
const Rect crop(8, 8, 24, 24);
// same as in SetCropBasic
@@ -1355,10 +1759,10 @@
shot->expectBorder(crop, Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetFinalCropEmpty) {
+TEST_F(LayerTransactionTest, SetFinalCropEmpty_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// same as in SetCropEmpty
{
@@ -1374,10 +1778,10 @@
}
}
-TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds) {
+TEST_F(LayerTransactionTest, SetFinalCropOutOfBounds_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// same as in SetCropOutOfBounds
Transaction().setFinalCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply();
@@ -1386,10 +1790,10 @@
shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetFinalCropWithTranslation) {
+TEST_F(LayerTransactionTest, SetFinalCropWithTranslation_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// final crop is applied post-translation
Transaction().setPosition(layer, 16, 16).setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).apply();
@@ -1398,10 +1802,10 @@
shot->expectBorder(Rect(16, 16, 24, 24), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetFinalCropWithScale) {
+TEST_F(LayerTransactionTest, SetFinalCropWithScale_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// final crop is not affected by matrix
Transaction()
@@ -1413,10 +1817,10 @@
shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
}
-TEST_F(LayerTransactionTest, SetFinalCropWithResize) {
+TEST_F(LayerTransactionTest, SetFinalCropWithResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// same as in SetCropWithResize
Transaction().setFinalCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply();
@@ -1427,7 +1831,7 @@
shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
{
SCOPED_TRACE("resize applied");
auto shot = screenshot();
@@ -1436,10 +1840,10 @@
}
}
-TEST_F(LayerTransactionTest, SetFinalCropWithNextResize) {
+TEST_F(LayerTransactionTest, SetFinalCropWithNextResize_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// same as in SetCropWithNextResize
Transaction()
@@ -1464,7 +1868,7 @@
}
// finally resize
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
{
SCOPED_TRACE("new final crop applied");
auto shot = screenshot();
@@ -1473,10 +1877,10 @@
}
}
-TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow) {
+TEST_F(LayerTransactionTest, SetFinalCropWithNextResizeScaleToWindow_BufferQueue) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32));
// same as in SetCropWithNextResizeScaleToWindow
Transaction()
@@ -1494,7 +1898,7 @@
// XXX final crop is never latched without other geometry change (b/69315677)
Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply();
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16));
Transaction().setPosition(layer, 0, 0).apply();
{
SCOPED_TRACE("new final crop applied");
@@ -1504,6 +1908,282 @@
}
}
+TEST_F(LayerTransactionTest, SetBufferBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetBufferMultipleBuffers_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("set buffer 1");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+
+ {
+ SCOPED_TRACE("set buffer 2");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+ {
+ SCOPED_TRACE("set buffer 3");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetBufferMultipleLayers_BufferState) {
+ sp<SurfaceControl> layer1;
+ ASSERT_NO_FATAL_FAILURE(
+ layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<SurfaceControl> layer2;
+ ASSERT_NO_FATAL_FAILURE(
+ layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64));
+
+ {
+ SCOPED_TRACE("set layer 1 buffer red");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32));
+
+ {
+ SCOPED_TRACE("set layer 2 buffer blue");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectColor(Rect(0, 32, 64, 64), Color::RED);
+ shot->expectColor(Rect(0, 32, 32, 64), Color::RED);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64));
+ {
+ SCOPED_TRACE("set layer 1 buffer green");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE);
+ shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN);
+ shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32));
+
+ {
+ SCOPED_TRACE("set layer 2 buffer white");
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE);
+ shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN);
+ shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
+ }
+}
+
+TEST_F(LayerTransactionTest, SetTransformRotate90_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90).apply();
+
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE,
+ Color::GREEN, true /* filtered */);
+}
+
+TEST_F(LayerTransactionTest, SetTransformFlipH_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H).apply();
+
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE,
+ Color::BLUE, true /* filtered */);
+}
+
+TEST_F(LayerTransactionTest, SetTransformFlipV_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN,
+ Color::BLUE, Color::WHITE));
+
+ Transaction().setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V).apply();
+
+ screenshot()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED,
+ Color::GREEN, true /* filtered */);
+}
+
+TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ Transaction().setTransformToDisplayInverse(layer, false).apply();
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32));
+
+ Transaction().setTransformToDisplayInverse(layer, true).apply();
+}
+
+TEST_F(LayerTransactionTest, SetFenceBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ sp<Fence> fence = new Fence(-1);
+
+ Transaction()
+ .setBuffer(layer, buffer)
+ .setAcquireFence(layer, fence)
+ .setSize(layer, 32, 32)
+ .apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetDataspaceBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ Transaction()
+ .setBuffer(layer, buffer)
+ .setDataspace(layer, ui::Dataspace::UNKNOWN)
+ .setSize(layer, 32, 32)
+ .apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetHdrMetadataBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ HdrMetadata hdrMetadata;
+ hdrMetadata.validTypes = 0;
+ Transaction()
+ .setBuffer(layer, buffer)
+ .setHdrMetadata(layer, hdrMetadata)
+ .setSize(layer, 32, 32)
+ .apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetSurfaceDamageRegionBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ Region region;
+ region.set(32, 32);
+ Transaction()
+ .setBuffer(layer, buffer)
+ .setSurfaceDamageRegion(layer, region)
+ .setSize(layer, 32, 32)
+ .apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetApiBasic_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED);
+
+ Transaction()
+ .setBuffer(layer, buffer)
+ .setApi(layer, NATIVE_WINDOW_API_CPU)
+ .setSize(layer, 32, 32)
+ .apply();
+
+ auto shot = screenshot();
+ shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
+ shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
+}
+
+TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(
+ layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
+
+ // verify this doesn't cause a crash
+ Transaction().setSidebandStream(layer, nullptr).apply();
+}
+
class LayerUpdateTest : public LayerTransactionTest {
protected:
virtual void SetUp() {
@@ -2569,8 +3249,8 @@
mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
0, redLayer.get());
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
SurfaceComposerClient::Transaction()
.setLayer(redLayer, INT32_MAX - 1)
@@ -2603,8 +3283,8 @@
mComposerClient->createSurface(String8("Blue surface"), 30, 30, PIXEL_FORMAT_RGBA_8888,
0, redLayer.get());
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30));
SurfaceComposerClient::Transaction()
.setLayer(redLayer, INT32_MAX - 1)
@@ -2636,7 +3316,7 @@
sp<SurfaceControl> redLayer = mComposerClient->createSurface(String8("Red surface"), 60, 60,
PIXEL_FORMAT_RGBA_8888, 0);
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+ ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
auto redLayerHandle = redLayer->getHandle();
mComposerClient->destroySurface(redLayerHandle);
@@ -2655,9 +3335,9 @@
void SetUp() override {
LayerTransactionTest::SetUp();
bgLayer = createLayer("BG layer", 20, 20);
- fillLayerColor(bgLayer, Color::RED);
+ fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20);
fgLayer = createLayer("FG layer", 20, 20);
- fillLayerColor(fgLayer, Color::BLUE);
+ fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20);
Transaction().setLayer(fgLayer, mLayerZBase + 1).apply();
{
SCOPED_TRACE("before anything");