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 BufferItem::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 46 BufferItem::~BufferItem() {} 47 48 template <typename T> 49 static void addAligned(size_t& size, T /* value */) { 50 size = FlattenableUtils::align<sizeof(T)>(size); 51 size += sizeof(T); 52 } 53 54 size_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 72 size_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 87 size_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 98 template <typename T> 99 static void writeAligned(void*& buffer, size_t& size, T value) { 100 size -= FlattenableUtils::align<alignof(T)>(buffer); 101 FlattenableUtils::write(buffer, size, value); 102 } 103 104 status_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 158 template <typename T> 159 static 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 164 status_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 214 const 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