blob: 2b72d7ce948783c7b2c945e32bdf1aeb71e0c63a [file] [log] [blame]
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -08001/*
2 * Copyright (C) 2007 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#define LOG_TAG "SurfaceFlinger"
18
19#include <stdlib.h>
20#include <stdint.h>
21#include <sys/types.h>
22
23#include <utils/Errors.h>
24#include <utils/Log.h>
25
26#include <core/SkBitmap.h>
27
28#include <ui/EGLDisplaySurface.h>
29
30#include "LayerBase.h"
31#include "LayerOrientationAnim.h"
32#include "SurfaceFlinger.h"
33#include "DisplayHardware/DisplayHardware.h"
34#include "OrientationAnimation.h"
35
36namespace android {
37// ---------------------------------------------------------------------------
38
39const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80;
40const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim";
41
42// ---------------------------------------------------------------------------
43
44LayerOrientationAnim::LayerOrientationAnim(
45 SurfaceFlinger* flinger, DisplayID display,
46 OrientationAnimation* anim,
47 const LayerBitmap& bitmap,
48 const LayerBitmap& bitmapIn)
49 : LayerBase(flinger, display), mAnim(anim),
50 mBitmap(bitmap), mBitmapIn(bitmapIn),
51 mTextureName(-1), mTextureNameIn(-1)
52{
53 mStartTime = systemTime();
54 mFinishTime = 0;
55 mOrientationCompleted = false;
56 mFirstRedraw = false;
57 mLastNormalizedTime = 0;
58 mLastScale = 0;
59 mNeedsBlending = false;
60}
61
62LayerOrientationAnim::~LayerOrientationAnim()
63{
64 if (mTextureName != -1U) {
65 LayerBase::deletedTextures.add(mTextureName);
66 }
67 if (mTextureNameIn != -1U) {
68 LayerBase::deletedTextures.add(mTextureNameIn);
69 }
70}
71
72bool LayerOrientationAnim::needsBlending() const
73{
74 return mNeedsBlending;
75}
76
77Point LayerOrientationAnim::getPhysicalSize() const
78{
79 const GraphicPlane& plane(graphicPlane(0));
80 const DisplayHardware& hw(plane.displayHardware());
81 return Point(hw.getWidth(), hw.getHeight());
82}
83
84void LayerOrientationAnim::validateVisibility(const Transform&)
85{
86 const Layer::State& s(drawingState());
The Android Open Source Projectac65e0b2009-02-13 12:57:50 -080087 const Transform tr(s.transform);
The Android Open Source Projecta6938ba2009-02-10 15:44:00 -080088 const Point size(getPhysicalSize());
89 uint32_t w = size.x;
90 uint32_t h = size.y;
91 mTransformedBounds = tr.makeBounds(w, h);
92 mLeft = tr.tx();
93 mTop = tr.ty();
94 transparentRegionScreen.clear();
95 mTransformed = true;
96 mCanUseCopyBit = false;
97 copybit_device_t* copybit = mFlinger->getBlitEngine();
98 if (copybit) {
99 mCanUseCopyBit = true;
100 }
101}
102
103void LayerOrientationAnim::onOrientationCompleted()
104{
105 mFinishTime = systemTime();
106 mOrientationCompleted = true;
107 mFirstRedraw = true;
108 mNeedsBlending = true;
109 mFlinger->invalidateLayerVisibility(this);
110}
111
112void LayerOrientationAnim::onDraw(const Region& clip) const
113{
114 // Animation...
115 const float MIN_SCALE = 0.5f;
116 const float DURATION = ms2ns(200);
117 const float BOUNCES_PER_SECOND = 1.618f;
118 const float BOUNCES_AMPLITUDE = 1.0f/32.0f;
119
120 const nsecs_t now = systemTime();
121 float scale, alpha;
122
123 if (mOrientationCompleted) {
124 if (mFirstRedraw) {
125 mFirstRedraw = false;
126
127 // make a copy of what's on screen
128 copybit_image_t image;
129 mBitmapIn.getBitmapSurface(&image);
130 const DisplayHardware& hw(graphicPlane(0).displayHardware());
131 hw.copyBackToImage(image);
132
133 // and erase the screen for this round
134 glDisable(GL_BLEND);
135 glDisable(GL_DITHER);
136 glDisable(GL_SCISSOR_TEST);
137 glClearColor(0,0,0,0);
138 glClear(GL_COLOR_BUFFER_BIT);
139
140 // FIXME: code below is gross
141 mNeedsBlending = false;
142 LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this));
143 mFlinger->invalidateLayerVisibility(self);
144 }
145
146 // make sure pick-up where we left off
147 const float duration = DURATION * mLastNormalizedTime;
148 const float normalizedTime = (float(now - mFinishTime) / duration);
149 if (normalizedTime <= 1.0f) {
150 const float squaredTime = normalizedTime*normalizedTime;
151 scale = (1.0f - mLastScale)*squaredTime + mLastScale;
152 alpha = (1.0f - normalizedTime);
153 alpha *= alpha;
154 alpha *= alpha;
155 } else {
156 mAnim->onAnimationFinished();
157 scale = 1.0f;
158 alpha = 0.0f;
159 }
160 } else {
161 const float normalizedTime = float(now - mStartTime) / DURATION;
162 if (normalizedTime <= 1.0f) {
163 mLastNormalizedTime = normalizedTime;
164 const float squaredTime = normalizedTime*normalizedTime;
165 scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f;
166 alpha = 1.0f;
167 } else {
168 mLastNormalizedTime = 1.0f;
169 const float to_seconds = DURATION / seconds(1);
170 const float phi = BOUNCES_PER_SECOND *
171 (((normalizedTime - 1.0f) * to_seconds)*M_PI*2);
172 scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi));
173 alpha = 1.0f;
174 }
175 mLastScale = scale;
176 }
177 drawScaled(scale, alpha);
178}
179
180void LayerOrientationAnim::drawScaled(float f, float alpha) const
181{
182 copybit_image_t dst;
183 const GraphicPlane& plane(graphicPlane(0));
184 const DisplayHardware& hw(plane.displayHardware());
185 hw.getDisplaySurface(&dst);
186
187 // clear screen
188 // TODO: with update on demand, we may be able
189 // to not erase the screen at all during the animation
190 if (!mOrientationCompleted) {
191 glDisable(GL_BLEND);
192 glDisable(GL_DITHER);
193 glDisable(GL_SCISSOR_TEST);
194 glClearColor(0,0,0,0);
195 glClear(GL_COLOR_BUFFER_BIT);
196 }
197
198 const int w = dst.w*f;
199 const int h = dst.h*f;
200 const int xc = uint32_t(dst.w-w)/2;
201 const int yc = uint32_t(dst.h-h)/2;
202 const copybit_rect_t drect = { xc, yc, xc+w, yc+h };
203
204 copybit_image_t src;
205 mBitmap.getBitmapSurface(&src);
206 const copybit_rect_t srect = { 0, 0, src.w, src.h };
207
208 int err = NO_ERROR;
209 const int can_use_copybit = canUseCopybit();
210 if (can_use_copybit) {
211 copybit_device_t* copybit = mFlinger->getBlitEngine();
212 copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
213 copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
214
215 if (alpha < 1.0f) {
216 copybit_image_t srcIn;
217 mBitmapIn.getBitmapSurface(&srcIn);
218 region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b )));
219 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
220 err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it);
221 }
222
223 if (!err && alpha > 0.0f) {
224 region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b )));
225 copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255));
226 err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
227 }
228 LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
229 }
230 if (!can_use_copybit || err) {
231 GGLSurface t;
232 t.version = sizeof(GGLSurface);
233 t.width = src.w;
234 t.height = src.h;
235 t.stride = src.w;
236 t.vstride= src.h;
237 t.format = src.format;
238 t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
239
240 Transform tr;
241 tr.set(f,0,0,f);
242 tr.set(xc, yc);
243
244 // FIXME: we should not access mVertices and mDrawingState like that,
245 // but since we control the animation, we know it's going to work okay.
246 // eventually we'd need a more formal way of doing things like this.
247 LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
248 tr.transform(self.mVertices[0], 0, 0);
249 tr.transform(self.mVertices[1], 0, src.h);
250 tr.transform(self.mVertices[2], src.w, src.h);
251 tr.transform(self.mVertices[3], src.w, 0);
252 if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
253 // Too slow to do this in software
254 self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
255 }
256
257 if (alpha < 1.0f) {
258 copybit_image_t src;
259 mBitmapIn.getBitmapSurface(&src);
260 t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
261 if (UNLIKELY(mTextureNameIn == -1LU)) {
262 mTextureNameIn = createTexture();
263 GLuint w=0, h=0;
264 const Region dirty(Rect(t.width, t.height));
265 loadTexture(dirty, mTextureNameIn, t, w, h);
266 }
267 self.mDrawingState.alpha = 255;
268 const Region clip(Rect( drect.l, drect.t, drect.r, drect.b ));
269 drawWithOpenGL(clip, mTextureName, t);
270 }
271
272 t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
273 if (UNLIKELY(mTextureName == -1LU)) {
274 mTextureName = createTexture();
275 GLuint w=0, h=0;
276 const Region dirty(Rect(t.width, t.height));
277 loadTexture(dirty, mTextureName, t, w, h);
278 }
279 self.mDrawingState.alpha = int(alpha*255);
280 const Region clip(Rect( drect.l, drect.t, drect.r, drect.b ));
281 drawWithOpenGL(clip, mTextureName, t);
282 }
283}
284
285// ---------------------------------------------------------------------------
286
287}; // namespace android