Skip to content

Commit 0ab84ef

Browse files
committed
Add a LayerScreenshot
A LayerScreenshot is a special type of layer that contains a screenshot of the screen acquired when its created. It works just like LayerDim. Make sure to call compositionComplete() after rendering into a FBO. Bug: 5446982, 5467587, 5466259 Change-Id: I5d8a1b4c327f9973d950cd4f4c0bca7f62825cd4
1 parent 526f0a0 commit 0ab84ef

File tree

9 files changed

+244
-64
lines changed

9 files changed

+244
-64
lines changed

core/java/android/view/Surface.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,9 @@ public OutOfResourcesException(String name) {
194194
*/
195195
public static final int FX_SURFACE_DIM = 0x00020000;
196196

197+
/** @hide */
198+
public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
199+
197200
/** Mask used for FX values above @hide */
198201
public static final int FX_SURFACE_MASK = 0x000F0000;
199202

include/surfaceflinger/ISurfaceComposer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ISurfaceComposer : public IInterface
5353
eFXSurfaceNormal = 0x00000000,
5454
eFXSurfaceBlur = 0x00010000,
5555
eFXSurfaceDim = 0x00020000,
56+
eFXSurfaceScreenshot= 0x00030000,
5657
eFXSurfaceMask = 0x000F0000,
5758
};
5859

services/java/com/android/server/wm/ScreenRotationAnimation.java

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -64,17 +64,16 @@ public ScreenRotationAnimation(Context context, SurfaceSession session,
6464
boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) {
6565
mContext = context;
6666

67-
Bitmap screenshot = Surface.screenshot(0, 0);
68-
69-
if (screenshot == null) {
70-
// Device is not capable of screenshots... we can't do an animation.
71-
return;
72-
}
73-
7467
// Screenshot does NOT include rotation!
7568
mSnapshotRotation = 0;
76-
mWidth = screenshot.getWidth();
77-
mHeight = screenshot.getHeight();
69+
if (originalRotation == Surface.ROTATION_90
70+
|| originalRotation == Surface.ROTATION_270) {
71+
mWidth = originalHeight;
72+
mHeight = originalWidth;
73+
} else {
74+
mWidth = originalWidth;
75+
mHeight = originalHeight;
76+
}
7877

7978
mOriginalRotation = originalRotation;
8079
mOriginalWidth = originalWidth;
@@ -89,7 +88,12 @@ public ScreenRotationAnimation(Context context, SurfaceSession session,
8988
try {
9089
try {
9190
mSurface = new Surface(session, 0, "FreezeSurface",
92-
-1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
91+
-1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT);
92+
if (mSurface == null || !mSurface.isValid()) {
93+
// Screenshot failed, punt.
94+
mSurface = null;
95+
return;
96+
}
9397
mSurface.setLayer(FREEZE_LAYER + 1);
9498
} catch (Surface.OutOfResourcesException e) {
9599
Slog.w(TAG, "Unable to allocate freeze surface", e);
@@ -100,38 +104,12 @@ public ScreenRotationAnimation(Context context, SurfaceSession session,
100104
" FREEZE " + mSurface + ": CREATE");
101105

102106
setRotation(originalRotation);
103-
104-
if (mSurface != null) {
105-
Rect dirty = new Rect(0, 0, mWidth, mHeight);
106-
Canvas c = null;
107-
try {
108-
c = mSurface.lockCanvas(dirty);
109-
} catch (IllegalArgumentException e) {
110-
Slog.w(TAG, "Unable to lock surface", e);
111-
} catch (Surface.OutOfResourcesException e) {
112-
Slog.w(TAG, "Unable to lock surface", e);
113-
}
114-
if (c == null) {
115-
Slog.w(TAG, "Null surface canvas");
116-
mSurface.destroy();
117-
mSurface = null;
118-
return;
119-
}
120-
121-
Paint paint = new Paint(0);
122-
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
123-
c.drawBitmap(screenshot, 0, 0, paint);
124-
125-
mSurface.unlockCanvasAndPost(c);
126-
}
127107
} finally {
128108
if (!inTransaction) {
129109
Surface.closeTransaction();
130110
if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
131111
"<<< CLOSE TRANSACTION ScreenRotationAnimation");
132112
}
133-
134-
screenshot.recycle();
135113
}
136114
}
137115

services/surfaceflinger/Android.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LOCAL_SRC_FILES:= \
55
Layer.cpp \
66
LayerBase.cpp \
77
LayerDim.cpp \
8+
LayerScreenshot.cpp \
89
DdmConnection.cpp \
910
DisplayHardware/DisplayHardware.cpp \
1011
DisplayHardware/DisplayHardwareBase.cpp \

services/surfaceflinger/Layer.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,8 @@ void Layer::onFirstRef()
8888

8989
Layer::~Layer()
9090
{
91-
class MessageDestroyGLState : public MessageBase {
92-
GLuint texture;
93-
public:
94-
MessageDestroyGLState(GLuint texture) : texture(texture) { }
95-
virtual bool handler() {
96-
glDeleteTextures(1, &texture);
97-
return true;
98-
}
99-
};
100-
mFlinger->postMessageAsync( new MessageDestroyGLState(mTextureName) );
91+
mFlinger->postMessageAsync(
92+
new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
10193
}
10294

10395
void Layer::onFrameQueued() {
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/*
2+
* Copyright (C) 2011 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include <stdlib.h>
18+
#include <stdint.h>
19+
#include <sys/types.h>
20+
21+
#include <utils/Errors.h>
22+
#include <utils/Log.h>
23+
24+
#include <ui/GraphicBuffer.h>
25+
26+
#include "LayerScreenshot.h"
27+
#include "SurfaceFlinger.h"
28+
#include "DisplayHardware/DisplayHardware.h"
29+
30+
namespace android {
31+
// ---------------------------------------------------------------------------
32+
33+
LayerScreenshot::LayerScreenshot(SurfaceFlinger* flinger, DisplayID display,
34+
const sp<Client>& client)
35+
: LayerBaseClient(flinger, display, client),
36+
mTextureName(0), mFlinger(flinger)
37+
{
38+
}
39+
40+
LayerScreenshot::~LayerScreenshot()
41+
{
42+
if (mTextureName) {
43+
mFlinger->postMessageAsync(
44+
new SurfaceFlinger::MessageDestroyGLTexture(mTextureName) );
45+
}
46+
}
47+
48+
status_t LayerScreenshot::capture() {
49+
GLfloat u, v;
50+
status_t result = mFlinger->renderScreenToTexture(0, &mTextureName, &u, &v);
51+
if (result != NO_ERROR) {
52+
return result;
53+
}
54+
55+
glBindTexture(GL_TEXTURE_2D, mTextureName);
56+
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
57+
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
58+
59+
mTexCoords[0] = 0; mTexCoords[1] = v;
60+
mTexCoords[2] = 0; mTexCoords[3] = 0;
61+
mTexCoords[4] = u; mTexCoords[5] = 0;
62+
mTexCoords[6] = u; mTexCoords[7] = v;
63+
64+
return NO_ERROR;
65+
}
66+
67+
void LayerScreenshot::onDraw(const Region& clip) const
68+
{
69+
const State& s(drawingState());
70+
Region::const_iterator it = clip.begin();
71+
Region::const_iterator const end = clip.end();
72+
if (s.alpha>0 && (it != end)) {
73+
const DisplayHardware& hw(graphicPlane(0).displayHardware());
74+
const GLfloat alpha = s.alpha/255.0f;
75+
const uint32_t fbHeight = hw.getHeight();
76+
77+
if (s.alpha == 0xFF) {
78+
glDisable(GL_BLEND);
79+
} else {
80+
glEnable(GL_BLEND);
81+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
82+
}
83+
84+
glColor4f(0, 0, 0, alpha);
85+
86+
glDisable(GL_TEXTURE_EXTERNAL_OES);
87+
glEnable(GL_TEXTURE_2D);
88+
89+
glBindTexture(GL_TEXTURE_2D, mTextureName);
90+
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
91+
glMatrixMode(GL_TEXTURE);
92+
glLoadIdentity();
93+
glMatrixMode(GL_MODELVIEW);
94+
95+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
96+
glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
97+
glVertexPointer(2, GL_FLOAT, 0, mVertices);
98+
99+
while (it != end) {
100+
const Rect& r = *it++;
101+
const GLint sy = fbHeight - (r.top + r.height());
102+
glScissor(r.left, sy, r.width(), r.height());
103+
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
104+
}
105+
106+
glDisable(GL_BLEND);
107+
glDisable(GL_TEXTURE_2D);
108+
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
109+
}
110+
}
111+
112+
// ---------------------------------------------------------------------------
113+
114+
}; // namespace android
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (C) 2011 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef ANDROID_LAYER_SCREENSHOT_H
18+
#define ANDROID_LAYER_SCREENSHOT_H
19+
20+
#include <stdint.h>
21+
#include <sys/types.h>
22+
23+
#include <EGL/egl.h>
24+
#include <EGL/eglext.h>
25+
26+
#include "LayerBase.h"
27+
28+
// ---------------------------------------------------------------------------
29+
30+
namespace android {
31+
32+
class LayerScreenshot : public LayerBaseClient
33+
{
34+
GLuint mTextureName;
35+
GLfloat mTexCoords[8];
36+
sp<SurfaceFlinger> mFlinger;
37+
public:
38+
LayerScreenshot(SurfaceFlinger* flinger, DisplayID display,
39+
const sp<Client>& client);
40+
virtual ~LayerScreenshot();
41+
42+
status_t capture();
43+
44+
virtual void onDraw(const Region& clip) const;
45+
virtual bool isOpaque() const { return false; }
46+
virtual bool isSecure() const { return false; }
47+
virtual bool isProtectedByApp() const { return false; }
48+
virtual bool isProtectedByDRM() const { return false; }
49+
virtual const char* getTypeId() const { return "LayerScreenshot"; }
50+
};
51+
52+
// ---------------------------------------------------------------------------
53+
54+
}; // namespace android
55+
56+
#endif // ANDROID_LAYER_SCREENSHOT_H

services/surfaceflinger/SurfaceFlinger.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include "DdmConnection.h"
5151
#include "Layer.h"
5252
#include "LayerDim.h"
53+
#include "LayerScreenshot.h"
5354
#include "SurfaceFlinger.h"
5455

5556
#include "DisplayHardware/DisplayHardware.h"
@@ -1358,6 +1359,9 @@ sp<ISurface> SurfaceFlinger::createSurface(
13581359
case eFXSurfaceDim:
13591360
layer = createDimSurface(client, d, w, h, flags);
13601361
break;
1362+
case eFXSurfaceScreenshot:
1363+
layer = createScreenshotSurface(client, d, w, h, flags);
1364+
break;
13611365
}
13621366

13631367
if (layer != 0) {
@@ -1420,7 +1424,19 @@ sp<LayerDim> SurfaceFlinger::createDimSurface(
14201424
uint32_t w, uint32_t h, uint32_t flags)
14211425
{
14221426
sp<LayerDim> layer = new LayerDim(this, display, client);
1423-
layer->initStates(w, h, flags);
1427+
return layer;
1428+
}
1429+
1430+
sp<LayerScreenshot> SurfaceFlinger::createScreenshotSurface(
1431+
const sp<Client>& client, DisplayID display,
1432+
uint32_t w, uint32_t h, uint32_t flags)
1433+
{
1434+
sp<LayerScreenshot> layer = new LayerScreenshot(this, display, client);
1435+
status_t err = layer->capture();
1436+
if (err != NO_ERROR) {
1437+
layer.clear();
1438+
LOGW("createScreenshotSurface failed (%s)", strerror(-err));
1439+
}
14241440
return layer;
14251441
}
14261442

@@ -1783,6 +1799,13 @@ void SurfaceFlinger::repaintEverything() {
17831799

17841800
// ---------------------------------------------------------------------------
17851801

1802+
status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
1803+
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
1804+
{
1805+
Mutex::Autolock _l(mStateLock);
1806+
return renderScreenToTextureLocked(dpy, textureName, uOut, vOut);
1807+
}
1808+
17861809
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
17871810
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
17881811
{
@@ -1833,6 +1856,8 @@ status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
18331856
layer->drawForSreenShot();
18341857
}
18351858

1859+
hw.compositionComplete();
1860+
18361861
// back to main framebuffer
18371862
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
18381863
glDisable(GL_SCISSOR_TEST);
@@ -1848,11 +1873,6 @@ status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
18481873

18491874
status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
18501875
{
1851-
status_t result = PERMISSION_DENIED;
1852-
1853-
if (!GLExtensions::getInstance().haveFramebufferObject())
1854-
return INVALID_OPERATION;
1855-
18561876
// get screen geometry
18571877
const DisplayHardware& hw(graphicPlane(0).displayHardware());
18581878
const uint32_t hw_w = hw.getWidth();
@@ -1861,7 +1881,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
18611881

18621882
GLfloat u, v;
18631883
GLuint tname;
1864-
result = renderScreenToTextureLocked(0, &tname, &u, &v);
1884+
status_t result = renderScreenToTextureLocked(0, &tname, &u, &v);
18651885
if (result != NO_ERROR) {
18661886
return result;
18671887
}
@@ -2038,10 +2058,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
20382058
return result;
20392059
}
20402060

2041-
// back to main framebuffer
2042-
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
2043-
glDisable(GL_SCISSOR_TEST);
2044-
20452061
GLfloat vtx[8];
20462062
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
20472063
glBindTexture(GL_TEXTURE_2D, tname);

0 commit comments

Comments
 (0)