分类: 嵌入式
2011-08-30 23:20:52
CM7手机的CRT关屏效果非常赞,在网上搜了半天,发现原来这是Android系统自带的功能,只是没有使能而已。
Android系统默认使用的关屏效果是fade,要激活旧CRT效果,需要修改以下文件,关闭fade效果。
frameworks/base/core/res/res/values/config.xml
- +
为啥如此修改就可以激活旧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 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 2406 status_t res = postMessageSync(msg); 2407 if (res == NO_ERROR) { 2408 res = static_cast 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 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 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帧。 当然,该函数有许多限制,不符合就会半途退出,你就看不到动画效果啦。 Rockie Cheng |