Add wide-color support to SurfaceFlinger
Test: manual testing
Bug: 29940137
Change-Id: I9358b3c982e0205e598fd20cbf8d2e956591b3ac
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 21ba1c3..07d4813 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -67,6 +67,7 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.configstore@1.0",
"libbase",
"libnativeloader",
"libcutils",
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index c3b48ca..976455e 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -80,6 +80,7 @@
uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
+// clang-format off
DisplayDevice::DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
@@ -91,7 +92,8 @@
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- EGLConfig config)
+ EGLConfig config,
+ bool supportWideColor)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
mType(type),
@@ -111,8 +113,10 @@
mLayerStack(NO_LAYER_STACK),
mOrientation(),
mPowerMode(HWC_POWER_MODE_OFF),
- mActiveConfig(0)
+ mActiveConfig(0),
+ mDisplayHasWideColor(supportWideColor)
{
+ // clang-format on
Surface* surface;
mNativeWindow = surface = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index caa7adc..e2852a7 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -83,6 +83,7 @@
NO_LAYER_STACK = 0xFFFFFFFF,
};
+ // clang-format off
DisplayDevice(
const sp<SurfaceFlinger>& flinger,
DisplayType type,
@@ -94,7 +95,9 @@
const wp<IBinder>& displayToken,
const sp<DisplaySurface>& displaySurface,
const sp<IGraphicBufferProducer>& producer,
- EGLConfig config);
+ EGLConfig config,
+ bool supportWideColor);
+ // clang-format on
~DisplayDevice();
@@ -146,6 +149,7 @@
status_t beginFrame(bool mustRecompose) const;
#ifdef USE_HWC2
status_t prepareFrame(HWComposer& hwc);
+ bool getWideColorSupport() const { return mDisplayHasWideColor; }
#else
status_t prepareFrame(const HWComposer& hwc) const;
#endif
@@ -264,6 +268,11 @@
#ifdef USE_HWC2
// current active color mode
android_color_mode_t mActiveColorMode;
+
+ // Need to know if display is wide-color capable or not.
+ // Initialized by SurfaceFlinger when the DisplayDevice is created.
+ // Fed to RenderEngine during composition.
+ bool mDisplayHasWideColor;
#endif
};
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 16d8160..c211c7b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1011,6 +1011,9 @@
return inverse(tr);
}
+/*
+ * onDraw will draw the current layer onto the presentable buffer
+ */
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
bool useIdentityTransform) const
{
@@ -1172,6 +1175,9 @@
RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha());
+#ifdef USE_HWC2
+ engine.setSourceDataSpace(mCurrentState.dataSpace);
+#endif
engine.drawMesh(mMesh);
engine.disableBlending();
}
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 406e611..33ea2bc 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -14,11 +14,16 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include <ui/ColorSpace.h>
+#include <ui/DebugUtils.h>
#include <ui/Rect.h>
#include <utils/String8.h>
@@ -35,6 +40,71 @@
#include "Mesh.h"
#include "Texture.h"
+#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <configstore/Utils.h>
+
+#include <fstream>
+
+static constexpr bool outputDebugPPMs = false;
+
+// ---------------------------------------------------------------------------
+bool checkGlError(const char* op, int lineNumber) {
+ bool errorFound = false;
+ GLint error = glGetError();
+ while (error != GL_NO_ERROR) {
+ errorFound = true;
+ error = glGetError();
+ ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
+ }
+ return errorFound;
+}
+
+void writePPM(const char* basename, GLuint width, GLuint height) {
+ ALOGV("writePPM #%s: %d x %d", basename, width, height);
+
+ std::vector<GLubyte> pixels(width * height * 4);
+ std::vector<GLubyte> outBuffer(width * height * 3);
+
+ // TODO(courtneygo): We can now have float formats, need
+ // to remove this code or update to support.
+ // Make returned pixels fit in uint32_t, one byte per component
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
+ if (checkGlError(__FUNCTION__, __LINE__)) {
+ return;
+ }
+
+ std::string filename(basename);
+ filename.append(".ppm");
+ std::ofstream file(filename.c_str(), std::ios::binary);
+ if (!file.is_open()) {
+ ALOGE("Unable to open file: %s", filename.c_str());
+ ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
+ "surfaceflinger to write debug images");
+ return;
+ }
+
+ file << "P6\n";
+ file << width << "\n";
+ file << height << "\n";
+ file << 255 << "\n";
+
+ auto ptr = reinterpret_cast<char*>(pixels.data());
+ auto outPtr = reinterpret_cast<char*>(outBuffer.data());
+ for (int y = height - 1; y >= 0; y--) {
+ char* data = ptr + y * width * sizeof(uint32_t);
+
+ for (GLuint x = 0; x < width; x++) {
+ // Only copy R, G and B components
+ outPtr[0] = data[0];
+ outPtr[1] = data[1];
+ outPtr[2] = data[2];
+ data += sizeof(uint32_t);
+ outPtr += 3;
+ }
+ }
+ file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
+}
+
// ---------------------------------------------------------------------------
namespace android {
// ---------------------------------------------------------------------------
@@ -59,6 +129,26 @@
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData);
//mColorBlindnessCorrection = M;
+
+ // retrieve wide-color and hdr settings from configstore
+ using namespace android::hardware::configstore;
+ using namespace android::hardware::configstore::V1_0;
+
+ mPlatformHasWideColor =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+ if (mPlatformHasWideColor) {
+ // Compute sRGB to DisplayP3 color transform
+ // NOTE: For now, we are limiting wide-color support to
+ // Display-P3 only.
+ mat3 srgbToP3 = ColorSpace::DisplayP3().getXYZtoRGB() * ColorSpace::sRGB().getRGBtoXYZ();
+
+ // color transform needs to be transposed and 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));
+ mSrgbToDisplayP3 = gamutTransform;
+ }
}
GLES20RenderEngine::~GLES20RenderEngine() {
@@ -170,6 +260,42 @@
}
}
+#ifdef USE_HWC2
+void GLES20RenderEngine::setColorMode(android_color_mode mode) {
+ ALOGV("setColorMode: %s (0x%x)", decodeColorMode(mode).c_str(), mode);
+
+ if (mColorMode == mode) return;
+
+ if (!mPlatformHasWideColor || !mDisplayHasWideColor || mode == HAL_COLOR_MODE_SRGB ||
+ mode == HAL_COLOR_MODE_NATIVE) {
+ // We are returning back to our default color_mode
+ mUseWideColor = false;
+ mWideColorFrameCount = 0;
+ } else {
+ mUseWideColor = true;
+ }
+
+ mColorMode = mode;
+}
+
+void GLES20RenderEngine::setSourceDataSpace(android_dataspace source) {
+ if (source == HAL_DATASPACE_UNKNOWN) {
+ // Treat UNKNOWN as SRGB
+ source = HAL_DATASPACE_V0_SRGB;
+ }
+ mDataSpace = source;
+}
+
+void GLES20RenderEngine::setWideColor(bool hasWideColor) {
+ ALOGV("setWideColor: %s", hasWideColor ? "true" : "false");
+ mDisplayHasWideColor = hasWideColor;
+}
+
+bool GLES20RenderEngine::usesWideColor() {
+ return mUseWideColor;
+}
+#endif
+
void GLES20RenderEngine::setupLayerTexturing(const Texture& texture) {
GLuint target = texture.getTextureTarget();
glBindTexture(target, texture.getTextureName());
@@ -242,8 +368,6 @@
void GLES20RenderEngine::drawMesh(const Mesh& mesh) {
- ProgramCache::getInstance().useProgram(mState);
-
if (mesh.getTexCoordsSize()) {
glEnableVertexAttribArray(Program::texCoords);
glVertexAttribPointer(Program::texCoords,
@@ -259,7 +383,26 @@
mesh.getByteStride(),
mesh.getPositions());
- glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+ if (usesWideColor()) {
+ Description wideColorState = mState;
+ if (mDataSpace != HAL_DATASPACE_DISPLAY_P3) {
+ wideColorState.setColorMatrix(mState.getColorMatrix() * mSrgbToDisplayP3);
+ ALOGV("drawMesh: gamut transform applied");
+ }
+ ProgramCache::getInstance().useProgram(wideColorState);
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+
+ if (outputDebugPPMs) {
+ std::ostringstream out;
+ out << "/data/texture_out" << mWideColorFrameCount++;
+ writePPM(out.str().c_str(), mVpWidth, mVpHeight);
+ }
+ } else {
+ ProgramCache::getInstance().useProgram(mState);
+
+ glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
+ }
if (mesh.getTexCoordsSize()) {
glDisableVertexAttribArray(Program::texCoords);
@@ -268,6 +411,11 @@
void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
+ if (usesWideColor()) {
+ result.append("Wide-color: On");
+ } else {
+ result.append("Wide-color: Off");
+ }
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 7c3f9b5..19cbb60 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -72,6 +72,27 @@
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
float alpha) override;
virtual void setupDimLayerBlending(float alpha) override;
+
+ // Color management related functions and state
+ void setColorMode(android_color_mode mode);
+ void setSourceDataSpace(android_dataspace source);
+ void setWideColor(bool hasWideColor);
+ bool usesWideColor();
+
+ // Current color mode of display using the render engine
+ android_color_mode mColorMode = HAL_COLOR_MODE_NATIVE;
+
+ // Current dataspace of layer being rendered
+ android_dataspace mDataSpace = HAL_DATASPACE_V0_SRGB;
+
+ // Indicate if wide-color mode is needed or not
+ bool mPlatformHasWideColor = false;
+ bool mDisplayHasWideColor = false;
+ bool mUseWideColor = false;
+ uint64_t mWideColorFrameCount = 0;
+
+ // Currently only supporting sRGB and DisplayP3 color spaces
+ mat4 mSrgbToDisplayP3;
#else
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
int alpha);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index d19137b..8b031bc 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -98,6 +98,10 @@
#ifdef USE_HWC2
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
virtual void setupDimLayerBlending(float alpha) = 0;
+ virtual void setColorMode(android_color_mode mode) = 0;
+ virtual void setSourceDataSpace(android_dataspace source) = 0;
+ virtual void setWideColor(bool hasWideColor) = 0;
+ virtual bool usesWideColor() = 0;
#else
virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
virtual void setupDimLayerBlending(int alpha) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 834c1c4..c343157 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -37,6 +37,7 @@
#include <dvr/vr_flinger.h>
+#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
@@ -119,6 +120,7 @@
bool SurfaceFlinger::hasSyncFramework;
bool SurfaceFlinger::useVrFlinger;
int64_t SurfaceFlinger::maxFrameBufferAcquiredBuffers;
+bool SurfaceFlinger::hasWideColorDisplay;
SurfaceFlinger::SurfaceFlinger()
: BnSurfaceComposer(),
@@ -189,6 +191,9 @@
maxFrameBufferAcquiredBuffers = getInt64< ISurfaceFlingerConfigs,
&ISurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers>(2);
+ hasWideColorDisplay =
+ getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(false);
+
// debugging stuff...
char value[PROPERTY_VALUE_MAX];
@@ -867,13 +872,10 @@
void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
android_color_mode_t mode) {
- ALOGD("Set active color mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
- this);
int32_t type = hw->getDisplayType();
android_color_mode_t currentMode = hw->getActiveColorMode();
if (mode == currentMode) {
- ALOGD("Screen type=%d is already in color mode=%d", hw->getDisplayType(), mode);
return;
}
@@ -882,6 +884,9 @@
return;
}
+ ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode,
+ hw->getDisplayType());
+
hw->setActiveColorMode(mode);
getHwComposer().setActiveColorMode(type, mode);
}
@@ -902,17 +907,17 @@
mFlinger.getDisplayColorModes(mDisplay, &modes);
bool exists = std::find(std::begin(modes), std::end(modes), mMode) != std::end(modes);
if (mMode < 0 || !exists) {
- ALOGE("Attempt to set invalid active color mode = %d for display %p", mMode,
- mDisplay.get());
+ ALOGE("Attempt to set invalid active color mode %s (%d) for display %p",
+ decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
return true;
}
sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
if (hw == nullptr) {
- ALOGE("Attempt to set active color mode = %d for null display %p",
- mMode, mDisplay.get());
+ ALOGE("Attempt to set active color mode %s (%d) for null display %p",
+ decodeColorMode(mMode).c_str(), mMode, mDisplay.get());
} else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to set active color mode= %d for virtual display",
- mMode);
+ ALOGW("Attempt to set active color mode %s %d for virtual display",
+ decodeColorMode(mMode).c_str(), mMode);
} else {
mFlinger.setActiveColorModeInternal(hw, mMode);
}
@@ -1144,10 +1149,30 @@
sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
DisplayDevice::DISPLAY_PRIMARY, consumer);
- sp<DisplayDevice> hw = new DisplayDevice(this,
- DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
- producer, mRenderEngine->getEGLConfig());
+
+ bool hasWideColorModes = false;
+ std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
+ for (android_color_mode_t colorMode : modes) {
+ switch (colorMode) {
+ case HAL_COLOR_MODE_DISPLAY_P3:
+ case HAL_COLOR_MODE_ADOBE_RGB:
+ case HAL_COLOR_MODE_DCI_P3:
+ hasWideColorModes = true;
+ break;
+ default:
+ break;
+ }
+ }
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
+ producer, mRenderEngine->getEGLConfig(),
+ hasWideColorModes && hasWideColorDisplay);
mDisplays.add(token, hw);
+ android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
+ if (hasWideColorModes && hasWideColorDisplay) {
+ defaultColorMode = HAL_COLOR_MODE_SRGB;
+ }
+ setActiveColorModeInternal(hw, defaultColorMode);
} else {
auto type = DisplayDevice::DISPLAY_EXTERNAL;
Mutex::Autolock _l(mStateLock);
@@ -1591,6 +1616,39 @@
}
}
+// pickColorMode translates a given dataspace into the best available color mode.
+// Currently only support sRGB and Display-P3.
+android_color_mode SurfaceFlinger::pickColorMode(android_dataspace dataSpace) {
+ switch (dataSpace) {
+ // treat Unknown as regular SRGB buffer, since that's what the rest of the
+ // system expects.
+ case HAL_DATASPACE_UNKNOWN:
+ case HAL_DATASPACE_SRGB:
+ case HAL_DATASPACE_V0_SRGB:
+ return HAL_COLOR_MODE_SRGB;
+ break;
+
+ case HAL_DATASPACE_DISPLAY_P3:
+ return HAL_COLOR_MODE_DISPLAY_P3;
+ break;
+
+ default:
+ // TODO (courtneygo): Do we want to assert an error here?
+ ALOGE("No color mode mapping for %s (%#x)", dataspaceDetails(dataSpace).c_str(),
+ dataSpace);
+ return HAL_COLOR_MODE_SRGB;
+ break;
+ }
+}
+
+android_dataspace SurfaceFlinger::bestTargetDataSpace(android_dataspace a, android_dataspace b) {
+ // Only support sRGB and Display-P3 right now.
+ if (a == HAL_DATASPACE_DISPLAY_P3 || b == HAL_DATASPACE_DISPLAY_P3) {
+ return HAL_DATASPACE_DISPLAY_P3;
+ }
+ return HAL_DATASPACE_V0_SRGB;
+}
+
void SurfaceFlinger::setUpHWComposer() {
ATRACE_CALL();
ALOGV("setUpHWComposer");
@@ -1661,6 +1719,7 @@
for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
auto& displayDevice = mDisplays[displayId];
const auto hwcId = displayDevice->getHwcDisplayId();
+
if (hwcId < 0) {
continue;
}
@@ -1672,6 +1731,21 @@
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
layer->setPerFrameData(displayDevice);
}
+
+ if (hasWideColorDisplay) {
+ android_color_mode newColorMode;
+ android_dataspace newDataSpace = HAL_DATASPACE_V0_SRGB;
+
+ for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace);
+ ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
+ layer->getName().string(), dataspaceDetails(layer->getDataSpace()).c_str(),
+ layer->getDataSpace(), dataspaceDetails(newDataSpace).c_str(), newDataSpace);
+ }
+ newColorMode = pickColorMode(newDataSpace);
+
+ setActiveColorModeInternal(displayDevice, newColorMode);
+ }
}
mPreviousColorMatrix = colorMatrix;
@@ -1950,10 +2024,11 @@
const wp<IBinder>& display(curr.keyAt(i));
if (dispSurface != NULL) {
- sp<DisplayDevice> hw = new DisplayDevice(this,
- state.type, hwcId, state.isSecure, display,
- dispSurface, producer,
- mRenderEngine->getEGLConfig());
+ sp<DisplayDevice> hw =
+ new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
+ dispSurface, producer,
+ mRenderEngine->getEGLConfig(),
+ hasWideColorDisplay);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation,
state.viewport, state.frame);
@@ -2369,6 +2444,10 @@
if (hasClientComposition) {
ALOGV("hasClientComposition");
+#ifdef USE_HWC2
+ mRenderEngine->setColorMode(displayDevice->getActiveColorMode());
+ mRenderEngine->setWideColor(displayDevice->getWideColorSupport());
+#endif
if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
displayDevice->getDisplayName().string());
@@ -3014,7 +3093,6 @@
int currentMode = hw->getPowerMode();
if (mode == currentMode) {
- ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
@@ -3341,7 +3419,6 @@
result.append("\n");
}
-
void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
String8& result) const
{
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ecbddd..10f93cc 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -151,6 +151,13 @@
// FramebufferSurface
static int64_t maxFrameBufferAcquiredBuffers;
+ // Indicate if platform supports color management on its
+ // wide-color display. This is typically found on devices
+ // with wide gamut (e.g. Display-P3) display.
+ // This also allows devices with wide-color displays that don't
+ // want to support color management to disable color management.
+ static bool hasWideColorDisplay;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
@@ -472,6 +479,12 @@
nsecs_t vsyncPhase, nsecs_t vsyncInterval,
nsecs_t compositeToPresentLatency);
void rebuildLayerStacks();
+
+ // Given a dataSpace, returns the appropriate color_mode to use
+ // to display that dataSpace.
+ android_color_mode pickColorMode(android_dataspace dataSpace);
+ android_dataspace bestTargetDataSpace(android_dataspace a, android_dataspace b);
+
void setUpHWComposer();
void doComposition();
void doDebugFlashRegions();