implement part of [3094280] New animation for screen on and screen off

add support for screen on animation

Change-Id: If50cf52ae04b95b42da7d74cf7fa96d5cb54d238
This commit is contained in:
Mathias Agopian 2010-10-12 16:05:48 -07:00
parent 137ef22cef
commit 9daa5c9b9d
5 changed files with 394 additions and 150 deletions

View File

@ -119,6 +119,7 @@ public:
uint32_t reqWidth, uint32_t reqHeight) = 0;
virtual status_t turnElectronBeamOff(int32_t mode) = 0;
virtual status_t turnElectronBeamOn(int32_t mode) = 0;
/* Signal surfaceflinger that there might be some work to do
* This is an ASYNCHRONOUS call.
@ -145,7 +146,8 @@ public:
UNFREEZE_DISPLAY,
SIGNAL,
CAPTURE_SCREEN,
TURN_ELECTRON_BEAM_OFF
TURN_ELECTRON_BEAM_OFF,
TURN_ELECTRON_BEAM_ON
};
virtual status_t onTransact( uint32_t code,

View File

@ -151,6 +151,15 @@ public:
return reply.readInt32();
}
virtual status_t turnElectronBeamOn(int32_t mode)
{
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeInt32(mode);
remote()->transact(BnSurfaceComposer::TURN_ELECTRON_BEAM_ON, data, &reply);
return reply.readInt32();
}
virtual void signal() const
{
Parcel data, reply;
@ -239,6 +248,12 @@ status_t BnSurfaceComposer::onTransact(
status_t res = turnElectronBeamOff(mode);
reply->writeInt32(res);
}
case TURN_ELECTRON_BEAM_ON: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
int32_t mode = data.readInt32();
status_t res = turnElectronBeamOn(mode);
reply->writeInt32(res);
}
default:
return BBinder::onTransact(code, data, reply, flags);
}

View File

@ -396,7 +396,6 @@ void DisplayHardwareBase::acquireScreen() const
{
status_t err = mDisplayEventThread->acquireScreen();
if (err >= 0) {
mCanDraw = true;
mScreenAcquired = true;
}
}

View File

@ -80,6 +80,7 @@ SurfaceFlinger::SurfaceFlinger()
mVisibleRegionsDirty(false),
mDeferReleaseConsole(false),
mFreezeDisplay(false),
mElectronBeamAnimation(false),
mFreezeCount(0),
mFreezeDisplayTime(0),
mDebugRegion(0),
@ -421,6 +422,10 @@ void SurfaceFlinger::handleConsoleEvents()
int what = android_atomic_and(0, &mConsoleSignals);
if (what & eConsoleAcquired) {
hw.acquireScreen();
// this is a temporary work-around, eventually this should be called
// by the power-manager
if (mElectronBeamAnimation)
SurfaceFlinger::turnElectronBeamOn(0);
}
if (mDeferReleaseConsole && hw.isScreenAcquired()) {
@ -1457,6 +1462,7 @@ status_t SurfaceFlinger::onTransact(
case UNFREEZE_DISPLAY:
case BOOT_FINISHED:
case TURN_ELECTRON_BEAM_OFF:
case TURN_ELECTRON_BEAM_ON:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
@ -1545,27 +1551,18 @@ status_t SurfaceFlinger::onTransact(
return err;
}
// ---------------------------------------------------------------------------
status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
{
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;
@ -1576,22 +1573,21 @@ status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
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);
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);
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);
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);
@ -1601,15 +1597,47 @@ status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
const sp<LayerBase>& layer(layers[i]);
layer->drawForSreenShot();
}
// back to main framebuffer
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDisable(GL_SCISSOR_TEST);
glDeleteFramebuffersOES(1, &name);
*textureName = tname;
*uOut = u;
*vOut = v;
return NO_ERROR;
}
// ---------------------------------------------------------------------------
status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
{
status_t result = PERMISSION_DENIED;
if (!GLExtensions::getInstance().haveFramebufferObject())
return INVALID_OPERATION;
// get screen geometry
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t hw_w = hw.getWidth();
const uint32_t hw_h = hw.getHeight();
const Region screenBounds(hw.bounds());
GLfloat u, v;
GLuint tname;
result = renderScreenToTextureLocked(0, &tname, &u, &v);
if (result != NO_ERROR) {
return result;
}
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);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, vtx);
@ -1665,11 +1693,11 @@ status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
// 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);
v_stretch vverts(hw_w, hw_h);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
for (int i=0 ; i<nbFrames ; i++) {
@ -1722,21 +1750,167 @@ status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
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;
glDeleteTextures(1, &tname);
return NO_ERROR;
}
glDeleteFramebuffersOES(1, &name);
status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
{
status_t result = PERMISSION_DENIED;
if (!GLExtensions::getInstance().haveFramebufferObject())
return INVALID_OPERATION;
// get screen geometry
const DisplayHardware& hw(graphicPlane(0).displayHardware());
const uint32_t hw_w = hw.getWidth();
const uint32_t hw_h = hw.getHeight();
const Region screenBounds(hw.bounds());
GLfloat u, v;
GLuint tname;
result = renderScreenToTextureLocked(0, &tname, &u, &v);
if (result != NO_ERROR) {
return result;
}
// 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_MODULATE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
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;
s_curve_interpolator itr(nbFrames, 7.5f);
s_curve_interpolator itg(nbFrames, 8.0f);
s_curve_interpolator itb(nbFrames, 8.5f);
h_stretch hverts(hw_w, hw_h);
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
glColorMask(1,1,1,1);
for (int i=nbFrames-1 ; i>=0 ; 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);
}
v_stretch vverts(hw_w, hw_h);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
for (int i=nbFrames-1 ; i>=0 ; 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);
hw.flip(screenBounds);
}
glColorMask(1,1,1,1);
glEnable(GL_SCISSOR_TEST);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDeleteTextures(1, &tname);
if (result == NO_ERROR) {
DisplayHardware& hw(graphicPlane(dpy).editDisplayHardware());
hw.setCanDraw(false);
return NO_ERROR;
}
// ---------------------------------------------------------------------------
status_t SurfaceFlinger::turnElectronBeamOffImplLocked()
{
DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
if (!hw.canDraw()) {
// we're already off
return NO_ERROR;
}
status_t result = electronBeamOffAnimationImplLocked();
if (result == NO_ERROR) {
hw.setCanDraw(false);
}
return result;
}
@ -1766,12 +1940,59 @@ status_t SurfaceFlinger::turnElectronBeamOff(int32_t mode)
status_t res = postMessageSync(msg);
if (res == NO_ERROR) {
res = static_cast<MessageTurnElectronBeamOff*>( msg.get() )->getResult();
// work-around: when the power-manager calls us we activate the
// animation. eventually, the "on" animation will be called
// by the power-manager itself
mElectronBeamAnimation = true;
}
return res;
}
// ---------------------------------------------------------------------------
status_t SurfaceFlinger::turnElectronBeamOnImplLocked()
{
DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
if (hw.canDraw()) {
// we're already on
return NO_ERROR;
}
status_t result = electronBeamOnAnimationImplLocked();
if (result == NO_ERROR) {
hw.setCanDraw(true);
}
return result;
}
status_t SurfaceFlinger::turnElectronBeamOn(int32_t mode)
{
if (!GLExtensions::getInstance().haveFramebufferObject())
return INVALID_OPERATION;
class MessageTurnElectronBeamOn : public MessageBase {
SurfaceFlinger* flinger;
status_t result;
public:
MessageTurnElectronBeamOn(SurfaceFlinger* flinger)
: flinger(flinger), result(PERMISSION_DENIED) {
}
status_t getResult() const {
return result;
}
virtual bool handler() {
Mutex::Autolock _l(flinger->mStateLock);
result = flinger->turnElectronBeamOnImplLocked();
return true;
}
};
postMessageAsync( new MessageTurnElectronBeamOn(this) );
return NO_ERROR;
}
// ---------------------------------------------------------------------------
status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy,
sp<IMemoryHeap>* heap,
uint32_t* w, uint32_t* h, PixelFormat* f,

View File

@ -202,6 +202,7 @@ public:
uint32_t reqWidth,
uint32_t reqHeight);
virtual status_t turnElectronBeamOff(int32_t mode);
virtual status_t turnElectronBeamOn(int32_t mode);
void screenReleased(DisplayID dpy);
void screenAcquired(DisplayID dpy);
@ -328,6 +329,11 @@ private:
uint32_t reqWidth = 0, uint32_t reqHeight = 0);
status_t turnElectronBeamOffImplLocked();
status_t turnElectronBeamOnImplLocked();
status_t electronBeamOffAnimationImplLocked();
status_t electronBeamOnAnimationImplLocked();
status_t renderScreenToTextureLocked(DisplayID dpy,
GLuint* textureName, GLfloat* uOut, GLfloat* vOut);
friend class FreezeLock;
sp<FreezeLock> getFreezeLock() const;
@ -389,6 +395,7 @@ private:
bool mVisibleRegionsDirty;
bool mDeferReleaseConsole;
bool mFreezeDisplay;
bool mElectronBeamAnimation;
int32_t mFreezeCount;
nsecs_t mFreezeDisplayTime;
Vector< sp<LayerBase> > mVisibleLayersSortedByZ;