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