Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright 2014 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 <gui/BufferItem.h>
     18 
     19 #include <ui/Fence.h>
     20 #include <ui/GraphicBuffer.h>
     21 
     22 #include <system/window.h>
     23 
     24 namespace android {
     25 
     26 template<typename T>
     27 static inline constexpr uint32_t low32(const T n) {
     28     return static_cast<uint32_t>(static_cast<uint64_t>(n));
     29 }
     30 
     31 template<typename T>
     32 static inline constexpr uint32_t high32(const T n) {
     33     return static_cast<uint32_t>(static_cast<uint64_t>(n)>>32);
     34 }
     35 
     36 template<typename T>
     37 static inline constexpr T to64(const uint32_t lo, const uint32_t hi) {
     38     return static_cast<T>(static_cast<uint64_t>(hi)<<32 | lo);
     39 }
     40 
     41 BufferItem::BufferItem() :
     42     mGraphicBuffer(NULL),
     43     mFence(NULL),
     44     mCrop(Rect::INVALID_RECT),
     45     mTransform(0),
     46     mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     47     mTimestamp(0),
     48     mIsAutoTimestamp(false),
     49     mDataSpace(HAL_DATASPACE_UNKNOWN),
     50     mFrameNumber(0),
     51     mSlot(INVALID_BUFFER_SLOT),
     52     mIsDroppable(false),
     53     mAcquireCalled(false),
     54     mTransformToDisplayInverse(false),
     55     mSurfaceDamage(),
     56     mAutoRefresh(false),
     57     mQueuedBuffer(true),
     58     mIsStale(false) {
     59 }
     60 
     61 BufferItem::~BufferItem() {}
     62 
     63 template <typename T>
     64 static void addAligned(size_t& size, T /* value */) {
     65     size = FlattenableUtils::align<sizeof(T)>(size);
     66     size += sizeof(T);
     67 }
     68 
     69 size_t BufferItem::getPodSize() const {
     70     size_t size = 0;
     71     addAligned(size, mCrop);
     72     addAligned(size, mTransform);
     73     addAligned(size, mScalingMode);
     74     addAligned(size, low32(mTimestamp));
     75     addAligned(size, high32(mTimestamp));
     76     addAligned(size, mIsAutoTimestamp);
     77     addAligned(size, mDataSpace);
     78     addAligned(size, low32(mFrameNumber));
     79     addAligned(size, high32(mFrameNumber));
     80     addAligned(size, mSlot);
     81     addAligned(size, mIsDroppable);
     82     addAligned(size, mAcquireCalled);
     83     addAligned(size, mTransformToDisplayInverse);
     84     addAligned(size, mAutoRefresh);
     85     addAligned(size, mQueuedBuffer);
     86     addAligned(size, mIsStale);
     87     return size;
     88 }
     89 
     90 size_t BufferItem::getFlattenedSize() const {
     91     size_t size = sizeof(uint32_t); // Flags
     92     if (mGraphicBuffer != 0) {
     93         size += mGraphicBuffer->getFlattenedSize();
     94         size = FlattenableUtils::align<4>(size);
     95     }
     96     if (mFence != 0) {
     97         size += mFence->getFlattenedSize();
     98         size = FlattenableUtils::align<4>(size);
     99     }
    100     size += mSurfaceDamage.getFlattenedSize();
    101     size = FlattenableUtils::align<8>(size);
    102     return size + getPodSize();
    103 }
    104 
    105 size_t BufferItem::getFdCount() const {
    106     size_t count = 0;
    107     if (mGraphicBuffer != 0) {
    108         count += mGraphicBuffer->getFdCount();
    109     }
    110     if (mFence != 0) {
    111         count += mFence->getFdCount();
    112     }
    113     return count;
    114 }
    115 
    116 template <typename T>
    117 static void writeAligned(void*& buffer, size_t& size, T value) {
    118     size -= FlattenableUtils::align<alignof(T)>(buffer);
    119     FlattenableUtils::write(buffer, size, value);
    120 }
    121 
    122 status_t BufferItem::flatten(
    123         void*& buffer, size_t& size, int*& fds, size_t& count) const {
    124 
    125     // make sure we have enough space
    126     if (size < BufferItem::getFlattenedSize()) {
    127         return NO_MEMORY;
    128     }
    129 
    130     // content flags are stored first
    131     uint32_t& flags = *static_cast<uint32_t*>(buffer);
    132 
    133     // advance the pointer
    134     FlattenableUtils::advance(buffer, size, sizeof(uint32_t));
    135 
    136     flags = 0;
    137     if (mGraphicBuffer != 0) {
    138         status_t err = mGraphicBuffer->flatten(buffer, size, fds, count);
    139         if (err) return err;
    140         size -= FlattenableUtils::align<4>(buffer);
    141         flags |= 1;
    142     }
    143     if (mFence != 0) {
    144         status_t err = mFence->flatten(buffer, size, fds, count);
    145         if (err) return err;
    146         size -= FlattenableUtils::align<4>(buffer);
    147         flags |= 2;
    148     }
    149 
    150     status_t err = mSurfaceDamage.flatten(buffer, size);
    151     if (err) return err;
    152     FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
    153 
    154     // Check we still have enough space
    155     if (size < getPodSize()) {
    156         return NO_MEMORY;
    157     }
    158 
    159     writeAligned(buffer, size, mCrop);
    160     writeAligned(buffer, size, mTransform);
    161     writeAligned(buffer, size, mScalingMode);
    162     writeAligned(buffer, size, low32(mTimestamp));
    163     writeAligned(buffer, size, high32(mTimestamp));
    164     writeAligned(buffer, size, mIsAutoTimestamp);
    165     writeAligned(buffer, size, mDataSpace);
    166     writeAligned(buffer, size, low32(mFrameNumber));
    167     writeAligned(buffer, size, high32(mFrameNumber));
    168     writeAligned(buffer, size, mSlot);
    169     writeAligned(buffer, size, mIsDroppable);
    170     writeAligned(buffer, size, mAcquireCalled);
    171     writeAligned(buffer, size, mTransformToDisplayInverse);
    172     writeAligned(buffer, size, mAutoRefresh);
    173     writeAligned(buffer, size, mQueuedBuffer);
    174     writeAligned(buffer, size, mIsStale);
    175 
    176     return NO_ERROR;
    177 }
    178 
    179 template <typename T>
    180 static void readAligned(const void*& buffer, size_t& size, T& value) {
    181     size -= FlattenableUtils::align<alignof(T)>(buffer);
    182     FlattenableUtils::read(buffer, size, value);
    183 }
    184 
    185 status_t BufferItem::unflatten(
    186         void const*& buffer, size_t& size, int const*& fds, size_t& count) {
    187 
    188     if (size < sizeof(uint32_t)) {
    189         return NO_MEMORY;
    190     }
    191 
    192     uint32_t flags = 0;
    193     FlattenableUtils::read(buffer, size, flags);
    194 
    195     if (flags & 1) {
    196         mGraphicBuffer = new GraphicBuffer();
    197         status_t err = mGraphicBuffer->unflatten(buffer, size, fds, count);
    198         if (err) return err;
    199         size -= FlattenableUtils::align<4>(buffer);
    200     }
    201 
    202     if (flags & 2) {
    203         mFence = new Fence();
    204         status_t err = mFence->unflatten(buffer, size, fds, count);
    205         if (err) return err;
    206         size -= FlattenableUtils::align<4>(buffer);
    207 
    208         mFenceTime = std::make_shared<FenceTime>(mFence);
    209     }
    210 
    211     status_t err = mSurfaceDamage.unflatten(buffer, size);
    212     if (err) return err;
    213     FlattenableUtils::advance(buffer, size, mSurfaceDamage.getFlattenedSize());
    214 
    215     // Check we still have enough space
    216     if (size < getPodSize()) {
    217         return NO_MEMORY;
    218     }
    219 
    220     uint32_t timestampLo = 0, timestampHi = 0;
    221     uint32_t frameNumberLo = 0, frameNumberHi = 0;
    222 
    223     readAligned(buffer, size, mCrop);
    224     readAligned(buffer, size, mTransform);
    225     readAligned(buffer, size, mScalingMode);
    226     readAligned(buffer, size, timestampLo);
    227     readAligned(buffer, size, timestampHi);
    228     mTimestamp = to64<int64_t>(timestampLo, timestampHi);
    229     readAligned(buffer, size, mIsAutoTimestamp);
    230     readAligned(buffer, size, mDataSpace);
    231     readAligned(buffer, size, frameNumberLo);
    232     readAligned(buffer, size, frameNumberHi);
    233     mFrameNumber = to64<uint64_t>(frameNumberLo, frameNumberHi);
    234     readAligned(buffer, size, mSlot);
    235     readAligned(buffer, size, mIsDroppable);
    236     readAligned(buffer, size, mAcquireCalled);
    237     readAligned(buffer, size, mTransformToDisplayInverse);
    238     readAligned(buffer, size, mAutoRefresh);
    239     readAligned(buffer, size, mQueuedBuffer);
    240     readAligned(buffer, size, mIsStale);
    241 
    242     return NO_ERROR;
    243 }
    244 
    245 const char* BufferItem::scalingModeName(uint32_t scalingMode) {
    246     switch (scalingMode) {
    247         case NATIVE_WINDOW_SCALING_MODE_FREEZE: return "FREEZE";
    248         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: return "SCALE_TO_WINDOW";
    249         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: return "SCALE_CROP";
    250         default: return "Unknown";
    251     }
    252 }
    253 
    254 } // namespace android
    255