Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steven676/7957779 to your computer and use it in GitHub Desktop.
Save steven676/7957779 to your computer and use it in GitHub Desktop.
[PATCH] Forward-port surface dithering from CM10.2
From f6cceade46953f40fa9eca9d737dbcd0da7b969b Mon Sep 17 00:00:00 2001
From: Steven Luo <steven@steven676.net>
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