Merge "Remove error when trying to get a global buffer that doesn't exist"
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 22de64e..af78bfb 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1242,13 +1242,7 @@
ALOGE("installd cannot compute input vdex location for '%s'\n", path);
return false;
}
- if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE) {
- // When we dex2oat because of boot image change, we are going to update
- // in-place the vdex file.
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
- } else {
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
- }
+ in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
}
// Infer the name of the output VDEX and create it.
@@ -1257,27 +1251,12 @@
return false;
}
- // If we are compiling because the boot image is out of date, we do not
- // need to recreate a vdex, and can use the same existing one.
- if (dexopt_action == DEX2OAT_FOR_BOOT_IMAGE &&
- in_vdex_wrapper_fd->get() != -1 &&
- in_vdex_path_str == out_vdex_path_str) {
- // We unlink the file in case the invocation of dex2oat fails, to ensure we don't
- // have bogus stale vdex files.
- out_vdex_wrapper_fd->reset(
- in_vdex_wrapper_fd->get(),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
- // Disable auto close for the in wrapper fd (it will be done when destructing the out
- // wrapper).
- in_vdex_wrapper_fd->DisableAutoClose();
- } else {
- out_vdex_wrapper_fd->reset(
- open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
- if (out_vdex_wrapper_fd->get() < 0) {
- ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
- return false;
- }
+ out_vdex_wrapper_fd->reset(
+ open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
+ [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+ if (out_vdex_wrapper_fd->get() < 0) {
+ ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
+ return false;
}
if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
out_vdex_path_str.c_str(), is_secondary_dex)) {
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index c836543..0f7e12a 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -160,6 +160,9 @@
status_t getUniqueId(uint64_t* outId) const;
+ // Returns the CLOCK_MONOTONIC start time of the last dequeueBuffer call
+ nsecs_t getLastDequeueStartTime() const;
+
protected:
virtual ~Surface();
@@ -421,6 +424,9 @@
nsecs_t mLastDequeueDuration = 0;
nsecs_t mLastQueueDuration = 0;
+ // Stores the time right before we call IGBP::dequeueBuffer
+ nsecs_t mLastDequeueStartTime = 0;
+
Condition mQueueBufferCondition;
uint64_t mNextFrameNumber = 1;
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index ec310cf..145c059 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -271,6 +271,7 @@
uint32_t getStride() const;
// size of allocated memory in bytes
size_t getSize() const;
+ android_dataspace getDataSpace() const;
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index d471dbf..409a3cb 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -503,13 +503,13 @@
int buf = -1;
sp<Fence> fence;
- nsecs_t now = systemTime();
+ nsecs_t startTime = systemTime();
FrameEventHistoryDelta frameTimestamps;
status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
reqWidth, reqHeight, reqFormat, reqUsage,
enableFrameTimestamps ? &frameTimestamps : nullptr);
- mLastDequeueDuration = systemTime() - now;
+ mLastDequeueDuration = systemTime() - startTime;
if (result < 0) {
ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
@@ -526,6 +526,9 @@
Mutex::Autolock lock(mMutex);
+ // Write this while holding the mutex
+ mLastDequeueStartTime = startTime;
+
sp<GraphicBuffer>& gbuf(mSlots[buf].buffer);
// this should never happen
@@ -1711,6 +1714,11 @@
return mGraphicBufferProducer->getUniqueId(outId);
}
+nsecs_t Surface::getLastDequeueStartTime() const {
+ Mutex::Autolock lock(mMutex);
+ return mLastDequeueStartTime;
+}
+
status_t Surface::getAndFlushRemovedBuffers(std::vector<sp<GraphicBuffer>>* out) {
if (out == nullptr) {
ALOGE("%s: out must not be null!", __FUNCTION__);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 8c83843..7ae2672 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1080,5 +1080,9 @@
return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
}
+android_dataspace ScreenshotClient::getDataSpace() const {
+ return mBuffer.dataSpace;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index fcaa23a..81820de 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -393,6 +393,22 @@
ASSERT_LE(removedBuffers.size(), 1u);
}
+TEST_F(SurfaceTest, TestGetLastDequeueStartTime) {
+ sp<ANativeWindow> anw(mSurface);
+ ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU));
+
+ ANativeWindowBuffer* buffer = nullptr;
+ int32_t fenceFd = -1;
+
+ nsecs_t before = systemTime(CLOCK_MONOTONIC);
+ anw->dequeueBuffer(anw.get(), &buffer, &fenceFd);
+ nsecs_t after = systemTime(CLOCK_MONOTONIC);
+
+ nsecs_t lastDequeueTime = mSurface->getLastDequeueStartTime();
+ ASSERT_LE(before, lastDequeueTime);
+ ASSERT_GE(after, lastDequeueTime);
+}
+
class FakeConsumer : public BnConsumerListener {
public:
void onFrameAvailable(const BufferItem& /*item*/) override {}
@@ -1568,4 +1584,4 @@
EXPECT_EQ(-1, outDisplayPresentTime);
}
-}
+} // namespace android
diff --git a/libs/math/include/math/TMatHelpers.h b/libs/math/include/math/TMatHelpers.h
index 5cb725d..1423ade 100644
--- a/libs/math/include/math/TMatHelpers.h
+++ b/libs/math/include/math/TMatHelpers.h
@@ -342,9 +342,9 @@
template <typename MATRIX>
String8 asString(const MATRIX& m) {
String8 s;
- for (size_t c = 0; c < MATRIX::col_size(); c++) {
+ for (size_t c = 0; c < MATRIX::COL_SIZE; c++) {
s.append("| ");
- for (size_t r = 0; r < MATRIX::row_size(); r++) {
+ for (size_t r = 0; r < MATRIX::ROW_SIZE; r++) {
s.appendFormat("%7.2f ", m[r][c]);
}
s.append("|\n");
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 0dab872..effd319 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -26,8 +26,7 @@
namespace android {
-Description::Description() :
- mUniformsDirty(true) {
+Description::Description() {
mPlaneAlpha = 1.0f;
mPremultipliedAlpha = false;
mOpaque = true;
@@ -41,28 +40,20 @@
}
void Description::setPlaneAlpha(GLclampf planeAlpha) {
- if (planeAlpha != mPlaneAlpha) {
- mUniformsDirty = true;
- mPlaneAlpha = planeAlpha;
- }
+ mPlaneAlpha = planeAlpha;
}
void Description::setPremultipliedAlpha(bool premultipliedAlpha) {
- if (premultipliedAlpha != mPremultipliedAlpha) {
- mPremultipliedAlpha = premultipliedAlpha;
- }
+ mPremultipliedAlpha = premultipliedAlpha;
}
void Description::setOpaque(bool opaque) {
- if (opaque != mOpaque) {
- mOpaque = opaque;
- }
+ mOpaque = opaque;
}
void Description::setTexture(const Texture& texture) {
mTexture = texture;
mTextureEnabled = true;
- mUniformsDirty = true;
}
void Description::disableTexture() {
@@ -74,12 +65,10 @@
mColor[1] = green;
mColor[2] = blue;
mColor[3] = alpha;
- mUniformsDirty = true;
}
void Description::setProjectionMatrix(const mat4& mtx) {
mProjectionMatrix = mtx;
- mUniformsDirty = true;
}
void Description::setColorMatrix(const mat4& mtx) {
@@ -92,5 +81,8 @@
return mColorMatrix;
}
+void Description::setWideGamut(bool wideGamut) {
+ mIsWideGamut = wideGamut;
+}
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 8a3447c..3beffdf 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -54,6 +54,8 @@
bool mColorMatrixEnabled;
mat4 mColorMatrix;
+ bool mIsWideGamut;
+
public:
Description();
~Description();
@@ -67,9 +69,7 @@
void setProjectionMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
const mat4& getColorMatrix() const;
-
-private:
- bool mUniformsDirty;
+ void setWideGamut(bool wideGamut);
};
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index a1ee294..37a530b 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -139,11 +139,10 @@
// Display-P3 only.
mat3 srgbToP3 = ColorSpaceConnector(ColorSpace::sRGB(), ColorSpace::DisplayP3()).getTransform();
- // color transform needs to be transposed and expanded to 4x4
- // to be what the shader wants
+ // color transform needs to be expanded to 4x4 to be what the shader wants
// mat has an initializer that expands mat3 to mat4, but
// not an assignment operator
- mat4 gamutTransform(transpose(srgbToP3));
+ mat4 gamutTransform(srgbToP3);
mSrgbToDisplayP3 = gamutTransform;
}
#endif
@@ -386,6 +385,7 @@
Description wideColorState = mState;
if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+ wideColorState.setWideGamut(true);
ALOGV("drawMesh: gamut transform applied");
}
ProgramCache::getInstance().useProgram(wideColorState);
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index ba11259..06b2252 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -129,7 +129,9 @@
.set(Key::OPACITY_MASK,
description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
.set(Key::COLOR_MATRIX_MASK,
- description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF);
+ description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
+ .set(Key::WIDE_GAMUT_MASK,
+ description.mIsWideGamut ? Key::WIDE_GAMUT_ON : Key::WIDE_GAMUT_OFF);
return needs;
}
@@ -175,6 +177,50 @@
if (needs.hasColorMatrix()) {
fs << "uniform mat4 colorMatrix;";
}
+ if (needs.hasColorMatrix()) {
+ // When in wide gamut mode, the color matrix will contain a color space
+ // conversion matrix that needs to be applied in linear space
+ // When not in wide gamut, we can simply no-op the transfer functions
+ // and let the shader compiler get rid of them
+ if (needs.isWideGamut()) {
+ fs << R"__SHADER__(
+ float OETF_sRGB(const float linear) {
+ return linear <= 0.0031308 ?
+ linear * 12.92 : (pow(linear, 1.0 / 2.4) * 1.055) - 0.055;
+ }
+
+ vec3 OETF_sRGB(const vec3 linear) {
+ return vec3(OETF_sRGB(linear.r), OETF_sRGB(linear.g), OETF_sRGB(linear.b));
+ }
+
+ vec3 OETF_scRGB(const vec3 linear) {
+ return sign(linear.rgb) * OETF_sRGB(abs(linear.rgb));
+ }
+
+ float EOTF_sRGB(float srgb) {
+ return srgb <= 0.04045 ? srgb / 12.92 : pow((srgb + 0.055) / 1.055, 2.4);
+ }
+
+ vec3 EOTF_sRGB(const vec3 srgb) {
+ return vec3(EOTF_sRGB(srgb.r), EOTF_sRGB(srgb.g), EOTF_sRGB(srgb.b));
+ }
+
+ vec3 EOTF_scRGB(const vec3 srgb) {
+ return sign(srgb.rgb) * EOTF_sRGB(abs(srgb.rgb));
+ }
+ )__SHADER__";
+ } else {
+ fs << R"__SHADER__(
+ vec3 OETF_scRGB(const vec3 linear) {
+ return linear;
+ }
+
+ vec3 EOTF_scRGB(const vec3 srgb) {
+ return srgb;
+ }
+ )__SHADER__";
+ }
+ }
fs << "void main(void) {" << indent;
if (needs.isTexturing()) {
fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
@@ -197,13 +243,15 @@
if (needs.hasColorMatrix()) {
if (!needs.isOpaque() && needs.isPremultiplied()) {
// un-premultiply if needed before linearization
- fs << "gl_FragColor.rgb = gl_FragColor.rgb/gl_FragColor.a;";
+ // avoid divide by 0 by adding 0.5/256 to the alpha channel
+ fs << "gl_FragColor.rgb = gl_FragColor.rgb / (gl_FragColor.a + 0.0019);";
}
- fs << "vec4 transformed = colorMatrix * vec4(gl_FragColor.rgb, 1);";
- fs << "gl_FragColor.rgb = transformed.rgb/transformed.a;";
+ fs << "vec4 transformed = colorMatrix * vec4(EOTF_scRGB(gl_FragColor.rgb), 1);";
+ // We assume the last row is always {0,0,0,1} and we skip the division by w
+ fs << "gl_FragColor.rgb = OETF_scRGB(transformed.rgb);";
if (!needs.isOpaque() && needs.isPremultiplied()) {
// and re-premultiply if needed after gamma correction
- fs << "gl_FragColor.rgb = gl_FragColor.rgb*gl_FragColor.a;";
+ fs << "gl_FragColor.rgb = gl_FragColor.rgb * (gl_FragColor.a + 0.0019);";
}
}
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 1fa53d3..5b0fbcd 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -69,6 +69,10 @@
COLOR_MATRIX_OFF = 0x00000000,
COLOR_MATRIX_ON = 0x00000020,
COLOR_MATRIX_MASK = 0x00000020,
+
+ WIDE_GAMUT_OFF = 0x00000000,
+ WIDE_GAMUT_ON = 0x00000040,
+ WIDE_GAMUT_MASK = 0x00000040,
};
inline Key() : mKey(0) { }
@@ -97,10 +101,13 @@
inline bool hasColorMatrix() const {
return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
}
+ inline bool isWideGamut() const {
+ return (mKey & WIDE_GAMUT_MASK) == WIDE_GAMUT_ON;
+ }
// this is the definition of a friend function -- not a method of class Needs
friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
- return (lhs.mKey < rhs.mKey) ? 1 : 0;
+ return (lhs.mKey < rhs.mKey) ? 1 : 0;
}
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7392006..beefc50 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1705,6 +1705,13 @@
if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
return HAL_DATASPACE_DISPLAY_P3;
}
+ if (a == HAL_DATASPACE_V0_SCRGB_LINEAR || b == HAL_DATASPACE_V0_SCRGB_LINEAR) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+ if (a == HAL_DATASPACE_V0_SCRGB || b == HAL_DATASPACE_V0_SCRGB) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+
return HAL_DATASPACE_V0_SRGB;
}
@@ -2508,8 +2515,8 @@
ALOGV("hasClientComposition");
#ifdef USE_HWC2
- mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+ mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
#endif
if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
@@ -3893,9 +3900,7 @@
// apply a color matrix
n = data.readInt32();
if (n) {
- // color matrix is sent as mat3 matrix followed by vec3
- // offset, then packed into a mat4 where the last row is
- // the offset and extra values are 0
+ // color matrix is sent as a row-major mat4 matrix
for (size_t i = 0 ; i < 4; i++) {
for (size_t j = 0; j < 4; j++) {
mColorMatrix[i][j] = data.readFloat();
@@ -3904,6 +3909,14 @@
} else {
mColorMatrix = mat4();
}
+
+ // Check that supplied matrix's last row is {0,0,0,1} so we can avoid
+ // the division by w in the fragment shader
+ float4 lastRow(transpose(mColorMatrix)[3]);
+ if (any(greaterThan(abs(lastRow - float4{0, 0, 0, 1}), float4{1e-4f}))) {
+ ALOGE("The color transform's last row must be (0, 0, 0, 1)");
+ }
+
invalidateHwcGeometry();
repaintEverything();
return NO_ERROR;
@@ -4210,6 +4223,11 @@
ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
}
+#ifdef USE_HWC2
+ engine.setWideColor(hw->getWideColorSupport());
+ engine.setColorMode(hw->getActiveColorMode());
+#endif
+
// make sure to clear all GL error flags
engine.checkErrors();
@@ -4313,6 +4331,8 @@
err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
err |= native_window_set_usage(window, usage);
+ err |= native_window_set_buffers_data_space(window, hw->getWideColorSupport()
+ ? HAL_DATASPACE_DISPLAY_P3 : HAL_DATASPACE_V0_SRGB);
if (err == NO_ERROR) {
ANativeWindowBuffer* buffer;