blob: 5fec325b807f19d551791120f7c7e235bb8307ba [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -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;
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -070058 mLastAngle = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080059 mLastScale = 0;
60 mNeedsBlending = false;
61}
62
63LayerOrientationAnim::~LayerOrientationAnim()
64{
65 if (mTextureName != -1U) {
66 LayerBase::deletedTextures.add(mTextureName);
67 }
68 if (mTextureNameIn != -1U) {
69 LayerBase::deletedTextures.add(mTextureNameIn);
70 }
71}
72
73bool LayerOrientationAnim::needsBlending() const
74{
75 return mNeedsBlending;
76}
77
78Point LayerOrientationAnim::getPhysicalSize() const
79{
80 const GraphicPlane& plane(graphicPlane(0));
81 const DisplayHardware& hw(plane.displayHardware());
82 return Point(hw.getWidth(), hw.getHeight());
83}
84
85void LayerOrientationAnim::validateVisibility(const Transform&)
86{
87 const Layer::State& s(drawingState());
88 const Transform tr(s.transform);
89 const Point size(getPhysicalSize());
90 uint32_t w = size.x;
91 uint32_t h = size.y;
92 mTransformedBounds = tr.makeBounds(w, h);
93 mLeft = tr.tx();
94 mTop = tr.ty();
95 transparentRegionScreen.clear();
96 mTransformed = true;
97 mCanUseCopyBit = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080098}
99
100void LayerOrientationAnim::onOrientationCompleted()
101{
102 mFinishTime = systemTime();
103 mOrientationCompleted = true;
104 mFirstRedraw = true;
105 mNeedsBlending = true;
106 mFlinger->invalidateLayerVisibility(this);
107}
108
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700109const float ROTATION = M_PI * 0.5f;
110const float ROTATION_FACTOR = 1.0f; // 1.0 or 2.0
111const float DURATION = ms2ns(200);
112const float BOUNCES_PER_SECOND = 1.618f;
113const float BOUNCES_AMPLITUDE = (5.0f/180.f) * M_PI;
114
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800115void LayerOrientationAnim::onDraw(const Region& clip) const
116{
117 // Animation...
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800118
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700119 // FIXME: works only for portrait framebuffers
120 const Point size(getPhysicalSize());
121 const float TARGET_SCALE = size.x * (1.0f / size.y);
122
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800123 const nsecs_t now = systemTime();
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700124 float angle, scale, alpha;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800125
126 if (mOrientationCompleted) {
127 if (mFirstRedraw) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800128 // make a copy of what's on screen
129 copybit_image_t image;
130 mBitmapIn.getBitmapSurface(&image);
131 const DisplayHardware& hw(graphicPlane(0).displayHardware());
132 hw.copyBackToImage(image);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800133
134 // FIXME: code below is gross
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700135 mFirstRedraw = false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800136 mNeedsBlending = false;
137 LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this));
138 mFlinger->invalidateLayerVisibility(self);
139 }
140
141 // make sure pick-up where we left off
142 const float duration = DURATION * mLastNormalizedTime;
143 const float normalizedTime = (float(now - mFinishTime) / duration);
144 if (normalizedTime <= 1.0f) {
145 const float squaredTime = normalizedTime*normalizedTime;
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700146 angle = (ROTATION*ROTATION_FACTOR - mLastAngle)*squaredTime + mLastAngle;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800147 scale = (1.0f - mLastScale)*squaredTime + mLastScale;
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700148 alpha = normalizedTime;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800149 } else {
150 mAnim->onAnimationFinished();
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700151 angle = ROTATION;
152 alpha = 1.0f;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800153 scale = 1.0f;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800154 }
155 } else {
156 const float normalizedTime = float(now - mStartTime) / DURATION;
157 if (normalizedTime <= 1.0f) {
158 mLastNormalizedTime = normalizedTime;
159 const float squaredTime = normalizedTime*normalizedTime;
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700160 angle = ROTATION * squaredTime;
161 scale = (TARGET_SCALE - 1.0f)*squaredTime + 1.0f;
162 alpha = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800163 } else {
164 mLastNormalizedTime = 1.0f;
165 const float to_seconds = DURATION / seconds(1);
166 const float phi = BOUNCES_PER_SECOND *
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700167 (((normalizedTime - 1.0f) * to_seconds)*M_PI*2);
168 angle = ROTATION + BOUNCES_AMPLITUDE * sinf(phi);
169 scale = TARGET_SCALE;
170 alpha = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800171 }
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700172 mLastAngle = angle;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800173 mLastScale = scale;
174 }
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700175 drawScaled(angle, scale, alpha);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176}
177
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700178void LayerOrientationAnim::drawScaled(float f, float s, float alpha) const
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800179{
180 copybit_image_t dst;
181 const GraphicPlane& plane(graphicPlane(0));
182 const DisplayHardware& hw(plane.displayHardware());
183 hw.getDisplaySurface(&dst);
184
185 // clear screen
186 // TODO: with update on demand, we may be able
187 // to not erase the screen at all during the animation
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700188 glDisable(GL_BLEND);
189 glDisable(GL_DITHER);
190 glDisable(GL_SCISSOR_TEST);
191 glClearColor(0,0,0,0);
192 glClear(GL_COLOR_BUFFER_BIT);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800193
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700194 const int w = dst.w;
195 const int h = dst.h;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800196
197 copybit_image_t src;
198 mBitmap.getBitmapSurface(&src);
199 const copybit_rect_t srect = { 0, 0, src.w, src.h };
200
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800201
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700202 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);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800210
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700211 const int targetOrientation = plane.getOrientation();
212 if (!targetOrientation) {
213 f = -f;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800214 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800215
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700216 Transform tr;
217 tr.set(f, w*0.5f, h*0.5f);
218 tr.scale(s, w*0.5f, h*0.5f);
219
220 // FIXME: we should not access mVertices and mDrawingState like that,
221 // but since we control the animation, we know it's going to work okay.
222 // eventually we'd need a more formal way of doing things like this.
223 LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
224 tr.transform(self.mVertices[0], 0, 0);
225 tr.transform(self.mVertices[1], 0, src.h);
226 tr.transform(self.mVertices[2], src.w, src.h);
227 tr.transform(self.mVertices[3], src.w, 0);
228
229 if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
230 // Too slow to do this in software
231 self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
232 }
233
234 if (UNLIKELY(mTextureName == -1LU)) {
235 mTextureName = createTexture();
236 GLuint w=0, h=0;
237 const Region dirty(Rect(t.width, t.height));
238 loadTexture(dirty, mTextureName, t, w, h);
239 }
240 self.mDrawingState.alpha = 255; //-int(alpha*255);
241 const Region clip(Rect( srect.l, srect.t, srect.r, srect.b ));
242 drawWithOpenGL(clip, mTextureName, t);
243
244 if (alpha > 0) {
245 const float sign = (!targetOrientation) ? 1.0f : -1.0f;
246 tr.set(f + sign*(M_PI * 0.5f * ROTATION_FACTOR), w*0.5f, h*0.5f);
247 tr.scale(s, w*0.5f, h*0.5f);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800248 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);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800252
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700253 copybit_image_t src;
254 mBitmapIn.getBitmapSurface(&src);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800255 t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700256 if (UNLIKELY(mTextureNameIn == -1LU)) {
257 mTextureNameIn = createTexture();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800258 GLuint w=0, h=0;
259 const Region dirty(Rect(t.width, t.height));
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700260 loadTexture(dirty, mTextureNameIn, t, w, h);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800261 }
262 self.mDrawingState.alpha = int(alpha*255);
The Android Open Source Project0c2bcbc2009-03-19 23:08:54 -0700263 const Region clip(Rect( srect.l, srect.t, srect.r, srect.b ));
264 drawWithOpenGL(clip, mTextureNameIn, t);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800265 }
266}
267
268// ---------------------------------------------------------------------------
269
270}; // namespace android