auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/LayerOrientationAnim.cpp b/libs/surfaceflinger/LayerOrientationAnim.cpp
new file mode 100644
index 0000000..2b72d7c
--- /dev/null
+++ b/libs/surfaceflinger/LayerOrientationAnim.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceFlinger"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+#include <core/SkBitmap.h>
+
+#include <ui/EGLDisplaySurface.h>
+
+#include "LayerBase.h"
+#include "LayerOrientationAnim.h"
+#include "SurfaceFlinger.h"
+#include "DisplayHardware/DisplayHardware.h"
+#include "OrientationAnimation.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+const uint32_t LayerOrientationAnim::typeInfo = LayerBase::typeInfo | 0x80;
+const char* const LayerOrientationAnim::typeID = "LayerOrientationAnim";
+
+// ---------------------------------------------------------------------------
+
+LayerOrientationAnim::LayerOrientationAnim(
+ SurfaceFlinger* flinger, DisplayID display,
+ OrientationAnimation* anim,
+ const LayerBitmap& bitmap,
+ const LayerBitmap& bitmapIn)
+ : LayerBase(flinger, display), mAnim(anim),
+ mBitmap(bitmap), mBitmapIn(bitmapIn),
+ mTextureName(-1), mTextureNameIn(-1)
+{
+ mStartTime = systemTime();
+ mFinishTime = 0;
+ mOrientationCompleted = false;
+ mFirstRedraw = false;
+ mLastNormalizedTime = 0;
+ mLastScale = 0;
+ mNeedsBlending = false;
+}
+
+LayerOrientationAnim::~LayerOrientationAnim()
+{
+ if (mTextureName != -1U) {
+ LayerBase::deletedTextures.add(mTextureName);
+ }
+ if (mTextureNameIn != -1U) {
+ LayerBase::deletedTextures.add(mTextureNameIn);
+ }
+}
+
+bool LayerOrientationAnim::needsBlending() const
+{
+ return mNeedsBlending;
+}
+
+Point LayerOrientationAnim::getPhysicalSize() const
+{
+ const GraphicPlane& plane(graphicPlane(0));
+ const DisplayHardware& hw(plane.displayHardware());
+ return Point(hw.getWidth(), hw.getHeight());
+}
+
+void LayerOrientationAnim::validateVisibility(const Transform&)
+{
+ const Layer::State& s(drawingState());
+ const Transform tr(s.transform);
+ const Point size(getPhysicalSize());
+ uint32_t w = size.x;
+ uint32_t h = size.y;
+ mTransformedBounds = tr.makeBounds(w, h);
+ mLeft = tr.tx();
+ mTop = tr.ty();
+ transparentRegionScreen.clear();
+ mTransformed = true;
+ mCanUseCopyBit = false;
+ copybit_device_t* copybit = mFlinger->getBlitEngine();
+ if (copybit) {
+ mCanUseCopyBit = true;
+ }
+}
+
+void LayerOrientationAnim::onOrientationCompleted()
+{
+ mFinishTime = systemTime();
+ mOrientationCompleted = true;
+ mFirstRedraw = true;
+ mNeedsBlending = true;
+ mFlinger->invalidateLayerVisibility(this);
+}
+
+void LayerOrientationAnim::onDraw(const Region& clip) const
+{
+ // Animation...
+ const float MIN_SCALE = 0.5f;
+ const float DURATION = ms2ns(200);
+ const float BOUNCES_PER_SECOND = 1.618f;
+ const float BOUNCES_AMPLITUDE = 1.0f/32.0f;
+
+ const nsecs_t now = systemTime();
+ float scale, alpha;
+
+ if (mOrientationCompleted) {
+ if (mFirstRedraw) {
+ mFirstRedraw = false;
+
+ // make a copy of what's on screen
+ copybit_image_t image;
+ mBitmapIn.getBitmapSurface(&image);
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ hw.copyBackToImage(image);
+
+ // and erase the screen for this round
+ glDisable(GL_BLEND);
+ glDisable(GL_DITHER);
+ glDisable(GL_SCISSOR_TEST);
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ // FIXME: code below is gross
+ mNeedsBlending = false;
+ LayerOrientationAnim* self(const_cast<LayerOrientationAnim*>(this));
+ mFlinger->invalidateLayerVisibility(self);
+ }
+
+ // make sure pick-up where we left off
+ const float duration = DURATION * mLastNormalizedTime;
+ const float normalizedTime = (float(now - mFinishTime) / duration);
+ if (normalizedTime <= 1.0f) {
+ const float squaredTime = normalizedTime*normalizedTime;
+ scale = (1.0f - mLastScale)*squaredTime + mLastScale;
+ alpha = (1.0f - normalizedTime);
+ alpha *= alpha;
+ alpha *= alpha;
+ } else {
+ mAnim->onAnimationFinished();
+ scale = 1.0f;
+ alpha = 0.0f;
+ }
+ } else {
+ const float normalizedTime = float(now - mStartTime) / DURATION;
+ if (normalizedTime <= 1.0f) {
+ mLastNormalizedTime = normalizedTime;
+ const float squaredTime = normalizedTime*normalizedTime;
+ scale = (MIN_SCALE-1.0f)*squaredTime + 1.0f;
+ alpha = 1.0f;
+ } else {
+ mLastNormalizedTime = 1.0f;
+ const float to_seconds = DURATION / seconds(1);
+ const float phi = BOUNCES_PER_SECOND *
+ (((normalizedTime - 1.0f) * to_seconds)*M_PI*2);
+ scale = MIN_SCALE + BOUNCES_AMPLITUDE * (1.0f - cosf(phi));
+ alpha = 1.0f;
+ }
+ mLastScale = scale;
+ }
+ drawScaled(scale, alpha);
+}
+
+void LayerOrientationAnim::drawScaled(float f, float alpha) const
+{
+ copybit_image_t dst;
+ const GraphicPlane& plane(graphicPlane(0));
+ const DisplayHardware& hw(plane.displayHardware());
+ hw.getDisplaySurface(&dst);
+
+ // clear screen
+ // TODO: with update on demand, we may be able
+ // to not erase the screen at all during the animation
+ if (!mOrientationCompleted) {
+ glDisable(GL_BLEND);
+ glDisable(GL_DITHER);
+ glDisable(GL_SCISSOR_TEST);
+ glClearColor(0,0,0,0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ const int w = dst.w*f;
+ const int h = dst.h*f;
+ const int xc = uint32_t(dst.w-w)/2;
+ const int yc = uint32_t(dst.h-h)/2;
+ const copybit_rect_t drect = { xc, yc, xc+w, yc+h };
+
+ copybit_image_t src;
+ mBitmap.getBitmapSurface(&src);
+ const copybit_rect_t srect = { 0, 0, src.w, src.h };
+
+ int err = NO_ERROR;
+ const int can_use_copybit = canUseCopybit();
+ if (can_use_copybit) {
+ copybit_device_t* copybit = mFlinger->getBlitEngine();
+ copybit->set_parameter(copybit, COPYBIT_TRANSFORM, 0);
+ copybit->set_parameter(copybit, COPYBIT_DITHER, COPYBIT_ENABLE);
+
+ if (alpha < 1.0f) {
+ copybit_image_t srcIn;
+ mBitmapIn.getBitmapSurface(&srcIn);
+ region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b )));
+ copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 0xFF);
+ err = copybit->stretch(copybit, &dst, &srcIn, &drect, &srect, &it);
+ }
+
+ if (!err && alpha > 0.0f) {
+ region_iterator it(Region(Rect( drect.l, drect.t, drect.r, drect.b )));
+ copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, int(alpha*255));
+ err = copybit->stretch(copybit, &dst, &src, &drect, &srect, &it);
+ }
+ LOGE_IF(err != NO_ERROR, "copybit failed (%s)", strerror(err));
+ }
+ if (!can_use_copybit || err) {
+ GGLSurface t;
+ t.version = sizeof(GGLSurface);
+ t.width = src.w;
+ t.height = src.h;
+ t.stride = src.w;
+ t.vstride= src.h;
+ t.format = src.format;
+ t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
+
+ Transform tr;
+ tr.set(f,0,0,f);
+ tr.set(xc, yc);
+
+ // FIXME: we should not access mVertices and mDrawingState like that,
+ // but since we control the animation, we know it's going to work okay.
+ // eventually we'd need a more formal way of doing things like this.
+ LayerOrientationAnim& self(const_cast<LayerOrientationAnim&>(*this));
+ tr.transform(self.mVertices[0], 0, 0);
+ tr.transform(self.mVertices[1], 0, src.h);
+ tr.transform(self.mVertices[2], src.w, src.h);
+ tr.transform(self.mVertices[3], src.w, 0);
+ if (!(mFlags & DisplayHardware::SLOW_CONFIG)) {
+ // Too slow to do this in software
+ self.mDrawingState.flags |= ISurfaceComposer::eLayerFilter;
+ }
+
+ if (alpha < 1.0f) {
+ copybit_image_t src;
+ mBitmapIn.getBitmapSurface(&src);
+ t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
+ if (UNLIKELY(mTextureNameIn == -1LU)) {
+ mTextureNameIn = createTexture();
+ GLuint w=0, h=0;
+ const Region dirty(Rect(t.width, t.height));
+ loadTexture(dirty, mTextureNameIn, t, w, h);
+ }
+ self.mDrawingState.alpha = 255;
+ const Region clip(Rect( drect.l, drect.t, drect.r, drect.b ));
+ drawWithOpenGL(clip, mTextureName, t);
+ }
+
+ t.data = (GGLubyte*)(intptr_t(src.base) + src.offset);
+ if (UNLIKELY(mTextureName == -1LU)) {
+ mTextureName = createTexture();
+ GLuint w=0, h=0;
+ const Region dirty(Rect(t.width, t.height));
+ loadTexture(dirty, mTextureName, t, w, h);
+ }
+ self.mDrawingState.alpha = int(alpha*255);
+ const Region clip(Rect( drect.l, drect.t, drect.r, drect.b ));
+ drawWithOpenGL(clip, mTextureName, t);
+ }
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android