| /* |
| * 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 <stdint.h> |
| #include <sys/types.h> |
| #include <limits.h> |
| |
| #include "LayerOrientationAnim.h" |
| #include "OrientationAnimation.h" |
| #include "SurfaceFlinger.h" |
| #include "VRamHeap.h" |
| |
| #include "DisplayHardware/DisplayHardware.h" |
| |
| namespace android { |
| |
| // --------------------------------------------------------------------------- |
| |
| OrientationAnimation::OrientationAnimation(const sp<SurfaceFlinger>& flinger) |
| : mFlinger(flinger), mLayerOrientationAnim(NULL), mState(DONE) |
| { |
| // allocate a memory-dealer for this the first time |
| mTemporaryDealer = mFlinger->getSurfaceHeapManager()->createHeap( |
| ISurfaceComposer::eHardware); |
| } |
| |
| OrientationAnimation::~OrientationAnimation() |
| { |
| } |
| |
| void OrientationAnimation::onOrientationChanged() |
| { |
| if (mState == DONE) |
| mState = PREPARE; |
| } |
| |
| void OrientationAnimation::onAnimationFinished() |
| { |
| if (mState != DONE) |
| mState = FINISH; |
| } |
| |
| bool OrientationAnimation::run_impl() |
| { |
| bool skip_frame; |
| switch (mState) { |
| default: |
| case DONE: |
| skip_frame = done(); |
| break; |
| case PREPARE: |
| skip_frame = prepare(); |
| break; |
| case PHASE1: |
| skip_frame = phase1(); |
| break; |
| case PHASE2: |
| skip_frame = phase2(); |
| break; |
| case FINISH: |
| skip_frame = finished(); |
| break; |
| } |
| return skip_frame; |
| } |
| |
| bool OrientationAnimation::done() |
| { |
| if (mFlinger->isFrozen()) { |
| // we are not allowed to draw, but pause a bit to make sure |
| // apps don't end up using the whole CPU, if they depend on |
| // surfaceflinger for synchronization. |
| usleep(8333); // 8.3ms ~ 120fps |
| return true; |
| } |
| return false; |
| } |
| |
| bool OrientationAnimation::prepare() |
| { |
| mState = PHASE1; |
| |
| const GraphicPlane& plane(mFlinger->graphicPlane(0)); |
| const DisplayHardware& hw(plane.displayHardware()); |
| const uint32_t w = hw.getWidth(); |
| const uint32_t h = hw.getHeight(); |
| |
| LayerBitmap bitmap; |
| bitmap.init(mTemporaryDealer); |
| bitmap.setBits(w, h, 1, hw.getFormat()); |
| |
| LayerBitmap bitmapIn; |
| bitmapIn.init(mTemporaryDealer); |
| bitmapIn.setBits(w, h, 1, hw.getFormat()); |
| |
| copybit_image_t front; |
| bitmap.getBitmapSurface(&front); |
| hw.copyFrontToImage(front); |
| |
| LayerOrientationAnim* l = new LayerOrientationAnim( |
| mFlinger.get(), 0, this, bitmap, bitmapIn); |
| l->initStates(w, h, 0); |
| l->setLayer(INT_MAX-1); |
| mFlinger->addLayer(l); |
| mLayerOrientationAnim = l; |
| return true; |
| } |
| |
| bool OrientationAnimation::phase1() |
| { |
| if (mFlinger->isFrozen() == false) { |
| // start phase 2 |
| mState = PHASE2; |
| mLayerOrientationAnim->onOrientationCompleted(); |
| mLayerOrientationAnim->invalidate(); |
| return true; |
| |
| } |
| mLayerOrientationAnim->invalidate(); |
| return false; |
| } |
| |
| bool OrientationAnimation::phase2() |
| { |
| // do the 2nd phase of the animation |
| mLayerOrientationAnim->invalidate(); |
| return false; |
| } |
| |
| bool OrientationAnimation::finished() |
| { |
| mState = DONE; |
| mFlinger->removeLayer(mLayerOrientationAnim); |
| mLayerOrientationAnim = NULL; |
| return true; |
| } |
| |
| // --------------------------------------------------------------------------- |
| |
| }; // namespace android |