Created
December 14, 2013 10:33
-
-
Save steven676/7957779 to your computer and use it in GitHub Desktop.
[PATCH] Forward-port surface dithering from CM10.2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From f6cceade46953f40fa9eca9d737dbcd0da7b969b Mon Sep 17 00:00:00 2001 | |
From: Steven Luo <[email protected]> | |
Date: Sat, 30 Mar 2013 00:44:11 -0700 | |
Subject: [PATCH] Forward-port surface dithering from CM10.2 | |
This allows the use of 16-bit color displays without excessive color | |
banding; | |
Change-Id: Icb469b9cb4beb686516c60bb576dbd0a73f505e0 | |
--- | |
include/ui/PixelFormat.h | 1 + | |
libs/ui/PixelFormat.cpp | 16 ++++++++++++++++ | |
services/surfaceflinger/Layer.cpp | 9 +++++++++ | |
services/surfaceflinger/Layer.h | 6 ++++++ | |
services/surfaceflinger/RenderEngine/RenderEngine.cpp | 8 ++++++++ | |
services/surfaceflinger/RenderEngine/RenderEngine.h | 2 ++ | |
services/surfaceflinger/SurfaceFlinger.cpp | 9 ++++++++- | |
services/surfaceflinger/SurfaceFlinger.h | 6 ++++++ | |
8 files changed, 56 insertions(+), 1 deletion(-) | |
diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h | |
index 19228c4..6278d7a 100644 | |
--- a/include/ui/PixelFormat.h | |
+++ b/include/ui/PixelFormat.h | |
@@ -122,6 +122,7 @@ status_t getPixelFormatInfo(PixelFormat format, PixelFormatInfo* info); | |
ssize_t bytesPerPixel(PixelFormat format); | |
ssize_t bitsPerPixel(PixelFormat format); | |
+ssize_t minColorDepth(PixelFormat format); | |
}; // namespace android | |
diff --git a/libs/ui/PixelFormat.cpp b/libs/ui/PixelFormat.cpp | |
index 0595315..e82f309 100644 | |
--- a/libs/ui/PixelFormat.cpp | |
+++ b/libs/ui/PixelFormat.cpp | |
@@ -160,6 +160,22 @@ ssize_t bitsPerPixel(PixelFormat format) { | |
return BAD_VALUE; | |
} | |
+ssize_t minColorDepth(PixelFormat format) { | |
+ switch (format) { | |
+ case PIXEL_FORMAT_RGBA_8888: | |
+ case PIXEL_FORMAT_RGBX_8888: | |
+ case PIXEL_FORMAT_BGRA_8888: | |
+ case PIXEL_FORMAT_RGB_888: | |
+ return 8; | |
+ case PIXEL_FORMAT_RGB_565: | |
+ case PIXEL_FORMAT_RGBA_5551: | |
+ return 5; | |
+ case PIXEL_FORMAT_RGBA_4444: | |
+ return 4; | |
+ } | |
+ return BAD_VALUE; | |
+} | |
+ | |
// ---------------------------------------------------------------------------- | |
}; // namespace android | |
// ---------------------------------------------------------------------------- | |
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp | |
index dd66f0b..0b668f6 100644 | |
--- a/services/surfaceflinger/Layer.cpp | |
+++ b/services/surfaceflinger/Layer.cpp | |
@@ -68,6 +68,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, | |
mDebug(false), | |
mFormat(PIXEL_FORMAT_NONE), | |
mOpaqueLayer(true), | |
+ mNeedsDithering(false), | |
mTransactionFlags(0), | |
mQueuedFrames(0), | |
mCurrentTransform(0), | |
@@ -199,6 +200,12 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h, | |
mSurfaceFlingerConsumer->setDefaultBufferFormat(format); | |
mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); | |
+ if (mFlinger->getUseDithering()) { | |
+ int displayMinColorDepth = mFlinger->getMinColorDepth(); | |
+ int layerMinColorDepth = minColorDepth(format); | |
+ mNeedsDithering = (layerMinColorDepth > displayMinColorDepth); | |
+ } | |
+ | |
return NO_ERROR; | |
} | |
@@ -573,6 +580,7 @@ void Layer::clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& cli | |
{ | |
RenderEngine& engine(mFlinger->getRenderEngine()); | |
computeGeometry(hw, mMesh); | |
+ engine.setDither(false); | |
engine.setupFillWithColor(red, green, blue, alpha); | |
engine.drawMesh(mMesh); | |
} | |
@@ -619,6 +627,7 @@ void Layer::drawWithOpenGL( | |
texCoords[3] = vec2(right, 1.0f - top); | |
RenderEngine& engine(mFlinger->getRenderEngine()); | |
+ engine.setDither(needsDithering()); | |
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha); | |
engine.drawMesh(mMesh); | |
engine.disableBlending(); | |
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h | |
index 9c36349..807d6af 100644 | |
--- a/services/surfaceflinger/Layer.h | |
+++ b/services/surfaceflinger/Layer.h | |
@@ -153,6 +153,11 @@ public: | |
virtual bool isOpaque() const; | |
/* | |
+ * needsDithering - true if this surface needs dithering | |
+ */ | |
+ virtual bool needsDithering() const { return mNeedsDithering; } | |
+ | |
+ /* | |
* isSecure - true if this surface is secure, that is if it prevents | |
* screenshots or VNC servers. | |
*/ | |
@@ -340,6 +345,7 @@ private: | |
mutable bool mDebug; | |
PixelFormat mFormat; | |
bool mOpaqueLayer; | |
+ bool mNeedsDithering; | |
// these are protected by an external lock | |
State mCurrentState; | |
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp | |
index 53aa85b..56d261a 100644 | |
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp | |
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp | |
@@ -223,6 +223,14 @@ void RenderEngine::readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* | |
glReadPixels(l, b, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | |
} | |
+void RenderEngine::setDither(bool dither) { | |
+ if (dither) { | |
+ glEnable(GL_DITHER); | |
+ } else { | |
+ glDisable(GL_DITHER); | |
+ } | |
+} | |
+ | |
void RenderEngine::dump(String8& result) { | |
const GLExtensions& extensions(GLExtensions::getInstance()); | |
result.appendFormat("GLES: %s, %s, %s\n", | |
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h | |
index 4ff83c0..ac4b1dc 100644 | |
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h | |
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h | |
@@ -76,6 +76,8 @@ public: | |
void deleteTextures(size_t count, uint32_t const* names); | |
void readPixels(size_t l, size_t b, size_t w, size_t h, uint32_t* pixels); | |
+ void setDither(bool dither); | |
+ | |
class BindImageAsFramebuffer { | |
RenderEngine& mEngine; | |
uint32_t mTexName, mFbName; | |
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp | |
index 88ad0bb..385df2b 100644 | |
--- a/services/surfaceflinger/SurfaceFlinger.cpp | |
+++ b/services/surfaceflinger/SurfaceFlinger.cpp | |
@@ -156,7 +156,8 @@ SurfaceFlinger::SurfaceFlinger() | |
mBootFinished(false), | |
mPrimaryHWVsyncEnabled(false), | |
mHWVsyncAvailable(false), | |
- mDaltonize(false) | |
+ mDaltonize(false), | |
+ mUseDithering(0) | |
{ | |
ALOGI("SurfaceFlinger is starting"); | |
@@ -614,6 +615,9 @@ void SurfaceFlinger::init() { | |
ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported"); | |
ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig); | |
+ // assume red has minimum color depth | |
+ mMinColorDepth = r; | |
+ | |
// get a RenderEngine for the given display / config (can't fail) | |
mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig); | |
@@ -651,6 +655,9 @@ void SurfaceFlinger::init() { | |
hw->acquireScreen(); | |
} | |
mDisplays.add(token, hw); | |
+ if (!mUseDithering && bitsPerPixel(mHwc->getFormat(i)) <= 16) { | |
+ mUseDithering = 1; | |
+ } | |
} | |
} | |
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h | |
index 12b07ef..0fbfcf3 100644 | |
--- a/services/surfaceflinger/SurfaceFlinger.h | |
+++ b/services/surfaceflinger/SurfaceFlinger.h | |
@@ -334,6 +334,10 @@ private: | |
size_t getMaxTextureSize() const; | |
size_t getMaxViewportDims() const; | |
+ uint32_t getMinColorDepth() const { return mMinColorDepth; } | |
+ // 0: surface doesn't need dithering, 1: use if necessary | |
+ inline int getUseDithering() const { return mUseDithering; } | |
+ | |
/* ------------------------------------------------------------------------ | |
* Display and layer stack management | |
*/ | |
@@ -440,6 +444,7 @@ private: | |
sp<EventThread> mEventThread; | |
sp<EventThread> mSFEventThread; | |
sp<EventControlThread> mEventControlThread; | |
+ uint32_t mMinColorDepth; | |
EGLContext mEGLContext; | |
EGLConfig mEGLConfig; | |
EGLDisplay mEGLDisplay; | |
@@ -467,6 +472,7 @@ private: | |
volatile nsecs_t mDebugInTransaction; | |
nsecs_t mLastTransactionTime; | |
bool mBootFinished; | |
+ int mUseDithering; | |
// these are thread safe | |
mutable MessageQueue mEventQueue; | |
-- | |
1.7.10.4 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment