From 0309f00908d2ed191de7336816c07ae3b469f9aa Mon Sep 17 00:00:00 2001 From: Steven Luo Date: Sat, 30 Mar 2013 00:44:11 -0700 Subject: Forward-port surface dithering from CM10 This allows the use of 16-bit color displays without excessive color banding; behavior can be controlled by the persist.sys.use_dithering property. Incorporates http://review.cyanogenmod.org/19532 from CM10 as well as code removed in upstream commit 1b03149. Change-Id: I290ca4ed4787dc81ac756d9af92cd6a690865a08 --- services/surfaceflinger/Layer.cpp | 18 ++++++++++++++++++ services/surfaceflinger/Layer.h | 2 ++ services/surfaceflinger/LayerBase.cpp | 7 +++++++ services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++++++++++++++++-- services/surfaceflinger/SurfaceFlinger.h | 6 ++++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 7edbdc5..c1561b2 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -63,6 +63,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& client) mFormat(PIXEL_FORMAT_NONE), mGLExtensions(GLExtensions::getInstance()), mOpaqueLayer(true), + mNeedsDithering(false), mSecure(false), mProtectedByApp(false) { @@ -194,6 +195,23 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, mSurfaceTexture->setDefaultBufferFormat(format); mSurfaceTexture->setConsumerUsageBits(getEffectiveUsage(0)); + int displayMinColorDepth; + int layerRedsize; + switch (mFlinger->getUseDithering()) { + case 0: + mNeedsDithering = false; + break; + case 1: + displayMinColorDepth = mFlinger->getMinColorDepth(); + // we use the red index + layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED); + mNeedsDithering = (layerRedsize > displayMinColorDepth); + break; + case 2: + mNeedsDithering = true; + break; + } + return NO_ERROR; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c5eb26b..a3d6ab9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -77,6 +77,7 @@ public: virtual uint32_t doTransaction(uint32_t transactionFlags); virtual Region latchBuffer(bool& recomputeVisibleRegions); virtual bool isOpaque() const; + virtual bool needsDithering() const { return mNeedsDithering; } virtual bool isSecure() const { return mSecure; } virtual bool isProtected() const; virtual void onRemoved(); @@ -142,6 +143,7 @@ private: PixelFormat mFormat; const GLExtensions& mGLExtensions; bool mOpaqueLayer; + bool mNeedsDithering; // page-flip thread (currently main thread) bool mSecure; // no screenshots diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 9b03c74..612e47b 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -354,6 +354,7 @@ void LayerBase::clearWithOpenGL(const sp& hw, const Region& glDisable(GL_TEXTURE_EXTERNAL_OES); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); + glDisable(GL_DITHER); LayerMesh mesh; computeGeometry(hw, &mesh); @@ -428,6 +429,12 @@ void LayerBase::drawWithOpenGL(const sp& hw, const Region& texCoords[i].v = 1.0f - texCoords[i].v; } + if (needsDithering()) { + glEnable(GL_DITHER); + } else { + glDisable(GL_DITHER); + } + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, texCoords); glVertexPointer(2, GL_FLOAT, 0, mesh.getVertices()); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index dc562f1..1842949 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -104,7 +104,8 @@ SurfaceFlinger::SurfaceFlinger() mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), - mBootFinished(false) + mBootFinished(false), + mUseDithering(0) { ALOGI("SurfaceFlinger is starting"); @@ -122,8 +123,13 @@ SurfaceFlinger::SurfaceFlinger() mDebugDDMS = 0; } } + + property_get("persist.sys.use_dithering", value, "1"); + mUseDithering = atoi(value); + ALOGI_IF(mDebugRegion, "showupdates enabled"); ALOGI_IF(mDebugDDMS, "DDMS debugging enabled"); + ALOGI_IF(mUseDithering, "use dithering"); #ifdef SAMSUNG_HDMI_SUPPORT ALOGD(">>> Run service"); @@ -429,7 +435,11 @@ void SurfaceFlinger::initializeGL(EGLDisplay display) { glPixelStorei(GL_PACK_ALIGNMENT, 4); glEnableClientState(GL_VERTEX_ARRAY); glShadeModel(GL_FLAT); - glDisable(GL_DITHER); + if (mUseDithering == 2) { + glEnable(GL_DITHER); + } else { + glDisable(GL_DITHER); + } glDisable(GL_CULL_FACE); struct pack565 { @@ -467,6 +477,9 @@ void SurfaceFlinger::initializeGL(EGLDisplay display) { ALOGI("extensions: %s", extensions.getExtension()); ALOGI("GL_MAX_TEXTURE_SIZE = %d", mMaxTextureSize); ALOGI("GL_MAX_VIEWPORT_DIMS = %d x %d", mMaxViewportDims[0], mMaxViewportDims[1]); + + // XXX Assume bit depth for red is equal to minimum depth of all colors + mMinColorDepth = r; } status_t SurfaceFlinger::readyToRun() @@ -564,6 +577,10 @@ uint32_t SurfaceFlinger::getMaxTextureSize() const { return mMaxTextureSize; } +uint32_t SurfaceFlinger::getMinColorDepth() const { + return mMinColorDepth; +} + uint32_t SurfaceFlinger::getMaxViewportDims() const { return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1]; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e8c4b9c..050d10f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -324,8 +324,12 @@ private: static EGLContext createGLContext(EGLDisplay disp, EGLConfig config); void initializeGL(EGLDisplay display); uint32_t getMaxTextureSize() const; + uint32_t getMinColorDepth() const; uint32_t getMaxViewportDims() const; + // 0: surface doesn't need dithering, 1: use if necessary, 2: use permanently + inline int getUseDithering() const { return mUseDithering; } + /* ------------------------------------------------------------------------ * Display and layer stack management */ @@ -423,6 +427,7 @@ private: sp mEventThread; GLint mMaxViewportDims[2]; GLint mMaxTextureSize; + GLint mMinColorDepth; EGLContext mEGLContext; EGLConfig mEGLConfig; EGLDisplay mEGLDisplay; @@ -448,6 +453,7 @@ private: volatile nsecs_t mDebugInTransaction; nsecs_t mLastTransactionTime; bool mBootFinished; + int mUseDithering; // these are thread safe mutable MessageQueue mEventQueue; -- cgit v1.1