summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2010-10-11 12:37:43 -0700
committerJoe Onorato <joeo@android.com>2010-10-12 14:16:11 -0700
commit59119e658a12279e8fff508f8773843de2d90917 (patch)
treedb492638cc54a48cb0ae03832e9fb66cad128dc6 /services/surfaceflinger/SurfaceFlinger.cpp
parent3c8e66f9a44e502d337d9d9d063738c8f831e5ba (diff)
downloadframeworks_native-59119e658a12279e8fff508f8773843de2d90917.zip
frameworks_native-59119e658a12279e8fff508f8773843de2d90917.tar.gz
frameworks_native-59119e658a12279e8fff508f8773843de2d90917.tar.bz2
turn off the electron beam
Change-Id: I335fb6719f1d5a3f1c6f37a046fd1c2c4ed2bbc6
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp234
1 files changed, 232 insertions, 2 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e5e87c6..a919ddf 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -423,14 +423,14 @@ void SurfaceFlinger::handleConsoleEvents()
hw.acquireScreen();
}
- if (mDeferReleaseConsole && hw.canDraw()) {
+ if (mDeferReleaseConsole && hw.isScreenAcquired()) {
// We got the release signal before the acquire signal
mDeferReleaseConsole = false;
hw.releaseScreen();
}
if (what & eConsoleReleased) {
- if (hw.canDraw()) {
+ if (hw.isScreenAcquired()) {
hw.releaseScreen();
} else {
mDeferReleaseConsole = true;
@@ -1456,6 +1456,7 @@ status_t SurfaceFlinger::onTransact(
case FREEZE_DISPLAY:
case UNFREEZE_DISPLAY:
case BOOT_FINISHED:
+ case TURN_ELECTRON_BEAM_OFF:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
@@ -1544,6 +1545,231 @@ status_t SurfaceFlinger::onTransact(
return err;
}
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
+{
+ status_t result = PERMISSION_DENIED;
+
+ if (!GLExtensions::getInstance().haveFramebufferObject())
+ return INVALID_OPERATION;
+
+ // get screen geometry
+ const int dpy = 0;
+ const DisplayHardware& hw(graphicPlane(dpy).displayHardware());
+ if (!hw.canDraw()) {
+ // we're already off
+ return NO_ERROR;
+ }
+
+ const uint32_t hw_w = hw.getWidth();
+ const uint32_t hw_h = hw.getHeight();
+ const Region screenBounds(hw.bounds());
+ GLfloat u = 1;
+ GLfloat v = 1;
+
+ // make sure to clear all GL error flags
+ while ( glGetError() != GL_NO_ERROR ) ;
+
+ // create a FBO
+ GLuint name, tname;
+ glGenTextures(1, &tname);
+ glBindTexture(GL_TEXTURE_2D, tname);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, hw_w, hw_h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ if (glGetError() != GL_NO_ERROR) {
+ GLint tw = (2 << (31 - clz(hw_w)));
+ GLint th = (2 << (31 - clz(hw_h)));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ u = GLfloat(hw_w) / tw;
+ v = GLfloat(hw_h) / th;
+ }
+ glGenFramebuffersOES(1, &name);
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, name);
+ glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, tname, 0);
+
+ GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+ if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
+ // redraw the screen entirely...
+ glClearColor(0,0,0,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ const size_t count = layers.size();
+ for (size_t i=0 ; i<count ; ++i) {
+ const sp<LayerBase>& layer(layers[i]);
+ layer->drawForSreenShot();
+ }
+ // back to main framebuffer
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+ glDisable(GL_SCISSOR_TEST);
+
+ GLfloat vtx[8];
+ const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, tname);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, vtx);
+
+ class s_curve_interpolator {
+ const float nbFrames, s, v;
+ public:
+ s_curve_interpolator(int nbFrames, float s)
+ : nbFrames(1.0f / (nbFrames-1)), s(s),
+ v(1.0f + expf(-s + 0.5f*s)) {
+ }
+ float operator()(int f) {
+ const float x = f * nbFrames;
+ return ((1.0f/(1.0f + expf(-x*s + 0.5f*s))) - 0.5f) * v + 0.5f;
+ }
+ };
+
+ class v_stretch {
+ const GLfloat hw_w, hw_h;
+ public:
+ v_stretch(uint32_t hw_w, uint32_t hw_h)
+ : hw_w(hw_w), hw_h(hw_h) {
+ }
+ void operator()(GLfloat* vtx, float v) {
+ const GLfloat w = hw_w + (hw_w * v);
+ const GLfloat h = hw_h - (hw_h * v);
+ const GLfloat x = (hw_w - w) * 0.5f;
+ const GLfloat y = (hw_h - h) * 0.5f;
+ vtx[0] = x; vtx[1] = y;
+ vtx[2] = x; vtx[3] = y + h;
+ vtx[4] = x + w; vtx[5] = y + h;
+ vtx[6] = x + w; vtx[7] = y;
+ }
+ };
+
+ class h_stretch {
+ const GLfloat hw_w, hw_h;
+ public:
+ h_stretch(uint32_t hw_w, uint32_t hw_h)
+ : hw_w(hw_w), hw_h(hw_h) {
+ }
+ void operator()(GLfloat* vtx, float v) {
+ const GLfloat w = hw_w - (hw_w * v);
+ const GLfloat h = 1.0f;
+ const GLfloat x = (hw_w - w) * 0.5f;
+ const GLfloat y = (hw_h - h) * 0.5f;
+ vtx[0] = x; vtx[1] = y;
+ vtx[2] = x; vtx[3] = y + h;
+ vtx[4] = x + w; vtx[5] = y + h;
+ vtx[6] = x + w; vtx[7] = y;
+ }
+ };
+
+ // the full animation is 24 frames
+ const int nbFrames = 12;
+
+ v_stretch vverts(hw_w, hw_h);
+ s_curve_interpolator itr(nbFrames, 7.5f);
+ s_curve_interpolator itg(nbFrames, 8.0f);
+ s_curve_interpolator itb(nbFrames, 8.5f);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ for (int i=0 ; i<nbFrames ; i++) {
+ float x, y, w, h;
+ const float vr = itr(i);
+ const float vg = itg(i);
+ const float vb = itb(i);
+
+ // clear screen
+ glColorMask(1,1,1,1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_TEXTURE_2D);
+
+ // draw the red plane
+ vverts(vtx, vr);
+ glColorMask(1,0,0,1);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // draw the green plane
+ vverts(vtx, vg);
+ glColorMask(0,1,0,1);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // draw the blue plane
+ vverts(vtx, vb);
+ glColorMask(0,0,1,1);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // draw the white highlight (we use the last vertices)
+ glDisable(GL_TEXTURE_2D);
+ glColorMask(1,1,1,1);
+ glColor4f(vg, vg, vg, 1);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ hw.flip(screenBounds);
+ }
+
+ h_stretch hverts(hw_w, hw_h);
+ glDisable(GL_BLEND);
+ glDisable(GL_TEXTURE_2D);
+ glColorMask(1,1,1,1);
+ for (int i=0 ; i<nbFrames ; i++) {
+ const float v = itg(i);
+ hverts(vtx, v);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColor4f(1-v, 1-v, 1-v, 1);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ hw.flip(screenBounds);
+ }
+
+ glColorMask(1,1,1,1);
+ glEnable(GL_SCISSOR_TEST);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ result = NO_ERROR;
+ } else {
+ // release FBO resources
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
+ result = BAD_VALUE;
+ }
+
+ glDeleteFramebuffersOES(1, &name);
+ glDeleteTextures(1, &tname);
+
+ if (result == NO_ERROR) {
+ DisplayHardware& hw(graphicPlane(dpy).editDisplayHardware());
+ hw.setCanDraw(false);
+ }
+
+ return result;
+}
+
+status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
+{
+ if (!GLExtensions::getInstance().haveFramebufferObject())
+ return INVALID_OPERATION;
+
+ class MessageTurnElectronBeamOff : public MessageBase {
+ SurfaceFlinger* flinger;
+ status_t result;
+ public:
+ MessageTurnElectronBeamOff(SurfaceFlinger* flinger)
+ : flinger(flinger), result(PERMISSION_DENIED) {
+ }
+ status_t getResult() const {
+ return result;
+ }
+ virtual bool handler() {
+ Mutex::Autolock _l(flinger->mStateLock);
+ result = flinger->turnElectronBeamOffImplLocked();
+ return true;
+ }
+ };
+
+ sp<MessageBase> msg = new MessageTurnElectronBeamOff(this);
+ status_t res = postMessageSync(msg);
+ if (res == NO_ERROR) {
+ res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();
+ }
+ return res;
+}
+
// ---------------------------------------------------------------------------
status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
@@ -2005,6 +2231,10 @@ const DisplayHardware& GraphicPlane::displayHardware() const {
return *mHw;
}
+DisplayHardware& GraphicPlane::editDisplayHardware() {
+ return *mHw;
+}
+
const Transform& GraphicPlane::transform() const {
return mGlobalTransform;
}