Loading libs/ui/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ cc_library_shared { shared_libs: [ "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.mapper@2.0", "android.hardware.configstore@1.0", "libbase", "libnativeloader", "libcutils", Loading services/surfaceflinger/DisplayDevice.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0; // clang-format off DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, Loading @@ -91,7 +92,8 @@ DisplayDevice::DisplayDevice( const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer, EGLConfig config) EGLConfig config, bool supportWideColor) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), mType(type), Loading @@ -111,8 +113,10 @@ DisplayDevice::DisplayDevice( 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(); Loading services/surfaceflinger/DisplayDevice.h +10 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ public: NO_LAYER_STACK = 0xFFFFFFFF, }; // clang-format off DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, Loading @@ -94,7 +95,9 @@ public: const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer, EGLConfig config); EGLConfig config, bool supportWideColor); // clang-format on ~DisplayDevice(); Loading Loading @@ -146,6 +149,7 @@ public: 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 Loading Loading @@ -264,6 +268,11 @@ private: #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 }; Loading services/surfaceflinger/Layer.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -1011,6 +1011,9 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { 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 { Loading Loading @@ -1172,6 +1175,9 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, RenderEngine& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha()); #ifdef USE_HWC2 engine.setSourceDataSpace(mCurrentState.dataSpace); #endif engine.drawMesh(mMesh); engine.disableBlending(); } Loading services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +151 −3 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 { // --------------------------------------------------------------------------- Loading @@ -59,6 +129,26 @@ GLES20RenderEngine::GLES20RenderEngine() : 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() { Loading Loading @@ -170,6 +260,42 @@ void GLES20RenderEngine::setupDimLayerBlending(int alpha) { } } #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()); Loading Loading @@ -242,8 +368,6 @@ void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) void GLES20RenderEngine::drawMesh(const Mesh& mesh) { ProgramCache::getInstance().useProgram(mState); if (mesh.getTexCoordsSize()) { glEnableVertexAttribArray(Program::texCoords); glVertexAttribPointer(Program::texCoords, Loading @@ -259,7 +383,26 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { mesh.getByteStride(), mesh.getPositions()); 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); Loading @@ -268,6 +411,11 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { void GLES20RenderEngine::dump(String8& result) { RenderEngine::dump(result); if (usesWideColor()) { result.append("Wide-color: On"); } else { result.append("Wide-color: Off"); } } // --------------------------------------------------------------------------- Loading Loading
libs/ui/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,7 @@ cc_library_shared { shared_libs: [ "android.hardware.graphics.allocator@2.0", "android.hardware.graphics.mapper@2.0", "android.hardware.configstore@1.0", "libbase", "libnativeloader", "libcutils", Loading
services/surfaceflinger/DisplayDevice.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ inline void eglSetSwapRectangleANDROID (EGLDisplay, EGLSurface, EGLint, EGLint, uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0; // clang-format off DisplayDevice::DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, Loading @@ -91,7 +92,8 @@ DisplayDevice::DisplayDevice( const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer, EGLConfig config) EGLConfig config, bool supportWideColor) : lastCompositionHadVisibleLayers(false), mFlinger(flinger), mType(type), Loading @@ -111,8 +113,10 @@ DisplayDevice::DisplayDevice( 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(); Loading
services/surfaceflinger/DisplayDevice.h +10 −1 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ public: NO_LAYER_STACK = 0xFFFFFFFF, }; // clang-format off DisplayDevice( const sp<SurfaceFlinger>& flinger, DisplayType type, Loading @@ -94,7 +95,9 @@ public: const wp<IBinder>& displayToken, const sp<DisplaySurface>& displaySurface, const sp<IGraphicBufferProducer>& producer, EGLConfig config); EGLConfig config, bool supportWideColor); // clang-format on ~DisplayDevice(); Loading Loading @@ -146,6 +149,7 @@ public: 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 Loading Loading @@ -264,6 +268,11 @@ private: #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 }; Loading
services/surfaceflinger/Layer.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -1011,6 +1011,9 @@ static constexpr mat4 inverseOrientation(uint32_t transform) { 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 { Loading Loading @@ -1172,6 +1175,9 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, RenderEngine& engine(mFlinger->getRenderEngine()); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), getAlpha()); #ifdef USE_HWC2 engine.setSourceDataSpace(mCurrentState.dataSpace); #endif engine.drawMesh(mMesh); engine.disableBlending(); } Loading
services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp +151 −3 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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 { // --------------------------------------------------------------------------- Loading @@ -59,6 +129,26 @@ GLES20RenderEngine::GLES20RenderEngine() : 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() { Loading Loading @@ -170,6 +260,42 @@ void GLES20RenderEngine::setupDimLayerBlending(int alpha) { } } #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()); Loading Loading @@ -242,8 +368,6 @@ void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) void GLES20RenderEngine::drawMesh(const Mesh& mesh) { ProgramCache::getInstance().useProgram(mState); if (mesh.getTexCoordsSize()) { glEnableVertexAttribArray(Program::texCoords); glVertexAttribPointer(Program::texCoords, Loading @@ -259,7 +383,26 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { mesh.getByteStride(), mesh.getPositions()); 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); Loading @@ -268,6 +411,11 @@ void GLES20RenderEngine::drawMesh(const Mesh& mesh) { void GLES20RenderEngine::dump(String8& result) { RenderEngine::dump(result); if (usesWideColor()) { result.append("Wide-color: On"); } else { result.append("Wide-color: Off"); } } // --------------------------------------------------------------------------- Loading