Skip to content

Commit 57337eb

Browse files
pixelflingerAndroid (Google) Code Review
authored andcommitted
Merge "Add a LayerScreenshot" into ics-mr0
2 parents eaf4952 + d6809f4 commit 57337eb

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: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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+
glDisable(GL_DITHER);
77+
78+
if (s.alpha == 0xFF) {
79+
glDisable(GL_BLEND);
80+
} else {
81+
glEnable(GL_BLEND);
82+
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
83+
}
84+
85+
glColor4f(0, 0, 0, alpha);
86+
87+
#if defined(GL_OES_EGL_image_external)
88+
if (GLExtensions::getInstance().haveTextureExternal()) {
89+
glDisable(GL_TEXTURE_EXTERNAL_OES);
90+
}
91+
#endif
92+
93+
glBindTexture(GL_TEXTURE_2D, mTextureName);
94+
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
95+
glEnable(GL_TEXTURE_2D);
96+
glMatrixMode(GL_TEXTURE);
97+
glLoadIdentity();
98+
glMatrixMode(GL_MODELVIEW);
99+
100+
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
101+
glTexCoordPointer(2, GL_FLOAT, 0, mTexCoords);
102+
glVertexPointer(2, GL_FLOAT, 0, mVertices);
103+
104+
while (it != end) {
105+
const Rect& r = *it++;
106+
const GLint sy = fbHeight - (r.top + r.height());
107+
glScissor(r.left, sy, r.width(), r.height());
108+
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
109+
}
110+
}
111+
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
112+
}
113+
114+
// ---------------------------------------------------------------------------
115+
116+
}; // 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: 25 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"
@@ -1353,6 +1354,9 @@ sp<ISurface> SurfaceFlinger::createSurface(
13531354
case eFXSurfaceDim:
13541355
layer = createDimSurface(client, d, w, h, flags);
13551356
break;
1357+
case eFXSurfaceScreenshot:
1358+
layer = createScreenshotSurface(client, d, w, h, flags);
1359+
break;
13561360
}
13571361

13581362
if (layer != 0) {
@@ -1415,7 +1419,19 @@ sp<LayerDim> SurfaceFlinger::createDimSurface(
14151419
uint32_t w, uint32_t h, uint32_t flags)
14161420
{
14171421
sp<LayerDim> layer = new LayerDim(this, display, client);
1418-
layer->initStates(w, h, flags);
1422+
return layer;
1423+
}
1424+
1425+
sp<LayerScreenshot> SurfaceFlinger::createScreenshotSurface(
1426+
const sp<Client>& client, DisplayID display,
1427+
uint32_t w, uint32_t h, uint32_t flags)
1428+
{
1429+
sp<LayerScreenshot> layer = new LayerScreenshot(this, display, client);
1430+
status_t err = layer->capture();
1431+
if (err != NO_ERROR) {
1432+
layer.clear();
1433+
LOGW("createScreenshotSurface failed (%s)", strerror(-err));
1434+
}
14191435
return layer;
14201436
}
14211437

@@ -1778,6 +1794,13 @@ void SurfaceFlinger::repaintEverything() {
17781794

17791795
// ---------------------------------------------------------------------------
17801796

1797+
status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
1798+
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
1799+
{
1800+
Mutex::Autolock _l(mStateLock);
1801+
return renderScreenToTextureLocked(dpy, textureName, uOut, vOut);
1802+
}
1803+
17811804
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
17821805
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
17831806
{
@@ -1841,11 +1864,6 @@ status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
18411864

18421865
status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
18431866
{
1844-
status_t result = PERMISSION_DENIED;
1845-
1846-
if (!GLExtensions::getInstance().haveFramebufferObject())
1847-
return INVALID_OPERATION;
1848-
18491867
// get screen geometry
18501868
const DisplayHardware& hw(graphicPlane(0).displayHardware());
18511869
const uint32_t hw_w = hw.getWidth();
@@ -1854,7 +1872,7 @@ status_t SurfaceFlinger::electronBeamOffAnimationImplLocked()
18541872

18551873
GLfloat u, v;
18561874
GLuint tname;
1857-
result = renderScreenToTextureLocked(0, &tname, &u, &v);
1875+
status_t result = renderScreenToTextureLocked(0, &tname, &u, &v);
18581876
if (result != NO_ERROR) {
18591877
return result;
18601878
}
@@ -2030,10 +2048,6 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
20302048
return result;
20312049
}
20322050

2033-
// back to main framebuffer
2034-
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
2035-
glDisable(GL_SCISSOR_TEST);
2036-
20372051
GLfloat vtx[8];
20382052
const GLfloat texCoords[4][2] = { {0,v}, {0,0}, {u,0}, {u,v} };
20392053
glBindTexture(GL_TEXTURE_2D, tname);

0 commit comments

Comments
 (0)