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