探寻Android系统中的Old CRT OFF

CM7手机的CRT关屏效果非常赞,在网上搜了半天,发现原来这是Android系统自带的功能,只是没有使能而已。

Android系统默认使用的关屏效果是fade,要激活旧CRT效果,需要修改以下文件,关闭fade效果。

frameworks/base/core/res/res/values/config.xml

<!-- If this is true, the screen will fade off. -->

-    <bool>true</bool>

+    <bool>false</bool>

为啥如此修改就可以激活旧CRT效果,让我们跟踪下代码,先贴上相关代码:

frameworks\base\services\java\com\android\server\PowerManagerService.java

475                 mAnimationSetting = 0;

476                 if (windowScale > 0.5f) {

477                     mAnimationSetting |= ANIM_SETTING_OFF;

478                 }

2284         public void run() {

2285             if (mAnimateScreenLights) {

2286                 synchronized (mLocks) {

2287                     long now = SystemClock.uptimeMillis();

2288                     boolean more = mScreenBrightness.stepLocked();

2289                     if (more) {

2290                         mScreenOffHandler.postAtTime(this, now+(1000/60));

2291                     }

2292                 }

2293             } else {

2294                 synchronized (mLocks) {

2295                     // we're turning off

2296                     final boolean animate = animating && targetValue == Power.BRIGHTNESS_OFF;

2297                     if (animate) {

2298                         // It's pretty scary to hold mLocks for this long, and we should

2299                         // redesign this, but it works for now.

2300                         nativeStartSurfaceFlingerAnimation(

2301                                 mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR

2302                                 ? 0 : mAnimationSetting);

2303                     }

2304                     mScreenBrightness.jumpToTargetLocked();

2305                 }

2306             }

2307         }

2308     }

frameworks/base/services/jni/com_android_server_PowerManagerService.cpp

131 static void android_server_PowerManagerService_nativeStartSurfaceFlingerAnimation(JNIEnv* env,

132         jobject obj, jint mode) {

133     sp<ISurfaceComposer> s(ComposerService::getComposerService());

134     s->turnElectronBeamOff(mode);

135 }

frameworks/base/services/surfaceflinger/SurfaceFlinger.cpp

2385 status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)

2386 {

2387     class MessageTurnElectronBeamOff : public MessageBase {

2388         SurfaceFlinger* flinger;

2389         int32_t mode;

2390         status_t result;

2391     public:

2392         MessageTurnElectronBeamOff(SurfaceFlinger* flinger, int32_t mode)

2393             : flinger(flinger), mode(mode), result(PERMISSION_DENIED) {

2394         }

2395         status_t getResult() const {

2396             return result;

2397         }

2398         virtual bool handler() {

2399             Mutex::Autolock _l(flinger->mStateLock);

2400             result = flinger->turnElectronBeamOffImplLocked(mode);

2401             return true;

2402         }

2403     };

2404

2405     sp<MessageBase> msg = new MessageTurnElectronBeamOff(this, mode);

2406     status_t res = postMessageSync(msg);

2407     if (res == NO_ERROR) {

2408         res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();

2409

2410         // work-around: when the power-manager calls us we activate the

2411         // animation. eventually, the "on" animation will be called

2412         // by the power-manager itself

2413         mElectronBeamAnimationMode = mode;

2414     }

2415     return res;

2416 }

2363 status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)

2364 {

2365     DisplayHardware& hw(graphicPlane(0).editDisplayHardware());

2366     if (!hw.canDraw()) {

2367         // we're already off

2368         return NO_ERROR;

2369     }

2370     if (mode & ISurfaceComposer::eElectronBeamAnimationOff) {

2371         electronBeamOffAnimationImplLocked();

2372     }

2373

2374     // always clear the whole screen at the end of the animation

2375     glClearColor(0,0,0,1);

2376     glDisable(GL_SCISSOR_TEST);

2377     glClear(GL_COLOR_BUFFER_BIT);

2378     glEnable(GL_SCISSOR_TEST);

2379     hw.flip( Region(hw.bounds()) );

2380

2381     hw.setCanDraw(false);

2382     return NO_ERROR;

2383 }

2073 status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()

2074 {

2075     status_t result = PERMISSION_DENIED;

2076

2077     if (!GLExtensions::getInstance().haveFramebufferObject())

2078         return INVALID_OPERATION;

2079

2080     // get screen geometry

2081     const DisplayHardware& hw(graphicPlane(0).displayHardware());

2082     const uint32_t hw_w = hw.getWidth();

2083     const uint32_t hw_h = hw.getHeight();

2084     const Region screenBounds(hw.bounds());

2085

2086     GLfloat u, v;

2087     GLuint tname;

2088     result = renderScreenToTextureLocked(0, &tname, &u, &v);

2089     if (result != NO_ERROR) {

2090         return result;

2091     }

2092

2093     GLfloat vtx[8];

2094     const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };

2095     glEnable(GL_TEXTURE_2D);

2096     glBindTexture(GL_TEXTURE_2D, tname);

2097     glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

2098     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

2099     glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

2100     glTexCoordPointer(2, GL_FLOAT, 0, texCoords);

2101     glEnableClientState(GL_TEXTURE_COORD_ARRAY);

2102     glVertexPointer(2, GL_FLOAT, 0, vtx);

2103

2104     class s_curve_interpolator {

2105         const float nbFrames, s, v;

2106     public:

2107         s_curve_interpolator(int nbFrames, float s)

2108         : nbFrames(1.0f / (nbFrames-1)), s(s),

2109           v(1.0f + expf(-s + 0.5f*s)) {

2110         }

2111         float operator()(int f) {

2112             const float x = f * nbFrames;

2113             return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;

2114         }

2115     };

2116

2117     class v_stretch {

2118         const GLfloat hw_w, hw_h;

2119     public:

2120         v_stretch(uint32_t hw_w, uint32_t hw_h)

2121         : hw_w(hw_w), hw_h(hw_h) {

2122         }

2123         void operator()(GLfloat* vtx, float v) {

2124             const GLfloat w = hw_w + (hw_w * v);

2125             const GLfloat h = hw_h - (hw_h * v);

2126             const GLfloat x = (hw_w - w) * 0.5f;

2127             const GLfloat y = (hw_h - h) * 0.5f;

2128             vtx[0] = x;         vtx[1] = y;

2129             vtx[2] = x;         vtx[3] = y + h;

2130             vtx[4] = x + w;     vtx[5] = y + h;

2131             vtx[6] = x + w;     vtx[7] = y;

2132         }

2133     };

2134

2135     class h_stretch {

2136         const GLfloat hw_w, hw_h;

2137     public:

2138         h_stretch(uint32_t hw_w, uint32_t hw_h)

2139         : hw_w(hw_w), hw_h(hw_h) {

2140         }

2141         void operator()(GLfloat* vtx, float v) {

2142             const GLfloat w = hw_w - (hw_w * v);

2143             const GLfloat h = 1.0f;

2144             const GLfloat x = (hw_w - w) * 0.5f;

2145             const GLfloat y = (hw_h - h) * 0.5f;

2146             vtx[0] = x;         vtx[1] = y;

2147             vtx[2] = x;         vtx[3] = y + h;

2148             vtx[4] = x + w;     vtx[5] = y + h;

2149             vtx[6] = x + w;     vtx[7] = y;

2150         }

2151     };

2152

2153     // the full animation is 24 frames

2154     const int nbFrames = 12;

2155     s_curve_interpolator itr(nbFrames, 7.5f);

2156     s_curve_interpolator itg(nbFrames, 8.0f);

2157     s_curve_interpolator itb(nbFrames, 8.5f);

2158

2159     v_stretch vverts(hw_w, hw_h);

2160     glEnable(GL_BLEND);

2161     glBlendFunc(GL_ONE, GL_ONE);

2162     for (int i=0 ; i<nbFrames ; i++) {

2163         float x, y, w, h;

2164         const float vr = itr(i);

2165         const float vg = itg(i);

2166         const float vb = itb(i);

2167

2168         // clear screen

2169         glColorMask(1,1,1,1);

2170         glClear(GL_COLOR_BUFFER_BIT);

2171         glEnable(GL_TEXTURE_2D);

2172

2173         // draw the red plane

2174         vverts(vtx, vr);

2175         glColorMask(1,0,0,1);

2176         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

2177

2178         // draw the green plane

2179         vverts(vtx, vg);

2180         glColorMask(0,1,0,1);

2181         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

2182

2183         // draw the blue plane

2184         vverts(vtx, vb);

2185         glColorMask(0,0,1,1);

2186         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

2187

2188         // draw the white highlight (we use the last vertices)

2189         glDisable(GL_TEXTURE_2D);

2190         glColorMask(1,1,1,1);

2191         glColor4f(vg, vg, vg, 1);

2192         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

2193         hw.flip(screenBounds);

2194     }

2195

2196     h_stretch hverts(hw_w, hw_h);

2197     glDisable(GL_BLEND);

2198     glDisable(GL_TEXTURE_2D);

2199     glColorMask(1,1,1,1);

2200     for (int i=0 ; i<nbFrames ; i++) {

2201         const float v = itg(i);

2202         hverts(vtx, v);

2203         glClear(GL_COLOR_BUFFER_BIT);

2204         glColor4f(1-v, 1-v, 1-v, 1);

2205         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

2206         hw.flip(screenBounds);

2207     }

2208

2209     glColorMask(1,1,1,1);

2210     glEnable(GL_SCISSOR_TEST);

2211     glDisableClientState(GL_TEXTURE_COORD_ARRAY);

2212     glDeleteTextures(1, &tname);

2213     return NO_ERROR;

2214 }

2215

OK,看完代码回来,首先是PowerManagerService.java中

mAnimationSetting如果标记为ANIM_SETTING_OFF,则打开旧CRT动画。

下面关屏动作run()中,因为我们将config_animateScreenLights置为false,因此mAnimateScreenLights为fasle

分支进入else,执行nativeStartSurfaceFlingerAnimation()函数。

nativeStartSurfaceFlingerAnimation()函数是一个JNI调用,在com_android_server_PowerManagerService.cpp文件中,

对应surfaceflinger的s->turnElectronBeamOff(mode)函数。

好的,现在跳入SurfaceFlinger.cpp函数,具体调用顺序是:

turnElectronBeamOff()

|

turnElectronBeamOffImplLocked()

|

electronBeamOffAnimationImplLocked()

electronBeamOffAnimationImplLocked()函数将调用openGL绘值旧CRT关屏效果,大概有24帧。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwgfyd.html