Home | History | Annotate | Download | only in surfaceflinger
      1 /*
      2  * Copyright (C) 2011 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 #include "LayerRejecter.h"
     18 
     19 #include <gui/BufferItem.h>
     20 #include <system/window.h>
     21 
     22 #include "clz.h"
     23 
     24 #define DEBUG_RESIZE 0
     25 
     26 namespace android {
     27 
     28 LayerRejecter::LayerRejecter(Layer::State& front,
     29                              Layer::State& current,
     30                              bool& recomputeVisibleRegions,
     31                              bool stickySet,
     32                              const char* name,
     33                              int32_t overrideScalingMode,
     34                              bool& freezePositionUpdates)
     35   : mFront(front),
     36     mCurrent(current),
     37     mRecomputeVisibleRegions(recomputeVisibleRegions),
     38     mStickyTransformSet(stickySet),
     39     mName(name),
     40     mOverrideScalingMode(overrideScalingMode),
     41     mFreezeGeometryUpdates(freezePositionUpdates) {}
     42 
     43 bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
     44     if (buf == nullptr) {
     45         return false;
     46     }
     47 
     48     uint32_t bufWidth = buf->getWidth();
     49     uint32_t bufHeight = buf->getHeight();
     50 
     51     // check that we received a buffer of the right size
     52     // (Take the buffer's orientation into account)
     53     if (item.mTransform & Transform::ROT_90) {
     54         swap(bufWidth, bufHeight);
     55     }
     56 
     57     int actualScalingMode = mOverrideScalingMode >= 0 ? mOverrideScalingMode : item.mScalingMode;
     58     bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
     59     if (mFront.active != mFront.requested) {
     60         if (isFixedSize || (bufWidth == mFront.requested.w && bufHeight == mFront.requested.h)) {
     61             // Here we pretend the transaction happened by updating the
     62             // current and drawing states. Drawing state is only accessed
     63             // in this thread, no need to have it locked
     64             mFront.active = mFront.requested;
     65 
     66             // We also need to update the current state so that
     67             // we don't end-up overwriting the drawing state with
     68             // this stale current state during the next transaction
     69             //
     70             // NOTE: We don't need to hold the transaction lock here
     71             // because State::active is only accessed from this thread.
     72             mCurrent.active = mFront.active;
     73             mCurrent.modified = true;
     74 
     75             // recompute visible region
     76             mRecomputeVisibleRegions = true;
     77 
     78             mFreezeGeometryUpdates = false;
     79 
     80             if (mFront.crop != mFront.requestedCrop) {
     81                 mFront.crop = mFront.requestedCrop;
     82                 mCurrent.crop = mFront.requestedCrop;
     83                 mRecomputeVisibleRegions = true;
     84             }
     85             if (mFront.finalCrop != mFront.requestedFinalCrop) {
     86                 mFront.finalCrop = mFront.requestedFinalCrop;
     87                 mCurrent.finalCrop = mFront.requestedFinalCrop;
     88                 mRecomputeVisibleRegions = true;
     89             }
     90         }
     91 
     92         ALOGD_IF(DEBUG_RESIZE,
     93                  "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
     94                  "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) "
     95                  "}\n"
     96                  "            requested={ wh={%4u,%4u} }}\n",
     97                  mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active.w,
     98                  mFront.active.h, mFront.crop.left, mFront.crop.top, mFront.crop.right,
     99                  mFront.crop.bottom, mFront.crop.getWidth(), mFront.crop.getHeight(),
    100                  mFront.requested.w, mFront.requested.h);
    101     }
    102 
    103     if (!isFixedSize && !mStickyTransformSet) {
    104         if (mFront.active.w != bufWidth || mFront.active.h != bufHeight) {
    105             // reject this buffer
    106             ALOGE("[%s] rejecting buffer: "
    107                   "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
    108                   mName, bufWidth, bufHeight, mFront.active.w, mFront.active.h);
    109             return true;
    110         }
    111     }
    112 
    113     // if the transparent region has changed (this test is
    114     // conservative, but that's fine, worst case we're doing
    115     // a bit of extra work), we latch the new one and we
    116     // trigger a visible-region recompute.
    117     //
    118     // We latch the transparent region here, instead of above where we latch
    119     // the rest of the geometry because it is only content but not necessarily
    120     // resize dependent.
    121     if (!mFront.activeTransparentRegion.isTriviallyEqual(mFront.requestedTransparentRegion)) {
    122         mFront.activeTransparentRegion = mFront.requestedTransparentRegion;
    123 
    124         // We also need to update the current state so that
    125         // we don't end-up overwriting the drawing state with
    126         // this stale current state during the next transaction
    127         //
    128         // NOTE: We don't need to hold the transaction lock here
    129         // because State::active is only accessed from this thread.
    130         mCurrent.activeTransparentRegion = mFront.activeTransparentRegion;
    131 
    132         // recompute visible region
    133         mRecomputeVisibleRegions = true;
    134     }
    135 
    136     return false;
    137 }
    138 
    139 }  // namespace android
    140