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