Merge "Game Driver: make GpuService the GpuStats holder"
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 609ddaf..670abea 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -80,8 +80,6 @@
// system/apex/apexd/apexd_main.cpp.
//
// Only scan the APEX directory under /system (within the chroot dir).
- // Note that this leaves around the loop devices created and used by
- // libapexd's code, but this is fine, as we expect to reboot soon after.
apex::scanPackagesDirAndActivate(apex::kApexPackageSystemDir);
return apex::getActivePackages();
}
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 0573187..0e79239 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -28,6 +28,7 @@
#include <sys/cdefs.h>
+#include <android/data_space.h>
#include <android/hardware_buffer.h>
#include <android/hdr_metadata.h>
#include <android/native_window.h>
@@ -316,6 +317,15 @@
ASurfaceControl* surface_control, float alpha)
__INTRODUCED_IN(29);
+/**
+ * Sets the data space of the surface_control's buffers.
+ *
+ * If no data space is set, the surface control defaults to ADATASPACE_SRGB.
+ */
+void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
+ ASurfaceControl* surface_control, ADataSpace data_space)
+ __INTRODUCED_IN(29);
+
/*
* SMPTE ST 2086 "Mastering Display Color Volume" static metadata
*
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 34d164c..ce8db91 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -165,6 +165,13 @@
extern std::string getInputDeviceConfigurationFilePathByName(
const std::string& name, InputDeviceConfigurationFileType type);
+enum ReservedInputDeviceId : int32_t {
+ // Device id of a special "virtual" keyboard that is always present.
+ VIRTUAL_KEYBOARD_ID = -1,
+ // Device id of the "built-in" keyboard if there is one.
+ BUILT_IN_KEYBOARD_ID = 0,
+};
+
} // namespace android
#endif // _LIBINPUT_INPUT_DEVICE_H
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 96ee295..cb0e08d 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -218,7 +218,7 @@
if (!e) return; // out of memory
}
- e->mRequestingSid = true;
+ e->mRequestingSid = requestingSid;
}
BBinder::~BBinder()
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index f6381f7..0d30560 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -54,6 +54,7 @@
virtual const String16& getInterfaceDescriptor() const;
protected:
+ typedef INTERFACE BaseInterface;
virtual IBinder* onAsBinder();
};
@@ -66,6 +67,7 @@
explicit BpInterface(const sp<IBinder>& remote);
protected:
+ typedef INTERFACE BaseInterface;
virtual IBinder* onAsBinder();
};
diff --git a/libs/binder/include/binder/SafeInterface.h b/libs/binder/include/binder/SafeInterface.h
index 3bfd462..5fa2ff6 100644
--- a/libs/binder/include/binder/SafeInterface.h
+++ b/libs/binder/include/binder/SafeInterface.h
@@ -152,6 +152,12 @@
return callParcel("writeParcelableVector",
[&]() { return parcel->writeParcelableVector(v); });
}
+ status_t read(const Parcel& parcel, float* f) const {
+ return callParcel("readFloat", [&]() { return parcel.readFloat(f); });
+ }
+ status_t write(Parcel* parcel, float f) const {
+ return callParcel("writeFloat", [&]() { return parcel->writeFloat(f); });
+ }
// Templates to handle integral types. We use a struct template to require that the called
// function exactly matches the signedness and size of the argument (e.g., the argument isn't
diff --git a/libs/binder/tests/binderSafeInterfaceTest.cpp b/libs/binder/tests/binderSafeInterfaceTest.cpp
index 6a16e24..3b1db27 100644
--- a/libs/binder/tests/binderSafeInterfaceTest.cpp
+++ b/libs/binder/tests/binderSafeInterfaceTest.cpp
@@ -229,6 +229,7 @@
IncrementUint32,
IncrementInt64,
IncrementUint64,
+ IncrementFloat,
IncrementTwo,
Last,
};
@@ -259,6 +260,7 @@
virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
virtual status_t increment(int64_t a, int64_t* aPlusOne) const = 0;
virtual status_t increment(uint64_t a, uint64_t* aPlusOne) const = 0;
+ virtual status_t increment(float a, float* aPlusOne) const = 0;
// This tests that input/output parameter interleaving works correctly
virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
@@ -353,6 +355,11 @@
using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
return callRemote<Signature>(Tag::IncrementUint64, a, aPlusOne);
}
+ status_t increment(float a, float* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ using Signature = status_t (ISafeInterfaceTest::*)(float, float*) const;
+ return callRemote<Signature>(Tag::IncrementFloat, a, aPlusOne);
+ }
status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature =
@@ -474,6 +481,11 @@
*aPlusOne = a + 1;
return NO_ERROR;
}
+ status_t increment(float a, float* aPlusOne) const override {
+ ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
+ *aPlusOne = a + 1.0f;
+ return NO_ERROR;
+ }
status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
@@ -555,6 +567,10 @@
using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
+ case ISafeInterfaceTest::Tag::IncrementFloat: {
+ using Signature = status_t (ISafeInterfaceTest::*)(float, float*) const;
+ return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
+ }
case ISafeInterfaceTest::Tag::IncrementTwo: {
using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
int32_t*) const;
@@ -804,6 +820,14 @@
ASSERT_EQ(a + 1, aPlusOne);
}
+TEST_F(SafeInterfaceTest, TestIncrementFloat) {
+ const float a = 1.0f;
+ float aPlusOne = 0.0f;
+ status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
+ ASSERT_EQ(NO_ERROR, result);
+ ASSERT_EQ(a + 1.0f, aPlusOne);
+}
+
TEST_F(SafeInterfaceTest, TestIncrementTwo) {
const int32_t a = 1;
int32_t aPlusOne = 0;
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 008f520..55488da 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -63,23 +63,25 @@
SurfaceControl::~SurfaceControl()
{
+ // Avoid reparenting the server-side surface to null if we are not the owner of it,
+ // meaning that we retrieved it from another process.
if (mClient != nullptr && mHandle != nullptr && mOwned) {
SurfaceComposerClient::doDropReferenceTransaction(mHandle, mClient->getClient());
}
- mClient.clear();
- mHandle.clear();
- mGraphicBufferProducer.clear();
- IPCThreadState::self()->flushCommands();
+ release();
}
void SurfaceControl::destroy()
{
- // Avoid destroying the server-side surface if we are not the owner of it, meaning that we
- // retrieved it from another process.
- if (isValid() && mOwned) {
+ if (isValid()) {
SurfaceComposerClient::Transaction().reparent(this, nullptr).apply();
}
- // clear all references and trigger an IPC now, to make sure things
+ release();
+}
+
+void SurfaceControl::release()
+{
+ // Trigger an IPC now, to make sure things
// happen without delay, since these resources are quite heavy.
mClient.clear();
mHandle.clear();
@@ -87,17 +89,6 @@
IPCThreadState::self()->flushCommands();
}
-void SurfaceControl::clear()
-{
- // here, the window manager tells us explicitly that we should destroy
- // the surface's resource. Soon after this call, it will also release
- // its last reference (which will call the dtor); however, it is possible
- // that a client living in the same process still holds references which
- // would delay the call to the dtor -- that is why we need this explicit
- // "clear()" call.
- destroy();
-}
-
void SurfaceControl::disconnect() {
if (mGraphicBufferProducer != nullptr) {
mGraphicBufferProducer->disconnect(
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index b584f36..55efcbf 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -58,8 +58,12 @@
static bool isSameSurface(
const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs);
- // release surface data from java
- void clear();
+ // Release the handles assosciated with the SurfaceControl, without reparenting
+ // them off-screen. At the moment if this isn't executed before ~SurfaceControl
+ // is called then the destructor will reparent the layer off-screen for you.
+ void release();
+ // Reparent off-screen and release. This is invoked by the destructor.
+ void destroy();
// disconnect any api that's connected
void disconnect();
@@ -98,7 +102,6 @@
sp<Surface> generateSurfaceLocked() const;
status_t validate() const;
- void destroy();
sp<SurfaceComposerClient> mClient;
sp<IBinder> mHandle;
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 6ea1270..8ef4896 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -263,8 +263,17 @@
if (!desc) return 0;
if (!AHardwareBuffer_isValidDescription(desc, /*log=*/false)) return 0;
- // Make a trial allocation.
- // TODO(b/115660272): add implementation that uses a HAL query.
+ bool supported = false;
+ GraphicBuffer* gBuffer = new GraphicBuffer();
+ status_t err = gBuffer->isSupported(desc->width, desc->height, desc->format, desc->layers,
+ desc->usage, &supported);
+
+ if (err == NO_ERROR) {
+ return supported;
+ }
+
+ // function isSupported is not implemented on device or an error occurred during HAL
+ // query. Make a trial allocation.
AHardwareBuffer_Desc trialDesc = *desc;
trialDesc.width = 4;
trialDesc.height = desc->format == AHARDWAREBUFFER_FORMAT_BLOB ? 1 : 4;
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index c5a9942..8f9071e 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -424,6 +424,7 @@
mTraceGpuCompletion = true;
mFlushTracer = std::make_unique<FlushTracer>(this);
}
+ mDrawingBuffer = createFramebuffer();
}
GLESRenderEngine::~GLESRenderEngine() {
@@ -439,6 +440,10 @@
return std::make_unique<GLImage>(*this);
}
+Framebuffer* GLESRenderEngine::getFramebufferForDrawing() {
+ return mDrawingBuffer.get();
+}
+
void GLESRenderEngine::primeCache() const {
ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
mFeatureFlags & USE_COLOR_MANAGEMENT);
@@ -449,6 +454,7 @@
}
base::unique_fd GLESRenderEngine::flush() {
+ ATRACE_CALL();
if (!GLExtensions::getInstance().hasNativeFenceSync()) {
return base::unique_fd();
}
@@ -479,6 +485,7 @@
}
bool GLESRenderEngine::finish() {
+ ATRACE_CALL();
if (!GLExtensions::getInstance().hasFenceSync()) {
ALOGW("no synchronization support");
return false;
@@ -544,6 +551,8 @@
}
void GLESRenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
+ ATRACE_CALL();
+ glDisable(GL_BLEND);
glClearColor(red, green, blue, alpha);
glClear(GL_COLOR_BUFFER_BIT);
}
@@ -594,6 +603,7 @@
}
void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
+ ATRACE_CALL();
const GLImage& glImage = static_cast<const GLImage&>(image);
const GLenum target = GL_TEXTURE_EXTERNAL_OES;
@@ -608,8 +618,15 @@
}
status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
+ sp<Fence> bufferFence, bool readCache) {
+ return bindExternalTextureBuffer(texName, buffer, bufferFence, readCache,
+ /*persistCache=*/false);
+}
+
+status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
sp<Fence> bufferFence, bool readCache,
bool persistCache) {
+ ATRACE_CALL();
if (readCache) {
auto cachedImage = mImageCache.find(buffer->getId());
@@ -655,7 +672,7 @@
}
// We don't always want to persist to the cache, e.g. on older devices we
- // might bind for synchronization purpoeses, but that might leak if we never
+ // might bind for synchronization purposes, but that might leak if we never
// call drawLayers again, so it's just better to recreate the image again
// if needed when we draw.
if (persistCache) {
@@ -666,6 +683,7 @@
}
void GLESRenderEngine::evictImages(const std::vector<LayerSettings>& layers) {
+ ATRACE_CALL();
// destroy old image references that we're not going to draw with.
std::unordered_set<uint64_t> bufIds;
for (auto layer : layers) {
@@ -703,6 +721,7 @@
}
status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
+ ATRACE_CALL();
GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
EGLImageKHR eglImage = glFramebuffer->getEGLImage();
uint32_t textureName = glFramebuffer->getTextureName();
@@ -731,6 +750,7 @@
}
void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
+ ATRACE_CALL();
mFboHeight = 0;
// back to main framebuffer
@@ -770,6 +790,7 @@
const std::vector<LayerSettings>& layers,
ANativeWindowBuffer* const buffer,
base::unique_fd* drawFence) {
+ ATRACE_CALL();
if (layers.empty()) {
ALOGV("Drawing empty layer stack");
return NO_ERROR;
@@ -786,6 +807,13 @@
evictImages(layers);
+ // clear the entire buffer, sometimes when we reuse buffers we'd persist
+ // ghost images otherwise.
+ // we also require a full transparent framebuffer for overlays. This is
+ // probably not quite efficient on all GPUs, since we could filter out
+ // opaque layers.
+ clearWithColor(0.0, 0.0, 0.0, 0.0);
+
setViewportAndProjection(display.physicalDisplay, display.clip);
setOutputDataSpace(display.outputDataspace);
@@ -794,6 +822,7 @@
mat4 projectionMatrix = mState.projectionMatrix * display.globalTransform;
mState.projectionMatrix = projectionMatrix;
if (!display.clearRegion.isEmpty()) {
+ glDisable(GL_BLEND);
fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
}
@@ -813,9 +842,11 @@
bool usePremultipliedAlpha = true;
bool disableTexture = true;
+ bool isOpaque = false;
if (layer.source.buffer.buffer != nullptr) {
disableTexture = false;
+ isOpaque = layer.source.buffer.isOpaque;
sp<GraphicBuffer> gBuf = layer.source.buffer.buffer;
@@ -825,17 +856,19 @@
usePremultipliedAlpha = layer.source.buffer.usePremultipliedAlpha;
Texture texture(Texture::TEXTURE_EXTERNAL, layer.source.buffer.textureName);
- texture.setMatrix(layer.source.buffer.textureTransform.asArray());
+ mat4 texMatrix = layer.source.buffer.textureTransform;
+
+ texture.setMatrix(texMatrix.asArray());
texture.setFiltering(layer.source.buffer.useTextureFiltering);
texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
setSourceY410BT2020(layer.source.buffer.isY410BT2020);
renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
- texCoords[0] = vec2(0.0, 1.0);
- texCoords[1] = vec2(0.0, 0.0);
- texCoords[2] = vec2(1.0, 0.0);
- texCoords[3] = vec2(1.0, 1.0);
+ texCoords[0] = vec2(0.0, 0.0);
+ texCoords[1] = vec2(0.0, 1.0);
+ texCoords[2] = vec2(1.0, 1.0);
+ texCoords[3] = vec2(1.0, 0.0);
setupLayerTexturing(texture);
}
@@ -843,8 +876,11 @@
const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
// Buffer sources will have a black solid color ignored in the shader,
// so in that scenario the solid color passed here is arbitrary.
- setupLayerBlending(usePremultipliedAlpha, layer.source.buffer.isOpaque, disableTexture,
- color, layer.geometry.roundedCornersRadius);
+ setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
+ layer.geometry.roundedCornersRadius);
+ if (layer.disableBlending) {
+ glDisable(GL_BLEND);
+ }
setSourceDataSpace(layer.sourceDataspace);
drawMesh(mesh);
@@ -903,6 +939,7 @@
}
void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
+ ATRACE_CALL();
mVpWidth = viewport.getWidth();
mVpHeight = viewport.getHeight();
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index e094860..7b72666 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -71,6 +71,8 @@
void genTextures(size_t count, uint32_t* names) override;
void deleteTextures(size_t count, uint32_t const* names) override;
void bindExternalTextureImage(uint32_t texName, const Image& image) override;
+ status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer, sp<Fence> fence,
+ bool readCache);
status_t bindFrameBuffer(Framebuffer* framebuffer) override;
void unbindFrameBuffer(Framebuffer* framebuffer) override;
void checkErrors() const override;
@@ -86,6 +88,7 @@
EGLConfig getEGLConfig() const { return mEGLConfig; }
protected:
+ Framebuffer* getFramebufferForDrawing() override;
void dump(std::string& result) override;
void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
ui::Transform::orientation_flags rotation) override;
@@ -184,8 +187,13 @@
const bool mUseColorManagement = false;
// Cache of GL images that we'll store per GraphicBuffer ID
+ // TODO: Layer should call back on destruction instead to clean this up,
+ // as it has better system utilization at the potential expense of a
+ // more complicated interface.
std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache;
+ std::unique_ptr<Framebuffer> mDrawingBuffer;
+
class FlushTracer {
public:
FlushTracer(GLESRenderEngine* engine);
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 4a519bb..0e3b405 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include "GLFramebuffer.h"
#include <GLES/gl.h>
@@ -21,6 +23,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <nativebase/nativebase.h>
+#include <utils/Trace.h>
#include "GLESRenderEngine.h"
namespace android {
@@ -40,6 +43,7 @@
}
bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) {
+ ATRACE_CALL();
if (mEGLImage != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mEGLDisplay, mEGLImage);
mEGLImage = EGL_NO_IMAGE_KHR;
diff --git a/libs/renderengine/gl/GLImage.cpp b/libs/renderengine/gl/GLImage.cpp
index 587cb31..77e648e 100644
--- a/libs/renderengine/gl/GLImage.cpp
+++ b/libs/renderengine/gl/GLImage.cpp
@@ -14,11 +14,14 @@
* limitations under the License.
*/
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
#include "GLImage.h"
#include <vector>
#include <log/log.h>
+#include <utils/Trace.h>
#include "GLESRenderEngine.h"
#include "GLExtensions.h"
@@ -50,6 +53,7 @@
}
bool GLImage::setNativeWindowBuffer(ANativeWindowBuffer* buffer, bool isProtected) {
+ ATRACE_CALL();
if (mEGLImage != EGL_NO_IMAGE_KHR) {
if (!eglDestroyImageKHR(mEGLDisplay, mEGLImage)) {
ALOGE("failed to destroy image: %#x", eglGetError());
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 56ac714..aa45ed8 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -126,6 +126,9 @@
// Additional layer-specific color transform to be applied before the global
// transform.
mat4 colorTransform = mat4();
+
+ // True if blending will be forced to be disabled.
+ bool disableBlending = false;
};
} // namespace renderengine
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 20dd996..b51ed22 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -108,6 +108,8 @@
virtual void genTextures(size_t count, uint32_t* names) = 0;
virtual void deleteTextures(size_t count, uint32_t const* names) = 0;
virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0;
+ virtual status_t bindExternalTextureBuffer(uint32_t texName, sp<GraphicBuffer> buffer,
+ sp<Fence> fence, bool cleanCache) = 0;
// When binding a native buffer, it must be done before setViewportAndProjection
// Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
@@ -172,37 +174,37 @@
// fence.
// @return An error code indicating whether drawing was successful. For
// now, this always returns NO_ERROR.
- // TODO(alecmouri): Consider making this a multi-display API, so that the
- // caller deoes not need to handle multiple fences.
virtual status_t drawLayers(const DisplaySettings& display,
const std::vector<LayerSettings>& layers,
ANativeWindowBuffer* buffer, base::unique_fd* drawFence) = 0;
- // TODO(alecmouri): Expose something like bindTexImage() so that devices
- // that don't support native sync fences can get rid of code duplicated
- // between BufferStateLayer and BufferQueueLayer for binding an external
- // texture.
-
- // TODO(alecmouri): Add API to help with managing a texture pool.
+protected:
+ // Gets a framebuffer to render to. This framebuffer may or may not be
+ // cached depending on the implementation.
+ //
+ // Note that this method does not transfer ownership, so the caller most not
+ // live longer than RenderEngine.
+ virtual Framebuffer* getFramebufferForDrawing() = 0;
+ friend class BindNativeBufferAsFramebuffer;
};
class BindNativeBufferAsFramebuffer {
public:
BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer)
- : mEngine(engine), mFramebuffer(mEngine.createFramebuffer()), mStatus(NO_ERROR) {
+ : mEngine(engine), mFramebuffer(mEngine.getFramebufferForDrawing()), mStatus(NO_ERROR) {
mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected())
- ? mEngine.bindFrameBuffer(mFramebuffer.get())
+ ? mEngine.bindFrameBuffer(mFramebuffer)
: NO_MEMORY;
}
~BindNativeBufferAsFramebuffer() {
mFramebuffer->setNativeWindowBuffer(nullptr, false);
- mEngine.unbindFrameBuffer(mFramebuffer.get());
+ mEngine.unbindFrameBuffer(mFramebuffer);
}
status_t getStatus() const { return mStatus; }
private:
RenderEngine& mEngine;
- std::unique_ptr<Framebuffer> mFramebuffer;
+ Framebuffer* mFramebuffer;
status_t mStatus;
};
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index b4c7c96..800eac3 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -36,6 +36,7 @@
MOCK_METHOD0(createFramebuffer, std::unique_ptr<renderengine::Framebuffer>());
MOCK_METHOD0(createImage, std::unique_ptr<renderengine::Image>());
+ MOCK_METHOD0(getFramebufferForDrawing, Framebuffer*());
MOCK_CONST_METHOD0(primeCache, void());
MOCK_METHOD1(dump, void(std::string&));
MOCK_CONST_METHOD0(useNativeFenceSync, bool());
@@ -52,6 +53,7 @@
MOCK_METHOD2(genTextures, void(size_t, uint32_t*));
MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*));
MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&));
+ MOCK_METHOD4(bindExternalTextureBuffer, status_t(uint32_t, sp<GraphicBuffer>, sp<Fence>, bool));
MOCK_CONST_METHOD0(checkErrors, void());
MOCK_METHOD4(setViewportAndProjection,
void(size_t, size_t, Rect, ui::Transform::orientation_flags));
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index bef25a8..f82beeb 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -178,6 +178,9 @@
template <typename SourceVariant>
void fillBufferWithRoundedCorners();
+ template <typename SourceVariant>
+ void overlayCorners();
+
void fillRedBufferTextureTransform();
void fillBufferTextureTransform();
@@ -194,7 +197,7 @@
void clearLeftRegion();
- void fillBufferThenClearRegion();
+ void clearRegion();
// Dumb hack to get aroud the fact that tear-down for renderengine isn't
// well defined right now, so we can't create multiple instances
@@ -543,6 +546,44 @@
255);
}
+template <typename SourceVariant>
+void RenderEngineTest::overlayCorners() {
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+
+ std::vector<renderengine::LayerSettings> layersFirst;
+
+ renderengine::LayerSettings layerOne;
+ layerOne.geometry.boundaries =
+ FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH / 3.0, DEFAULT_DISPLAY_HEIGHT / 3.0);
+ SourceVariant::fillColor(layerOne, 1.0f, 0.0f, 0.0f, this);
+ layerOne.alpha = 0.2;
+
+ layersFirst.push_back(layerOne);
+ invokeDraw(settings, layersFirst, mBuffer);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 51, 0, 0, 51);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1,
+ DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ 0, 0, 0, 0);
+
+ std::vector<renderengine::LayerSettings> layersSecond;
+ renderengine::LayerSettings layerTwo;
+ layerTwo.geometry.boundaries =
+ FloatRect(DEFAULT_DISPLAY_WIDTH / 3.0, DEFAULT_DISPLAY_HEIGHT / 3.0,
+ DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT);
+ SourceVariant::fillColor(layerTwo, 0.0f, 1.0f, 0.0f, this);
+ layerTwo.alpha = 1.0f;
+
+ layersSecond.push_back(layerTwo);
+ invokeDraw(settings, layersSecond, mBuffer);
+
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3), 0, 0, 0, 0);
+ expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 3 + 1, DEFAULT_DISPLAY_HEIGHT / 3 + 1,
+ DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ 0, 255, 0, 255);
+}
+
void RenderEngineTest::fillRedBufferTextureTransform() {
renderengine::DisplaySettings settings;
settings.physicalDisplay = fullscreenRect();
@@ -685,14 +726,13 @@
invokeDraw(settings, layers, mBuffer);
}
-void RenderEngineTest::fillBufferThenClearRegion() {
- fillGreenBuffer<ColorSourceVariant>();
+void RenderEngineTest::clearRegion() {
// Reuse mBuffer
clearLeftRegion();
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT), 0, 0, 0, 255);
expectBufferColor(Rect(DEFAULT_DISPLAY_WIDTH / 2, 0, DEFAULT_DISPLAY_WIDTH,
DEFAULT_DISPLAY_HEIGHT),
- 0, 255, 0, 255);
+ 0, 0, 0, 0);
}
TEST_F(RenderEngineTest, drawLayers_noLayersToDraw) {
@@ -747,6 +787,10 @@
fillBufferWithRoundedCorners<ColorSourceVariant>();
}
+TEST_F(RenderEngineTest, drawLayers_overlayCorners_colorSource) {
+ overlayCorners<ColorSourceVariant>();
+}
+
TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_opaqueBufferSource) {
fillRedBuffer<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
@@ -795,6 +839,10 @@
fillBufferWithRoundedCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
}
+TEST_F(RenderEngineTest, drawLayers_overlayCorners_opaqueBufferSource) {
+ overlayCorners<BufferSourceVariant<ForceOpaqueBufferVariant>>();
+}
+
TEST_F(RenderEngineTest, drawLayers_fillRedBuffer_bufferSource) {
fillRedBuffer<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
@@ -843,6 +891,10 @@
fillBufferWithRoundedCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
}
+TEST_F(RenderEngineTest, drawLayers_overlayCorners_bufferSource) {
+ overlayCorners<BufferSourceVariant<RelaxOpaqueBufferVariant>>();
+}
+
TEST_F(RenderEngineTest, drawLayers_fillBufferTextureTransform) {
fillBufferTextureTransform();
}
@@ -855,8 +907,8 @@
fillBufferWithoutPremultiplyAlpha();
}
-TEST_F(RenderEngineTest, drawLayers_fillBufferThenClearRegion) {
- fillBufferThenClearRegion();
+TEST_F(RenderEngineTest, drawLayers_clearRegion) {
+ clearRegion();
}
} // namespace android
diff --git a/libs/ui/BufferHubBuffer.cpp b/libs/ui/BufferHubBuffer.cpp
index 4b20772..7693fcb 100644
--- a/libs/ui/BufferHubBuffer.cpp
+++ b/libs/ui/BufferHubBuffer.cpp
@@ -24,12 +24,12 @@
#include <utils/Trace.h>
using ::android::base::unique_fd;
-using ::android::BufferHubDefs::AnyClientAcquired;
-using ::android::BufferHubDefs::AnyClientGained;
-using ::android::BufferHubDefs::IsClientAcquired;
-using ::android::BufferHubDefs::IsClientGained;
-using ::android::BufferHubDefs::IsClientPosted;
-using ::android::BufferHubDefs::IsClientReleased;
+using ::android::BufferHubDefs::isAnyClientAcquired;
+using ::android::BufferHubDefs::isAnyClientGained;
+using ::android::BufferHubDefs::isClientAcquired;
+using ::android::BufferHubDefs::isClientGained;
+using ::android::BufferHubDefs::isClientPosted;
+using ::android::BufferHubDefs::isClientReleased;
using ::android::frameworks::bufferhub::V1_0::BufferHubStatus;
using ::android::frameworks::bufferhub::V1_0::BufferTraits;
using ::android::frameworks::bufferhub::V1_0::IBufferClient;
@@ -39,22 +39,22 @@
namespace android {
-std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Create(uint32_t width, uint32_t height,
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::create(uint32_t width, uint32_t height,
uint32_t layerCount, uint32_t format,
uint64_t usage, size_t userMetadataSize) {
auto buffer = std::unique_ptr<BufferHubBuffer>(
new BufferHubBuffer(width, height, layerCount, format, usage, userMetadataSize));
- return buffer->IsValid() ? std::move(buffer) : nullptr;
+ return buffer->isValid() ? std::move(buffer) : nullptr;
}
-std::unique_ptr<BufferHubBuffer> BufferHubBuffer::Import(const native_handle_t* token) {
+std::unique_ptr<BufferHubBuffer> BufferHubBuffer::import(const native_handle_t* token) {
if (token == nullptr) {
ALOGE("%s: token cannot be nullptr!", __FUNCTION__);
return nullptr;
}
auto buffer = std::unique_ptr<BufferHubBuffer>(new BufferHubBuffer(token));
- return buffer->IsValid() ? std::move(buffer) : nullptr;
+ return buffer->isValid() ? std::move(buffer) : nullptr;
}
BufferHubBuffer::BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount,
@@ -169,8 +169,8 @@
// Import fds. Dup fds because hidl_handle owns the fds.
unique_fd ashmemFd(fcntl(bufferTraits.bufferInfo->data[0], F_DUPFD_CLOEXEC, 0));
- mMetadata = BufferHubMetadata::Import(std::move(ashmemFd));
- if (!mMetadata.IsValid()) {
+ mMetadata = BufferHubMetadata::import(std::move(ashmemFd));
+ if (!mMetadata.isValid()) {
ALOGE("%s: Received an invalid metadata.", __FUNCTION__);
return -EINVAL;
}
@@ -196,29 +196,29 @@
uint32_t userMetadataSize;
memcpy(&userMetadataSize, &bufferTraits.bufferInfo->data[4], sizeof(userMetadataSize));
- if (mMetadata.user_metadata_size() != userMetadataSize) {
+ if (mMetadata.userMetadataSize() != userMetadataSize) {
ALOGE("%s: user metadata size not match: expected %u, actual %zu.", __FUNCTION__,
- userMetadataSize, mMetadata.user_metadata_size());
+ userMetadataSize, mMetadata.userMetadataSize());
return -EINVAL;
}
- size_t metadataSize = static_cast<size_t>(mMetadata.metadata_size());
+ size_t metadataSize = static_cast<size_t>(mMetadata.metadataSize());
if (metadataSize < BufferHubDefs::kMetadataHeaderSize) {
ALOGE("%s: metadata too small: %zu", __FUNCTION__, metadataSize);
return -EINVAL;
}
// Populate shortcuts to the atomics in metadata.
- auto metadata_header = mMetadata.metadata_header();
- buffer_state_ = &metadata_header->buffer_state;
- fence_state_ = &metadata_header->fence_state;
- active_clients_bit_mask_ = &metadata_header->active_clients_bit_mask;
+ auto metadata_header = mMetadata.metadataHeader();
+ mBufferState = &metadata_header->buffer_state;
+ mFenceState = &metadata_header->fence_state;
+ mActiveClientsBitMask = &metadata_header->active_clients_bit_mask;
// The C++ standard recommends (but does not require) that lock-free atomic operations are
// also address-free, that is, suitable for communication between processes using shared
// memory.
- LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(buffer_state_) ||
- !std::atomic_is_lock_free(fence_state_) ||
- !std::atomic_is_lock_free(active_clients_bit_mask_),
+ LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(mBufferState) ||
+ !std::atomic_is_lock_free(mFenceState) ||
+ !std::atomic_is_lock_free(mActiveClientsBitMask),
"Atomic variables in ashmen are not lock free.");
// Import the buffer: We only need to hold on the native_handle_t here so that
@@ -231,104 +231,104 @@
// TODO(b/112012161) Set up shared fences.
ALOGD("%s: id=%d, buffer_state=%" PRIx32 ".", __FUNCTION__, mId,
- buffer_state_->load(std::memory_order_acquire));
+ mBufferState->load(std::memory_order_acquire));
return 0;
}
-int BufferHubBuffer::Gain() {
- uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- if (IsClientGained(current_buffer_state, mClientStateMask)) {
+int BufferHubBuffer::gain() {
+ uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
+ if (isClientGained(currentBufferState, mClientStateMask)) {
ALOGV("%s: Buffer is already gained by this client %" PRIx32 ".", __FUNCTION__,
mClientStateMask);
return 0;
}
do {
- if (AnyClientGained(current_buffer_state & (~mClientStateMask)) ||
- AnyClientAcquired(current_buffer_state)) {
+ if (isAnyClientGained(currentBufferState & (~mClientStateMask)) ||
+ isAnyClientAcquired(currentBufferState)) {
ALOGE("%s: Buffer is in use, id=%d mClientStateMask=%" PRIx32 " state=%" PRIx32 ".",
- __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+ __FUNCTION__, mId, mClientStateMask, currentBufferState);
return -EBUSY;
}
// Change the buffer state to gained state, whose value happens to be the same as
// mClientStateMask.
- } while (!buffer_state_->compare_exchange_weak(current_buffer_state, mClientStateMask,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
+ } while (!mBufferState->compare_exchange_weak(currentBufferState, mClientStateMask,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
// TODO(b/119837586): Update fence state and return GPU fence.
return 0;
}
-int BufferHubBuffer::Post() {
- uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- uint32_t updated_buffer_state = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
+int BufferHubBuffer::post() {
+ uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
+ uint32_t updatedBufferState = (~mClientStateMask) & BufferHubDefs::kHighBitsMask;
do {
- if (!IsClientGained(current_buffer_state, mClientStateMask)) {
+ if (!isClientGained(currentBufferState, mClientStateMask)) {
ALOGE("%s: Cannot post a buffer that is not gained by this client. buffer_id=%d "
"mClientStateMask=%" PRIx32 " state=%" PRIx32 ".",
- __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+ __FUNCTION__, mId, mClientStateMask, currentBufferState);
return -EBUSY;
}
// Set the producer client buffer state to released, other clients' buffer state to posted.
// Post to all existing and non-existing clients.
- } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
+ } while (!mBufferState->compare_exchange_weak(currentBufferState, updatedBufferState,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
// TODO(b/119837586): Update fence state and return GPU fence if needed.
return 0;
}
-int BufferHubBuffer::Acquire() {
- uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- if (IsClientAcquired(current_buffer_state, mClientStateMask)) {
+int BufferHubBuffer::acquire() {
+ uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
+ if (isClientAcquired(currentBufferState, mClientStateMask)) {
ALOGV("%s: Buffer is already acquired by this client %" PRIx32 ".", __FUNCTION__,
mClientStateMask);
return 0;
}
- uint32_t updated_buffer_state = 0U;
+ uint32_t updatedBufferState = 0U;
do {
- if (!IsClientPosted(current_buffer_state, mClientStateMask)) {
+ if (!isClientPosted(currentBufferState, mClientStateMask)) {
ALOGE("%s: Cannot acquire a buffer that is not in posted state. buffer_id=%d "
"mClientStateMask=%" PRIx32 " state=%" PRIx32 ".",
- __FUNCTION__, mId, mClientStateMask, current_buffer_state);
+ __FUNCTION__, mId, mClientStateMask, currentBufferState);
return -EBUSY;
}
// Change the buffer state for this consumer from posted to acquired.
- updated_buffer_state = current_buffer_state ^ mClientStateMask;
- } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
+ updatedBufferState = currentBufferState ^ mClientStateMask;
+ } while (!mBufferState->compare_exchange_weak(currentBufferState, updatedBufferState,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
// TODO(b/119837586): Update fence state and return GPU fence.
return 0;
}
-int BufferHubBuffer::Release() {
- uint32_t current_buffer_state = buffer_state_->load(std::memory_order_acquire);
- if (IsClientReleased(current_buffer_state, mClientStateMask)) {
+int BufferHubBuffer::release() {
+ uint32_t currentBufferState = mBufferState->load(std::memory_order_acquire);
+ if (isClientReleased(currentBufferState, mClientStateMask)) {
ALOGV("%s: Buffer is already released by this client %" PRIx32 ".", __FUNCTION__,
mClientStateMask);
return 0;
}
- uint32_t updated_buffer_state = 0U;
+ uint32_t updatedBufferState = 0U;
do {
- updated_buffer_state = current_buffer_state & (~mClientStateMask);
- } while (!buffer_state_->compare_exchange_weak(current_buffer_state, updated_buffer_state,
- std::memory_order_acq_rel,
- std::memory_order_acquire));
+ updatedBufferState = currentBufferState & (~mClientStateMask);
+ } while (!mBufferState->compare_exchange_weak(currentBufferState, updatedBufferState,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire));
// TODO(b/119837586): Update fence state and return GPU fence if needed.
return 0;
}
-bool BufferHubBuffer::IsReleased() const {
- return (buffer_state_->load(std::memory_order_acquire) &
- active_clients_bit_mask_->load(std::memory_order_acquire)) == 0;
+bool BufferHubBuffer::isReleased() const {
+ return (mBufferState->load(std::memory_order_acquire) &
+ mActiveClientsBitMask->load(std::memory_order_acquire)) == 0;
}
-bool BufferHubBuffer::IsValid() const {
+bool BufferHubBuffer::isValid() const {
return mBufferHandle.getNativeHandle() != nullptr && mId >= 0 && mClientStateMask != 0U &&
- mEventFd.get() >= 0 && mMetadata.IsValid() && mBufferClient != nullptr;
+ mEventFd.get() >= 0 && mMetadata.isValid() && mBufferClient != nullptr;
}
-native_handle_t* BufferHubBuffer::Duplicate() {
+native_handle_t* BufferHubBuffer::duplicate() {
if (mBufferClient == nullptr) {
ALOGE("%s: missing BufferClient!", __FUNCTION__);
return nullptr;
diff --git a/libs/ui/BufferHubMetadata.cpp b/libs/ui/BufferHubMetadata.cpp
index 816707d..05bc7dd 100644
--- a/libs/ui/BufferHubMetadata.cpp
+++ b/libs/ui/BufferHubMetadata.cpp
@@ -34,7 +34,7 @@
using BufferHubDefs::MetadataHeader;
/* static */
-BufferHubMetadata BufferHubMetadata::Create(size_t userMetadataSize) {
+BufferHubMetadata BufferHubMetadata::create(size_t userMetadataSize) {
// The size the of metadata buffer is used as the "width" parameter during allocation. Thus it
// cannot overflow uint32_t.
if (userMetadataSize >= (std::numeric_limits<uint32_t>::max() - kMetadataHeaderSize)) {
@@ -59,11 +59,11 @@
return {};
}
- return BufferHubMetadata::Import(std::move(ashmemFd));
+ return BufferHubMetadata::import(std::move(ashmemFd));
}
/* static */
-BufferHubMetadata BufferHubMetadata::Import(unique_fd ashmemFd) {
+BufferHubMetadata BufferHubMetadata::import(unique_fd ashmemFd) {
if (!ashmem_valid(ashmemFd.get())) {
ALOGE("BufferHubMetadata::Import: invalid ashmem fd.");
return {};
@@ -94,7 +94,7 @@
BufferHubMetadata::~BufferHubMetadata() {
if (mMetadataHeader != nullptr) {
- int ret = munmap(mMetadataHeader, metadata_size());
+ int ret = munmap(mMetadataHeader, metadataSize());
ALOGE_IF(ret != 0,
"BufferHubMetadata::~BufferHubMetadata: failed to unmap ashmem, error=%d.", errno);
mMetadataHeader = nullptr;
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index e678c58..f487dfa 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -100,7 +100,7 @@
return;
}
- mInitCheck = initWithHandle(buffer->DuplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
+ mInitCheck = initWithHandle(buffer->duplicateHandle(), /*method=*/TAKE_UNREGISTERED_HANDLE,
buffer->desc().width, buffer->desc().height,
static_cast<PixelFormat>(buffer->desc().format),
buffer->desc().layers, buffer->desc().usage, buffer->desc().stride);
@@ -286,22 +286,22 @@
return res;
}
-status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd)
-{
+status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
const Rect lockBounds(width, height);
- status_t res = lockAsync(inUsage, lockBounds, vaddr, fenceFd);
+ status_t res =
+ lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
return res;
}
-status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect,
- void** vaddr, int fenceFd)
-{
- return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd);
+status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
+ return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
}
-status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage,
- uint64_t inConsumerUsage, const Rect& rect, void** vaddr, int fenceFd)
-{
+status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
+ const Rect& rect, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
if (rect.left < 0 || rect.right > width ||
rect.top < 0 || rect.bottom > height) {
ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
@@ -310,9 +310,9 @@
return BAD_VALUE;
}
- int32_t bytesPerPixel, bytesPerStride;
status_t res = getBufferMapper().lockAsync(handle, inProducerUsage, inConsumerUsage, rect,
- vaddr, fenceFd, &bytesPerPixel, &bytesPerStride);
+ vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
+
return res;
}
diff --git a/libs/ui/include/ui/BufferHubBuffer.h b/libs/ui/include/ui/BufferHubBuffer.h
index 0b6d75a..eac8c84 100644
--- a/libs/ui/include/ui/BufferHubBuffer.h
+++ b/libs/ui/include/ui/BufferHubBuffer.h
@@ -29,14 +29,14 @@
class BufferHubBuffer {
public:
// Allocates a standalone BufferHubBuffer.
- static std::unique_ptr<BufferHubBuffer> Create(uint32_t width, uint32_t height,
+ static std::unique_ptr<BufferHubBuffer> create(uint32_t width, uint32_t height,
uint32_t layerCount, uint32_t format,
uint64_t usage, size_t userMetadataSize);
// Imports the given token to a BufferHubBuffer. Not taking ownership of the token. Caller
// should close and destroy the token after calling this function regardless of output.
// TODO(b/122543147): use a movable wrapper for token
- static std::unique_ptr<BufferHubBuffer> Import(const native_handle_t* token);
+ static std::unique_ptr<BufferHubBuffer> import(const native_handle_t* token);
BufferHubBuffer(const BufferHubBuffer&) = delete;
void operator=(const BufferHubBuffer&) = delete;
@@ -52,51 +52,51 @@
// Duplicate the underlying Gralloc buffer handle. Caller is responsible to free the handle
// after use.
- native_handle_t* DuplicateHandle() {
+ native_handle_t* duplicateHandle() {
return native_handle_clone(mBufferHandle.getNativeHandle());
}
const BufferHubEventFd& eventFd() const { return mEventFd; }
// Returns the current value of MetadataHeader::buffer_state.
- uint32_t buffer_state() const { return buffer_state_->load(std::memory_order_acquire); }
+ uint32_t bufferState() const { return mBufferState->load(std::memory_order_acquire); }
// A state mask which is unique to a buffer hub client among all its siblings sharing the same
// concrete graphic buffer.
- uint32_t client_state_mask() const { return mClientStateMask; }
+ uint32_t clientStateMask() const { return mClientStateMask; }
- size_t user_metadata_size() const { return mMetadata.user_metadata_size(); }
+ size_t userMetadataSize() const { return mMetadata.userMetadataSize(); }
// Returns true if the BufferClient is still alive.
- bool IsConnected() const { return mBufferClient->ping().isOk(); }
+ bool isConnected() const { return mBufferClient->ping().isOk(); }
// Returns true if the buffer is valid: non-null buffer handle, valid id, valid client bit mask,
// valid metadata and valid buffer client
- bool IsValid() const;
+ bool isValid() const;
// Gains the buffer for exclusive write permission. Read permission is implied once a buffer is
// gained.
// The buffer can be gained as long as there is no other client in acquired or gained state.
- int Gain();
+ int gain();
// Posts the gained buffer for other buffer clients to use the buffer.
// The buffer can be posted iff the buffer state for this client is gained.
// After posting the buffer, this client is put to released state and does not have access to
// the buffer for this cycle of the usage of the buffer.
- int Post();
+ int post();
// Acquires the buffer for shared read permission.
// The buffer can be acquired iff the buffer state for this client is posted.
- int Acquire();
+ int acquire();
// Releases the buffer.
// The buffer can be released from any buffer state.
// After releasing the buffer, this client no longer have any permissions to the buffer for the
// current cycle of the usage of the buffer.
- int Release();
+ int release();
// Returns whether the buffer is released by all active clients or not.
- bool IsReleased() const;
+ bool isReleased() const;
// Creates a token that stands for this BufferHubBuffer client and could be used for Import to
// create another BufferHubBuffer. The new BufferHubBuffer will share the same underlying
@@ -104,7 +104,7 @@
// should free it after use.
// Returns a valid token on success, nullptr on failure.
// TODO(b/122543147): use a movable wrapper for token
- native_handle_t* Duplicate();
+ native_handle_t* duplicate();
private:
BufferHubBuffer(uint32_t width, uint32_t height, uint32_t layerCount, uint32_t format,
@@ -134,9 +134,9 @@
// bufferhubd daemon and all buffer clients.
BufferHubMetadata mMetadata;
// Shortcuts to the atomics inside the header of mMetadata.
- std::atomic<uint32_t>* buffer_state_ = nullptr;
- std::atomic<uint32_t>* fence_state_ = nullptr;
- std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr;
+ std::atomic<uint32_t>* mBufferState = nullptr;
+ std::atomic<uint32_t>* mFenceState = nullptr;
+ std::atomic<uint32_t>* mActiveClientsBitMask = nullptr;
// HwBinder backend
sp<frameworks::bufferhub::V1_0::IBufferClient> mBufferClient;
diff --git a/libs/ui/include/ui/BufferHubDefs.h b/libs/ui/include/ui/BufferHubDefs.h
index ff970cb..722a060 100644
--- a/libs/ui/include/ui/BufferHubDefs.h
+++ b/libs/ui/include/ui/BufferHubDefs.h
@@ -63,19 +63,19 @@
static constexpr uint32_t kFirstClientBitMask = (1U << kMaxNumberOfClients) + 1U;
// Returns true if any of the client is in gained state.
-static inline bool AnyClientGained(uint32_t state) {
+static inline bool isAnyClientGained(uint32_t state) {
uint32_t high_bits = state >> kMaxNumberOfClients;
uint32_t low_bits = state & kLowbitsMask;
return high_bits == low_bits && low_bits != 0U;
}
// Returns true if the input client is in gained state.
-static inline bool IsClientGained(uint32_t state, uint32_t client_bit_mask) {
+static inline bool isClientGained(uint32_t state, uint32_t client_bit_mask) {
return state == client_bit_mask;
}
// Returns true if any of the client is in posted state.
-static inline bool AnyClientPosted(uint32_t state) {
+static inline bool isAnyClientPosted(uint32_t state) {
uint32_t high_bits = state >> kMaxNumberOfClients;
uint32_t low_bits = state & kLowbitsMask;
uint32_t posted_or_acquired = high_bits ^ low_bits;
@@ -83,7 +83,7 @@
}
// Returns true if the input client is in posted state.
-static inline bool IsClientPosted(uint32_t state, uint32_t client_bit_mask) {
+static inline bool isClientPosted(uint32_t state, uint32_t client_bit_mask) {
uint32_t client_bits = state & client_bit_mask;
if (client_bits == 0U) return false;
uint32_t low_bits = client_bits & kLowbitsMask;
@@ -91,7 +91,7 @@
}
// Return true if any of the client is in acquired state.
-static inline bool AnyClientAcquired(uint32_t state) {
+static inline bool isAnyClientAcquired(uint32_t state) {
uint32_t high_bits = state >> kMaxNumberOfClients;
uint32_t low_bits = state & kLowbitsMask;
uint32_t posted_or_acquired = high_bits ^ low_bits;
@@ -99,7 +99,7 @@
}
// Return true if the input client is in acquired state.
-static inline bool IsClientAcquired(uint32_t state, uint32_t client_bit_mask) {
+static inline bool isClientAcquired(uint32_t state, uint32_t client_bit_mask) {
uint32_t client_bits = state & client_bit_mask;
if (client_bits == 0U) return false;
uint32_t high_bits = client_bits & kHighBitsMask;
@@ -107,13 +107,13 @@
}
// Returns true if the input client is in released state.
-static inline bool IsClientReleased(uint32_t state, uint32_t client_bit_mask) {
+static inline bool isClientReleased(uint32_t state, uint32_t client_bit_mask) {
return (state & client_bit_mask) == 0U;
}
// Returns the next available buffer client's client_state_masks.
// @params union_bits. Union of all existing clients' client_state_masks.
-static inline uint32_t FindNextAvailableClientStateMask(uint32_t union_bits) {
+static inline uint32_t findNextAvailableClientStateMask(uint32_t union_bits) {
uint32_t low_union = union_bits & kLowbitsMask;
if (low_union == kLowbitsMask) return 0U;
uint32_t incremented = low_union + 1U;
diff --git a/libs/ui/include/ui/BufferHubMetadata.h b/libs/ui/include/ui/BufferHubMetadata.h
index 2121894..3482507 100644
--- a/libs/ui/include/ui/BufferHubMetadata.h
+++ b/libs/ui/include/ui/BufferHubMetadata.h
@@ -33,12 +33,12 @@
// @param userMetadataSize Size in bytes of the user defined metadata. The entire metadata
// shared memory region to be allocated is the size of canonical
// BufferHubDefs::MetadataHeader plus userMetadataSize.
- static BufferHubMetadata Create(size_t userMetadataSize);
+ static BufferHubMetadata create(size_t userMetadataSize);
// Imports an existing BufferHubMetadata from an ashmem FD.
//
// @param ashmemFd Ashmem file descriptor representing an ashmem region.
- static BufferHubMetadata Import(unique_fd ashmemFd);
+ static BufferHubMetadata import(unique_fd ashmemFd);
BufferHubMetadata() = default;
@@ -63,13 +63,13 @@
// Returns true if the metadata is valid, i.e. the metadata has a valid ashmem fd and the ashmem
// has been mapped into virtual address space.
- bool IsValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; }
+ bool isValid() const { return mAshmemFd.get() != -1 && mMetadataHeader != nullptr; }
- size_t user_metadata_size() const { return mUserMetadataSize; }
- size_t metadata_size() const { return mUserMetadataSize + BufferHubDefs::kMetadataHeaderSize; }
+ size_t userMetadataSize() const { return mUserMetadataSize; }
+ size_t metadataSize() const { return mUserMetadataSize + BufferHubDefs::kMetadataHeaderSize; }
- const unique_fd& ashmem_fd() const { return mAshmemFd; }
- BufferHubDefs::MetadataHeader* metadata_header() { return mMetadataHeader; }
+ const unique_fd& ashmemFd() const { return mAshmemFd; }
+ BufferHubDefs::MetadataHeader* metadataHeader() { return mMetadataHeader; }
private:
BufferHubMetadata(size_t userMetadataSize, unique_fd ashmemFd,
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 7d88c58..4d4ee68 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -180,11 +180,15 @@
status_t lockYCbCr(uint32_t inUsage, const Rect& rect,
android_ycbcr *ycbcr);
status_t unlock();
- status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd);
- status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr,
- int fenceFd);
- status_t lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
- const Rect& rect, void** vaddr, int fenceFd);
+ // For the following three lockAsync functions, if bytesPerStride or bytesPerPixel
+ // are unknown or variable, -1 will be returned
+ status_t lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
+ status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr);
+ status_t lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage, const Rect& rect,
+ void** vaddr, int fenceFd, int32_t* outBytesPerPixel = nullptr,
+ int32_t* outBytesPerStride = nullptr);
status_t lockAsyncYCbCr(uint32_t inUsage, android_ycbcr *ycbcr,
int fenceFd);
status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
diff --git a/libs/ui/tests/BufferHubBuffer_test.cpp b/libs/ui/tests/BufferHubBuffer_test.cpp
index 3bcd935..3087a90 100644
--- a/libs/ui/tests/BufferHubBuffer_test.cpp
+++ b/libs/ui/tests/BufferHubBuffer_test.cpp
@@ -32,13 +32,13 @@
namespace {
-using ::android::BufferHubDefs::AnyClientAcquired;
-using ::android::BufferHubDefs::AnyClientGained;
-using ::android::BufferHubDefs::AnyClientPosted;
-using ::android::BufferHubDefs::IsClientAcquired;
-using ::android::BufferHubDefs::IsClientGained;
-using ::android::BufferHubDefs::IsClientPosted;
-using ::android::BufferHubDefs::IsClientReleased;
+using ::android::BufferHubDefs::isAnyClientAcquired;
+using ::android::BufferHubDefs::isAnyClientGained;
+using ::android::BufferHubDefs::isAnyClientPosted;
+using ::android::BufferHubDefs::isClientAcquired;
+using ::android::BufferHubDefs::isClientGained;
+using ::android::BufferHubDefs::isClientPosted;
+using ::android::BufferHubDefs::isClientReleased;
using ::android::BufferHubDefs::kMetadataHeaderSize;
using ::testing::IsNull;
using ::testing::NotNull;
@@ -81,88 +81,88 @@
};
void BufferHubBufferStateTransitionTest::CreateTwoClientsOfABuffer() {
- b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
+ b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
ASSERT_THAT(b1, NotNull());
- b1ClientMask = b1->client_state_mask();
+ b1ClientMask = b1->clientStateMask();
ASSERT_NE(b1ClientMask, 0U);
- native_handle_t* token = b1->Duplicate();
+ native_handle_t* token = b1->duplicate();
ASSERT_THAT(token, NotNull());
// TODO(b/122543147): use a movalbe wrapper for token
- b2 = BufferHubBuffer::Import(token);
+ b2 = BufferHubBuffer::import(token);
native_handle_close(token);
native_handle_delete(token);
ASSERT_THAT(b2, NotNull());
- b2ClientMask = b2->client_state_mask();
+ b2ClientMask = b2->clientStateMask();
ASSERT_NE(b2ClientMask, 0U);
ASSERT_NE(b2ClientMask, b1ClientMask);
}
TEST_F(BufferHubBufferTest, CreateBufferFails) {
// Buffer Creation will fail: BLOB format requires height to be 1.
- auto b1 = BufferHubBuffer::Create(kWidth, /*height=*/2, kLayerCount,
+ auto b1 = BufferHubBuffer::create(kWidth, /*height=*/2, kLayerCount,
/*format=*/HAL_PIXEL_FORMAT_BLOB, kUsage, kUserMetadataSize);
EXPECT_THAT(b1, IsNull());
// Buffer Creation will fail: user metadata size too large.
- auto b2 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ auto b2 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
/*userMetadataSize=*/std::numeric_limits<size_t>::max());
EXPECT_THAT(b2, IsNull());
// Buffer Creation will fail: user metadata size too large.
const size_t userMetadataSize = std::numeric_limits<size_t>::max() - kMetadataHeaderSize;
- auto b3 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ auto b3 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
userMetadataSize);
EXPECT_THAT(b3, IsNull());
}
TEST_F(BufferHubBufferTest, CreateBuffer) {
- auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
ASSERT_THAT(b1, NotNull());
- EXPECT_TRUE(b1->IsConnected());
- EXPECT_TRUE(b1->IsValid());
+ EXPECT_TRUE(b1->isConnected());
+ EXPECT_TRUE(b1->isValid());
EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), kDesc));
- EXPECT_EQ(b1->user_metadata_size(), kUserMetadataSize);
+ EXPECT_EQ(b1->userMetadataSize(), kUserMetadataSize);
}
TEST_F(BufferHubBufferTest, DuplicateAndImportBuffer) {
- auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
ASSERT_THAT(b1, NotNull());
- EXPECT_TRUE(b1->IsValid());
+ EXPECT_TRUE(b1->isValid());
- native_handle_t* token = b1->Duplicate();
+ native_handle_t* token = b1->duplicate();
EXPECT_TRUE(token);
// The detached buffer should still be valid.
- EXPECT_TRUE(b1->IsConnected());
- EXPECT_TRUE(b1->IsValid());
+ EXPECT_TRUE(b1->isConnected());
+ EXPECT_TRUE(b1->isValid());
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
native_handle_close(token);
native_handle_delete(token);
ASSERT_THAT(b2, NotNull());
- EXPECT_TRUE(b2->IsValid());
+ EXPECT_TRUE(b2->isValid());
EXPECT_TRUE(cmpAHardwareBufferDesc(b1->desc(), b2->desc()));
- EXPECT_EQ(b1->user_metadata_size(), b2->user_metadata_size());
+ EXPECT_EQ(b1->userMetadataSize(), b2->userMetadataSize());
// These two buffer instances are based on the same physical buffer under the
// hood, so they should share the same id.
EXPECT_EQ(b1->id(), b2->id());
- // We use client_state_mask() to tell those two instances apart.
- EXPECT_NE(b1->client_state_mask(), b2->client_state_mask());
+ // We use clientStateMask() to tell those two instances apart.
+ EXPECT_NE(b1->clientStateMask(), b2->clientStateMask());
// Both buffer instances should be in released state currently.
- EXPECT_TRUE(b1->IsReleased());
- EXPECT_TRUE(b2->IsReleased());
+ EXPECT_TRUE(b1->isReleased());
+ EXPECT_TRUE(b2->isReleased());
// The event fd should behave like duped event fds.
const BufferHubEventFd& eventFd1 = b1->eventFd();
@@ -192,19 +192,19 @@
}
TEST_F(BufferHubBufferTest, ImportFreedBuffer) {
- auto b1 = BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ auto b1 = BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
ASSERT_THAT(b1, NotNull());
- EXPECT_TRUE(b1->IsValid());
+ EXPECT_TRUE(b1->isValid());
- native_handle_t* token = b1->Duplicate();
+ native_handle_t* token = b1->duplicate();
EXPECT_TRUE(token);
// Explicitly destroy b1. Backend buffer should be freed and token becomes invalid
b1.reset();
// TODO(b/122543147): use a movalbe wrapper for token
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
native_handle_close(token);
native_handle_delete(token);
@@ -214,7 +214,7 @@
// nullptr must not crash the service
TEST_F(BufferHubBufferTest, ImportNullToken) {
- auto b1 = BufferHubBuffer::Import(nullptr);
+ auto b1 = BufferHubBuffer::import(nullptr);
EXPECT_THAT(b1, IsNull());
}
@@ -222,185 +222,185 @@
native_handle_t* token = native_handle_create(/*numFds=*/0, /*numInts=*/1);
token->data[0] = 0;
- auto b1 = BufferHubBuffer::Import(token);
+ auto b1 = BufferHubBuffer::import(token);
native_handle_delete(token);
EXPECT_THAT(b1, IsNull());
}
TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromReleasedState) {
- ASSERT_TRUE(b1->IsReleased());
+ ASSERT_TRUE(b1->isReleased());
// Successful gaining the buffer should change the buffer state bit of b1 to
// gained state, other client state bits to released state.
- EXPECT_EQ(b1->Gain(), 0);
- EXPECT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+ EXPECT_EQ(b1->gain(), 0);
+ EXPECT_TRUE(isClientGained(b1->bufferState(), b1ClientMask));
}
TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromGainedState) {
- ASSERT_EQ(b1->Gain(), 0);
- auto current_buffer_state = b1->buffer_state();
- ASSERT_TRUE(IsClientGained(current_buffer_state, b1ClientMask));
+ ASSERT_EQ(b1->gain(), 0);
+ auto currentBufferState = b1->bufferState();
+ ASSERT_TRUE(isClientGained(currentBufferState, b1ClientMask));
// Gaining from gained state by the same client should not return error.
- EXPECT_EQ(b1->Gain(), 0);
+ EXPECT_EQ(b1->gain(), 0);
// Gaining from gained state by another client should return error.
- EXPECT_EQ(b2->Gain(), -EBUSY);
+ EXPECT_EQ(b2->gain(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromAcquiredState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_EQ(b2->Acquire(), 0);
- ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_EQ(b2->acquire(), 0);
+ ASSERT_TRUE(isAnyClientAcquired(b1->bufferState()));
// Gaining from acquired state should fail.
- EXPECT_EQ(b1->Gain(), -EBUSY);
- EXPECT_EQ(b2->Gain(), -EBUSY);
+ EXPECT_EQ(b1->gain(), -EBUSY);
+ EXPECT_EQ(b2->gain(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromOtherClientInPostedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
// Gaining a buffer who has other posted client should succeed.
- EXPECT_EQ(b1->Gain(), 0);
+ EXPECT_EQ(b1->gain(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, GainBuffer_fromSelfInPostedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
// A posted client should be able to gain the buffer when there is no other clients in
// acquired state.
- EXPECT_EQ(b2->Gain(), 0);
+ EXPECT_EQ(b2->gain(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromOtherInGainedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask));
- EXPECT_EQ(b2->Post(), -EBUSY);
+ EXPECT_EQ(b2->post(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromSelfInGainedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_TRUE(IsClientGained(b1->buffer_state(), b1ClientMask));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_TRUE(isClientGained(b1->bufferState(), b1ClientMask));
- EXPECT_EQ(b1->Post(), 0);
- auto current_buffer_state = b1->buffer_state();
- EXPECT_TRUE(IsClientReleased(current_buffer_state, b1ClientMask));
- EXPECT_TRUE(IsClientPosted(current_buffer_state, b2ClientMask));
+ EXPECT_EQ(b1->post(), 0);
+ auto currentBufferState = b1->bufferState();
+ EXPECT_TRUE(isClientReleased(currentBufferState, b1ClientMask));
+ EXPECT_TRUE(isClientPosted(currentBufferState, b2ClientMask));
}
TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromPostedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
// Post from posted state should fail.
- EXPECT_EQ(b1->Post(), -EBUSY);
- EXPECT_EQ(b2->Post(), -EBUSY);
+ EXPECT_EQ(b1->post(), -EBUSY);
+ EXPECT_EQ(b2->post(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromAcquiredState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_EQ(b2->Acquire(), 0);
- ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_EQ(b2->acquire(), 0);
+ ASSERT_TRUE(isAnyClientAcquired(b1->bufferState()));
// Posting from acquired state should fail.
- EXPECT_EQ(b1->Post(), -EBUSY);
- EXPECT_EQ(b2->Post(), -EBUSY);
+ EXPECT_EQ(b1->post(), -EBUSY);
+ EXPECT_EQ(b2->post(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, PostBuffer_fromReleasedState) {
- ASSERT_TRUE(b1->IsReleased());
+ ASSERT_TRUE(b1->isReleased());
// Posting from released state should fail.
- EXPECT_EQ(b1->Post(), -EBUSY);
- EXPECT_EQ(b2->Post(), -EBUSY);
+ EXPECT_EQ(b1->post(), -EBUSY);
+ EXPECT_EQ(b2->post(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInPostedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask));
// Acquire from posted state should pass.
- EXPECT_EQ(b2->Acquire(), 0);
+ EXPECT_EQ(b2->acquire(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromOtherInPostedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_TRUE(IsClientPosted(b1->buffer_state(), b2ClientMask));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_TRUE(isClientPosted(b1->bufferState(), b2ClientMask));
// Acquire from released state should fail, although there are other clients
// in posted state.
- EXPECT_EQ(b1->Acquire(), -EBUSY);
+ EXPECT_EQ(b1->acquire(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromSelfInAcquiredState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_EQ(b2->Acquire(), 0);
- auto current_buffer_state = b1->buffer_state();
- ASSERT_TRUE(IsClientAcquired(current_buffer_state, b2ClientMask));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_EQ(b2->acquire(), 0);
+ auto currentBufferState = b1->bufferState();
+ ASSERT_TRUE(isClientAcquired(currentBufferState, b2ClientMask));
// Acquiring from acquired state by the same client should not error out.
- EXPECT_EQ(b2->Acquire(), 0);
+ EXPECT_EQ(b2->acquire(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromReleasedState) {
- ASSERT_TRUE(b1->IsReleased());
+ ASSERT_TRUE(b1->isReleased());
// Acquiring form released state should fail.
- EXPECT_EQ(b1->Acquire(), -EBUSY);
- EXPECT_EQ(b2->Acquire(), -EBUSY);
+ EXPECT_EQ(b1->acquire(), -EBUSY);
+ EXPECT_EQ(b2->acquire(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, AcquireBuffer_fromGainedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_TRUE(AnyClientGained(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_TRUE(isAnyClientGained(b1->bufferState()));
// Acquiring from gained state should fail.
- EXPECT_EQ(b1->Acquire(), -EBUSY);
- EXPECT_EQ(b2->Acquire(), -EBUSY);
+ EXPECT_EQ(b1->acquire(), -EBUSY);
+ EXPECT_EQ(b2->acquire(), -EBUSY);
}
TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInReleasedState) {
- ASSERT_TRUE(b1->IsReleased());
+ ASSERT_TRUE(b1->isReleased());
- EXPECT_EQ(b1->Release(), 0);
+ EXPECT_EQ(b1->release(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInGainedState) {
- ASSERT_TRUE(b1->IsReleased());
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_TRUE(AnyClientGained(b1->buffer_state()));
+ ASSERT_TRUE(b1->isReleased());
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_TRUE(isAnyClientGained(b1->bufferState()));
- EXPECT_EQ(b1->Release(), 0);
+ EXPECT_EQ(b1->release(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInPostedState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_TRUE(AnyClientPosted(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_TRUE(isAnyClientPosted(b1->bufferState()));
- EXPECT_EQ(b2->Release(), 0);
+ EXPECT_EQ(b2->release(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, ReleaseBuffer_fromSelfInAcquiredState) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_EQ(b2->Acquire(), 0);
- ASSERT_TRUE(AnyClientAcquired(b1->buffer_state()));
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_EQ(b2->acquire(), 0);
+ ASSERT_TRUE(isAnyClientAcquired(b1->bufferState()));
- EXPECT_EQ(b2->Release(), 0);
+ EXPECT_EQ(b2->release(), 0);
}
TEST_F(BufferHubBufferStateTransitionTest, BasicUsage) {
@@ -408,60 +408,60 @@
// Test if this set of basic operation succeed:
// Producer post three times to the consumer, and released by consumer.
for (int i = 0; i < 3; ++i) {
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
- ASSERT_EQ(b2->Acquire(), 0);
- ASSERT_EQ(b2->Release(), 0);
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ ASSERT_EQ(b2->acquire(), 0);
+ ASSERT_EQ(b2->release(), 0);
}
}
TEST_F(BufferHubBufferTest, createNewConsumerAfterGain) {
// Create a poducer buffer and gain.
std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
ASSERT_THAT(b1, NotNull());
- ASSERT_EQ(b1->Gain(), 0);
+ ASSERT_EQ(b1->gain(), 0);
// Create a consumer of the buffer and test if the consumer can acquire the
// buffer if producer posts.
// TODO(b/122543147): use a movalbe wrapper for token
- native_handle_t* token = b1->Duplicate();
+ native_handle_t* token = b1->duplicate();
ASSERT_TRUE(token);
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
native_handle_close(token);
native_handle_delete(token);
ASSERT_THAT(b2, NotNull());
- ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+ ASSERT_NE(b1->clientStateMask(), b2->clientStateMask());
- ASSERT_EQ(b1->Post(), 0);
- EXPECT_EQ(b2->Acquire(), 0);
+ ASSERT_EQ(b1->post(), 0);
+ EXPECT_EQ(b2->acquire(), 0);
}
TEST_F(BufferHubBufferTest, createNewConsumerAfterPost) {
// Create a poducer buffer and post.
std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::Create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
+ BufferHubBuffer::create(kWidth, kHeight, kLayerCount, kFormat, kUsage,
kUserMetadataSize);
- ASSERT_EQ(b1->Gain(), 0);
- ASSERT_EQ(b1->Post(), 0);
+ ASSERT_EQ(b1->gain(), 0);
+ ASSERT_EQ(b1->post(), 0);
// Create a consumer of the buffer and test if the consumer can acquire the
// buffer if producer posts.
// TODO(b/122543147): use a movalbe wrapper for token
- native_handle_t* token = b1->Duplicate();
+ native_handle_t* token = b1->duplicate();
ASSERT_TRUE(token);
- std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::Import(token);
+ std::unique_ptr<BufferHubBuffer> b2 = BufferHubBuffer::import(token);
native_handle_close(token);
native_handle_delete(token);
ASSERT_THAT(b2, NotNull());
- ASSERT_NE(b1->client_state_mask(), b2->client_state_mask());
+ ASSERT_NE(b1->clientStateMask(), b2->clientStateMask());
- EXPECT_EQ(b2->Acquire(), 0);
+ EXPECT_EQ(b2->acquire(), 0);
}
} // namespace
diff --git a/libs/ui/tests/BufferHubMetadata_test.cpp b/libs/ui/tests/BufferHubMetadata_test.cpp
index b7f0b4b..f02c4fc 100644
--- a/libs/ui/tests/BufferHubMetadata_test.cpp
+++ b/libs/ui/tests/BufferHubMetadata_test.cpp
@@ -25,74 +25,73 @@
class BufferHubMetadataTest : public ::testing::Test {};
TEST_F(BufferHubMetadataTest, Create_UserMetdataSizeTooBig) {
- BufferHubMetadata m1 =
- BufferHubMetadata::Create(std::numeric_limits<uint32_t>::max());
- EXPECT_FALSE(m1.IsValid());
+ BufferHubMetadata m1 = BufferHubMetadata::create(std::numeric_limits<uint32_t>::max());
+ EXPECT_FALSE(m1.isValid());
}
TEST_F(BufferHubMetadataTest, Create_Success) {
- BufferHubMetadata m1 = BufferHubMetadata::Create(kEmptyUserMetadataSize);
- EXPECT_TRUE(m1.IsValid());
- EXPECT_NE(m1.metadata_header(), nullptr);
+ BufferHubMetadata m1 = BufferHubMetadata::create(kEmptyUserMetadataSize);
+ EXPECT_TRUE(m1.isValid());
+ EXPECT_NE(m1.metadataHeader(), nullptr);
}
TEST_F(BufferHubMetadataTest, Import_Success) {
- BufferHubMetadata m1 = BufferHubMetadata::Create(kEmptyUserMetadataSize);
- EXPECT_TRUE(m1.IsValid());
- EXPECT_NE(m1.metadata_header(), nullptr);
+ BufferHubMetadata m1 = BufferHubMetadata::create(kEmptyUserMetadataSize);
+ EXPECT_TRUE(m1.isValid());
+ EXPECT_NE(m1.metadataHeader(), nullptr);
- unique_fd h2 = unique_fd(dup(m1.ashmem_fd().get()));
- EXPECT_NE(h2.get(), -1);
+ unique_fd h2 = unique_fd(dup(m1.ashmemFd().get()));
+ EXPECT_NE(h2.get(), -1);
- BufferHubMetadata m2 = BufferHubMetadata::Import(std::move(h2));
- EXPECT_EQ(h2.get(), -1);
- EXPECT_TRUE(m1.IsValid());
- BufferHubDefs::MetadataHeader* mh1 = m1.metadata_header();
- EXPECT_NE(mh1, nullptr);
+ BufferHubMetadata m2 = BufferHubMetadata::import(std::move(h2));
+ EXPECT_EQ(h2.get(), -1);
+ EXPECT_TRUE(m1.isValid());
+ BufferHubDefs::MetadataHeader* mh1 = m1.metadataHeader();
+ EXPECT_NE(mh1, nullptr);
- // Check if the newly allocated buffer is initialized in released state (i.e.
- // state equals to 0U).
- EXPECT_TRUE(mh1->buffer_state.load() == 0U);
+ // Check if the newly allocated buffer is initialized in released state (i.e.
+ // state equals to 0U).
+ EXPECT_TRUE(mh1->buffer_state.load() == 0U);
- EXPECT_TRUE(m2.IsValid());
- BufferHubDefs::MetadataHeader* mh2 = m2.metadata_header();
- EXPECT_NE(mh2, nullptr);
+ EXPECT_TRUE(m2.isValid());
+ BufferHubDefs::MetadataHeader* mh2 = m2.metadataHeader();
+ EXPECT_NE(mh2, nullptr);
- // Check if the newly allocated buffer is initialized in released state (i.e.
- // state equals to 0U).
- EXPECT_TRUE(mh2->buffer_state.load() == 0U);
+ // Check if the newly allocated buffer is initialized in released state (i.e.
+ // state equals to 0U).
+ EXPECT_TRUE(mh2->buffer_state.load() == 0U);
}
TEST_F(BufferHubMetadataTest, MoveMetadataInvalidatesOldOne) {
- BufferHubMetadata m1 = BufferHubMetadata::Create(sizeof(int));
- EXPECT_TRUE(m1.IsValid());
- EXPECT_NE(m1.metadata_header(), nullptr);
- EXPECT_NE(m1.ashmem_fd().get(), -1);
- EXPECT_EQ(m1.user_metadata_size(), sizeof(int));
+ BufferHubMetadata m1 = BufferHubMetadata::create(sizeof(int));
+ EXPECT_TRUE(m1.isValid());
+ EXPECT_NE(m1.metadataHeader(), nullptr);
+ EXPECT_NE(m1.ashmemFd().get(), -1);
+ EXPECT_EQ(m1.userMetadataSize(), sizeof(int));
- BufferHubMetadata m2 = std::move(m1);
+ BufferHubMetadata m2 = std::move(m1);
- // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
- EXPECT_EQ(m1.metadata_header(), nullptr);
- EXPECT_NE(m2.metadata_header(), nullptr);
+ // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
+ EXPECT_EQ(m1.metadataHeader(), nullptr);
+ EXPECT_NE(m2.metadataHeader(), nullptr);
- EXPECT_EQ(m1.ashmem_fd().get(), -1);
- EXPECT_NE(m2.ashmem_fd().get(), -1);
+ EXPECT_EQ(m1.ashmemFd().get(), -1);
+ EXPECT_NE(m2.ashmemFd().get(), -1);
- EXPECT_EQ(m1.user_metadata_size(), 0U);
- EXPECT_EQ(m2.user_metadata_size(), sizeof(int));
+ EXPECT_EQ(m1.userMetadataSize(), 0U);
+ EXPECT_EQ(m2.userMetadataSize(), sizeof(int));
- BufferHubMetadata m3{std::move(m2)};
+ BufferHubMetadata m3{std::move(m2)};
- // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
- EXPECT_EQ(m2.metadata_header(), nullptr);
- EXPECT_NE(m3.metadata_header(), nullptr);
+ // After the move, the metadata header (a raw pointer) should be reset in the older buffer.
+ EXPECT_EQ(m2.metadataHeader(), nullptr);
+ EXPECT_NE(m3.metadataHeader(), nullptr);
- EXPECT_EQ(m2.ashmem_fd().get(), -1);
- EXPECT_NE(m3.ashmem_fd().get(), -1);
+ EXPECT_EQ(m2.ashmemFd().get(), -1);
+ EXPECT_NE(m3.ashmemFd().get(), -1);
- EXPECT_EQ(m2.user_metadata_size(), 0U);
- EXPECT_EQ(m3.user_metadata_size(), sizeof(int));
+ EXPECT_EQ(m2.userMetadataSize(), 0U);
+ EXPECT_EQ(m3.userMetadataSize(), sizeof(int));
}
} // namespace dvr
diff --git a/libs/ui/tests/GraphicBuffer_test.cpp b/libs/ui/tests/GraphicBuffer_test.cpp
index 5b46454..c767ce0 100644
--- a/libs/ui/tests/GraphicBuffer_test.cpp
+++ b/libs/ui/tests/GraphicBuffer_test.cpp
@@ -37,10 +37,10 @@
TEST_F(GraphicBufferTest, CreateFromBufferHubBuffer) {
std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+ BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
kTestUsage, /*userMetadataSize=*/0);
ASSERT_NE(b1, nullptr);
- EXPECT_TRUE(b1->IsValid());
+ EXPECT_TRUE(b1->isValid());
sp<GraphicBuffer> gb(new GraphicBuffer(std::move(b1)));
EXPECT_TRUE(gb->isBufferHubBuffer());
@@ -61,10 +61,10 @@
TEST_F(GraphicBufferTest, BufferIdMatchesBufferHubBufferId) {
std::unique_ptr<BufferHubBuffer> b1 =
- BufferHubBuffer::Create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
+ BufferHubBuffer::create(kTestWidth, kTestHeight, kTestLayerCount, kTestFormat,
kTestUsage, /*userMetadataSize=*/0);
EXPECT_NE(b1, nullptr);
- EXPECT_TRUE(b1->IsValid());
+ EXPECT_TRUE(b1->isValid());
int b1_id = b1->id();
EXPECT_GE(b1_id, 0);
diff --git a/libs/vr/libbufferhub/buffer_hub-test.cpp b/libs/vr/libbufferhub/buffer_hub-test.cpp
index 527a27d..27ab024 100644
--- a/libs/vr/libbufferhub/buffer_hub-test.cpp
+++ b/libs/vr/libbufferhub/buffer_hub-test.cpp
@@ -20,12 +20,12 @@
return result; \
})()
-using android::BufferHubDefs::AnyClientAcquired;
-using android::BufferHubDefs::AnyClientGained;
-using android::BufferHubDefs::AnyClientPosted;
-using android::BufferHubDefs::IsClientAcquired;
-using android::BufferHubDefs::IsClientPosted;
-using android::BufferHubDefs::IsClientReleased;
+using android::BufferHubDefs::isAnyClientAcquired;
+using android::BufferHubDefs::isAnyClientGained;
+using android::BufferHubDefs::isAnyClientPosted;
+using android::BufferHubDefs::isClientAcquired;
+using android::BufferHubDefs::isClientPosted;
+using android::BufferHubDefs::isClientReleased;
using android::BufferHubDefs::kFirstClientBitMask;
using android::dvr::ConsumerBuffer;
using android::dvr::ProducerBuffer;
@@ -268,7 +268,7 @@
// Post in gained state should succeed.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
EXPECT_EQ(p->buffer_state(), c->buffer_state());
- EXPECT_TRUE(AnyClientPosted(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientPosted(p->buffer_state()));
// Post and gain in posted state should fail.
EXPECT_EQ(-EBUSY, p->PostAsync(&metadata, invalid_fence));
@@ -280,7 +280,7 @@
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
EXPECT_FALSE(invalid_fence.IsValid());
EXPECT_EQ(p->buffer_state(), c->buffer_state());
- EXPECT_TRUE(AnyClientAcquired(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientAcquired(p->buffer_state()));
// Acquire, post, and gain in acquired state should fail.
EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
@@ -304,7 +304,7 @@
EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
EXPECT_FALSE(invalid_fence.IsValid());
EXPECT_EQ(p->buffer_state(), c->buffer_state());
- EXPECT_TRUE(AnyClientGained(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientGained(p->buffer_state()));
// Acquire and gain in gained state should fail.
EXPECT_EQ(-EBUSY, c->AcquireAsync(&metadata, &invalid_fence));
@@ -329,7 +329,7 @@
ASSERT_TRUE(c.get() != nullptr);
ASSERT_EQ(0, p->GainAsync());
ASSERT_EQ(0, p->Post(LocalHandle()));
- ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
+ ASSERT_TRUE(isAnyClientPosted(p->buffer_state()));
// Gain in posted state should only succeed with gain_posted_buffer = true.
LocalHandle invalid_fence;
@@ -346,7 +346,7 @@
ASSERT_TRUE(c.get() != nullptr);
ASSERT_EQ(0, p->GainAsync());
ASSERT_EQ(0, p->Post(LocalHandle()));
- ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
+ ASSERT_TRUE(isAnyClientPosted(p->buffer_state()));
// GainAsync in posted state should only succeed with gain_posted_buffer
// equals true.
@@ -364,9 +364,9 @@
ASSERT_EQ(0, p->Post(LocalHandle()));
// Producer state bit is in released state after post, other clients shall be
// in posted state although there is no consumer of this buffer yet.
- ASSERT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask()));
+ ASSERT_TRUE(isClientReleased(p->buffer_state(), p->client_state_mask()));
ASSERT_TRUE(p->is_released());
- ASSERT_TRUE(AnyClientPosted(p->buffer_state()));
+ ASSERT_TRUE(isAnyClientPosted(p->buffer_state()));
// Gain in released state should succeed.
LocalHandle invalid_fence;
@@ -393,14 +393,14 @@
// Post the producer should trigger all consumers to be available.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
- EXPECT_TRUE(IsClientReleased(p->buffer_state(), p->client_state_mask()));
+ EXPECT_TRUE(isClientReleased(p->buffer_state(), p->client_state_mask()));
for (size_t i = 0; i < kMaxConsumerCount; ++i) {
EXPECT_TRUE(
- IsClientPosted(cs[i]->buffer_state(), cs[i]->client_state_mask()));
+ isClientPosted(cs[i]->buffer_state(), cs[i]->client_state_mask()));
EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(cs[i])));
EXPECT_EQ(0, cs[i]->AcquireAsync(&metadata, &invalid_fence));
EXPECT_TRUE(
- IsClientAcquired(p->buffer_state(), cs[i]->client_state_mask()));
+ isClientAcquired(p->buffer_state(), cs[i]->client_state_mask()));
}
// All consumers have to release before the buffer is considered to be
@@ -424,22 +424,22 @@
kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
ASSERT_TRUE(p.get() != nullptr);
EXPECT_EQ(0, p->GainAsync());
- EXPECT_TRUE(AnyClientGained(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientGained(p->buffer_state()));
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
ASSERT_TRUE(c.get() != nullptr);
- EXPECT_TRUE(AnyClientGained(c->buffer_state()));
+ EXPECT_TRUE(isAnyClientGained(c->buffer_state()));
DvrNativeBufferMetadata metadata;
LocalHandle invalid_fence;
// Post the gained buffer should signal already created consumer.
EXPECT_EQ(0, p->PostAsync(&metadata, invalid_fence));
- EXPECT_TRUE(AnyClientPosted(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientPosted(p->buffer_state()));
EXPECT_LT(0, RETRY_EINTR(PollBufferEvent(c)));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
- EXPECT_TRUE(AnyClientAcquired(c->buffer_state()));
+ EXPECT_TRUE(isAnyClientAcquired(c->buffer_state()));
}
TEST_F(LibBufferHubTest, TestCreateTheFirstConsumerAfterPostingBuffer) {
@@ -447,7 +447,7 @@
kWidth, kHeight, kFormat, kUsage, sizeof(uint64_t));
ASSERT_TRUE(p.get() != nullptr);
EXPECT_EQ(0, p->GainAsync());
- EXPECT_TRUE(AnyClientGained(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientGained(p->buffer_state()));
DvrNativeBufferMetadata metadata;
LocalHandle invalid_fence;
@@ -462,7 +462,7 @@
std::unique_ptr<ConsumerBuffer> c =
ConsumerBuffer::Import(p->CreateConsumer());
ASSERT_TRUE(c.get() != nullptr);
- EXPECT_TRUE(IsClientPosted(c->buffer_state(), c->client_state_mask()));
+ EXPECT_TRUE(isClientPosted(c->buffer_state(), c->client_state_mask()));
EXPECT_EQ(0, c->AcquireAsync(&metadata, &invalid_fence));
}
@@ -500,7 +500,7 @@
EXPECT_TRUE(p->is_released());
EXPECT_EQ(0, p->GainAsync(&metadata, &invalid_fence));
- EXPECT_TRUE(AnyClientGained(p->buffer_state()));
+ EXPECT_TRUE(isAnyClientGained(p->buffer_state()));
}
TEST_F(LibBufferHubTest, TestWithCustomMetadata) {
diff --git a/libs/vr/libbufferhub/consumer_buffer.cpp b/libs/vr/libbufferhub/consumer_buffer.cpp
index b6ca64e..115e866 100644
--- a/libs/vr/libbufferhub/consumer_buffer.cpp
+++ b/libs/vr/libbufferhub/consumer_buffer.cpp
@@ -38,7 +38,7 @@
// The buffer can be acquired iff the buffer state for this client is posted.
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
- if (!BufferHubDefs::IsClientPosted(current_buffer_state,
+ if (!BufferHubDefs::isClientPosted(current_buffer_state,
client_state_mask())) {
ALOGE(
"%s: Failed to acquire the buffer. The buffer is not posted, id=%d "
@@ -58,7 +58,7 @@
" when trying to acquire the buffer and modify the buffer state to "
"%" PRIx32 ". About to try again if the buffer is still posted.",
__FUNCTION__, current_buffer_state, updated_buffer_state);
- if (!BufferHubDefs::IsClientPosted(current_buffer_state,
+ if (!BufferHubDefs::isClientPosted(current_buffer_state,
client_state_mask())) {
ALOGE(
"%s: Failed to acquire the buffer. The buffer is no longer posted, "
@@ -144,7 +144,7 @@
// released state.
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
- if (BufferHubDefs::IsClientReleased(current_buffer_state,
+ if (BufferHubDefs::isClientReleased(current_buffer_state,
client_state_mask())) {
return 0;
}
diff --git a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
index bab7367..e610e18 100644
--- a/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
+++ b/libs/vr/libbufferhub/include/private/dvr/buffer_hub_defs.h
@@ -27,38 +27,38 @@
static constexpr uint32_t kFirstClientBitMask =
android::BufferHubDefs::kFirstClientBitMask;
-static inline bool AnyClientGained(uint32_t state) {
- return android::BufferHubDefs::AnyClientGained(state);
+static inline bool isAnyClientGained(uint32_t state) {
+ return android::BufferHubDefs::isAnyClientGained(state);
}
-static inline bool IsClientGained(uint32_t state, uint32_t client_bit_mask) {
- return android::BufferHubDefs::IsClientGained(state, client_bit_mask);
+static inline bool isClientGained(uint32_t state, uint32_t client_bit_mask) {
+ return android::BufferHubDefs::isClientGained(state, client_bit_mask);
}
-static inline bool AnyClientPosted(uint32_t state) {
- return android::BufferHubDefs::AnyClientPosted(state);
+static inline bool isAnyClientPosted(uint32_t state) {
+ return android::BufferHubDefs::isAnyClientPosted(state);
}
-static inline bool IsClientPosted(uint32_t state, uint32_t client_bit_mask) {
- return android::BufferHubDefs::IsClientPosted(state, client_bit_mask);
+static inline bool isClientPosted(uint32_t state, uint32_t client_bit_mask) {
+ return android::BufferHubDefs::isClientPosted(state, client_bit_mask);
}
-static inline bool AnyClientAcquired(uint32_t state) {
- return android::BufferHubDefs::AnyClientAcquired(state);
+static inline bool isAnyClientAcquired(uint32_t state) {
+ return android::BufferHubDefs::isAnyClientAcquired(state);
}
-static inline bool IsClientAcquired(uint32_t state, uint32_t client_bit_mask) {
- return android::BufferHubDefs::IsClientAcquired(state, client_bit_mask);
+static inline bool isClientAcquired(uint32_t state, uint32_t client_bit_mask) {
+ return android::BufferHubDefs::isClientAcquired(state, client_bit_mask);
}
-static inline bool IsClientReleased(uint32_t state, uint32_t client_bit_mask) {
- return android::BufferHubDefs::IsClientReleased(state, client_bit_mask);
+static inline bool isClientReleased(uint32_t state, uint32_t client_bit_mask) {
+ return android::BufferHubDefs::isClientReleased(state, client_bit_mask);
}
// Returns the next available buffer client's client_state_masks.
// @params union_bits. Union of all existing clients' client_state_masks.
-static inline uint32_t FindNextAvailableClientStateMask(uint32_t union_bits) {
- return android::BufferHubDefs::FindNextAvailableClientStateMask(union_bits);
+static inline uint32_t findNextAvailableClientStateMask(uint32_t union_bits) {
+ return android::BufferHubDefs::findNextAvailableClientStateMask(union_bits);
}
using MetadataHeader = android::BufferHubDefs::MetadataHeader;
diff --git a/libs/vr/libbufferhub/producer_buffer.cpp b/libs/vr/libbufferhub/producer_buffer.cpp
index edfdddf..3d88ba5 100644
--- a/libs/vr/libbufferhub/producer_buffer.cpp
+++ b/libs/vr/libbufferhub/producer_buffer.cpp
@@ -82,7 +82,7 @@
// The buffer can be posted iff the buffer state for this client is gained.
uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
- if (!BufferHubDefs::IsClientGained(current_buffer_state,
+ if (!BufferHubDefs::isClientGained(current_buffer_state,
client_state_mask())) {
ALOGE("%s: not gained, id=%d state=%" PRIx32 ".", __FUNCTION__, id(),
current_buffer_state);
@@ -103,7 +103,7 @@
"%" PRIx32
". About to try again if the buffer is still gained by this client.",
__FUNCTION__, current_buffer_state, updated_buffer_state);
- if (!BufferHubDefs::IsClientGained(current_buffer_state,
+ if (!BufferHubDefs::isClientGained(current_buffer_state,
client_state_mask())) {
ALOGE(
"%s: Failed to post the buffer. The buffer is no longer gained, "
@@ -166,14 +166,14 @@
ALOGD_IF(TRACE, "%s: buffer=%d, state=%" PRIx32 ".", __FUNCTION__, id(),
current_buffer_state);
- if (BufferHubDefs::IsClientGained(current_buffer_state,
+ if (BufferHubDefs::isClientGained(current_buffer_state,
client_state_mask())) {
ALOGV("%s: already gained id=%d.", __FUNCTION__, id());
return 0;
}
- if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
- BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(
+ if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) ||
+ BufferHubDefs::isAnyClientGained(current_buffer_state) ||
+ (BufferHubDefs::isAnyClientPosted(
current_buffer_state &
active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
@@ -195,9 +195,9 @@
"clients.",
__FUNCTION__, current_buffer_state, updated_buffer_state);
- if (BufferHubDefs::AnyClientAcquired(current_buffer_state) ||
- BufferHubDefs::AnyClientGained(current_buffer_state) ||
- (BufferHubDefs::AnyClientPosted(
+ if (BufferHubDefs::isAnyClientAcquired(current_buffer_state) ||
+ BufferHubDefs::isAnyClientGained(current_buffer_state) ||
+ (BufferHubDefs::isAnyClientPosted(
current_buffer_state &
active_clients_bit_mask_->load(std::memory_order_acquire)) &&
!gain_posted_buffer)) {
@@ -291,7 +291,7 @@
// TODO(b/112338294) Keep here for reference. Remove it after new logic is
// written.
/* uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
- if (!BufferHubDefs::IsClientGained(
+ if (!BufferHubDefs::isClientGained(
buffer_state, BufferHubDefs::kFirstClientStateMask)) {
// Can only detach a ProducerBuffer when it's in gained state.
ALOGW("ProducerBuffer::Detach: The buffer (id=%d, state=0x%" PRIx32
diff --git a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
index d7833f3..2d3fa4a 100644
--- a/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
+++ b/libs/vr/libbufferhubqueue/buffer_hub_queue_client.cpp
@@ -532,7 +532,7 @@
Status<size_t> ProducerQueue::InsertBuffer(
const std::shared_ptr<ProducerBuffer>& buffer) {
if (buffer == nullptr ||
- !BufferHubDefs::IsClientGained(buffer->buffer_state(),
+ !BufferHubDefs::isClientGained(buffer->buffer_state(),
buffer->client_state_mask())) {
ALOGE(
"ProducerQueue::InsertBuffer: Can only insert a buffer when it's in "
@@ -638,7 +638,7 @@
static_cast<int>(*slot));
return ErrorStatus(EIO);
}
- if (!BufferHubDefs::AnyClientAcquired(buffer->buffer_state())) {
+ if (!BufferHubDefs::isAnyClientAcquired(buffer->buffer_state())) {
*slot = *iter;
unavailable_buffers_slot_.erase(iter);
unavailable_buffers_slot_.push_back(*slot);
diff --git a/opengl/libagl/Android.bp b/opengl/libagl/Android.bp
new file mode 100644
index 0000000..6ec24b3
--- /dev/null
+++ b/opengl/libagl/Android.bp
@@ -0,0 +1,99 @@
+//
+// Build the software OpenGL ES library
+//
+
+cc_defaults {
+ name: "libGLES_android_defaults",
+
+ cflags: [
+ "-DLOG_TAG=\"libagl\"",
+ "-DGL_GLEXT_PROTOTYPES",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ "-fvisibility=hidden",
+ "-Wall",
+ "-Werror",
+ ],
+
+ shared_libs: [
+ "libcutils",
+ "libhardware",
+ "libutils",
+ "liblog",
+ "libpixelflinger",
+ "libETC1",
+ "libui",
+ "libnativewindow",
+ ],
+
+ // we need to access the private Bionic header <bionic_tls.h>
+ include_dirs: ["bionic/libc/private"],
+
+ arch: {
+ arm: {
+ cflags: ["-fstrict-aliasing"],
+ },
+
+ mips: {
+ cflags: [
+ "-fstrict-aliasing",
+ // The graphics code can generate division by zero
+ "-mno-check-zero-division",
+ ],
+ },
+ },
+}
+
+cc_library_shared {
+ name: "libGLES_android",
+ defaults: ["libGLES_android_defaults"],
+
+ whole_static_libs: ["libGLES_android_arm"],
+
+ srcs: [
+ "egl.cpp",
+ "state.cpp",
+ "texture.cpp",
+ "Tokenizer.cpp",
+ "TokenManager.cpp",
+ "TextureObjectManager.cpp",
+ "BufferObjectManager.cpp",
+ ],
+
+ arch: {
+ arm: {
+ srcs: [
+ "fixed_asm.S",
+ "iterators.S",
+ ],
+ },
+
+ mips: {
+ rev6: {
+ srcs: ["arch-mips/fixed_asm.S"],
+ },
+ },
+ },
+
+ relative_install_path: "egl",
+}
+
+cc_library_static {
+ name: "libGLES_android_arm",
+ defaults: ["libGLES_android_defaults"],
+
+ srcs: [
+ "array.cpp",
+ "fp.cpp",
+ "light.cpp",
+ "matrix.cpp",
+ "mipmap.cpp",
+ "primitives.cpp",
+ "vertex.cpp",
+ ],
+
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+}
diff --git a/opengl/libagl/Android.mk b/opengl/libagl/Android.mk
deleted file mode 100644
index 15a12e4..0000000
--- a/opengl/libagl/Android.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-#
-# Build the software OpenGL ES library
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- egl.cpp \
- state.cpp \
- texture.cpp \
- Tokenizer.cpp \
- TokenManager.cpp \
- TextureObjectManager.cpp \
- BufferObjectManager.cpp \
- array.cpp.arm \
- fp.cpp.arm \
- light.cpp.arm \
- matrix.cpp.arm \
- mipmap.cpp.arm \
- primitives.cpp.arm \
- vertex.cpp.arm
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libagl\"
-LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
-LOCAL_CFLAGS += -fvisibility=hidden
-
-LOCAL_SHARED_LIBRARIES := libcutils libhardware libutils liblog libpixelflinger libETC1 libui libnativewindow
-
-LOCAL_SRC_FILES_arm += fixed_asm.S iterators.S
-LOCAL_CFLAGS_arm += -fstrict-aliasing
-
-ifndef ARCH_MIPS_REV6
-LOCAL_SRC_FILES_mips += arch-mips/fixed_asm.S
-endif
-LOCAL_CFLAGS_mips += -fstrict-aliasing
-# The graphics code can generate division by zero
-LOCAL_CFLAGS_mips += -mno-check-zero-division
-
-LOCAL_CFLAGS += -Wall -Werror
-
-# we need to access the private Bionic header <bionic_tls.h>
-LOCAL_C_INCLUDES += bionic/libc/private
-
-LOCAL_MODULE_RELATIVE_PATH := egl
-LOCAL_MODULE:= libGLES_android
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/services/bufferhub/BufferHubService.cpp b/services/bufferhub/BufferHubService.cpp
index 6b802fb..90ac1c2 100644
--- a/services/bufferhub/BufferHubService.cpp
+++ b/services/bufferhub/BufferHubService.cpp
@@ -53,7 +53,7 @@
std::make_shared<BufferNode>(desc.width, desc.height, desc.layers, desc.format,
desc.usage, userMetadataSize,
BufferHubIdGenerator::getInstance().getId());
- if (node == nullptr || !node->IsValid()) {
+ if (node == nullptr || !node->isValid()) {
ALOGE("%s: creating BufferNode failed.", __FUNCTION__);
_hidl_cb(/*status=*/BufferHubStatus::ALLOCATION_FAILED, /*bufferClient=*/nullptr,
/*bufferTraits=*/{});
@@ -70,11 +70,11 @@
NATIVE_HANDLE_DECLARE_STORAGE(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds,
BufferHubDefs::kBufferInfoNumInts);
hidl_handle bufferInfo =
- buildBufferInfo(bufferInfoStorage, node->id(), node->AddNewActiveClientsBitToMask(),
- node->user_metadata_size(), node->metadata().ashmem_fd(),
+ buildBufferInfo(bufferInfoStorage, node->id(), node->addNewActiveClientsBitToMask(),
+ node->userMetadataSize(), node->metadata().ashmemFd(),
node->eventFd().get());
BufferTraits bufferTraits = {/*bufferDesc=*/description,
- /*bufferHandle=*/hidl_handle(node->buffer_handle()),
+ /*bufferHandle=*/hidl_handle(node->bufferHandle()),
/*bufferInfo=*/std::move(bufferInfo)};
_hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
@@ -141,7 +141,7 @@
}
sp<BufferClient> client = new BufferClient(*originClient);
- uint32_t clientStateMask = client->getBufferNode()->AddNewActiveClientsBitToMask();
+ uint32_t clientStateMask = client->getBufferNode()->addNewActiveClientsBitToMask();
if (clientStateMask == 0U) {
// Reach max client count
ALOGE("%s: import failed, BufferNode#%u reached maximum clients.", __FUNCTION__,
@@ -157,17 +157,17 @@
std::shared_ptr<BufferNode> node = client->getBufferNode();
HardwareBufferDescription bufferDesc;
- memcpy(&bufferDesc, &node->buffer_desc(), sizeof(HardwareBufferDescription));
+ memcpy(&bufferDesc, &node->bufferDesc(), sizeof(HardwareBufferDescription));
// Allocate memory for bufferInfo of type hidl_handle on the stack. See
// http://aosp/286282 for the usage of NATIVE_HANDLE_DECLARE_STORAGE.
NATIVE_HANDLE_DECLARE_STORAGE(bufferInfoStorage, BufferHubDefs::kBufferInfoNumFds,
BufferHubDefs::kBufferInfoNumInts);
hidl_handle bufferInfo = buildBufferInfo(bufferInfoStorage, node->id(), clientStateMask,
- node->user_metadata_size(),
- node->metadata().ashmem_fd(), node->eventFd().get());
+ node->userMetadataSize(), node->metadata().ashmemFd(),
+ node->eventFd().get());
BufferTraits bufferTraits = {/*bufferDesc=*/bufferDesc,
- /*bufferHandle=*/hidl_handle(node->buffer_handle()),
+ /*bufferHandle=*/hidl_handle(node->bufferHandle()),
/*bufferInfo=*/std::move(bufferInfo)};
_hidl_cb(/*status=*/BufferHubStatus::NO_ERROR, /*bufferClient=*/client,
@@ -231,10 +231,10 @@
for (auto iter = clientCount.begin(); iter != clientCount.end(); ++iter) {
const std::shared_ptr<BufferNode> node = std::move(iter->second.first);
const uint32_t clientCount = iter->second.second;
- AHardwareBuffer_Desc desc = node->buffer_desc();
+ AHardwareBuffer_Desc desc = node->bufferDesc();
MetadataHeader* metadataHeader =
- const_cast<BufferHubMetadata*>(&node->metadata())->metadata_header();
+ const_cast<BufferHubMetadata*>(&node->metadata())->metadataHeader();
const uint32_t state = metadataHeader->buffer_state.load(std::memory_order_acquire);
const uint64_t index = metadataHeader->queue_index;
diff --git a/services/bufferhub/BufferNode.cpp b/services/bufferhub/BufferNode.cpp
index 5106390..4f877b2 100644
--- a/services/bufferhub/BufferNode.cpp
+++ b/services/bufferhub/BufferNode.cpp
@@ -11,20 +11,19 @@
namespace V1_0 {
namespace implementation {
-void BufferNode::InitializeMetadata() {
+void BufferNode::initializeMetadata() {
// Using placement new here to reuse shared memory instead of new allocation
// Initialize the atomic variables to zero.
- BufferHubDefs::MetadataHeader* metadata_header = metadata_.metadata_header();
- buffer_state_ = new (&metadata_header->buffer_state) std::atomic<uint32_t>(0);
- fence_state_ = new (&metadata_header->fence_state) std::atomic<uint32_t>(0);
- active_clients_bit_mask_ =
- new (&metadata_header->active_clients_bit_mask) std::atomic<uint32_t>(0);
+ BufferHubDefs::MetadataHeader* metadataHeader = mMetadata.metadataHeader();
+ mBufferState = new (&metadataHeader->buffer_state) std::atomic<uint32_t>(0);
+ mFenceState = new (&metadataHeader->fence_state) std::atomic<uint32_t>(0);
+ mActiveClientsBitMask = new (&metadataHeader->active_clients_bit_mask) std::atomic<uint32_t>(0);
// The C++ standard recommends (but does not require) that lock-free atomic operations are
// also address-free, that is, suitable for communication between processes using shared
// memory.
- LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(buffer_state_) ||
- !std::atomic_is_lock_free(fence_state_) ||
- !std::atomic_is_lock_free(active_clients_bit_mask_),
+ LOG_ALWAYS_FATAL_IF(!std::atomic_is_lock_free(mBufferState) ||
+ !std::atomic_is_lock_free(mFenceState) ||
+ !std::atomic_is_lock_free(mActiveClientsBitMask),
"Atomic variables in ashmen are not lock free.");
}
@@ -38,35 +37,35 @@
// hardcoded service name "bufferhub".
int ret = GraphicBufferAllocator::get().allocate(width, height, format, layer_count, usage,
const_cast<const native_handle_t**>(
- &buffer_handle_),
+ &mBufferHandle),
&out_stride,
/*graphicBufferId=*/0,
/*requestor=*/"bufferhub");
- if (ret != OK || buffer_handle_ == nullptr) {
+ if (ret != OK || mBufferHandle == nullptr) {
ALOGE("%s: Failed to allocate buffer: %s", __FUNCTION__, strerror(-ret));
return;
}
- buffer_desc_.width = width;
- buffer_desc_.height = height;
- buffer_desc_.layers = layer_count;
- buffer_desc_.format = format;
- buffer_desc_.usage = usage;
- buffer_desc_.stride = out_stride;
+ mBufferDesc.width = width;
+ mBufferDesc.height = height;
+ mBufferDesc.layers = layer_count;
+ mBufferDesc.format = format;
+ mBufferDesc.usage = usage;
+ mBufferDesc.stride = out_stride;
- metadata_ = BufferHubMetadata::Create(user_metadata_size);
- if (!metadata_.IsValid()) {
+ mMetadata = BufferHubMetadata::create(user_metadata_size);
+ if (!mMetadata.isValid()) {
ALOGE("%s: Failed to allocate metadata.", __FUNCTION__);
return;
}
- InitializeMetadata();
+ initializeMetadata();
}
BufferNode::~BufferNode() {
// Free the handle
- if (buffer_handle_ != nullptr) {
- status_t ret = GraphicBufferAllocator::get().free(buffer_handle_);
+ if (mBufferHandle != nullptr) {
+ status_t ret = GraphicBufferAllocator::get().free(mBufferHandle);
if (ret != OK) {
ALOGE("%s: Failed to free handle; Got error: %d", __FUNCTION__, ret);
}
@@ -78,33 +77,33 @@
}
}
-uint32_t BufferNode::GetActiveClientsBitMask() const {
- return active_clients_bit_mask_->load(std::memory_order_acquire);
+uint32_t BufferNode::getActiveClientsBitMask() const {
+ return mActiveClientsBitMask->load(std::memory_order_acquire);
}
-uint32_t BufferNode::AddNewActiveClientsBitToMask() {
- uint32_t current_active_clients_bit_mask = GetActiveClientsBitMask();
+uint32_t BufferNode::addNewActiveClientsBitToMask() {
+ uint32_t currentActiveClientsBitMask = getActiveClientsBitMask();
uint32_t client_state_mask = 0U;
- uint32_t updated_active_clients_bit_mask = 0U;
+ uint32_t updatedActiveClientsBitMask = 0U;
do {
client_state_mask =
- BufferHubDefs::FindNextAvailableClientStateMask(current_active_clients_bit_mask);
+ BufferHubDefs::findNextAvailableClientStateMask(currentActiveClientsBitMask);
if (client_state_mask == 0U) {
ALOGE("%s: reached the maximum number of channels per buffer node: %d.", __FUNCTION__,
BufferHubDefs::kMaxNumberOfClients);
errno = E2BIG;
return 0U;
}
- updated_active_clients_bit_mask = current_active_clients_bit_mask | client_state_mask;
- } while (!(active_clients_bit_mask_->compare_exchange_weak(current_active_clients_bit_mask,
- updated_active_clients_bit_mask,
- std::memory_order_acq_rel,
- std::memory_order_acquire)));
+ updatedActiveClientsBitMask = currentActiveClientsBitMask | client_state_mask;
+ } while (!(mActiveClientsBitMask->compare_exchange_weak(currentActiveClientsBitMask,
+ updatedActiveClientsBitMask,
+ std::memory_order_acq_rel,
+ std::memory_order_acquire)));
return client_state_mask;
}
-void BufferNode::RemoveClientsBitFromMask(const uint32_t& value) {
- active_clients_bit_mask_->fetch_and(~value);
+void BufferNode::removeClientsBitFromMask(const uint32_t& value) {
+ mActiveClientsBitMask->fetch_and(~value);
}
} // namespace implementation
diff --git a/services/bufferhub/include/bufferhub/BufferNode.h b/services/bufferhub/include/bufferhub/BufferNode.h
index 4729e1c..04970fd 100644
--- a/services/bufferhub/include/bufferhub/BufferNode.h
+++ b/services/bufferhub/include/bufferhub/BufferNode.h
@@ -22,73 +22,73 @@
~BufferNode();
// Returns whether the object holds a valid metadata.
- bool IsValid() const { return metadata_.IsValid(); }
+ bool isValid() const { return mMetadata.isValid(); }
int id() const { return mId; }
- size_t user_metadata_size() const { return metadata_.user_metadata_size(); }
+ size_t userMetadataSize() const { return mMetadata.userMetadataSize(); }
// Accessors of the buffer description and handle
- const native_handle_t* buffer_handle() const { return buffer_handle_; }
- const AHardwareBuffer_Desc& buffer_desc() const { return buffer_desc_; }
+ const native_handle_t* bufferHandle() const { return mBufferHandle; }
+ const AHardwareBuffer_Desc& bufferDesc() const { return mBufferDesc; }
// Accessor of event fd.
const BufferHubEventFd& eventFd() const { return mEventFd; }
- // Accessors of metadata.
- const BufferHubMetadata& metadata() const { return metadata_; }
+ // Accessors of mMetadata.
+ const BufferHubMetadata& metadata() const { return mMetadata; }
- // Gets the current value of active_clients_bit_mask in metadata_ with
+ // Gets the current value of mActiveClientsBitMask in mMetadata with
// std::memory_order_acquire, so that all previous releases of
- // active_clients_bit_mask from all threads will be returned here.
- uint32_t GetActiveClientsBitMask() const;
+ // mActiveClientsBitMask from all threads will be returned here.
+ uint32_t getActiveClientsBitMask() const;
- // Find and add a new client_state_mask to active_clients_bit_mask in
- // metadata_.
- // Return the new client_state_mask that is added to active_clients_bit_mask.
+ // Find and add a new client state mask to mActiveClientsBitMask in
+ // mMetadata.
+ // Return the new client state mask that is added to mActiveClientsBitMask.
// Return 0U if there are already 16 clients of the buffer.
- uint32_t AddNewActiveClientsBitToMask();
+ uint32_t addNewActiveClientsBitToMask();
- // Removes the value from active_clients_bit_mask in metadata_ with
+ // Removes the value from active_clients_bit_mask in mMetadata with
// std::memory_order_release, so that the change will be visible to any
- // acquire of active_clients_bit_mask_ in any threads after the succeed of
+ // acquire of mActiveClientsBitMask in any threads after the succeed of
// this operation.
- void RemoveClientsBitFromMask(const uint32_t& value);
+ void removeClientsBitFromMask(const uint32_t& value);
private:
// Helper method for constructors to initialize atomic metadata header
// variables in shared memory.
- void InitializeMetadata();
+ void initializeMetadata();
// Gralloc buffer handles.
- native_handle_t* buffer_handle_;
- AHardwareBuffer_Desc buffer_desc_;
+ native_handle_t* mBufferHandle;
+ AHardwareBuffer_Desc mBufferDesc;
// Eventfd used for signalling buffer events among the clients of the buffer.
BufferHubEventFd mEventFd;
// Metadata in shared memory.
- BufferHubMetadata metadata_;
+ BufferHubMetadata mMetadata;
// A system-unique id generated by bufferhub from 0 to std::numeric_limits<int>::max().
// BufferNodes not created by bufferhub will have id < 0, meaning "not specified".
// TODO(b/118891412): remove default id = -1 and update comments after pdx is no longer in use
const int mId = -1;
- // The following variables are atomic variables in metadata_ that are visible
+ // The following variables are atomic variables in mMetadata that are visible
// to Bn object and Bp objects. Please find more info in
// BufferHubDefs::MetadataHeader.
- // buffer_state_ tracks the state of the buffer. Buffer can be in one of these
+ // mBufferState tracks the state of the buffer. Buffer can be in one of these
// four states: gained, posted, acquired, released.
- std::atomic<uint32_t>* buffer_state_ = nullptr;
+ std::atomic<uint32_t>* mBufferState = nullptr;
- // TODO(b/112012161): add comments to fence_state_.
- std::atomic<uint32_t>* fence_state_ = nullptr;
+ // TODO(b/112012161): add comments to mFenceState.
+ std::atomic<uint32_t>* mFenceState = nullptr;
- // active_clients_bit_mask_ tracks all the bp clients of the buffer. It is the
+ // mActiveClientsBitMask tracks all the bp clients of the buffer. It is the
// union of all client_state_mask of all bp clients.
- std::atomic<uint32_t>* active_clients_bit_mask_ = nullptr;
+ std::atomic<uint32_t>* mActiveClientsBitMask = nullptr;
};
} // namespace implementation
diff --git a/services/bufferhub/tests/BufferNode_test.cpp b/services/bufferhub/tests/BufferNode_test.cpp
index ccb1197..b9f1c81 100644
--- a/services/bufferhub/tests/BufferNode_test.cpp
+++ b/services/bufferhub/tests/BufferNode_test.cpp
@@ -28,7 +28,7 @@
void SetUp() override {
buffer_node =
new BufferNode(kWidth, kHeight, kLayerCount, kFormat, kUsage, kUserMetadataSize);
- ASSERT_TRUE(buffer_node->IsValid());
+ ASSERT_TRUE(buffer_node->isValid());
}
void TearDown() override {
@@ -41,65 +41,64 @@
};
TEST_F(BufferNodeTest, TestCreateBufferNode) {
- EXPECT_EQ(buffer_node->user_metadata_size(), kUserMetadataSize);
+ EXPECT_EQ(buffer_node->userMetadataSize(), kUserMetadataSize);
// Test the handle just allocated is good (i.e. able to be imported)
GraphicBufferMapper& mapper = GraphicBufferMapper::get();
const native_handle_t* outHandle;
status_t ret =
- mapper.importBuffer(buffer_node->buffer_handle(), buffer_node->buffer_desc().width,
- buffer_node->buffer_desc().height,
- buffer_node->buffer_desc().layers,
- buffer_node->buffer_desc().format, buffer_node->buffer_desc().usage,
- buffer_node->buffer_desc().stride, &outHandle);
+ mapper.importBuffer(buffer_node->bufferHandle(), buffer_node->bufferDesc().width,
+ buffer_node->bufferDesc().height, buffer_node->bufferDesc().layers,
+ buffer_node->bufferDesc().format, buffer_node->bufferDesc().usage,
+ buffer_node->bufferDesc().stride, &outHandle);
EXPECT_EQ(ret, OK);
EXPECT_THAT(outHandle, NotNull());
}
-TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_twoNewClients) {
- uint32_t new_client_state_mask_1 = buffer_node->AddNewActiveClientsBitToMask();
- EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), new_client_state_mask_1);
+TEST_F(BufferNodeTest, TestaddNewActiveClientsBitToMask_twoNewClients) {
+ uint32_t new_client_state_mask_1 = buffer_node->addNewActiveClientsBitToMask();
+ EXPECT_EQ(buffer_node->getActiveClientsBitMask(), new_client_state_mask_1);
// Request and add a new client_state_mask again.
// Active clients bit mask should be the union of the two new
// client_state_masks.
- uint32_t new_client_state_mask_2 = buffer_node->AddNewActiveClientsBitToMask();
- EXPECT_EQ(buffer_node->GetActiveClientsBitMask(),
+ uint32_t new_client_state_mask_2 = buffer_node->addNewActiveClientsBitToMask();
+ EXPECT_EQ(buffer_node->getActiveClientsBitMask(),
new_client_state_mask_1 | new_client_state_mask_2);
}
-TEST_F(BufferNodeTest, TestAddNewActiveClientsBitToMask_32NewClients) {
+TEST_F(BufferNodeTest, TestaddNewActiveClientsBitToMask_32NewClients) {
uint32_t new_client_state_mask = 0U;
uint32_t current_mask = 0U;
uint32_t expected_mask = 0U;
for (int i = 0; i < BufferHubDefs::kMaxNumberOfClients; ++i) {
- new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask();
+ new_client_state_mask = buffer_node->addNewActiveClientsBitToMask();
EXPECT_NE(new_client_state_mask, 0U);
EXPECT_FALSE(new_client_state_mask & current_mask);
expected_mask = current_mask | new_client_state_mask;
- current_mask = buffer_node->GetActiveClientsBitMask();
+ current_mask = buffer_node->getActiveClientsBitMask();
EXPECT_EQ(current_mask, expected_mask);
}
// Method should fail upon requesting for more than maximum allowable clients.
- new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask();
+ new_client_state_mask = buffer_node->addNewActiveClientsBitToMask();
EXPECT_EQ(new_client_state_mask, 0U);
EXPECT_EQ(errno, E2BIG);
}
TEST_F(BufferNodeTest, TestRemoveActiveClientsBitFromMask) {
- buffer_node->AddNewActiveClientsBitToMask();
- uint32_t current_mask = buffer_node->GetActiveClientsBitMask();
- uint32_t new_client_state_mask = buffer_node->AddNewActiveClientsBitToMask();
- EXPECT_NE(buffer_node->GetActiveClientsBitMask(), current_mask);
+ buffer_node->addNewActiveClientsBitToMask();
+ uint32_t current_mask = buffer_node->getActiveClientsBitMask();
+ uint32_t new_client_state_mask = buffer_node->addNewActiveClientsBitToMask();
+ EXPECT_NE(buffer_node->getActiveClientsBitMask(), current_mask);
- buffer_node->RemoveClientsBitFromMask(new_client_state_mask);
- EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), current_mask);
+ buffer_node->removeClientsBitFromMask(new_client_state_mask);
+ EXPECT_EQ(buffer_node->getActiveClientsBitMask(), current_mask);
// Remove the test_mask again to the active client bit mask should not modify
// the value of active clients bit mask.
- buffer_node->RemoveClientsBitFromMask(new_client_state_mask);
- EXPECT_EQ(buffer_node->GetActiveClientsBitMask(), current_mask);
+ buffer_node->removeClientsBitFromMask(new_client_state_mask);
+ EXPECT_EQ(buffer_node->getActiveClientsBitMask(), current_mask);
}
} // namespace
diff --git a/services/inputflinger/BlockingQueue.h b/services/inputflinger/BlockingQueue.h
index b892120..c9eb683 100644
--- a/services/inputflinger/BlockingQueue.h
+++ b/services/inputflinger/BlockingQueue.h
@@ -80,6 +80,16 @@
mQueue.clear();
};
+ /**
+ * How many elements are currently stored in the queue.
+ * Primary used for debugging.
+ * Does not block.
+ */
+ size_t size() {
+ std::scoped_lock lock(mLock);
+ return mQueue.size();
+ }
+
private:
size_t mCapacity;
/**
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index cf9d3c7..c13bac6 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -763,7 +763,7 @@
}
EventHub::Device* EventHub::getDeviceLocked(int32_t deviceId) const {
- if (deviceId == BUILT_IN_KEYBOARD_ID) {
+ if (deviceId == ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID) {
deviceId = mBuiltInKeyboardId;
}
ssize_t index = mDevices.indexOfKey(deviceId);
@@ -835,7 +835,8 @@
device->id, device->path.c_str());
mClosingDevices = device->next;
event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? BUILT_IN_KEYBOARD_ID : device->id;
+ event->deviceId = (device->id == mBuiltInKeyboardId) ?
+ ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID : device->id;
event->type = DEVICE_REMOVED;
event += 1;
delete device;
@@ -1081,7 +1082,7 @@
ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
}
}
- if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
+ if (mDevices.indexOfKey(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) < 0) {
createVirtualKeyboardLocked();
}
}
@@ -1580,7 +1581,8 @@
identifier.uniqueId = "<virtual>";
assignDescriptorLocked(identifier);
- Device* device = new Device(-1, VIRTUAL_KEYBOARD_ID, "<virtual>", identifier);
+ Device* device = new Device(-1, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, "<virtual>",
+ identifier);
device->classes = INPUT_DEVICE_CLASS_KEYBOARD
| INPUT_DEVICE_CLASS_ALPHAKEY
| INPUT_DEVICE_CLASS_DPAD
diff --git a/services/inputflinger/include/EventHub.h b/services/inputflinger/EventHub.h
similarity index 98%
rename from services/inputflinger/include/EventHub.h
rename to services/inputflinger/EventHub.h
index 295aca8..d176648 100644
--- a/services/inputflinger/include/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -46,13 +46,6 @@
namespace android {
-enum {
- // Device id of a special "virtual" keyboard that is always present.
- VIRTUAL_KEYBOARD_ID = -1,
- // Device id of the "built-in" keyboard if there is one.
- BUILT_IN_KEYBOARD_ID = 0,
-};
-
/*
* A raw event as retrieved from the EventHub.
*/
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 7ade0d4..09a004c 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -19,6 +19,7 @@
#include "InputClassifier.h"
#include <algorithm>
+#include <android-base/stringprintf.h>
#include <cmath>
#include <inttypes.h>
#include <log/log.h>
@@ -26,9 +27,17 @@
#include <pthread.h>
#endif
#include <server_configurable_flags/get_flags.h>
+#include <unordered_set>
#include <android/hardware/input/classifier/1.0/IInputClassifier.h>
+#define INDENT1 " "
+#define INDENT2 " "
+#define INDENT3 " "
+#define INDENT4 " "
+#define INDENT5 " "
+
+using android::base::StringPrintf;
using android::hardware::hidl_bitfield;
using android::hardware::hidl_vec;
using namespace android::hardware::input;
@@ -646,6 +655,30 @@
mEvents.push(std::make_unique<NotifyDeviceResetArgs>(args));
}
+void MotionClassifier::dump(std::string& dump) {
+ std::scoped_lock lock(mLock);
+ std::string serviceStatus = mService->ping().isOk() ? "running" : " not responding";
+ dump += StringPrintf(INDENT2 "mService status: %s\n", serviceStatus.c_str());
+ dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n",
+ mEvents.size(), MAX_EVENTS);
+ dump += INDENT2 "mClassifications, mLastDownTimes:\n";
+ dump += INDENT3 "Device Id\tClassification\tLast down time";
+ // Combine mClassifications and mLastDownTimes into a single table.
+ // Create a superset of device ids.
+ std::unordered_set<int32_t> deviceIds;
+ std::for_each(mClassifications.begin(), mClassifications.end(),
+ [&deviceIds](auto pair){ deviceIds.insert(pair.first); });
+ std::for_each(mLastDownTimes.begin(), mLastDownTimes.end(),
+ [&deviceIds](auto pair){ deviceIds.insert(pair.first); });
+ for(int32_t deviceId : deviceIds) {
+ const MotionClassification classification =
+ getValueForKey(mClassifications, deviceId, MotionClassification::NONE);
+ const nsecs_t downTime = getValueForKey(mLastDownTimes, deviceId, static_cast<nsecs_t>(0));
+ dump += StringPrintf("\n" INDENT4 "%" PRId32 "\t%s\t%" PRId64,
+ deviceId, motionClassificationToString(classification), downTime);
+ }
+}
+
// --- InputClassifier ---
InputClassifier::InputClassifier(const sp<InputListenerInterface>& listener) :
@@ -694,4 +727,16 @@
mListener->notifyDeviceReset(args);
}
+void InputClassifier::dump(std::string& dump) {
+ dump += "Input Classifier State:\n";
+
+ dump += INDENT1 "Motion Classifier:\n";
+ if (mMotionClassifier) {
+ mMotionClassifier->dump(dump);
+ } else {
+ dump += INDENT2 "<nullptr>";
+ }
+ dump += "\n";
+}
+
} // namespace android
\ No newline at end of file
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index cb46494..4b9dae2 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -70,6 +70,11 @@
virtual MotionClassification classify(const NotifyMotionArgs& args) = 0;
virtual void reset() = 0;
virtual void reset(const NotifyDeviceResetArgs& args) = 0;
+
+ /**
+ * Dump the state of the motion classifier
+ */
+ virtual void dump(std::string& dump) = 0;
};
/**
@@ -77,6 +82,12 @@
* Provides classification to events.
*/
class InputClassifierInterface : public virtual RefBase, public InputListenerInterface {
+public:
+ /**
+ * Dump the state of the input classifier.
+ * This method may be called on any thread (usually by the input manager).
+ */
+ virtual void dump(std::string& dump) = 0;
protected:
InputClassifierInterface() { }
virtual ~InputClassifierInterface() { }
@@ -110,6 +121,8 @@
virtual void reset() override;
virtual void reset(const NotifyDeviceResetArgs& args) override;
+ virtual void dump(std::string& dump) override;
+
private:
// The events that need to be sent to the HAL.
BlockingQueue<ClassifierEvent> mEvents;
@@ -186,6 +199,8 @@
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+ virtual void dump(std::string& dump) override;
+
private:
std::unique_ptr<MotionClassifierInterface> mMotionClassifier = nullptr;
// The next stage to pass input events to
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index e537e09..a403f31 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -28,12 +28,12 @@
NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
uint32_t sequenceNum, nsecs_t eventTime) :
- NotifyArgs(sequenceNum), eventTime(eventTime) {
+ NotifyArgs(sequenceNum, eventTime) {
}
NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
const NotifyConfigurationChangedArgs& other) :
- NotifyArgs(other.sequenceNum), eventTime(other.eventTime) {
+ NotifyArgs(other.sequenceNum, other.eventTime) {
}
bool NotifyConfigurationChangedArgs::operator==(const NotifyConfigurationChangedArgs& rhs) const {
@@ -51,14 +51,14 @@
uint32_t source, int32_t displayId, uint32_t policyFlags,
int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
int32_t metaState, nsecs_t downTime) :
- NotifyArgs(sequenceNum), eventTime(eventTime), deviceId(deviceId), source(source),
+ NotifyArgs(sequenceNum, eventTime), deviceId(deviceId), source(source),
displayId(displayId), policyFlags(policyFlags),
action(action), flags(flags), keyCode(keyCode), scanCode(scanCode),
metaState(metaState), downTime(downTime) {
}
NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) :
- NotifyArgs(other.sequenceNum), eventTime(other.eventTime), deviceId(other.deviceId),
+ NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId),
source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
action(other.action), flags(other.flags),
keyCode(other.keyCode), scanCode(other.scanCode),
@@ -95,7 +95,7 @@
const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
float xPrecision, float yPrecision, nsecs_t downTime,
const std::vector<TouchVideoFrame>& videoFrames) :
- NotifyArgs(sequenceNum), eventTime(eventTime), deviceId(deviceId), source(source),
+ NotifyArgs(sequenceNum, eventTime), deviceId(deviceId), source(source),
displayId(displayId), policyFlags(policyFlags),
action(action), actionButton(actionButton),
flags(flags), metaState(metaState), buttonState(buttonState),
@@ -110,7 +110,7 @@
}
NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other) :
- NotifyArgs(other.sequenceNum), eventTime(other.eventTime), deviceId(other.deviceId),
+ NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId),
source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
action(other.action), actionButton(other.actionButton), flags(other.flags),
metaState(other.metaState), buttonState(other.buttonState),
@@ -170,12 +170,12 @@
NotifySwitchArgs::NotifySwitchArgs(uint32_t sequenceNum, nsecs_t eventTime, uint32_t policyFlags,
uint32_t switchValues, uint32_t switchMask) :
- NotifyArgs(sequenceNum), eventTime(eventTime), policyFlags(policyFlags),
+ NotifyArgs(sequenceNum, eventTime), policyFlags(policyFlags),
switchValues(switchValues), switchMask(switchMask) {
}
NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
- NotifyArgs(other.sequenceNum), eventTime(other.eventTime), policyFlags(other.policyFlags),
+ NotifyArgs(other.sequenceNum, other.eventTime), policyFlags(other.policyFlags),
switchValues(other.switchValues), switchMask(other.switchMask) {
}
@@ -196,11 +196,11 @@
NotifyDeviceResetArgs::NotifyDeviceResetArgs(
uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId) :
- NotifyArgs(sequenceNum), eventTime(eventTime), deviceId(deviceId) {
+ NotifyArgs(sequenceNum, eventTime), deviceId(deviceId) {
}
NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) :
- NotifyArgs(other.sequenceNum), eventTime(other.eventTime), deviceId(other.deviceId) {
+ NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId) {
}
bool NotifyDeviceResetArgs::operator==(const NotifyDeviceResetArgs& rhs) const {
diff --git a/services/inputflinger/InputManager.cpp b/services/inputflinger/InputManager.cpp
index b3b9e3e..a7fd9ba 100644
--- a/services/inputflinger/InputManager.cpp
+++ b/services/inputflinger/InputManager.cpp
@@ -84,6 +84,10 @@
return mReader;
}
+sp<InputClassifierInterface> InputManager::getClassifier() {
+ return mClassifier;
+}
+
sp<InputDispatcherInterface> InputManager::getDispatcher() {
return mDispatcher;
}
diff --git a/services/inputflinger/InputManager.h b/services/inputflinger/InputManager.h
index 142ec0c..e632da3 100644
--- a/services/inputflinger/InputManager.h
+++ b/services/inputflinger/InputManager.h
@@ -90,6 +90,7 @@
virtual status_t stop();
virtual sp<InputReaderInterface> getReader();
+ virtual sp<InputClassifierInterface> getClassifier();
virtual sp<InputDispatcherInterface> getDispatcher();
virtual void setInputWindows(const Vector<InputWindowInfo>& handles);
diff --git a/services/inputflinger/include/TouchVideoDevice.h b/services/inputflinger/TouchVideoDevice.h
similarity index 96%
rename from services/inputflinger/include/TouchVideoDevice.h
rename to services/inputflinger/TouchVideoDevice.h
index 7ff2653..3d5c8c6 100644
--- a/services/inputflinger/include/TouchVideoDevice.h
+++ b/services/inputflinger/TouchVideoDevice.h
@@ -73,6 +73,8 @@
size_t readAndQueueFrames();
/**
* Return all of the queued frames, and erase them from the local buffer.
+ * The returned frames are in the order that they were received from the
+ * v4l2 device, with the oldest frame at the index 0.
*/
std::vector<TouchVideoFrame> consumeFrames();
/**
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 13ae7dd..cd8caf7 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -32,10 +32,12 @@
/* Superclass of all input event argument objects */
struct NotifyArgs {
uint32_t sequenceNum;
+ nsecs_t eventTime;
- inline NotifyArgs() : sequenceNum(0) { }
+ inline NotifyArgs() : sequenceNum(0), eventTime(0) { }
- inline explicit NotifyArgs(uint32_t sequenceNum) : sequenceNum(sequenceNum) { }
+ inline explicit NotifyArgs(uint32_t sequenceNum, nsecs_t eventTime) :
+ sequenceNum(sequenceNum), eventTime(eventTime) { }
virtual ~NotifyArgs() { }
@@ -45,7 +47,6 @@
/* Describes a configuration change event. */
struct NotifyConfigurationChangedArgs : public NotifyArgs {
- nsecs_t eventTime;
inline NotifyConfigurationChangedArgs() { }
@@ -63,7 +64,6 @@
/* Describes a key event. */
struct NotifyKeyArgs : public NotifyArgs {
- nsecs_t eventTime;
int32_t deviceId;
uint32_t source;
int32_t displayId;
@@ -93,7 +93,6 @@
/* Describes a motion event. */
struct NotifyMotionArgs : public NotifyArgs {
- nsecs_t eventTime;
int32_t deviceId;
uint32_t source;
int32_t displayId;
@@ -146,7 +145,6 @@
/* Describes a switch event. */
struct NotifySwitchArgs : public NotifyArgs {
- nsecs_t eventTime;
uint32_t policyFlags;
uint32_t switchValues;
uint32_t switchMask;
@@ -169,7 +167,6 @@
/* Describes a device reset event, such as when a device is added,
* reconfigured, or removed. */
struct NotifyDeviceResetArgs : public NotifyArgs {
- nsecs_t eventTime;
int32_t deviceId;
inline NotifyDeviceResetArgs() { }
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 65308a6..63748bf 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -57,8 +57,6 @@
compositionengine::LayerCreationArgs{this})} {
ALOGV("Creating Layer %s", args.name.string());
- mTexture.init(renderengine::Texture::TEXTURE_EXTERNAL, mTextureName);
-
mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied);
mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
@@ -129,13 +127,11 @@
return inverse(tr);
}
-/*
- * onDraw will draw the current layer onto the presentable buffer
- */
-void BufferLayer::onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) {
+bool BufferLayer::prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform, Region& clearRegion,
+ renderengine::LayerSettings& layer) {
ATRACE_CALL();
-
+ Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, layer);
if (CC_UNLIKELY(mActiveBuffer == 0)) {
// the texture has not been created yet, this Layer has
// in fact never been drawn into. This happens frequently with
@@ -153,30 +149,27 @@
finished = true;
return;
}
- under.orSelf(renderArea.getTransform().transform(layer->visibleRegion));
+ under.orSelf(layer->visibleRegion);
});
// if not everything below us is covered, we plug the holes!
Region holes(clip.subtract(under));
if (!holes.isEmpty()) {
- clearWithOpenGL(renderArea, 0, 0, 0, 1);
+ clearRegion.orSelf(holes);
}
- return;
+ return false;
}
-
- // Bind the current buffer to the GL texture, and wait for it to be
- // ready for us to draw into.
- status_t err = bindTextureImage();
- if (err != NO_ERROR) {
- ALOGW("onDraw: bindTextureImage failed (err=%d)", err);
- // Go ahead and draw the buffer anyway; no matter what we do the screen
- // is probably going to have something visibly wrong.
- }
-
bool blackOutLayer = isProtected() || (isSecure() && !renderArea.isSecure());
-
- auto& engine(mFlinger->getRenderEngine());
-
+ const State& s(getDrawingState());
if (!blackOutLayer) {
+ layer.source.buffer.buffer = mActiveBuffer;
+ layer.source.buffer.isOpaque = isOpaque(s);
+ layer.source.buffer.fence = mActiveBufferFence;
+ layer.source.buffer.cacheHint = useCachedBufferForClientComposition()
+ ? renderengine::Buffer::CachingHint::USE_CACHE
+ : renderengine::Buffer::CachingHint::NO_CACHE;
+ layer.source.buffer.textureName = mTextureName;
+ layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
+ layer.source.buffer.isY410BT2020 = isHdrY410();
// TODO: we could be more subtle with isFixedSize()
const bool useFiltering = needsFiltering() || renderArea.needsFiltering() || isFixedSize();
@@ -213,17 +206,31 @@
memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
}
- // Set things up for texturing.
- mTexture.setDimensions(mActiveBuffer->getWidth(), mActiveBuffer->getHeight());
- mTexture.setFiltering(useFiltering);
- mTexture.setMatrix(textureMatrix);
+ const Rect win{computeBounds()};
+ const float bufferWidth = getBufferSize(s).getWidth();
+ const float bufferHeight = getBufferSize(s).getHeight();
- engine.setupLayerTexturing(mTexture);
+ const float scaleHeight = (float(win.bottom) - float(win.top)) / bufferHeight;
+ const float scaleWidth = (float(win.right) - float(win.left)) / bufferWidth;
+ const float translateY = float(win.top) / bufferHeight;
+ const float translateX = float(win.left) / bufferWidth;
+
+ // Flip y-coordinates because GLConsumer expects OpenGL convention.
+ mat4 tr = mat4::translate(vec4(.5, .5, 0, 1)) * mat4::scale(vec4(1, -1, 1, 1)) *
+ mat4::translate(vec4(-.5, -.5, 0, 1)) *
+ mat4::translate(vec4(translateX, translateY, 0, 1)) *
+ mat4::scale(vec4(scaleWidth, scaleHeight, 1.0, 1.0));
+
+ layer.source.buffer.useTextureFiltering = useFiltering;
+ layer.source.buffer.textureTransform = mat4(static_cast<const float*>(textureMatrix)) * tr;
} else {
- engine.setupLayerBlackedOut();
+ // If layer is blacked out, force alpha to 1 so that we draw a black color
+ // layer.
+ layer.source.buffer.buffer = nullptr;
+ layer.alpha = 1.0;
}
- drawWithOpenGL(renderArea, useIdentityTransform);
- engine.disableTexturing();
+
+ return true;
}
bool BufferLayer::isHdrY410() const {
@@ -365,20 +372,18 @@
return true;
}
-Region BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) {
+bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) {
ATRACE_CALL();
- std::optional<Region> sidebandStreamDirtyRegion = latchSidebandStream(recomputeVisibleRegions);
+ bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
- if (sidebandStreamDirtyRegion) {
- return *sidebandStreamDirtyRegion;
+ if (refreshRequired) {
+ return refreshRequired;
}
- Region dirtyRegion;
-
if (!hasReadyFrame()) {
- return dirtyRegion;
+ return false;
}
// if we've already called updateTexImage() without going through
@@ -387,14 +392,14 @@
// compositionComplete() call.
// we'll trigger an update in onPreComposition().
if (mRefreshPending) {
- return dirtyRegion;
+ return false;
}
// If the head buffer's acquire fence hasn't signaled yet, return and
// try again later
if (!fenceHasSignaled()) {
mFlinger->signalLayerUpdate();
- return dirtyRegion;
+ return false;
}
// Capture the old state of the layer for comparisons later
@@ -404,24 +409,24 @@
if (!allTransactionsSignaled()) {
mFlinger->signalLayerUpdate();
- return dirtyRegion;
+ return false;
}
status_t err = updateTexImage(recomputeVisibleRegions, latchTime, releaseFence);
if (err != NO_ERROR) {
- return dirtyRegion;
+ return false;
}
err = updateActiveBuffer();
if (err != NO_ERROR) {
- return dirtyRegion;
+ return false;
}
mBufferLatched = true;
err = updateFrameNumber(latchTime);
if (err != NO_ERROR) {
- return dirtyRegion;
+ return false;
}
mRefreshPending = true;
@@ -461,11 +466,14 @@
Rect crop(getDrawingCrop());
const uint32_t transform(getDrawingTransform());
const uint32_t scalingMode(getDrawingScalingMode());
+ const bool transformToDisplayInverse(getTransformToDisplayInverse());
if ((crop != mCurrentCrop) || (transform != mCurrentTransform) ||
- (scalingMode != mCurrentScalingMode)) {
+ (scalingMode != mCurrentScalingMode) ||
+ (transformToDisplayInverse != mTransformToDisplayInverse)) {
mCurrentCrop = crop;
mCurrentTransform = transform;
mCurrentScalingMode = scalingMode;
+ mTransformToDisplayInverse = transformToDisplayInverse;
recomputeVisibleRegions = true;
}
@@ -502,9 +510,7 @@
}
}
- // FIXME: postedRegion should be dirty & bounds
- // transform the dirty region to window-manager space
- return getTransform().transform(Region(getBufferSize(s)));
+ return true;
}
// transaction
@@ -606,67 +612,6 @@
sourceCrop.getWidth() != displayFrame.getWidth();
}
-void BufferLayer::drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const {
- ATRACE_CALL();
- const State& s(getDrawingState());
-
- computeGeometry(renderArea, getBE().mMesh, useIdentityTransform);
-
- /*
- * NOTE: the way we compute the texture coordinates here produces
- * different results than when we take the HWC path -- in the later case
- * the "source crop" is rounded to texel boundaries.
- * This can produce significantly different results when the texture
- * is scaled by a large amount.
- *
- * The GL code below is more logical (imho), and the difference with
- * HWC is due to a limitation of the HWC API to integers -- a question
- * is suspend is whether we should ignore this problem or revert to
- * GL composition when a buffer scaling is applied (maybe with some
- * minimal value)? Or, we could make GL behave like HWC -- but this feel
- * like more of a hack.
- */
- const Rect bounds{computeBounds()}; // Rounds from FloatRect
-
- Rect win = bounds;
- const int bufferWidth = getBufferSize(s).getWidth();
- const int bufferHeight = getBufferSize(s).getHeight();
-
- const float left = float(win.left) / float(bufferWidth);
- const float top = float(win.top) / float(bufferHeight);
- const float right = float(win.right) / float(bufferWidth);
- const float bottom = float(win.bottom) / float(bufferHeight);
-
- // TODO: we probably want to generate the texture coords with the mesh
- // here we assume that we only have 4 vertices
- renderengine::Mesh::VertexArray<vec2> texCoords(getBE().mMesh.getTexCoordArray<vec2>());
- // flip texcoords vertically because BufferLayerConsumer expects them to be in GL convention
- texCoords[0] = vec2(left, 1.0f - top);
- texCoords[1] = vec2(left, 1.0f - bottom);
- texCoords[2] = vec2(right, 1.0f - bottom);
- texCoords[3] = vec2(right, 1.0f - top);
-
- const auto roundedCornerState = getRoundedCornerState();
- const auto cropRect = roundedCornerState.cropRect;
- setupRoundedCornersCropCoordinates(win, cropRect);
-
- auto& engine(mFlinger->getRenderEngine());
- engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), false /* disableTexture */,
- getColor(), roundedCornerState.radius);
- engine.setSourceDataSpace(mCurrentDataSpace);
-
- if (isHdrY410()) {
- engine.setSourceY410BT2020(true);
- }
-
- engine.setupCornerRadiusCropSize(cropRect.getWidth(), cropRect.getHeight());
-
- engine.drawMesh(getBE().mMesh);
- engine.disableBlending();
-
- engine.setSourceY410BT2020(false);
-}
-
uint64_t BufferLayer::getHeadFrameNumber() const {
if (hasFrameUpdate()) {
return getFrameNumber();
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 8158d6c..c118b78 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -22,6 +22,7 @@
#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
+#include <renderengine/Image.h>
#include <renderengine/Mesh.h>
#include <renderengine/Texture.h>
#include <system/window.h> // For NATIVE_WINDOW_SCALING_MODE_FREEZE
@@ -77,10 +78,6 @@
// isFixedSize - true if content has a fixed size
bool isFixedSize() const override;
- // onDraw - draws the surface.
- void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) override;
-
bool isHdrY410() const override;
void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
@@ -99,8 +96,8 @@
// If there was a GL composition step rendering the previous frame, then
// releaseFence will be populated with a native fence that fires when
// composition has completed.
- Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
- const sp<Fence>& releaseFence) override;
+ bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
+ const sp<Fence>& releaseFence) override;
bool isBufferLatched() const override { return mRefreshPending; }
@@ -137,7 +134,8 @@
virtual bool getAutoRefresh() const = 0;
virtual bool getSidebandStreamChanged() const = 0;
- virtual std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) = 0;
+ // Latch sideband stream and returns true if the dirty region should be updated.
+ virtual bool latchSidebandStream(bool& recomputeVisibleRegions) = 0;
virtual bool hasFrameUpdate() const = 0;
@@ -168,23 +166,28 @@
bool mRefreshPending{false};
+ // Returns true if, when drawing the active buffer during gpu compositon, we
+ // should use a cached buffer or not.
+ virtual bool useCachedBufferForClientComposition() const = 0;
+
+ // prepareClientLayer - constructs a RenderEngine layer for GPU composition.
+ bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform, Region& clearRegion,
+ renderengine::LayerSettings& layer);
+
private:
// Returns true if this layer requires filtering
bool needsFiltering() const;
- // drawing
- void drawWithOpenGL(const RenderArea& renderArea, bool useIdentityTransform) const;
-
uint64_t getHeadFrameNumber() const;
uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE};
+ bool mTransformToDisplayInverse{false};
+
// main thread.
bool mBufferLatched{false}; // TODO: Use mActiveBuffer?
- // The texture used to draw the layer in GLES composition mode
- mutable renderengine::Texture mTexture;
-
Rect getBufferSize(const State& s) const override;
std::shared_ptr<compositionengine::Layer> mCompositionLayer;
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
index 6826050..7ed8184 100644
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ b/services/surfaceflinger/BufferLayerConsumer.cpp
@@ -272,6 +272,7 @@
// Update the BufferLayerConsumer state.
mCurrentTexture = slot;
mCurrentTextureBuffer = nextTextureBuffer;
+ mCurrentTextureBufferStaleForGpu = false;
mCurrentTextureImageFreed = nullptr;
mCurrentCrop = item.mCrop;
mCurrentTransform = item.mTransform;
@@ -294,48 +295,7 @@
status_t BufferLayerConsumer::bindTextureImageLocked() {
ATRACE_CALL();
- mRE.checkErrors();
-
- // It is possible for the current slot's buffer to be freed before a new one
- // is bound. In that scenario we still want to bind the image.
- if (mCurrentTexture == BufferQueue::INVALID_BUFFER_SLOT && mCurrentTextureBuffer == nullptr) {
- BLC_LOGE("bindTextureImage: no currently-bound texture");
- mRE.bindExternalTextureImage(mTexName, *mRE.createImage());
- return NO_INIT;
- }
-
- renderengine::Image* imageToRender;
-
- // mCurrentTextureImageFreed is non-null iff mCurrentTexture ==
- // BufferQueue::INVALID_BUFFER_SLOT, so we can omit that check.
- if (mCurrentTextureImageFreed) {
- imageToRender = mCurrentTextureImageFreed.get();
- } else if (mImages[mCurrentTexture]) {
- imageToRender = mImages[mCurrentTexture].get();
- } else {
- std::unique_ptr<renderengine::Image> image = mRE.createImage();
- bool success = image->setNativeWindowBuffer(mCurrentTextureBuffer->getNativeBuffer(),
- mCurrentTextureBuffer->getUsage() &
- GRALLOC_USAGE_PROTECTED);
- if (!success) {
- BLC_LOGE("bindTextureImage: Failed to create image. size=%ux%u st=%u usage=%#" PRIx64
- " fmt=%d",
- mCurrentTextureBuffer->getWidth(), mCurrentTextureBuffer->getHeight(),
- mCurrentTextureBuffer->getStride(), mCurrentTextureBuffer->getUsage(),
- mCurrentTextureBuffer->getPixelFormat());
- BLC_LOGW("bindTextureImage: can't create image on slot=%d", mCurrentTexture);
- mRE.bindExternalTextureImage(mTexName, *image);
- return UNKNOWN_ERROR;
- }
- imageToRender = image.get();
- // Cache the image here so that we can reuse it.
- mImages[mCurrentTexture] = std::move(image);
- }
-
- mRE.bindExternalTextureImage(mTexName, *imageToRender);
-
- // Wait for the new buffer to be ready.
- return doFenceWaitLocked();
+ return mRE.bindExternalTextureBuffer(mTexName, mCurrentTextureBuffer, mCurrentFence, false);
}
status_t BufferLayerConsumer::syncForReleaseLocked(const sp<Fence>& releaseFence) {
@@ -433,16 +393,29 @@
return mCurrentApi;
}
-sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot) const {
+sp<GraphicBuffer> BufferLayerConsumer::getCurrentBuffer(int* outSlot, sp<Fence>* outFence) const {
Mutex::Autolock lock(mMutex);
if (outSlot != nullptr) {
*outSlot = mCurrentTexture;
}
+ if (outFence != nullptr) {
+ *outFence = mCurrentFence;
+ }
+
return mCurrentTextureBuffer;
}
+bool BufferLayerConsumer::getAndSetCurrentBufferCacheHint() {
+ Mutex::Autolock lock(mMutex);
+ bool useCache = mCurrentTextureBufferStaleForGpu;
+ // Set the staleness bit here, as this function is only called during a
+ // client composition path.
+ mCurrentTextureBufferStaleForGpu = true;
+ return useCache;
+}
+
Rect BufferLayerConsumer::getCurrentCrop() const {
Mutex::Autolock lock(mMutex);
return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
index ea46245..e2ef399 100644
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ b/services/surfaceflinger/BufferLayerConsumer.h
@@ -150,10 +150,16 @@
// for use with bilinear filtering.
void setFilteringEnabled(bool enabled);
+ // Sets mCurrentTextureBufferStaleForGpu to true to indicate that the
+ // buffer is now "stale" for GPU composition, and returns the old staleness
+ // bit as a caching hint.
+ bool getAndSetCurrentBufferCacheHint();
+
// getCurrentBuffer returns the buffer associated with the current image.
// When outSlot is not nullptr, the current buffer slot index is also
- // returned.
- sp<GraphicBuffer> getCurrentBuffer(int* outSlot = nullptr) const;
+ // returned. Simiarly, when outFence is not nullptr, the current output
+ // fence is returned.
+ sp<GraphicBuffer> getCurrentBuffer(int* outSlot = nullptr, sp<Fence>* outFence = nullptr) const;
// getCurrentCrop returns the cropping rectangle of the current buffer.
Rect getCurrentCrop() const;
@@ -255,6 +261,10 @@
// must track it separately in order to support the getCurrentBuffer method.
sp<GraphicBuffer> mCurrentTextureBuffer;
+ // True if the buffer was used for the previous client composition frame,
+ // and false otherwise.
+ bool mCurrentTextureBufferStaleForGpu;
+
// mCurrentCrop is the crop rectangle that applies to the current texture.
// It gets set each time updateTexImage is called.
Rect mCurrentCrop;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 42021d1..3915757 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -190,7 +190,7 @@
return mSidebandStreamChanged;
}
-std::optional<Region> BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
+bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
bool sidebandStreamChanged = true;
if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
// mSidebandStreamChanged was changed to false
@@ -202,10 +202,9 @@
}
recomputeVisibleRegions = true;
- const State& s(getDrawingState());
- return getTransform().transform(Region(Rect(s.active_legacy.w, s.active_legacy.h)));
+ return true;
}
- return {};
+ return false;
}
bool BufferQueueLayer::hasFrameUpdate() const {
@@ -235,9 +234,28 @@
const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
? mFlinger->mScheduler->mPrimaryDispSync->expectedPresentTime()
: mFlinger->mPrimaryDispSync->expectedPresentTime();
+
+ // updateTexImage() below might drop the some buffers at the head of the queue if there is a
+ // buffer behind them which is timely to be presented. However this buffer may not be signaled
+ // yet. The code below makes sure that this wouldn't happen by setting maxFrameNumber to the
+ // last buffer that was signaled.
+ uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived;
+ {
+ Mutex::Autolock lock(mQueueItemLock);
+ for (int i = 0; i < mQueueItems.size(); i++) {
+ bool fenceSignaled =
+ mQueueItems[i].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
+ if (!fenceSignaled) {
+ break;
+ }
+ lastSignaledFrameNumber = mQueueItems[i].mFrameNumber;
+ }
+ }
+ const uint64_t maxFrameNumberToAcquire =
+ std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
status_t updateResult =
mConsumer->updateTexImage(&r, expectedPresentTime, &mAutoRefresh, &queuedBuffer,
- mLastFrameNumberReceived, releaseFence);
+ maxFrameNumberToAcquire, releaseFence);
if (updateResult == BufferQueue::PRESENT_LATER) {
// Producer doesn't want buffer to be displayed yet. Signal a
// layer update so we check again at the next opportunity.
@@ -306,7 +324,7 @@
status_t BufferQueueLayer::updateActiveBuffer() {
// update the active buffer
- mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot);
+ mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence);
getBE().compositionInfo.mBuffer = mActiveBuffer;
getBE().compositionInfo.mBufferSlot = mActiveBufferSlot;
@@ -317,6 +335,10 @@
return NO_ERROR;
}
+bool BufferQueueLayer::useCachedBufferForClientComposition() const {
+ return mConsumer->getAndSetCurrentBufferCacheHint();
+}
+
status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) {
mPreviousFrameNumber = mCurrentFrameNumber;
mCurrentFrameNumber = mConsumer->getFrameNumber();
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index d7c3f6a..d392a69 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -62,6 +62,9 @@
public:
bool fenceHasSignaled() const override;
+protected:
+ bool useCachedBufferForClientComposition() const override;
+
private:
nsecs_t getDesiredPresentTime() override;
std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
@@ -81,7 +84,7 @@
bool getAutoRefresh() const override;
bool getSidebandStreamChanged() const override;
- std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
+ bool latchSidebandStream(bool& recomputeVisibleRegions) override;
bool hasFrameUpdate() const override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 044662c..b0506fe 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -42,6 +42,7 @@
BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args) {
mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+ mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
}
BufferStateLayer::~BufferStateLayer() = default;
@@ -96,7 +97,8 @@
bool BufferStateLayer::willPresentCurrentTransaction() const {
// Returns true if the most recent Transaction applied to CurrentState will be presented.
return getSidebandStreamChanged() || getAutoRefresh() ||
- (mCurrentState.modified && mCurrentState.buffer != nullptr);
+ (mCurrentState.modified &&
+ (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr));
}
bool BufferStateLayer::getTransformToDisplayInverse() const {
@@ -420,7 +422,7 @@
return mSidebandStreamChanged.load();
}
-std::optional<Region> BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
+bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) {
if (mSidebandStreamChanged.exchange(false)) {
const State& s(getDrawingState());
// mSidebandStreamChanged was true
@@ -432,13 +434,14 @@
}
recomputeVisibleRegions = true;
- return getTransform().transform(Region(Rect(s.active.w, s.active.h)));
+ return true;
}
- return {};
+ return false;
}
bool BufferStateLayer::hasFrameUpdate() const {
- return mCurrentStateModified && getCurrentState().buffer != nullptr;
+ const State& c(getCurrentState());
+ return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
}
void BufferStateLayer::setFilteringEnabled(bool enabled) {
@@ -450,46 +453,7 @@
const State& s(getDrawingState());
auto& engine(mFlinger->getRenderEngine());
- engine.checkErrors();
-
- // TODO(marissaw): once buffers are cached, don't create a new image everytime
- mTextureImage = engine.createImage();
-
- 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;
+ return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence, false);
}
status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
@@ -497,6 +461,11 @@
const State& s(getDrawingState());
if (!s.buffer) {
+ if (s.bgColorLayer) {
+ for (auto& handle : mDrawingState.callbackHandles) {
+ handle->latchTime = latchTime;
+ }
+ }
return NO_ERROR;
}
@@ -612,12 +581,18 @@
}
mActiveBuffer = s.buffer;
+ mActiveBufferFence = s.acquireFence;
getBE().compositionInfo.mBuffer = mActiveBuffer;
getBE().compositionInfo.mBufferSlot = 0;
return NO_ERROR;
}
+bool BufferStateLayer::useCachedBufferForClientComposition() const {
+ // TODO: Store a proper staleness bit to support EGLImage caching.
+ return false;
+}
+
status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) {
// TODO(marissaw): support frame history events
mCurrentFrameNumber = mFrameNumber;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 3f891d3..ef287b9 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -95,6 +95,9 @@
// -----------------------------------------------------------------------
bool fenceHasSignaled() const override;
+protected:
+ bool useCachedBufferForClientComposition() const override;
+
private:
nsecs_t getDesiredPresentTime() override;
std::shared_ptr<FenceTime> getCurrentFenceTime() const override;
@@ -114,7 +117,7 @@
bool getAutoRefresh() const override;
bool getSidebandStreamChanged() const override;
- std::optional<Region> latchSidebandStream(bool& recomputeVisibleRegions) override;
+ bool latchSidebandStream(bool& recomputeVisibleRegions) override;
bool hasFrameUpdate() const override;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index b4e9d17..d82ff0e 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -44,28 +44,14 @@
ColorLayer::~ColorLayer() = default;
-void ColorLayer::onDraw(const RenderArea& renderArea, const Region& /* clip */,
- bool useIdentityTransform) {
- half4 color = getColor();
- if (color.a > 0) {
- renderengine::Mesh mesh(renderengine::Mesh::TRIANGLE_FAN, 4, 2);
- computeGeometry(renderArea, mesh, useIdentityTransform);
- auto& engine(mFlinger->getRenderEngine());
-
- Rect win{computeBounds()};
-
- const auto roundedCornerState = getRoundedCornerState();
- const auto cropRect = roundedCornerState.cropRect;
- setupRoundedCornersCropCoordinates(win, cropRect);
-
- engine.setupLayerBlending(getPremultipledAlpha(), false /* opaque */,
- true /* disableTexture */, color, roundedCornerState.radius);
-
- engine.setSourceDataSpace(mCurrentDataSpace);
- engine.setupCornerRadiusCropSize(cropRect.getWidth(), cropRect.getHeight());
- engine.drawMesh(mesh);
- engine.disableBlending();
- }
+bool ColorLayer::prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform, Region& clearRegion,
+ renderengine::LayerSettings& layer) {
+ Layer::prepareClientLayer(renderArea, clip, useIdentityTransform, clearRegion, layer);
+ half4 color(getColor());
+ half3 solidColor(color.r, color.g, color.b);
+ layer.source.solidColor = solidColor;
+ return true;
}
bool ColorLayer::isVisible() const {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 3b98e8c..ed4c2d8 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -31,8 +31,6 @@
std::shared_ptr<compositionengine::Layer> getCompositionLayer() const override;
virtual const char* getTypeId() const { return "ColorLayer"; }
- virtual void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform);
bool isVisible() const override;
bool setColor(const half3& color) override;
@@ -44,6 +42,9 @@
protected:
FloatRect computeCrop(const sp<const DisplayDevice>& /*display*/) const override { return {}; }
+ virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform, Region& clearRegion,
+ renderengine::LayerSettings& layer);
private:
std::shared_ptr<compositionengine::Layer> mCompositionLayer;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index a7ab472..84b2423 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -97,10 +97,9 @@
// TODO(lpique): Make this protected once it is only internally called.
virtual OutputCompositionState& editState() = 0;
- // Gets the physical space dirty region. If repaintEverything is true, this
- // will be the full display bounds. Internally the dirty region is stored in
- // logical (aka layer stack) space.
- virtual Region getPhysicalSpaceDirtyRegion(bool repaintEverything) const = 0;
+ // Gets the dirty region in layer stack space.
+ // If repaintEverything is true, this will be the full display bounds.
+ virtual Region getDirtyRegion(bool repaintEverything) const = 0;
// Tests whether a given layerStackId belongs in this output.
// A layer belongs to the output if its layerStackId matches the of the output layerStackId,
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index dd01b05..ddeb730 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -75,16 +75,13 @@
// Allocates a buffer as scratch space for GPU composition
virtual sp<GraphicBuffer> dequeueBuffer() = 0;
- // Queues the drawn buffer for consumption by HWC
- virtual void queueBuffer() = 0;
+ // Queues the drawn buffer for consumption by HWC. readyFence is the fence
+ // which will fire when the buffer is ready for consumption.
+ virtual void queueBuffer(base::unique_fd&& readyFence) = 0;
// Called after the HWC calls are made to present the display
virtual void onPresentDisplayCompleted() = 0;
- // Marks the current buffer has finished, so that it can be presented and
- // swapped out
- virtual void finishBuffer() = 0;
-
// Called to set the viewport and projection state for rendering into this
// surface
virtual void setViewportAndProjection() = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index d876c03..3fd057c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -61,7 +61,7 @@
const OutputCompositionState& getState() const override;
OutputCompositionState& editState() override;
- Region getPhysicalSpaceDirtyRegion(bool repaintEverything) const override;
+ Region getDirtyRegion(bool repaintEverything) const override;
bool belongsInOutput(uint32_t, bool) const override;
compositionengine::OutputLayer* getOutputLayerForLayer(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 0489310..2f0fceb 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -53,9 +53,8 @@
status_t beginFrame(bool mustRecompose) override;
status_t prepareFrame(std::vector<CompositionInfo>& compositionData) override;
sp<GraphicBuffer> dequeueBuffer() override;
- void queueBuffer() override;
+ void queueBuffer(base::unique_fd&& readyFence) override;
void onPresentDisplayCompleted() override;
- void finishBuffer() override;
void setViewportAndProjection() override;
void flip() override;
@@ -77,9 +76,6 @@
const sp<ANativeWindow> mNativeWindow;
// Current buffer being rendered into
sp<GraphicBuffer> mGraphicBuffer;
- // File descriptor indicating that mGraphicBuffer is ready for display, i.e.
- // that drawing to the buffer is now complete.
- base::unique_fd mBufferReady;
const sp<DisplaySurface> mDisplaySurface;
ui::Size mSize;
std::uint32_t mPageFlipCount{0};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index e79a44c..2972ad7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -56,7 +56,7 @@
MOCK_CONST_METHOD0(getState, const OutputCompositionState&());
MOCK_METHOD0(editState, OutputCompositionState&());
- MOCK_CONST_METHOD1(getPhysicalSpaceDirtyRegion, Region(bool));
+ MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
MOCK_CONST_METHOD2(belongsInOutput, bool(uint32_t, bool));
MOCK_CONST_METHOD1(getOutputLayerForLayer,
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index 2269e57..e9ff330 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -39,9 +39,8 @@
MOCK_METHOD1(beginFrame, status_t(bool mustRecompose));
MOCK_METHOD1(prepareFrame, status_t(std::vector<CompositionInfo>& compositionData));
MOCK_METHOD0(dequeueBuffer, sp<GraphicBuffer>());
- MOCK_METHOD0(queueBuffer, void());
+ MOCK_METHOD1(queueBuffer, void(base::unique_fd&&));
MOCK_METHOD0(onPresentDisplayCompleted, void());
- MOCK_METHOD0(finishBuffer, void());
MOCK_METHOD0(setViewportAndProjection, void());
MOCK_METHOD0(flip, void());
MOCK_CONST_METHOD1(dump, void(std::string& result));
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 6d5147d..e103ebe 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -90,13 +90,25 @@
void Output::setColorTransform(const mat4& transform) {
const bool isIdentity = (transform == mat4());
-
- mState.colorTransform =
+ const auto newColorTransform =
isIdentity ? HAL_COLOR_TRANSFORM_IDENTITY : HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
+
+ if (mState.colorTransform == newColorTransform) {
+ return;
+ }
+
+ mState.colorTransform = newColorTransform;
+
+ dirtyEntireOutput();
}
void Output::setColorMode(ui::ColorMode mode, ui::Dataspace dataspace,
ui::RenderIntent renderIntent) {
+ if (mState.colorMode == mode && mState.dataspace == dataspace &&
+ mState.renderIntent == renderIntent) {
+ return;
+ }
+
mState.colorMode = mode;
mState.dataspace = dataspace;
mState.renderIntent = renderIntent;
@@ -106,6 +118,8 @@
ALOGV("Set active color mode: %s (%d), active render intent: %s (%d)",
decodeColorMode(mode).c_str(), mode, decodeRenderIntent(renderIntent).c_str(),
renderIntent);
+
+ dirtyEntireOutput();
}
void Output::dump(std::string& out) const {
@@ -170,13 +184,10 @@
return mState;
}
-Region Output::getPhysicalSpaceDirtyRegion(bool repaintEverything) const {
- Region dirty;
- if (repaintEverything) {
- dirty.set(mState.bounds);
- } else {
- dirty = mState.transform.transform(mState.dirtyRegion);
- dirty.andSelf(mState.bounds);
+Region Output::getDirtyRegion(bool repaintEverything) const {
+ Region dirty(mState.viewport);
+ if (!repaintEverything) {
+ dirty.andSelf(mState.dirtyRegion);
}
return dirty;
}
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index d546fc8..3f841d2 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -156,7 +156,7 @@
return mGraphicBuffer;
}
-void RenderSurface::queueBuffer() {
+void RenderSurface::queueBuffer(base::unique_fd&& readyFence) {
auto& hwc = mCompositionEngine.getHwComposer();
const auto id = mDisplay.getId();
@@ -178,9 +178,9 @@
if (mGraphicBuffer == nullptr) {
ALOGE("No buffer is ready for display [%s]", mDisplay.getName().c_str());
} else {
- status_t result = mNativeWindow->queueBuffer(mNativeWindow.get(),
- mGraphicBuffer->getNativeBuffer(),
- dup(mBufferReady));
+ status_t result =
+ mNativeWindow->queueBuffer(mNativeWindow.get(),
+ mGraphicBuffer->getNativeBuffer(), dup(readyFence));
if (result != NO_ERROR) {
ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(),
result);
@@ -190,12 +190,10 @@
LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result);
} else {
mNativeWindow->cancelBuffer(mNativeWindow.get(),
- mGraphicBuffer->getNativeBuffer(),
- dup(mBufferReady));
+ mGraphicBuffer->getNativeBuffer(), dup(readyFence));
}
}
- mBufferReady.reset();
mGraphicBuffer = nullptr;
}
}
@@ -217,14 +215,6 @@
ui::Transform::ROT_0);
}
-void RenderSurface::finishBuffer() {
- auto& renderEngine = mCompositionEngine.getRenderEngine();
- mBufferReady = renderEngine.flush();
- if (mBufferReady.get() < 0) {
- renderEngine.finish();
- }
-}
-
void RenderSurface::flip() {
mPageFlipCount++;
}
@@ -263,9 +253,5 @@
return mGraphicBuffer;
}
-base::unique_fd& RenderSurface::mutableBufferReadyForTest() {
- return mBufferReady;
-}
-
} // namespace impl
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 8cb6936..cd2d454 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -156,17 +156,17 @@
EXPECT_EQ(ui::RenderIntent::COLORIMETRIC, mDisplay.getState().renderIntent);
// Otherwise if the values are different, updates happen
- EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::SRGB)).Times(1);
+ EXPECT_CALL(*renderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
EXPECT_CALL(mHwComposer,
- setActiveColorMode(DEFAULT_DISPLAY_ID, ui::ColorMode::BT2100_PQ,
+ setActiveColorMode(DEFAULT_DISPLAY_ID, ui::ColorMode::DISPLAY_P3,
ui::RenderIntent::TONE_MAP_COLORIMETRIC))
.Times(1);
- mDisplay.setColorMode(ui::ColorMode::BT2100_PQ, ui::Dataspace::SRGB,
+ mDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
ui::RenderIntent::TONE_MAP_COLORIMETRIC);
- EXPECT_EQ(ui::ColorMode::BT2100_PQ, mDisplay.getState().colorMode);
- EXPECT_EQ(ui::Dataspace::SRGB, mDisplay.getState().dataspace);
+ EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mDisplay.getState().colorMode);
+ EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mDisplay.getState().dataspace);
EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mDisplay.getState().renderIntent);
}
@@ -174,7 +174,7 @@
impl::Display virtualDisplay{mCompositionEngine,
DisplayCreationArgs{false, true, DEFAULT_DISPLAY_ID}};
- virtualDisplay.setColorMode(ui::ColorMode::BT2100_PQ, ui::Dataspace::SRGB,
+ virtualDisplay.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
ui::RenderIntent::TONE_MAP_COLORIMETRIC);
EXPECT_EQ(ui::ColorMode::NATIVE, virtualDisplay.getState().colorMode);
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index cc1211b..cb71821 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -43,15 +43,21 @@
mOutput.setDisplayColorProfileForTest(
std::unique_ptr<DisplayColorProfile>(mDisplayColorProfile));
mOutput.setRenderSurfaceForTest(std::unique_ptr<RenderSurface>(mRenderSurface));
+
+ mOutput.editState().bounds = kDefaultDisplaySize;
}
~OutputTest() override = default;
+ static const Rect kDefaultDisplaySize;
+
StrictMock<mock::CompositionEngine> mCompositionEngine;
mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>();
mock::RenderSurface* mRenderSurface = new StrictMock<mock::RenderSurface>();
impl::Output mOutput{mCompositionEngine};
};
+const Rect OutputTest::kDefaultDisplaySize{100, 200};
+
/* ------------------------------------------------------------------------
* Basic construction
*/
@@ -76,8 +82,6 @@
*/
TEST_F(OutputTest, setCompositionEnabledDoesNothingIfAlreadyEnabled) {
- const Rect displaySize{100, 200};
- mOutput.editState().bounds = displaySize;
mOutput.editState().isEnabled = true;
mOutput.setCompositionEnabled(true);
@@ -87,25 +91,21 @@
}
TEST_F(OutputTest, setCompositionEnabledSetsEnabledAndDirtiesEntireOutput) {
- const Rect displaySize{100, 200};
- mOutput.editState().bounds = displaySize;
mOutput.editState().isEnabled = false;
mOutput.setCompositionEnabled(true);
EXPECT_TRUE(mOutput.getState().isEnabled);
- EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(displaySize)));
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
}
TEST_F(OutputTest, setCompositionEnabledSetsDisabledAndDirtiesEntireOutput) {
- const Rect displaySize{100, 200};
- mOutput.editState().bounds = displaySize;
mOutput.editState().isEnabled = true;
mOutput.setCompositionEnabled(false);
EXPECT_FALSE(mOutput.getState().isEnabled);
- EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(displaySize)));
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
}
/* ------------------------------------------------------------------------
@@ -135,7 +135,7 @@
*/
TEST_F(OutputTest, setBoundsSetsSizeAndDirtiesEntireOutput) {
- const ui::Size displaySize{100, 200};
+ const ui::Size displaySize{200, 400};
EXPECT_CALL(*mRenderSurface, setDisplaySize(displaySize)).Times(1);
EXPECT_CALL(*mRenderSurface, getSize()).WillOnce(ReturnRef(displaySize));
@@ -152,16 +152,13 @@
*/
TEST_F(OutputTest, setLayerStackFilterSetsFilterAndDirtiesEntireOutput) {
- const Rect displaySize{100, 200};
- mOutput.editState().bounds = displaySize;
-
const uint32_t layerStack = 123u;
mOutput.setLayerStackFilter(layerStack, true);
EXPECT_TRUE(mOutput.getState().layerStackInternal);
EXPECT_EQ(layerStack, mOutput.getState().layerStackId);
- EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(displaySize)));
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
}
/* ------------------------------------------------------------------------
@@ -176,27 +173,45 @@
EXPECT_EQ(HAL_COLOR_TRANSFORM_IDENTITY, mOutput.getState().colorTransform);
+ // Since identity is the default, the dirty region should be unchanged (empty)
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
+
// Non-identity matrix sets a non-identity state value
const mat4 nonIdentity = mat4() * 2;
mOutput.setColorTransform(nonIdentity);
EXPECT_EQ(HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX, mOutput.getState().colorTransform);
+
+ // Since this is a state change, the entire output should now be dirty.
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
}
/* ------------------------------------------------------------------------
* Output::setColorMode
*/
-TEST_F(OutputTest, setColorModeSetsModeUnlessNoChange) {
- EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::SRGB)).Times(1);
+TEST_F(OutputTest, setColorModeSetsStateAndDirtiesOutputIfChanged) {
+ EXPECT_CALL(*mRenderSurface, setBufferDataspace(ui::Dataspace::DISPLAY_P3)).Times(1);
- mOutput.setColorMode(ui::ColorMode::BT2100_PQ, ui::Dataspace::SRGB,
+ mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
ui::RenderIntent::TONE_MAP_COLORIMETRIC);
- EXPECT_EQ(ui::ColorMode::BT2100_PQ, mOutput.getState().colorMode);
- EXPECT_EQ(ui::Dataspace::SRGB, mOutput.getState().dataspace);
+ EXPECT_EQ(ui::ColorMode::DISPLAY_P3, mOutput.getState().colorMode);
+ EXPECT_EQ(ui::Dataspace::DISPLAY_P3, mOutput.getState().dataspace);
EXPECT_EQ(ui::RenderIntent::TONE_MAP_COLORIMETRIC, mOutput.getState().renderIntent);
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region(kDefaultDisplaySize)));
+}
+
+TEST_F(OutputTest, setColorModeDoesNothingIfNoChange) {
+ mOutput.editState().colorMode = ui::ColorMode::DISPLAY_P3;
+ mOutput.editState().dataspace = ui::Dataspace::DISPLAY_P3;
+ mOutput.editState().renderIntent = ui::RenderIntent::TONE_MAP_COLORIMETRIC;
+
+ mOutput.setColorMode(ui::ColorMode::DISPLAY_P3, ui::Dataspace::DISPLAY_P3,
+ ui::RenderIntent::TONE_MAP_COLORIMETRIC);
+
+ EXPECT_THAT(mOutput.getState().dirtyRegion, RegionEq(Region()));
}
/* ------------------------------------------------------------------------
@@ -215,52 +230,32 @@
}
/* ------------------------------------------------------------------------
- * Output::getPhysicalSpaceDirtyRegion()
+ * Output::getDirtyRegion()
*/
-TEST_F(OutputTest, getPhysicalSpaceDirtyRegionWithRepaintEverythingTrue) {
- const Rect displaySize{100, 200};
- mOutput.editState().bounds = displaySize;
+TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingTrue) {
+ const Rect viewport{100, 200};
+ mOutput.editState().viewport = viewport;
mOutput.editState().dirtyRegion.set(50, 300);
{
- Region result = mOutput.getPhysicalSpaceDirtyRegion(true);
+ Region result = mOutput.getDirtyRegion(true);
- EXPECT_THAT(result, RegionEq(Region(displaySize)));
- }
-
- // For repaint everything == true, the returned value does not depend on the display
- // rotation.
- mOutput.editState().transform.set(ui::Transform::ROT_90, 0, 0);
-
- {
- Region result = mOutput.getPhysicalSpaceDirtyRegion(true);
-
- EXPECT_THAT(result, RegionEq(Region(displaySize)));
+ EXPECT_THAT(result, RegionEq(Region(viewport)));
}
}
-TEST_F(OutputTest, getPhysicalSpaceDirtyRegionWithRepaintEverythingFalse) {
- const Rect displaySize{100, 200};
- mOutput.editState().bounds = displaySize;
+TEST_F(OutputTest, getDirtyRegionWithRepaintEverythingFalse) {
+ const Rect viewport{100, 200};
+ mOutput.editState().viewport = viewport;
mOutput.editState().dirtyRegion.set(50, 300);
{
- Region result = mOutput.getPhysicalSpaceDirtyRegion(false);
+ Region result = mOutput.getDirtyRegion(false);
// The dirtyRegion should be clipped to the display bounds.
EXPECT_THAT(result, RegionEq(Region(Rect(50, 200))));
}
-
- mOutput.editState().transform.set(ui::Transform::ROT_90, displaySize.getWidth(),
- displaySize.getHeight());
-
- {
- Region result = mOutput.getPhysicalSpaceDirtyRegion(false);
-
- // The dirtyRegion should be rotated and clipped to the display bounds.
- EXPECT_THAT(result, RegionEq(Region(Rect(100, 50))));
- }
}
/* ------------------------------------------------------------------------
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index 13cc663..c56d92a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -373,7 +373,7 @@
.WillOnce(Return(false));
EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
- mSurface.queueBuffer();
+ mSurface.queueBuffer(base::unique_fd());
EXPECT_EQ(buffer.get(), mSurface.mutableGraphicBufferForTest().get());
}
@@ -387,7 +387,7 @@
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
- mSurface.queueBuffer();
+ mSurface.queueBuffer(base::unique_fd());
EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get());
}
@@ -402,7 +402,7 @@
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
- mSurface.queueBuffer();
+ mSurface.queueBuffer(base::unique_fd());
EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get());
}
@@ -419,7 +419,7 @@
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
- mSurface.queueBuffer();
+ mSurface.queueBuffer(base::unique_fd());
EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get());
}
@@ -436,7 +436,7 @@
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(*mDisplaySurface, advanceFrame()).Times(1);
- mSurface.queueBuffer();
+ mSurface.queueBuffer(base::unique_fd());
EXPECT_EQ(nullptr, mSurface.mutableGraphicBufferForTest().get());
}
@@ -452,29 +452,6 @@
}
/* ------------------------------------------------------------------------
- * RenderSurface::finishBuffer()
- */
-
-TEST_F(RenderSurfaceTest, finishBufferJustFlushesRenderEngine) {
- int fd = dup(1);
-
- EXPECT_CALL(mRenderEngine, flush()).WillOnce(Return(ByMove(base::unique_fd(fd))));
-
- mSurface.finishBuffer();
-
- EXPECT_EQ(fd, mSurface.mutableBufferReadyForTest().release());
-}
-
-TEST_F(RenderSurfaceTest, finishBufferFlushesAndFinishesRenderEngine) {
- EXPECT_CALL(mRenderEngine, flush()).WillOnce(Return(ByMove(base::unique_fd(-2))));
- EXPECT_CALL(mRenderEngine, finish()).Times(1);
-
- mSurface.finishBuffer();
-
- EXPECT_EQ(-2, mSurface.mutableBufferReadyForTest().release());
-}
-
-/* ------------------------------------------------------------------------
* RenderSurface::setViewportAndProjection()
*/
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index ca49f6c..941b4ad 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -26,9 +26,16 @@
ContainerLayer::~ContainerLayer() = default;
-void ContainerLayer::onDraw(const RenderArea&, const Region& /* clip */, bool) {}
+bool ContainerLayer::prepareClientLayer(const RenderArea&, const Region&, bool, Region&,
+ renderengine::LayerSettings&) {
+ return false;
+}
bool ContainerLayer::isVisible() const {
+ return false;
+}
+
+bool ContainerLayer::canReceiveInput() const {
return !isHiddenByPolicy();
}
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index 413844b..fec82d7 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -29,16 +29,21 @@
~ContainerLayer() override;
const char* getTypeId() const override { return "ContainerLayer"; }
- void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) override;
bool isVisible() const override;
+ bool canReceiveInput() const override;
+
void setPerFrameData(DisplayId displayId, const ui::Transform& transform, const Rect& viewport,
int32_t supportedPerFrameMetadata) override;
bool isCreatedFromMainThread() const override { return true; }
bool onPreComposition(nsecs_t /*refreshStartTime*/) override { return false; }
+
+protected:
+ bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform, Region& clearRegion,
+ renderengine::LayerSettings& layer);
};
} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2de169d..46e587d 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -639,7 +639,7 @@
* Here we cancel out the orientation component of the WM transform.
* The scaling and translate components are already included in our bounds
* computation so it's enough to just omit it in the composition.
- * See comment in onDraw with ref to b/36727915 for why.
+ * See comment in BufferLayer::prepareClientLayer with ref to b/36727915 for why.
*/
transform = ui::Transform(invTransform) * tr * bufferOrientation;
}
@@ -681,7 +681,7 @@
}
// This gives us only the "orientation" component of the transform
- const State& s(getCurrentState());
+ const State& s(getDrawingState());
// Apply the layer's transform, followed by the display's global transform
// Here we're guaranteed that the layer's transform preserves rects
@@ -707,12 +707,51 @@
// drawing...
// ---------------------------------------------------------------------------
-void Layer::draw(const RenderArea& renderArea, const Region& clip) {
- onDraw(renderArea, clip, false);
+bool Layer::prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ Region& clearRegion, renderengine::LayerSettings& layer) {
+ return prepareClientLayer(renderArea, clip, false, clearRegion, layer);
}
-void Layer::draw(const RenderArea& renderArea, bool useIdentityTransform) {
- onDraw(renderArea, Region(renderArea.getBounds()), useIdentityTransform);
+bool Layer::prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform,
+ Region& clearRegion, renderengine::LayerSettings& layer) {
+ return prepareClientLayer(renderArea, Region(renderArea.getBounds()), useIdentityTransform,
+ clearRegion, layer);
+}
+
+bool Layer::prepareClientLayer(const RenderArea& /*renderArea*/, const Region& /*clip*/,
+ bool useIdentityTransform, Region& /*clearRegion*/,
+ renderengine::LayerSettings& layer) {
+ FloatRect bounds = computeBounds();
+ half alpha = getAlpha();
+ layer.geometry.boundaries = bounds;
+ if (useIdentityTransform) {
+ layer.geometry.positionTransform = mat4();
+ } else {
+ const ui::Transform transform = getTransform();
+ mat4 m;
+ m[0][0] = transform[0][0];
+ m[0][1] = transform[0][1];
+ m[0][3] = transform[0][2];
+ m[1][0] = transform[1][0];
+ m[1][1] = transform[1][1];
+ m[1][3] = transform[1][2];
+ m[3][0] = transform[2][0];
+ m[3][1] = transform[2][1];
+ m[3][3] = transform[2][2];
+ layer.geometry.positionTransform = m;
+ }
+
+ if (hasColorTransform()) {
+ layer.colorTransform = getColorTransform();
+ }
+
+ const auto roundedCornerState = getRoundedCornerState();
+ layer.geometry.roundedCornersRadius = roundedCornerState.radius;
+ layer.geometry.roundedCornersCrop = roundedCornerState.cropRect;
+
+ layer.alpha = alpha;
+ layer.sourceDataspace = mCurrentDataSpace;
+ return true;
}
void Layer::clearWithOpenGL(const RenderArea& renderArea, float red, float green, float blue,
@@ -1039,13 +1078,18 @@
ATRACE_CALL();
if (mLayerDetached) {
- return 0;
+ return flags;
+ }
+
+ if (mChildrenChanged) {
+ flags |= eVisibleRegion;
+ mChildrenChanged = false;
}
pushPendingState();
State c = getCurrentState();
if (!applyPendingStates(&c)) {
- return 0;
+ return flags;
}
flags = doTransactionResize(flags, &c);
@@ -1067,11 +1111,6 @@
mNeedsFiltering = (!getActiveTransform(c).preserveRects() || type >= ui::Transform::SCALE);
}
- if (mChildrenChanged) {
- flags |= eVisibleRegion;
- mChildrenChanged = false;
- }
-
// If the layer is hidden, signal and clear out all local sync points so
// that transactions for layers depending on this layer's frames becoming
// visible are not blocked
@@ -1241,7 +1280,12 @@
bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace) {
if (!mCurrentState.bgColorLayer && alpha == 0) {
return false;
- } else if (!mCurrentState.bgColorLayer && alpha != 0) {
+ }
+ mCurrentState.sequence++;
+ mCurrentState.modified = true;
+ setTransactionFlags(eTransactionNeeded);
+
+ if (!mCurrentState.bgColorLayer && alpha != 0) {
// create background color layer if one does not yet exist
uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor;
const String8& name = mName + "BackgroundColorLayer";
@@ -1595,6 +1639,7 @@
void Layer::addChild(const sp<Layer>& layer) {
mChildrenChanged = true;
+ setTransactionFlags(eTransactionNeeded);
mCurrentChildren.add(layer);
layer->setParent(this);
@@ -1602,6 +1647,7 @@
ssize_t Layer::removeChild(const sp<Layer>& layer) {
mChildrenChanged = true;
+ setTransactionFlags(eTransactionNeeded);
layer->setParent(nullptr);
return mCurrentChildren.remove(layer);
@@ -2206,7 +2252,7 @@
// Position the touchable region relative to frame screen location and restrict it to frame
// bounds.
info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop);
- info.visible = isVisible();
+ info.visible = canReceiveInput();
return info;
}
@@ -2218,6 +2264,10 @@
return nullptr;
}
+bool Layer::canReceiveInput() const {
+ return isVisible();
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f099df6..8b6d4c7 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -387,6 +387,11 @@
bool isHiddenByPolicy() const;
/*
+ * Returns whether this layer can receive input.
+ */
+ virtual bool canReceiveInput() const;
+
+ /*
* isProtected - true if the layer may contain protected content in the
* GRALLOC_USAGE_PROTECTED sense.
*/
@@ -421,11 +426,9 @@
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
protected:
- /*
- * onDraw - draws the surface.
- */
- virtual void onDraw(const RenderArea& renderArea, const Region& clip,
- bool useIdentityTransform) = 0;
+ virtual bool prepareClientLayer(const RenderArea& renderArea, const Region& clip,
+ bool useIdentityTransform, Region& clearRegion,
+ renderengine::LayerSettings& layer) = 0;
public:
virtual void setDefaultBufferSize(uint32_t /*w*/, uint32_t /*h*/) {}
@@ -475,11 +478,14 @@
virtual void releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) { }
/*
- * draw - performs some global clipping optimizations
- * and calls onDraw().
+ * prepareClientLayer - populates a renderengine::LayerSettings to passed to
+ * RenderEngine::drawLayers. Returns true if the layer can be used, and
+ * false otherwise.
*/
- void draw(const RenderArea& renderArea, const Region& clip);
- void draw(const RenderArea& renderArea, bool useIdentityTransform);
+ bool prepareClientLayer(const RenderArea& renderArea, const Region& clip, Region& clearRegion,
+ renderengine::LayerSettings& layer);
+ bool prepareClientLayer(const RenderArea& renderArea, bool useIdentityTransform,
+ Region& clearRegion, renderengine::LayerSettings& layer);
/*
* doTransaction - process the transaction. This is a good place to figure
@@ -517,8 +523,8 @@
* operation, so this should be set only if needed). Typically this is used
* to figure out if the content or size of a surface has changed.
*/
- virtual Region latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
- const sp<Fence>& /*releaseFence*/) {
+ virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/,
+ const sp<Fence>& /*releaseFence*/) {
return {};
}
@@ -810,7 +816,13 @@
FenceTimeline mReleaseTimeline;
// main thread
+ // Active buffer fields
sp<GraphicBuffer> mActiveBuffer;
+ sp<Fence> mActiveBufferFence;
+ // False if the buffer and its contents have been previously used for GPU
+ // composition, true otherwise.
+ bool mIsActiveBufferUpdatedForGpu = true;
+
ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN;
Rect mCurrentCrop;
uint32_t mCurrentTransform{0};
@@ -866,7 +878,6 @@
const LayerVector::Visitor& visitor);
LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
const std::vector<Layer*>& layersInTree);
-
/**
* Retuns the child bounds in layer space cropped to its bounds as well all its parent bounds.
* The cropped bounds must be transformed back from parent layer space to child layer space by
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index dc2b300..ce0611c 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -1,3 +1,4 @@
+akrulec@google.com
chaviw@google.com
lpy@google.com
marissaw@google.com
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 91ae087..5d9cfde 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -100,8 +100,10 @@
} // namespace
EventThreadConnection::EventThreadConnection(EventThread* eventThread,
- ResyncCallback resyncCallback)
+ ResyncCallback resyncCallback,
+ ResetIdleTimerCallback resetIdleTimerCallback)
: resyncCallback(std::move(resyncCallback)),
+ resetIdleTimerCallback(std::move(resetIdleTimerCallback)),
mEventThread(eventThread),
mChannel(gui::BitTube::DefaultSize) {}
@@ -147,22 +149,18 @@
namespace impl {
EventThread::EventThread(std::unique_ptr<VSyncSource> src,
- const InterceptVSyncsCallback& interceptVSyncsCallback,
- const ResetIdleTimerCallback& resetIdleTimerCallback,
- const char* threadName)
- : EventThread(nullptr, std::move(src), interceptVSyncsCallback, threadName) {
- mResetIdleTimer = resetIdleTimerCallback;
-}
+ InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
+ : EventThread(nullptr, std::move(src), std::move(interceptVSyncsCallback), threadName) {}
EventThread::EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
const char* threadName)
- : EventThread(src, nullptr, interceptVSyncsCallback, threadName) {}
+ : EventThread(src, nullptr, std::move(interceptVSyncsCallback), threadName) {}
EventThread::EventThread(VSyncSource* src, std::unique_ptr<VSyncSource> uniqueSrc,
InterceptVSyncsCallback interceptVSyncsCallback, const char* threadName)
: mVSyncSource(src),
mVSyncSourceUnique(std::move(uniqueSrc)),
- mInterceptVSyncsCallback(interceptVSyncsCallback),
+ mInterceptVSyncsCallback(std::move(interceptVSyncsCallback)),
mThreadName(threadName) {
if (src == nullptr) {
mVSyncSource = mVSyncSourceUnique.get();
@@ -205,8 +203,10 @@
mVSyncSource->setPhaseOffset(phaseOffset);
}
-sp<EventThreadConnection> EventThread::createEventConnection(ResyncCallback resyncCallback) const {
- return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback));
+sp<EventThreadConnection> EventThread::createEventConnection(
+ ResyncCallback resyncCallback, ResetIdleTimerCallback resetIdleTimerCallback) const {
+ return new EventThreadConnection(const_cast<EventThread*>(this), std::move(resyncCallback),
+ std::move(resetIdleTimerCallback));
}
status_t EventThread::registerDisplayEventConnection(const sp<EventThreadConnection>& connection) {
@@ -249,9 +249,9 @@
}
void EventThread::requestNextVsync(const sp<EventThreadConnection>& connection, bool reset) {
- if (mResetIdleTimer && reset) {
+ if (connection->resetIdleTimerCallback && reset) {
ATRACE_NAME("resetIdleTimer");
- mResetIdleTimer();
+ connection->resetIdleTimerCallback();
}
if (connection->resyncCallback) {
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 62b6a8b..b275183 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -45,6 +45,7 @@
// ---------------------------------------------------------------------------
using ResyncCallback = std::function<void()>;
+using ResetIdleTimerCallback = std::function<void()>;
enum class VSyncRequest {
None = -1,
@@ -69,7 +70,7 @@
class EventThreadConnection : public BnDisplayEventConnection {
public:
- EventThreadConnection(EventThread* eventThread, ResyncCallback resyncCallback);
+ EventThreadConnection(EventThread*, ResyncCallback, ResetIdleTimerCallback);
virtual ~EventThreadConnection();
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -83,6 +84,7 @@
// Called in response to requestNextVsync.
const ResyncCallback resyncCallback;
+ const ResetIdleTimerCallback resetIdleTimerCallback;
VSyncRequest vsyncRequest = VSyncRequest::None;
@@ -96,8 +98,8 @@
public:
virtual ~EventThread();
- virtual sp<EventThreadConnection> createEventConnection(
- ResyncCallback resyncCallback) const = 0;
+ virtual sp<EventThreadConnection> createEventConnection(ResyncCallback,
+ ResetIdleTimerCallback) const = 0;
// called before the screen is turned off from main thread
virtual void onScreenReleased() = 0;
@@ -124,17 +126,14 @@
class EventThread : public android::EventThread, private VSyncSource::Callback {
public:
using InterceptVSyncsCallback = std::function<void(nsecs_t)>;
- using ResetIdleTimerCallback = std::function<void()>;
// TODO(b/113612090): Once the Scheduler is complete this constructor will become obsolete.
- EventThread(VSyncSource* src, InterceptVSyncsCallback interceptVSyncsCallback,
- const char* threadName);
- EventThread(std::unique_ptr<VSyncSource> src,
- const InterceptVSyncsCallback& interceptVSyncsCallback,
- const ResetIdleTimerCallback& resetIdleTimerCallback, const char* threadName);
+ EventThread(VSyncSource*, InterceptVSyncsCallback, const char* threadName);
+ EventThread(std::unique_ptr<VSyncSource>, InterceptVSyncsCallback, const char* threadName);
~EventThread();
- sp<EventThreadConnection> createEventConnection(ResyncCallback resyncCallback) const override;
+ sp<EventThreadConnection> createEventConnection(ResyncCallback,
+ ResetIdleTimerCallback) const override;
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
@@ -220,9 +219,6 @@
State mState GUARDED_BY(mMutex) = State::Idle;
static const char* toCString(State);
-
- // Callback that resets the idle timer when the next vsync is received.
- ResetIdleTimerCallback mResetIdleTimer;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 75a410b..1f18ead 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -96,7 +96,8 @@
}
mEventThread = eventThread;
- mEvents = eventThread->createEventConnection(std::move(resyncCallback));
+ mEvents =
+ eventThread->createEventConnection(std::move(resyncCallback), ResetIdleTimerCallback());
mEvents->stealReceiveChannel(&mEventTube);
mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver,
this);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3060f1d..2f581d2 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -87,6 +87,7 @@
sp<Scheduler::ConnectionHandle> Scheduler::createConnection(
const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
+ ResetIdleTimerCallback resetIdleTimerCallback,
impl::EventThread::InterceptVSyncsCallback interceptCallback) {
const int64_t id = sNextId++;
ALOGV("Creating a connection handle with ID: %" PRId64 "\n", id);
@@ -94,12 +95,14 @@
std::unique_ptr<EventThread> eventThread =
makeEventThread(connectionName, mPrimaryDispSync.get(), phaseOffsetNs,
std::move(interceptCallback));
- auto connection = std::make_unique<Connection>(new ConnectionHandle(id),
- eventThread->createEventConnection(
- std::move(resyncCallback)),
- std::move(eventThread));
- mConnections.insert(std::make_pair(id, std::move(connection)));
+ auto eventThreadConnection =
+ createConnectionInternal(eventThread.get(), std::move(resyncCallback),
+ std::move(resetIdleTimerCallback));
+ mConnections.emplace(id,
+ std::make_unique<Connection>(new ConnectionHandle(id),
+ eventThreadConnection,
+ std::move(eventThread)));
return mConnections[id]->handle;
}
@@ -109,14 +112,29 @@
std::unique_ptr<VSyncSource> eventThreadSource =
std::make_unique<DispSyncSource>(dispSync, phaseOffsetNs, true, connectionName);
return std::make_unique<impl::EventThread>(std::move(eventThreadSource),
- std::move(interceptCallback),
- [this] { resetIdleTimer(); }, connectionName);
+ std::move(interceptCallback), connectionName);
+}
+
+sp<EventThreadConnection> Scheduler::createConnectionInternal(
+ EventThread* eventThread, ResyncCallback&& resyncCallback,
+ ResetIdleTimerCallback&& resetIdleTimerCallback) {
+ return eventThread->createEventConnection(std::move(resyncCallback),
+ [this,
+ resetIdleTimerCallback =
+ std::move(resetIdleTimerCallback)] {
+ resetIdleTimer();
+ if (resetIdleTimerCallback) {
+ resetIdleTimerCallback();
+ }
+ });
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback) {
+ const sp<Scheduler::ConnectionHandle>& handle, ResyncCallback resyncCallback,
+ ResetIdleTimerCallback resetIdleTimerCallback) {
RETURN_VALUE_IF_INVALID(nullptr);
- return mConnections[handle->id]->thread->createEventConnection(std::move(resyncCallback));
+ return createConnectionInternal(mConnections[handle->id]->thread.get(),
+ std::move(resyncCallback), std::move(resetIdleTimerCallback));
}
EventThread* Scheduler::getEventThread(const sp<Scheduler::ConnectionHandle>& handle) {
@@ -241,11 +259,6 @@
mExpiredTimerCallback = expiredTimerCallback;
}
-void Scheduler::setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback) {
- std::lock_guard<std::mutex> lock(mCallbackLock);
- mResetTimerCallback = resetTimerCallback;
-}
-
void Scheduler::updateFrameSkipping(const int64_t skipCount) {
ATRACE_INT("FrameSkipCount", skipCount);
if (mSkipCount != skipCount) {
@@ -336,11 +349,6 @@
mIdleTimer->reset();
ATRACE_INT("ExpiredIdleTimer", 0);
}
-
- std::lock_guard<std::mutex> lock(mCallbackLock);
- if (mResetTimerCallback) {
- mResetTimerCallback();
- }
}
void Scheduler::expiredTimerCallback() {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index e77dc06..4abf027 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -37,7 +37,6 @@
class Scheduler {
public:
using ExpiredIdleTimerCallback = std::function<void()>;
- using ResetIdleTimerCallback = std::function<void()>;
// Enum to indicate whether to start the transaction early, or at vsync time.
enum class TransactionStart { EARLY, NORMAL };
@@ -72,12 +71,13 @@
virtual ~Scheduler();
/** Creates an EventThread connection. */
- sp<ConnectionHandle> createConnection(
- const char* connectionName, int64_t phaseOffsetNs, ResyncCallback resyncCallback,
- impl::EventThread::InterceptVSyncsCallback interceptCallback);
+ sp<ConnectionHandle> createConnection(const char* connectionName, int64_t phaseOffsetNs,
+ ResyncCallback, ResetIdleTimerCallback,
+ impl::EventThread::InterceptVSyncsCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(const sp<ConnectionHandle>& handle,
- ResyncCallback resyncCallback);
+ ResyncCallback,
+ ResetIdleTimerCallback);
// Getter methods.
EventThread* getEventThread(const sp<ConnectionHandle>& handle);
@@ -116,8 +116,6 @@
void incrementFrameCounter();
// Callback that gets invoked once the idle timer expires.
void setExpiredIdleTimerCallback(const ExpiredIdleTimerCallback& expiredTimerCallback);
- // Callback that gets invoked once the idle timer is reset.
- void setResetIdleTimerCallback(const ResetIdleTimerCallback& resetTimerCallback);
// Returns relevant information about Scheduler for dumpsys purposes.
std::string doDump();
@@ -127,6 +125,10 @@
impl::EventThread::InterceptVSyncsCallback interceptCallback);
private:
+ // Creates a connection on the given EventThread and forwards the given callbacks.
+ sp<EventThreadConnection> createConnectionInternal(EventThread*, ResyncCallback&&,
+ ResetIdleTimerCallback&&);
+
nsecs_t calculateAverage() const;
void updateFrameSkipping(const int64_t skipCount);
// Collects the statistical mean (average) and median between timestamp
@@ -184,7 +186,6 @@
std::mutex mCallbackLock;
ExpiredIdleTimerCallback mExpiredTimerCallback GUARDED_BY(mCallbackLock);
- ResetIdleTimerCallback mResetTimerCallback GUARDED_BY(mCallbackLock);
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1a64f69..5f8de83 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-// #define LOG_NDEBUG 0
+//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <sys/types.h>
@@ -120,6 +120,7 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using namespace android::sysprop;
+
using base::StringAppendF;
using ui::ColorMode;
using ui::Dataspace;
@@ -127,6 +128,8 @@
using ui::Hdr;
using ui::RenderIntent;
+using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType;
+
namespace {
#pragma clang diagnostic push
@@ -211,6 +214,9 @@
constexpr float kSrgbWhiteY = 1.0000f;
constexpr float kSrgbWhiteZ = 1.0891f;
+constexpr float kDefaultRefreshRate = 60.f;
+constexpr float kPerformanceRefreshRate = 90.f;
+
// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -627,13 +633,17 @@
mPhaseOffsets->setRefreshRateType(
scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
+ auto resetIdleTimerCallback =
+ std::bind(&SurfaceFlinger::setRefreshRateTo, this, RefreshRateType::PERFORMANCE);
+
mAppConnectionHandle =
mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(),
- resyncCallback,
+ resyncCallback, resetIdleTimerCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(),
- resyncCallback, [this](nsecs_t timestamp) {
+ resyncCallback, resetIdleTimerCallback,
+ [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
@@ -731,20 +741,11 @@
}
if (mUseScheduler) {
- mScheduler->setExpiredIdleTimerCallback([this]() {
- mPhaseOffsets->setRefreshRateType(
- scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
- const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
- mVsyncModulator.setPhaseOffsets(early, gl, late);
- setRefreshRateTo(60.f /* fps */);
+ mScheduler->setExpiredIdleTimerCallback([this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::DEFAULT);
});
- mScheduler->setResetIdleTimerCallback([this]() {
- mPhaseOffsets->setRefreshRateType(
- scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
- const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
- mVsyncModulator.setPhaseOffsets(early, gl, late);
- setRefreshRateTo(90.f /* fps */);
- });
+
mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(getHwComposer().getConfigs(
*display->getId()),
@@ -956,13 +957,6 @@
return display->getActiveConfig();
}
-status_t SurfaceFlinger::setActiveConfigAsync(const sp<IBinder>& displayToken, int mode) {
- ATRACE_NAME("setActiveConfigAsync");
- postMessageAsync(new LambdaMessage(
- [=]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
- return NO_ERROR;
-}
-
status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
ATRACE_NAME("setActiveConfigSync");
postMessageSync(new LambdaMessage(
@@ -1269,16 +1263,21 @@
});
if (mUseScheduler) {
- if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mScheduler->createDisplayEventConnection(mSfConnectionHandle, resyncCallback);
- } else {
- return mScheduler->createDisplayEventConnection(mAppConnectionHandle, resyncCallback);
- }
+ auto resetIdleTimerCallback = [this] {
+ Mutex::Autolock lock(mStateLock);
+ setRefreshRateTo(RefreshRateType::PERFORMANCE);
+ };
+
+ const auto& handle = vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle
+ : mAppConnectionHandle;
+
+ return mScheduler->createDisplayEventConnection(handle, std::move(resyncCallback),
+ std::move(resetIdleTimerCallback));
} else {
if (vsyncSource == eVsyncSourceSurfaceFlinger) {
- return mSFEventThread->createEventConnection(resyncCallback);
+ return mSFEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
} else {
- return mEventThread->createEventConnection(resyncCallback);
+ return mEventThread->createEventConnection(resyncCallback, ResetIdleTimerCallback());
}
}
}
@@ -1440,12 +1439,16 @@
*compositorTiming = getBE().mCompositorTiming;
}
-// TODO(b/123715322): Fix thread safety.
-void SurfaceFlinger::setRefreshRateTo(float newFps) NO_THREAD_SAFETY_ANALYSIS {
- const auto display = getDefaultDisplayDeviceLocked();
- if (!display || mBootStage != BootStage::FINISHED) {
+void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate) {
+ mPhaseOffsets->setRefreshRateType(refreshRate);
+
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
+
+ if (mBootStage != BootStage::FINISHED) {
return;
}
+
// TODO(b/113612090): There should be a message queue flush here. Because this esentially
// runs on a mainthread, we cannot call postMessageSync. This can be resolved in a better
// manner, once the setActiveConfig is synchronous, and is executed at a known time in a
@@ -1456,14 +1459,20 @@
if (currentVsyncPeriod == 0) {
return;
}
+
// TODO(b/113612090): Consider having an enum value for correct refresh rates, rather than
// floating numbers.
const float currentFps = 1e9 / currentVsyncPeriod;
+ const float newFps = refreshRate == RefreshRateType::PERFORMANCE ? kPerformanceRefreshRate
+ : kDefaultRefreshRate;
if (std::abs(currentFps - newFps) <= 1) {
return;
}
- auto configs = getHwComposer().getConfigs(*display->getId());
+ const auto displayId = getInternalDisplayIdLocked();
+ LOG_ALWAYS_FATAL_IF(!displayId);
+
+ auto configs = getHwComposer().getConfigs(*displayId);
for (int i = 0; i < configs.size(); i++) {
const nsecs_t vsyncPeriod = configs.at(i)->getVsyncPeriod();
if (vsyncPeriod == 0) {
@@ -1473,12 +1482,7 @@
// TODO(b/113612090): There should be a better way at determining which config
// has the right refresh rate.
if (std::abs(fps - newFps) <= 1) {
- const sp<IBinder> token = display->getDisplayToken().promote();
- LOG_ALWAYS_FATAL_IF(token == nullptr);
-
- // This is posted in async function to avoid deadlock when getDisplayDevice
- // requires mStateLock.
- setActiveConfigAsync(token, i);
+ setActiveConfigInternal(getInternalDisplayTokenLocked(), i);
ATRACE_INT("FPS", newFps);
}
}
@@ -1648,6 +1652,10 @@
bool refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
+
+ updateCursorAsync();
+ updateInputFlinger();
+
refreshNeeded |= mRepaintEverything;
if (refreshNeeded && CC_LIKELY(mBootStage != BootStage::BOOTLOADER)) {
// Signal a refresh if a transaction modified the window state,
@@ -1742,7 +1750,15 @@
bool SurfaceFlinger::handleMessageInvalidate() {
ATRACE_CALL();
- return handlePageFlip();
+ bool refreshNeeded = handlePageFlip();
+
+ for (auto& layer : mLayersPendingRefresh) {
+ Region visibleReg;
+ visibleReg.set(layer->computeScreenBounds());
+ invalidateLayerStack(layer, visibleReg);
+ }
+ mLayersPendingRefresh.clear();
+ return refreshNeeded;
}
void SurfaceFlinger::calculateWorkingSet() {
@@ -1863,16 +1879,13 @@
if (displayState.isEnabled) {
// transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = display->getPhysicalSpaceDirtyRegion(repaintEverything);
+ const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
if (!dirtyRegion.isEmpty()) {
+ base::unique_fd readyFence;
// redraw the whole screen
- doComposeSurfaces(displayDevice);
+ doComposeSurfaces(displayDevice, dirtyRegion, &readyFence);
- // and draw the dirty region
- auto& engine(getRenderEngine());
- engine.fillRegionWithColor(dirtyRegion, 1, 0, 1, 1);
-
- display->getRenderSurface()->queueBuffer();
+ display->getRenderSurface()->queueBuffer(std::move(readyFence));
}
}
@@ -2409,7 +2422,7 @@
auto display = displayDevice->getCompositionDisplay();
const auto& displayState = display->getState();
- bool dirty = !display->getPhysicalSpaceDirtyRegion(false).isEmpty();
+ bool dirty = !display->getDirtyRegion(false).isEmpty();
bool empty = displayDevice->getVisibleLayersSortedByZ().size() == 0;
bool wasEmpty = !displayState.lastCompositionHadVisibleLayers;
@@ -2460,7 +2473,7 @@
if (displayState.isEnabled) {
// transform the dirty region into this screen's coordinate space
- const Region dirtyRegion = display->getPhysicalSpaceDirtyRegion(repaintEverything);
+ const Region dirtyRegion = display->getDirtyRegion(repaintEverything);
// repaint the framebuffer (if needed)
doDisplayComposition(displayDevice, dirtyRegion);
@@ -2849,7 +2862,6 @@
* (perform the transaction for each of them if needed)
*/
- bool inputChanged = false;
if (transactionFlags & eTraversalNeeded) {
mCurrentState.traverseInZOrder([&](Layer* layer) {
uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
@@ -2860,7 +2872,7 @@
mVisibleRegionsDirty = true;
if (flags & Layer::eInputInfoChanged) {
- inputChanged = true;
+ mInputInfoChanged = true;
}
});
}
@@ -2972,22 +2984,23 @@
}
commitTransaction();
-
- if (inputChanged || mVisibleRegionsDirty) {
- updateInputWindows();
- }
- executeInputWindowCommands();
-
- updateCursorAsync();
}
-void SurfaceFlinger::updateInputWindows() {
+void SurfaceFlinger::updateInputFlinger() {
ATRACE_CALL();
-
- if (mInputFlinger == nullptr) {
+ if (!mInputFlinger) {
return;
}
+ if (mVisibleRegionsDirty || mInputInfoChanged) {
+ mInputInfoChanged = false;
+ updateInputWindowInfo();
+ }
+
+ executeInputWindowCommands();
+}
+
+void SurfaceFlinger::updateInputWindowInfo() {
Vector<InputWindowInfo> inputHandles;
mDrawingState.traverseInReverseZOrder([&](Layer* layer) {
@@ -3001,10 +3014,6 @@
}
void SurfaceFlinger::executeInputWindowCommands() {
- if (!mInputFlinger) {
- return;
- }
-
for (const auto& transferTouchFocusCommand : mInputWindowCommands.transferTouchFocusCommands) {
if (transferTouchFocusCommand.fromToken != nullptr &&
transferTouchFocusCommand.toToken != nullptr &&
@@ -3281,9 +3290,10 @@
Mutex::Autolock lock(mStateLock);
for (auto& layer : mLayersWithQueuedFrames) {
- const Region dirty(layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence));
+ if (layer->latchBuffer(visibleRegions, latchTime, getBE().flushFence)) {
+ mLayersPendingRefresh.push_back(layer);
+ }
layer->useSurfaceDamage();
- invalidateLayerStack(layer, dirty);
if (layer->isBufferLatched()) {
newDataLatched = true;
}
@@ -3297,11 +3307,6 @@
mVisibleRegionsDirty |= visibleRegions;
- if (visibleRegions) {
- // Update input window info if the layer receives its first buffer.
- updateInputWindows();
- }
-
// If we will need to wake up at some time in the future to deal with a
// queued frame that shouldn't be displayed during this vsync period, wake
// up during the next vsync period to check again.
@@ -3327,7 +3332,6 @@
void SurfaceFlinger::doDisplayComposition(const sp<DisplayDevice>& displayDevice,
const Region& inDirtyRegion) {
auto display = displayDevice->getCompositionDisplay();
-
// We only need to actually compose the display if:
// 1) It is being handled by hardware composer, which may need this to
// keep its virtual display state machine in sync, or
@@ -3338,13 +3342,16 @@
}
ALOGV("doDisplayComposition");
- if (!doComposeSurfaces(displayDevice)) return;
+ base::unique_fd readyFence;
+ if (!doComposeSurfaces(displayDevice, Region::INVALID_REGION, &readyFence)) return;
// swap buffers (presentation)
- display->getRenderSurface()->queueBuffer();
+ display->getRenderSurface()->queueBuffer(std::move(readyFence));
}
-bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice) {
+bool SurfaceFlinger::doComposeSurfaces(const sp<DisplayDevice>& displayDevice,
+ const Region& debugRegion, base::unique_fd* readyFence) {
+ ATRACE_CALL();
ALOGV("doComposeSurfaces");
auto display = displayDevice->getCompositionDisplay();
@@ -3359,13 +3366,14 @@
mat4 colorMatrix;
bool applyColorMatrix = false;
- // Framebuffer will live in this scope for GPU composition.
- std::unique_ptr<renderengine::BindNativeBufferAsFramebuffer> fbo;
+ renderengine::DisplaySettings clientCompositionDisplay;
+ std::vector<renderengine::LayerSettings> clientCompositionLayers;
+ sp<GraphicBuffer> buf;
if (hasClientComposition) {
ALOGV("hasClientComposition");
- sp<GraphicBuffer> buf = display->getRenderSurface()->dequeueBuffer();
+ buf = display->getRenderSurface()->dequeueBuffer();
if (buf == nullptr) {
ALOGW("Dequeuing buffer for display [%s] failed, bailing out of "
@@ -3374,24 +3382,30 @@
return false;
}
- // Bind the framebuffer in this scope.
- fbo = std::make_unique<renderengine::BindNativeBufferAsFramebuffer>(getRenderEngine(),
- buf->getNativeBuffer());
+ clientCompositionDisplay.physicalDisplay = displayState.scissor;
+ clientCompositionDisplay.clip = displayState.scissor;
+ const ui::Transform& displayTransform = displayState.transform;
+ mat4 m;
+ m[0][0] = displayTransform[0][0];
+ m[0][1] = displayTransform[0][1];
+ m[0][3] = displayTransform[0][2];
+ m[1][0] = displayTransform[1][0];
+ m[1][1] = displayTransform[1][1];
+ m[1][3] = displayTransform[1][2];
+ m[3][0] = displayTransform[2][0];
+ m[3][1] = displayTransform[2][1];
+ m[3][3] = displayTransform[2][2];
- if (fbo->getStatus() != NO_ERROR) {
- ALOGW("Binding buffer for display [%s] failed with status: %d",
- displayDevice->getDisplayName().c_str(), fbo->getStatus());
- return false;
- }
+ clientCompositionDisplay.globalTransform = m;
const auto* profile = display->getDisplayColorProfile();
Dataspace outputDataspace = Dataspace::UNKNOWN;
if (profile->hasWideColorGamut()) {
outputDataspace = displayState.dataspace;
}
- getRenderEngine().setOutputDataSpace(outputDataspace);
- getRenderEngine().setDisplayMaxLuminance(
- profile->getHdrCapabilities().getDesiredMaxLuminance());
+ clientCompositionDisplay.outputDataspace = outputDataspace;
+ clientCompositionDisplay.maxLuminance =
+ profile->getHdrCapabilities().getDesiredMaxLuminance();
const bool hasDeviceComposition = getHwComposer().hasDeviceComposition(displayId);
const bool skipClientColorTransform =
@@ -3402,44 +3416,7 @@
// Compute the global color transform matrix.
applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
- colorMatrix = mDrawingState.colorMatrix;
- }
-
- display->getRenderSurface()->setViewportAndProjection();
-
- // Never touch the framebuffer if we don't have any framebuffer layers
- if (hasDeviceComposition) {
- // when using overlays, we assume a fully transparent framebuffer
- // NOTE: we could reduce how much we need to clear, for instance
- // remove where there are opaque FB layers. however, on some
- // GPUs doing a "clean slate" clear might be more efficient.
- // We'll revisit later if needed.
- getRenderEngine().clearWithColor(0, 0, 0, 0);
- } else {
- // we start with the whole screen area and remove the scissor part
- // we're left with the letterbox region
- // (common case is that letterbox ends-up being empty)
- const Region letterbox = bounds.subtract(displayState.scissor);
-
- // compute the area to clear
- const Region region = displayState.undefinedRegion.merge(letterbox);
-
- // screen is already cleared here
- if (!region.isEmpty()) {
- // can happen with SurfaceView
- drawWormhole(region);
- }
- }
-
- const Rect& bounds = displayState.bounds;
- const Rect& scissor = displayState.scissor;
- if (scissor != bounds) {
- // scissor doesn't match the screen's dimensions, so we
- // need to clear everything outside of it and enable
- // the GL scissor so we don't draw anything where we shouldn't
-
- // enable scissor for this frame
- getRenderEngine().setScissor(scissor);
+ clientCompositionDisplay.colorTransform = colorMatrix;
}
}
@@ -3448,10 +3425,11 @@
*/
ALOGV("Rendering client layers");
- const ui::Transform& displayTransform = displayState.transform;
bool firstLayer = true;
+ Region clearRegion = Region::INVALID_REGION;
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- const Region clip(bounds.intersect(displayTransform.transform(layer->visibleRegion)));
+ const Region viewportRegion(displayState.viewport);
+ const Region clip(viewportRegion.intersect(layer->visibleRegion));
ALOGV("Layer: %s", layer->getName().string());
ALOGV(" Composition type: %s", to_string(layer->getCompositionType(displayId)).c_str());
if (!clip.isEmpty()) {
@@ -3467,22 +3445,28 @@
layer->getRoundedCornerState().radius == 0.0f && hasClientComposition) {
// never clear the very first layer since we're
// guaranteed the FB is already cleared
- layer->clearWithOpenGL(renderArea);
+ renderengine::LayerSettings layerSettings;
+ Region dummyRegion;
+ bool prepared = layer->prepareClientLayer(renderArea, clip, dummyRegion,
+ layerSettings);
+
+ if (prepared) {
+ layerSettings.source.buffer.buffer = nullptr;
+ layerSettings.source.solidColor = half3(0.0, 0.0, 0.0);
+ layerSettings.alpha = half(0.0);
+ layerSettings.disableBlending = true;
+ clientCompositionLayers.push_back(layerSettings);
+ }
}
break;
}
case HWC2::Composition::Client: {
- if (layer->hasColorTransform()) {
- mat4 tmpMatrix;
- if (applyColorMatrix) {
- tmpMatrix = mDrawingState.colorMatrix;
- }
- tmpMatrix *= layer->getColorTransform();
- getRenderEngine().setColorTransform(tmpMatrix);
- } else {
- getRenderEngine().setColorTransform(colorMatrix);
+ renderengine::LayerSettings layerSettings;
+ bool prepared =
+ layer->prepareClientLayer(renderArea, clip, clearRegion, layerSettings);
+ if (prepared) {
+ clientCompositionLayers.push_back(layerSettings);
}
- layer->draw(renderArea, clip);
break;
}
default:
@@ -3496,12 +3480,22 @@
// Perform some cleanup steps if we used client composition.
if (hasClientComposition) {
- getRenderEngine().setColorTransform(mat4());
- getRenderEngine().disableScissor();
- display->getRenderSurface()->finishBuffer();
- // Clear out error flags here so that we don't wait until next
- // composition to log.
- getRenderEngine().checkErrors();
+ clientCompositionDisplay.clearRegion = clearRegion;
+ if (!debugRegion.isEmpty()) {
+ Region::const_iterator it = debugRegion.begin();
+ Region::const_iterator end = debugRegion.end();
+ while (it != end) {
+ const Rect& rect = *it++;
+ renderengine::LayerSettings layerSettings;
+ layerSettings.source.buffer.buffer = nullptr;
+ layerSettings.source.solidColor = half3(1.0, 0.0, 1.0);
+ layerSettings.geometry.boundaries = rect.toFloatRect();
+ layerSettings.alpha = half(1.0);
+ clientCompositionLayers.push_back(layerSettings);
+ }
+ }
+ getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers,
+ buf->getNativeBuffer(), readyFence);
}
return true;
}
@@ -5396,8 +5390,8 @@
DisplayRenderArea renderArea(display, sourceCrop, reqWidth, reqHeight, reqDataspace,
renderAreaRotation);
- auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
- display, std::placeholders::_1);
+ auto traverseLayers = std::bind(&SurfaceFlinger::traverseLayersInDisplay, this, display,
+ std::placeholders::_1);
return captureScreenCommon(renderArea, traverseLayers, outBuffer, reqPixelFormat,
useIdentityTransform);
}
@@ -5616,35 +5610,109 @@
void SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
- bool useIdentityTransform) {
+ ANativeWindowBuffer* buffer, bool useIdentityTransform,
+ int* outSyncFd) {
ATRACE_CALL();
- auto& engine(getRenderEngine());
-
const auto reqWidth = renderArea.getReqWidth();
const auto reqHeight = renderArea.getReqHeight();
const auto sourceCrop = renderArea.getSourceCrop();
const auto rotation = renderArea.getRotationFlags();
- engine.setOutputDataSpace(renderArea.getReqDataSpace());
- engine.setDisplayMaxLuminance(DisplayDevice::sDefaultMaxLumiance);
+ renderengine::DisplaySettings clientCompositionDisplay;
+ std::vector<renderengine::LayerSettings> clientCompositionLayers;
- // make sure to clear all GL error flags
- engine.checkErrors();
+ // assume that bounds are never offset, and that they are the same as the
+ // buffer bounds.
+ clientCompositionDisplay.physicalDisplay = Rect(reqWidth, reqHeight);
+ ui::Transform transform = renderArea.getTransform();
+ mat4 m;
+ m[0][0] = transform[0][0];
+ m[0][1] = transform[0][1];
+ m[0][3] = transform[0][2];
+ m[1][0] = transform[1][0];
+ m[1][1] = transform[1][1];
+ m[1][3] = transform[1][2];
+ m[3][0] = transform[2][0];
+ m[3][1] = transform[2][1];
+ m[3][3] = transform[2][2];
- // set-up our viewport
- engine.setViewportAndProjection(reqWidth, reqHeight, sourceCrop, rotation);
- engine.disableTexturing();
+ clientCompositionDisplay.globalTransform = m;
+ mat4 rotMatrix;
+ // Displacement for repositioning the clipping rectangle after rotating it
+ // with the rotation hint.
+ int displacementX = 0;
+ int displacementY = 0;
+ float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
+ switch (rotation) {
+ case ui::Transform::ROT_90:
+ rotMatrix = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
+ displacementX = reqWidth;
+ break;
+ case ui::Transform::ROT_180:
+ rotMatrix = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
+ displacementX = reqWidth;
+ displacementY = reqHeight;
+ break;
+ case ui::Transform::ROT_270:
+ rotMatrix = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
+ displacementY = reqHeight;
+ break;
+ default:
+ break;
+ }
+ // We need to transform the clipping window into the right spot.
+ // First, rotate the clipping rectangle by the rotation hint to get the
+ // right orientation
+ const vec4 clipTL = vec4(sourceCrop.left, sourceCrop.top, 0, 1);
+ const vec4 clipBR = vec4(sourceCrop.right, sourceCrop.bottom, 0, 1);
+ const vec4 rotClipTL = rotMatrix * clipTL;
+ const vec4 rotClipBR = rotMatrix * clipBR;
+ const int newClipLeft = std::min(rotClipTL[0], rotClipBR[0]);
+ const int newClipTop = std::min(rotClipTL[1], rotClipBR[1]);
+ const int newClipRight = std::max(rotClipTL[0], rotClipBR[0]);
+ const int newClipBottom = std::max(rotClipTL[1], rotClipBR[1]);
+
+ // Now reposition the clipping rectangle with the displacement vector
+ // computed above.
+ const mat4 displacementMat = mat4::translate(vec4(displacementX, displacementY, 0, 1));
+
+ clientCompositionDisplay.clip =
+ Rect(newClipLeft + displacementX, newClipTop + displacementY,
+ newClipRight + displacementX, newClipBottom + displacementY);
+
+ // We need to perform the same transformation in layer space, so propagate
+ // it to the global transform.
+ mat4 clipTransform = displacementMat * rotMatrix;
+ clientCompositionDisplay.globalTransform *= clipTransform;
+ clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
+ clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
- // redraw the screen entirely...
- engine.clearWithColor(0, 0, 0, alpha);
+ renderengine::LayerSettings fillLayer;
+ fillLayer.source.buffer.buffer = nullptr;
+ fillLayer.source.solidColor = half3(0.0, 0.0, 0.0);
+ fillLayer.geometry.boundaries = FloatRect(0.0, 0.0, 1.0, 1.0);
+ fillLayer.alpha = half(alpha);
+ clientCompositionLayers.push_back(fillLayer);
+
+ Region clearRegion = Region::INVALID_REGION;
traverseLayers([&](Layer* layer) {
- engine.setColorTransform(layer->getColorTransform());
- layer->draw(renderArea, useIdentityTransform);
- engine.setColorTransform(mat4());
+ renderengine::LayerSettings layerSettings;
+ bool prepared = layer->prepareClientLayer(renderArea, useIdentityTransform, clearRegion,
+ layerSettings);
+ if (prepared) {
+ clientCompositionLayers.push_back(layerSettings);
+ }
});
+
+ clientCompositionDisplay.clearRegion = clearRegion;
+ base::unique_fd drawFence;
+ getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayers, buffer,
+ &drawFence);
+
+ *outSyncFd = drawFence.release();
}
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
@@ -5668,28 +5736,7 @@
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
- auto& engine(getRenderEngine());
-
- // this binds the given EGLImage as a framebuffer for the
- // duration of this scope.
- renderengine::BindNativeBufferAsFramebuffer bufferBond(engine, buffer);
- if (bufferBond.getStatus() != NO_ERROR) {
- ALOGE("got ANWB binding error while taking screenshot");
- return INVALID_OPERATION;
- }
-
- // this will in fact render into our dequeued buffer
- // via an FBO, which means we didn't have to create
- // an EGLSurface and therefore we're not
- // dependent on the context's EGLConfig.
- renderScreenImplLocked(renderArea, traverseLayers, useIdentityTransform);
-
- base::unique_fd syncFd = engine.flush();
- if (syncFd < 0) {
- engine.finish();
- }
- *outSyncFd = syncFd.release();
-
+ renderScreenImplLocked(renderArea, traverseLayers, buffer, useIdentityTransform, outSyncFd);
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index c878a08..6546973 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -60,6 +60,7 @@
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
#include "Scheduler/PhaseOffsets.h"
+#include "Scheduler/RefreshRateConfigs.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncModulator.h"
@@ -502,8 +503,6 @@
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays() REQUIRES(mStateLock);
- // setActiveConfigInternal() posted on a main thread for async execution
- status_t setActiveConfigAsync(const sp<IBinder>& displayToken, int mode);
// called on the main thread in response to setActiveConfig()
void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
// called on the main thread in response to setPowerMode()
@@ -520,7 +519,8 @@
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(uint32_t transactionFlags);
- void updateInputWindows();
+ void updateInputFlinger();
+ void updateInputWindowInfo();
void executeInputWindowCommands();
void updateCursorAsync();
@@ -598,7 +598,8 @@
void startBootAnim();
void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
- bool useIdentityTransform);
+ ANativeWindowBuffer* buffer, bool useIdentityTransform,
+ int* outSyncFd);
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
sp<GraphicBuffer>* outBuffer, const ui::PixelFormat reqPixelFormat,
bool useIdentityTransform);
@@ -737,8 +738,11 @@
void logLayerStats();
void doDisplayComposition(const sp<DisplayDevice>& display, const Region& dirtyRegion);
- // This fails if using GL and the surface has been destroyed.
- bool doComposeSurfaces(const sp<DisplayDevice>& display);
+ // This fails if using GL and the surface has been destroyed. readyFence
+ // will be populated if using GL and native fence sync is supported, to
+ // signal when drawing has completed.
+ bool doComposeSurfaces(const sp<DisplayDevice>& display, const Region& debugRegionm,
+ base::unique_fd* readyFence);
void postFramebuffer(const sp<DisplayDevice>& display);
void postFrame();
@@ -765,9 +769,9 @@
void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
void disableHardwareVsync(bool makeUnavailable);
- // Sets the refresh rate to newFps by switching active configs, if they are available for
+ // Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
- void setRefreshRateTo(float newFps);
+ void setRefreshRateTo(scheduler::RefreshRateConfigs::RefreshRateType) REQUIRES(mStateLock);
using GetVsyncPeriod = std::function<nsecs_t()>;
@@ -947,9 +951,13 @@
// don't need synchronization
State mDrawingState{LayerVector::StateSet::Drawing};
bool mVisibleRegionsDirty;
+ // Set during transaction commit stage to track if the input info for a layer has changed.
+ bool mInputInfoChanged{false};
bool mGeometryInvalid;
bool mAnimCompositionPending;
std::vector<sp<Layer>> mLayersWithQueuedFrames;
+ // Tracks layers that need to update a display's dirty region.
+ std::vector<sp<Layer>> mLayersPendingRefresh;
sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
bool mHadClientComposition = false;
diff --git a/services/surfaceflinger/TimeStats/OWNERS b/services/surfaceflinger/TimeStats/OWNERS
new file mode 100644
index 0000000..ac02d12
--- /dev/null
+++ b/services/surfaceflinger/TimeStats/OWNERS
@@ -0,0 +1 @@
+zzyiwei@google.com
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp
index 89c26f4..ee857b0 100644
--- a/services/surfaceflinger/tests/Stress_test.cpp
+++ b/services/surfaceflinger/tests/Stress_test.cpp
@@ -34,7 +34,7 @@
auto surf = client->createSurface(String8("t"), 100, 100,
PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(surf != nullptr);
- surf->clear();
+ surf.clear();
}
};
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 3770317..7b21dbc 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -1134,7 +1134,7 @@
.setRelativeLayer(layerG, layerR->getHandle(), 1)
.apply();
- layerG->clear();
+ layerG.clear();
// layerG should have been removed
getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
@@ -1537,7 +1537,6 @@
SCOPED_TRACE("default before setting background color layer");
screenshot()->expectColor(Rect(0, 0, width, height), expectedColor);
}
-
Transaction()
.setBackgroundColor(layer, half3(0, 1.0f, 0), alpha, ui::Dataspace::UNKNOWN)
.apply();
@@ -3126,16 +3125,25 @@
}
static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper,
- const sp<SurfaceControl>& layer = nullptr) {
+ const sp<SurfaceControl>& layer = nullptr, bool setBuffer = true,
+ bool setBackgroundColor = false) {
if (layer) {
sp<GraphicBuffer> buffer;
sp<Fence> fence;
- int err = getBuffer(&buffer, &fence);
- if (err != NO_ERROR) {
- return err;
+ if (setBuffer) {
+ int err = getBuffer(&buffer, &fence);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ transaction.setBuffer(layer, buffer);
+ transaction.setAcquireFence(layer, fence);
}
- transaction.setBuffer(layer, buffer).setAcquireFence(layer, fence);
+ if (setBackgroundColor) {
+ transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f,
+ ui::Dataspace::UNKNOWN);
+ }
}
transaction.addTransactionCompletedCallback(callbackHelper->function,
@@ -3166,13 +3174,13 @@
}
};
-TEST_F(LayerCallbackTest, Basic) {
+TEST_F(LayerCallbackTest, BufferColor) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
Transaction transaction;
CallbackHelper callback;
- int err = fillTransaction(transaction, &callback, layer);
+ int err = fillTransaction(transaction, &callback, layer, true, true);
if (err) {
GTEST_SUCCEED() << "test not supported";
return;
@@ -3185,13 +3193,13 @@
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
}
-TEST_F(LayerCallbackTest, NoBuffer) {
+TEST_F(LayerCallbackTest, NoBufferNoColor) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
Transaction transaction;
CallbackHelper callback;
- int err = fillTransaction(transaction, &callback);
+ int err = fillTransaction(transaction, &callback, layer, false, false);
if (err) {
GTEST_SUCCEED() << "test not supported";
return;
@@ -3205,6 +3213,45 @@
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
}
+TEST_F(LayerCallbackTest, BufferNoColor) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, true, false);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
+TEST_F(LayerCallbackTest, NoBufferColor) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+
+ Transaction transaction;
+ CallbackHelper callback;
+ int err = fillTransaction(transaction, &callback, layer, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
+}
+
TEST_F(LayerCallbackTest, NoStateChange) {
Transaction transaction;
CallbackHelper callback;
@@ -3239,7 +3286,7 @@
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true));
}
-TEST_F(LayerCallbackTest, Merge) {
+TEST_F(LayerCallbackTest, MergeBufferNoColor) {
sp<SurfaceControl> layer1, layer2;
ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
@@ -3266,6 +3313,62 @@
EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
}
+TEST_F(LayerCallbackTest, MergeNoBufferColor) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer1, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2},
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
+
+TEST_F(LayerCallbackTest, MergeOneBufferOneColor) {
+ sp<SurfaceControl> layer1, layer2;
+ ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+
+ Transaction transaction1, transaction2;
+ CallbackHelper callback1, callback2;
+ int err = fillTransaction(transaction1, &callback1, layer1);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+ err = fillTransaction(transaction2, &callback2, layer2, false, true);
+ if (err) {
+ GTEST_SUCCEED() << "test not supported";
+ return;
+ }
+
+ transaction1.setFrame(layer1, Rect(0, 0, 32, 32));
+ transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply();
+
+ ExpectedResult expected;
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1);
+ expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer2,
+ ExpectedResult::Buffer::NOT_ACQUIRED);
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true));
+ EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true));
+}
TEST_F(LayerCallbackTest, Merge_SameCallback) {
sp<SurfaceControl> layer1, layer2;
ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
@@ -4332,7 +4435,7 @@
mCapture->checkPixel(64, 64, 111, 111, 111);
}
- mChild->clear();
+ mChild.clear();
{
SCOPED_TRACE("After destroying child");
@@ -5204,7 +5307,7 @@
ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
auto redLayerHandle = redLayer->getHandle();
- redLayer->clear();
+ redLayer.clear();
SurfaceComposerClient::Transaction().apply(true);
sp<GraphicBuffer> outBuffer;
diff --git a/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h b/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h
index 2245ee1..8bed766 100644
--- a/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h
+++ b/services/surfaceflinger/tests/unittests/AsyncCallRecorder.h
@@ -75,14 +75,16 @@
template <typename... Args>
class AsyncCallRecorder<void (*)(Args...)> {
public:
- // For the tests, we expect the wait for an expected change to be signaled
- // to be much shorter than this.
- static constexpr std::chrono::milliseconds DEFAULT_CALL_EXPECTED_TIMEOUT{10};
+ // This wait value needs to be large enough to avoid flakes caused by delays
+ // scheduling threads, but small enough that tests don't take forever if
+ // something really is wrong. Based on some empirical evidence, 100ms should
+ // be enough to avoid the former.
+ static constexpr std::chrono::milliseconds DEFAULT_CALL_EXPECTED_TIMEOUT{100};
- // The wait here is tricky. We don't expect a change, but we don't want to
- // wait forever (or for longer than the typical test function runtime). As
- // even the simplest Google Test can take 1ms (1000us) to run, we wait for
- // half that time.
+ // The wait here is tricky. It's for when We don't expect to record a call,
+ // but we don't want to wait forever (or for longer than the typical test
+ // function runtime). As even the simplest Google Test can take 1ms (1000us)
+ // to run, we wait for half that time.
static constexpr std::chrono::microseconds UNEXPECTED_CALL_TIMEOUT{500};
using ArgTuple = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index e092aed..ee79c18 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -45,8 +45,10 @@
using testing::_;
using testing::AtLeast;
+using testing::Between;
using testing::ByMove;
using testing::DoAll;
+using testing::Field;
using testing::Invoke;
using testing::IsNull;
using testing::Mock;
@@ -159,7 +161,6 @@
renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine();
mock::MessageQueue* mMessageQueue = new mock::MessageQueue();
mock::DispSync* mPrimaryDispSync = new mock::DispSync();
- renderengine::mock::Image* mReImage = new renderengine::mock::Image();
renderengine::mock::Framebuffer* mReFrameBuffer = new renderengine::mock::Framebuffer();
sp<Fence> mClientTargetAcquireFence = Fence::NO_FENCE;
@@ -279,11 +280,10 @@
EXPECT_CALL(*test->mComposer, getReleaseFences(HWC_DISPLAY, _, _)).Times(1);
EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true));
- EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return());
- EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
-
+ // TODO: remove once we verify that we can just grab the fence from the
+ // FramebufferSurface.
EXPECT_CALL(*test->mRenderEngine, flush()).WillRepeatedly(Invoke([]() {
- return base::unique_fd(0);
+ return base::unique_fd();
}));
EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1);
@@ -295,36 +295,18 @@
template <typename Case>
static void setupCommonScreensCaptureCallExpectations(CompositionTest* test) {
- // Called once with a non-null value to set a framebuffer, and then
- // again with nullptr to clear it.
- EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull(), false))
- .WillOnce(Return(true));
- EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull(), false))
- .WillOnce(Return(true));
-
- EXPECT_CALL(*test->mRenderEngine, checkErrors()).WillRepeatedly(Return());
- EXPECT_CALL(*test->mRenderEngine, createFramebuffer())
- .WillOnce(Return(
- ByMove(std::unique_ptr<renderengine::Framebuffer>(test->mReFrameBuffer))));
- EXPECT_CALL(*test->mRenderEngine, bindFrameBuffer(test->mReFrameBuffer)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, unbindFrameBuffer(test->mReFrameBuffer)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, clearWithColor(0, 0, 0, 1)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, flush()).WillOnce(Return(ByMove(base::unique_fd())));
- EXPECT_CALL(*test->mRenderEngine, finish()).WillOnce(Return(true));
-
- EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(_)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE))
- .Times(1);
- // This expectation retires on saturation as setViewportAndProjection is
- // called an extra time for the code path this setup is for.
- // TODO: Investigate this extra call
- EXPECT_CALL(*test->mRenderEngine,
- setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
- Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
- ui::Transform::ROT_0))
- .Times(1)
- .RetiresOnSaturation();
- EXPECT_CALL(*test->mRenderEngine, disableTexturing()).Times(1);
+ EXPECT_CALL(*test->mRenderEngine, drawLayers)
+ .WillRepeatedly(
+ [](const renderengine::DisplaySettings& displaySettings,
+ const std::vector<renderengine::LayerSettings>& /*layerSettings*/,
+ ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.physicalDisplay);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.clip);
+ return NO_ERROR;
+ });
}
static void setupNonEmptyFrameCompositionCallExpectations(CompositionTest* test) {
@@ -348,31 +330,23 @@
EXPECT_CALL(*test->mDisplaySurface, getClientTargetAcquireFence())
.WillRepeatedly(ReturnRef(test->mClientTargetAcquireFence));
- EXPECT_CALL(*test->mRenderEngine, setOutputDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setDisplayMaxLuminance(DEFAULT_DISPLAY_MAX_LUMINANCE))
- .Times(1);
- EXPECT_CALL(*test->mRenderEngine, setColorTransform(_)).Times(2);
- // These expectations retire on saturation as the code path these
- // expectations are for appears to make an extra call to them.
- // TODO: Investigate this extra call
- EXPECT_CALL(*test->mRenderEngine,
- setViewportAndProjection(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT,
- Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
- ui::Transform::ROT_0))
- .Times(1);
- EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(NotNull(), false))
- .WillOnce(Return(true));
- EXPECT_CALL(*test->mReFrameBuffer, setNativeWindowBuffer(IsNull(), false))
- .WillOnce(Return(true));
- EXPECT_CALL(*test->mRenderEngine, createFramebuffer())
- .WillOnce(Return(
- ByMove(std::unique_ptr<renderengine::Framebuffer>(test->mReFrameBuffer))));
- EXPECT_CALL(*test->mRenderEngine, bindFrameBuffer(test->mReFrameBuffer)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, unbindFrameBuffer(test->mReFrameBuffer)).Times(1);
EXPECT_CALL(*test->mNativeWindow, queueBuffer(_, _)).WillOnce(Return(0));
EXPECT_CALL(*test->mNativeWindow, dequeueBuffer(_, _))
.WillOnce(DoAll(SetArgPointee<0>(test->mNativeWindowBuffer), SetArgPointee<1>(-1),
Return(0)));
+ EXPECT_CALL(*test->mRenderEngine, drawLayers)
+ .WillRepeatedly(
+ [](const renderengine::DisplaySettings& displaySettings,
+ const std::vector<renderengine::LayerSettings>& /*layerSettings*/,
+ ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.physicalDisplay);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.clip);
+ EXPECT_EQ(ui::Dataspace::UNKNOWN, displaySettings.outputDataspace);
+ return NO_ERROR;
+ });
}
template <typename Case>
@@ -383,8 +357,6 @@
template <typename Case>
static void setupRELayerScreenshotCompositionCallExpectations(CompositionTest* test) {
Case::Layer::setupREScreenshotCompositionCallExpectations(test);
-
- EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
}
};
@@ -396,16 +368,11 @@
template <typename Case>
static void setupRELayerCompositionCallExpectations(CompositionTest* test) {
Case::Layer::setupInsecureRECompositionCallExpectations(test);
-
- // TODO: Investigate this extra call
- EXPECT_CALL(*test->mRenderEngine, disableScissor()).Times(1);
}
template <typename Case>
static void setupRELayerScreenshotCompositionCallExpectations(CompositionTest* test) {
Case::Layer::setupInsecureREScreenshotCompositionCallExpectations(test);
-
- EXPECT_CALL(*test->mRenderEngine, isCurrent()).WillRepeatedly(Return(true));
}
};
@@ -516,7 +483,6 @@
bool ignoredRecomputeVisibleRegions;
layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, Fence::NO_FENCE);
Mock::VerifyAndClear(test->mRenderEngine);
- Mock::VerifyAndClear(test->mReImage);
}
static void setupLayerState(CompositionTest* test, sp<BufferQueueLayer> layer) {
@@ -598,33 +564,35 @@
}
static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mRenderEngine,
- setupLayerBlending(true, false, false,
- half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
- LayerProperties::COLOR[2], LayerProperties::COLOR[3]),
- 0.0f))
- .Times(1);
-
- EXPECT_CALL(*test->mRenderEngine, createImage())
- .WillOnce(Return(ByMove(std::unique_ptr<renderengine::Image>(test->mReImage))));
- EXPECT_CALL(*test->mReImage, setNativeWindowBuffer(_, _)).WillOnce(Return(true));
- EXPECT_CALL(*test->mRenderEngine, bindExternalTextureImage(DEFAULT_TEXTURE_ID, _)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setupLayerTexturing(_)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setSourceDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, drawMesh(_)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, disableBlending()).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setSourceY410BT2020(false)).Times(1);
- // This call retires on saturation as the code that renders a texture disables the state,
- // along with a top-level disable to ensure it is disabled for non-buffer layers.
- EXPECT_CALL(*test->mRenderEngine, disableTexturing()).Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*test->mRenderEngine, drawLayers)
+ .WillOnce([](const renderengine::DisplaySettings& displaySettings,
+ const std::vector<renderengine::LayerSettings>& layerSettings,
+ ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.physicalDisplay);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.clip);
+ // screen capture adds an additional color layer as an alpha
+ // prefill, so gtet the back layer.
+ renderengine::LayerSettings layer = layerSettings.back();
+ EXPECT_THAT(layer.source.buffer.buffer, Not(IsNull()));
+ EXPECT_THAT(layer.source.buffer.fence, Not(IsNull()));
+ EXPECT_EQ(renderengine::Buffer::CachingHint::NO_CACHE,
+ layer.source.buffer.cacheHint);
+ EXPECT_EQ(DEFAULT_TEXTURE_ID, layer.source.buffer.textureName);
+ EXPECT_EQ(false, layer.source.buffer.isY410BT2020);
+ EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha);
+ EXPECT_EQ(false, layer.source.buffer.isOpaque);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius);
+ EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
+ EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha);
+ return NO_ERROR;
+ });
}
static void setupREBufferCompositionCallExpectations(CompositionTest* test) {
LayerProperties::setupREBufferCompositionCommonCallExpectations(test);
-
- // TODO - Investigate and eliminate these differences between display
- // composition and screenshot composition.
- EXPECT_CALL(*test->mRenderEngine, disableScissor()).Times(1);
}
static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
@@ -639,20 +607,28 @@
LayerProperties::setupREBufferCompositionCommonCallExpectations(test);
}
- static void setupREColorCompositionCommonCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mRenderEngine, disableScissor()).Times(1);
- }
-
static void setupREColorCompositionCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mRenderEngine, setSourceDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
- EXPECT_CALL(*test->mRenderEngine,
- setupLayerBlending(true, false, true,
- half4(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
- LayerProperties::COLOR[2], LayerProperties::COLOR[3]),
- 0.0f))
- .Times(1);
- EXPECT_CALL(*test->mRenderEngine, drawMesh(_)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, disableBlending()).Times(1);
+ EXPECT_CALL(*test->mRenderEngine, drawLayers)
+ .WillOnce([](const renderengine::DisplaySettings& displaySettings,
+ const std::vector<renderengine::LayerSettings>& layerSettings,
+ ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.physicalDisplay);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.clip);
+ // screen capture adds an additional color layer as an alpha
+ // prefill, so get the back layer.
+ renderengine::LayerSettings layer = layerSettings.back();
+ EXPECT_THAT(layer.source.buffer.buffer, IsNull());
+ EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
+ LayerProperties::COLOR[2]),
+ layer.source.solidColor);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius);
+ EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
+ EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha);
+ return NO_ERROR;
+ });
}
static void setupREColorScreenshotCompositionCallExpectations(CompositionTest* test) {
@@ -692,10 +668,7 @@
EXPECT_CALL(*test->mComposer, setLayerSurfaceDamage(HWC_DISPLAY, HWC_LAYER, _)).Times(1);
}
- static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mRenderEngine, setupFillWithColor(0, 0, 0, 1)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, drawMesh(_)).Times(1);
- }
+ static void setupREBufferCompositionCommonCallExpectations(CompositionTest* /*test*/) {}
};
struct SecureLayerProperties : public BaseLayerProperties<SecureLayerProperties> {
@@ -704,25 +677,25 @@
static constexpr uint32_t LAYER_FLAGS = ISurfaceComposerClient::eSecure;
static void setupInsecureREBufferCompositionCommonCallExpectations(CompositionTest* test) {
- EXPECT_CALL(*test->mRenderEngine, createImage())
- .WillOnce(Return(ByMove(std::unique_ptr<renderengine::Image>(test->mReImage))));
- EXPECT_CALL(*test->mReImage, setNativeWindowBuffer(_, _)).WillOnce(Return(true));
- EXPECT_CALL(*test->mRenderEngine, bindExternalTextureImage(DEFAULT_TEXTURE_ID, _)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setupLayerBlackedOut()).Times(1);
-
- EXPECT_CALL(*test->mRenderEngine,
- setupLayerBlending(true, false, false,
- half4(Base::COLOR[0], Base::COLOR[1], Base::COLOR[2],
- Base::COLOR[3]),
- 0.0f))
- .Times(1);
- EXPECT_CALL(*test->mRenderEngine, setSourceDataSpace(ui::Dataspace::UNKNOWN)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, drawMesh(_)).Times(1);
- EXPECT_CALL(*test->mRenderEngine, disableBlending()).Times(1);
- EXPECT_CALL(*test->mRenderEngine, setSourceY410BT2020(false)).Times(1);
- // This call retires on saturation as the code that renders a texture disables the state,
- // along with a top-level disable to ensure it is disabled for non-buffer layers.
- EXPECT_CALL(*test->mRenderEngine, disableTexturing()).Times(1).RetiresOnSaturation();
+ EXPECT_CALL(*test->mRenderEngine, drawLayers)
+ .WillOnce([](const renderengine::DisplaySettings& displaySettings,
+ const std::vector<renderengine::LayerSettings>& layerSettings,
+ ANativeWindowBuffer*, base::unique_fd*) -> status_t {
+ EXPECT_EQ(DEFAULT_DISPLAY_MAX_LUMINANCE, displaySettings.maxLuminance);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.physicalDisplay);
+ EXPECT_EQ(Rect(DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT),
+ displaySettings.clip);
+ // screen capture adds an additional color layer as an alpha
+ // prefill, so get the back layer.
+ renderengine::LayerSettings layer = layerSettings.back();
+ EXPECT_THAT(layer.source.buffer.buffer, IsNull());
+ EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius);
+ EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
+ EXPECT_EQ(1.0f, layer.alpha);
+ return NO_ERROR;
+ });
}
static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
@@ -826,7 +799,6 @@
}
static void setupRECompositionCallExpectations(CompositionTest* test) {
- LayerProperties::setupREColorCompositionCommonCallExpectations(test);
LayerProperties::setupREColorCompositionCallExpectations(test);
}
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index ad7dcb4..3a7cfba 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -53,8 +53,10 @@
class MockEventThreadConnection : public EventThreadConnection {
public:
MockEventThreadConnection(android::impl::EventThread* eventThread,
- ResyncCallback&& resyncCallback)
- : EventThreadConnection(eventThread, std::move(resyncCallback)) {}
+ ResyncCallback&& resyncCallback,
+ ResetIdleTimerCallback&& resetIdleTimerCallback)
+ : EventThreadConnection(eventThread, std::move(resyncCallback),
+ std::move(resetIdleTimerCallback)) {}
MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
};
@@ -82,6 +84,7 @@
AsyncCallRecorder<void (*)(VSyncSource::Callback*)> mVSyncSetCallbackCallRecorder;
AsyncCallRecorder<void (*)(nsecs_t)> mVSyncSetPhaseOffsetCallRecorder;
AsyncCallRecorder<void (*)()> mResyncCallRecorder;
+ AsyncCallRecorder<void (*)()> mResetIdleTimerCallRecorder;
AsyncCallRecorder<void (*)(nsecs_t)> mInterceptVSyncCallRecorder;
ConnectionEventRecorder mConnectionEventCallRecorder{0};
@@ -119,7 +122,7 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
// EventThread should unregister itself as VSyncSource callback.
- EXPECT_FALSE(expectVSyncSetCallbackCallReceived());
+ EXPECT_TRUE(!mVSyncSetCallbackCallRecorder.waitForUnexpectedCall().has_value());
}
void EventThreadTest::createThread() {
@@ -136,7 +139,8 @@
sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
ConnectionEventRecorder& recorder) {
sp<MockEventThreadConnection> connection =
- new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable());
+ new MockEventThreadConnection(mThread.get(), mResyncCallRecorder.getInvocable(),
+ mResetIdleTimerCallRecorder.getInvocable());
EXPECT_CALL(*connection, postEvent(_)).WillRepeatedly(Invoke(recorder.getInvocable()));
return connection;
}
@@ -207,6 +211,7 @@
EXPECT_FALSE(mVSyncSetCallbackCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mVSyncSetPhaseOffsetCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mResyncCallRecorder.waitForCall(0us).has_value());
+ EXPECT_FALSE(mResetIdleTimerCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mInterceptVSyncCallRecorder.waitForCall(0us).has_value());
EXPECT_FALSE(mConnectionEventCallRecorder.waitForCall(0us).has_value());
}
@@ -224,9 +229,10 @@
TEST_F(EventThreadTest, requestNextVsyncPostsASingleVSyncEventToTheConnection) {
// Signal that we want the next vsync event to be posted to the connection
- mThread->requestNextVsync(mConnection, false);
+ mThread->requestNextVsync(mConnection, true);
- // EventThread should immediately request a resync.
+ // EventThread should immediately reset the idle timer and request a resync.
+ EXPECT_TRUE(mResetIdleTimerCallRecorder.waitForCall().has_value());
EXPECT_TRUE(mResyncCallRecorder.waitForCall().has_value());
// EventThread should enable vsync callbacks.
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 0db96d9..26b6d0c 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -25,7 +25,7 @@
class MockEventThreadConnection : public android::EventThreadConnection {
public:
explicit MockEventThreadConnection(EventThread* eventThread)
- : EventThreadConnection(eventThread, ResyncCallback()) {}
+ : EventThreadConnection(eventThread, ResyncCallback(), ResetIdleTimerCallback()) {}
~MockEventThreadConnection() = default;
MOCK_METHOD1(stealReceiveChannel, status_t(gui::BitTube* outChannel));
@@ -78,10 +78,11 @@
// createConnection call to scheduler makes a createEventConnection call to EventThread. Make
// sure that call gets executed and returns an EventThread::Connection object.
- EXPECT_CALL(*mEventThread, createEventConnection(_))
+ EXPECT_CALL(*mEventThread, createEventConnection(_, _))
.WillRepeatedly(Return(mEventThreadConnection));
mConnectionHandle = mScheduler->createConnection("appConnection", 16, ResyncCallback(),
+ ResetIdleTimerCallback(),
impl::EventThread::InterceptVSyncsCallback());
EXPECT_TRUE(mConnectionHandle != nullptr);
}
@@ -102,7 +103,8 @@
// exceptions, just gracefully continues.
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
- returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback()));
+ returnedValue = mScheduler->createDisplayEventConnection(nullptr, ResyncCallback(),
+ ResetIdleTimerCallback()));
EXPECT_TRUE(returnedValue == nullptr);
EXPECT_TRUE(mScheduler->getEventThread(nullptr) == nullptr);
EXPECT_TRUE(mScheduler->getEventConnection(nullptr) == nullptr);
@@ -123,7 +125,8 @@
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback()));
+ mScheduler->createDisplayEventConnection(connectionHandle, ResyncCallback(),
+ ResetIdleTimerCallback()));
EXPECT_TRUE(returnedValue == nullptr);
EXPECT_TRUE(mScheduler->getEventThread(connectionHandle) == nullptr);
EXPECT_TRUE(mScheduler->getEventConnection(connectionHandle) == nullptr);
@@ -152,7 +155,8 @@
sp<IDisplayEventConnection> returnedValue;
ASSERT_NO_FATAL_FAILURE(
returnedValue =
- mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback()));
+ mScheduler->createDisplayEventConnection(mConnectionHandle, ResyncCallback(),
+ ResetIdleTimerCallback()));
EXPECT_TRUE(returnedValue != nullptr);
ASSERT_EQ(returnedValue, mEventThreadConnection);
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index aaf67e9..589237d 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,7 +28,8 @@
EventThread();
~EventThread() override;
- MOCK_CONST_METHOD1(createEventConnection, sp<EventThreadConnection>(ResyncCallback));
+ MOCK_CONST_METHOD2(createEventConnection,
+ sp<EventThreadConnection>(ResyncCallback, ResetIdleTimerCallback));
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
diff --git a/services/vr/bufferhubd/producer_channel.cpp b/services/vr/bufferhubd/producer_channel.cpp
index 164d9e6..f3e54a0 100644
--- a/services/vr/bufferhubd/producer_channel.cpp
+++ b/services/vr/bufferhubd/producer_channel.cpp
@@ -253,7 +253,7 @@
uint32_t current_active_clients_bit_mask =
active_clients_bit_mask_->load(std::memory_order_acquire);
uint32_t consumer_state_mask =
- BufferHubDefs::FindNextAvailableClientStateMask(
+ BufferHubDefs::findNextAvailableClientStateMask(
current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
if (consumer_state_mask == 0U) {
ALOGE("%s: reached the maximum mumber of consumers per producer: 63.",
@@ -279,7 +279,7 @@
"condition.",
__FUNCTION__, updated_active_clients_bit_mask,
current_active_clients_bit_mask);
- consumer_state_mask = BufferHubDefs::FindNextAvailableClientStateMask(
+ consumer_state_mask = BufferHubDefs::findNextAvailableClientStateMask(
current_active_clients_bit_mask | orphaned_consumer_bit_mask_);
if (consumer_state_mask == 0U) {
ALOGE("%s: reached the maximum mumber of consumers per producer: %d.",
@@ -337,13 +337,13 @@
// consumer to a buffer that is available to producer (a.k.a a fully-released
// buffer) or a gained buffer.
if (current_buffer_state == 0U ||
- BufferHubDefs::AnyClientGained(current_buffer_state)) {
+ BufferHubDefs::isAnyClientGained(current_buffer_state)) {
return {status.take()};
}
// Signal the new consumer when adding it to a posted producer.
bool update_buffer_state = true;
- if (!BufferHubDefs::IsClientPosted(current_buffer_state,
+ if (!BufferHubDefs::isClientPosted(current_buffer_state,
consumer_state_mask)) {
uint32_t updated_buffer_state =
current_buffer_state ^
@@ -360,7 +360,7 @@
"released.",
__FUNCTION__, current_buffer_state, updated_buffer_state);
if (current_buffer_state == 0U ||
- BufferHubDefs::AnyClientGained(current_buffer_state)) {
+ BufferHubDefs::isAnyClientGained(current_buffer_state)) {
ALOGI("%s: buffer is gained or fully released, state=%" PRIx32 ".",
__FUNCTION__, current_buffer_state);
update_buffer_state = false;
@@ -371,7 +371,7 @@
(consumer_state_mask & BufferHubDefs::kHighBitsMask);
}
}
- if (update_buffer_state || BufferHubDefs::IsClientPosted(
+ if (update_buffer_state || BufferHubDefs::isClientPosted(
buffer_state_->load(std::memory_order_acquire),
consumer_state_mask)) {
consumer->OnProducerPosted();
@@ -457,7 +457,7 @@
buffer_id());
uint32_t buffer_state = buffer_state_->load(std::memory_order_acquire);
- if (!BufferHubDefs::IsClientGained(
+ if (!BufferHubDefs::isClientGained(
buffer_state, BufferHubDefs::kFirstClientStateMask)) {
// Can only detach a ProducerBuffer when it's in gained state.
ALOGW(
@@ -616,9 +616,9 @@
const uint32_t current_buffer_state =
buffer_state_->load(std::memory_order_acquire);
- if (BufferHubDefs::IsClientPosted(current_buffer_state,
+ if (BufferHubDefs::isClientPosted(current_buffer_state,
consumer_state_mask) ||
- BufferHubDefs::IsClientAcquired(current_buffer_state,
+ BufferHubDefs::isClientAcquired(current_buffer_state,
consumer_state_mask)) {
// The consumer client is being destoryed without releasing. This could
// happen in corner cases when the consumer crashes. Here we mark it
@@ -627,9 +627,9 @@
return;
}
- if (BufferHubDefs::IsClientReleased(current_buffer_state,
+ if (BufferHubDefs::isClientReleased(current_buffer_state,
consumer_state_mask) ||
- BufferHubDefs::AnyClientGained(current_buffer_state)) {
+ BufferHubDefs::isAnyClientGained(current_buffer_state)) {
// The consumer is being close while it is suppose to signal a release
// fence. Signal the dummy fence here.
if (fence_state_->load(std::memory_order_acquire) & consumer_state_mask) {
diff --git a/services/vr/bufferhubd/producer_queue_channel.cpp b/services/vr/bufferhubd/producer_queue_channel.cpp
index 6b33f50..004dc7c 100644
--- a/services/vr/bufferhubd/producer_queue_channel.cpp
+++ b/services/vr/bufferhubd/producer_queue_channel.cpp
@@ -323,7 +323,7 @@
// memory to indicate which client is the last producer of the buffer.
// Currently, the first client is the only producer to the buffer.
// Thus, it checks whether the first client gains the buffer below.
- if (!BufferHubDefs::IsClientGained(buffer_state,
+ if (!BufferHubDefs::isClientGained(buffer_state,
BufferHubDefs::kFirstClientBitMask)) {
// Rejects the request if the requested buffer is not in Gained state.
ALOGE(