1*38e8c45fSAndroid Build Coastguard Worker /*
2*38e8c45fSAndroid Build Coastguard Worker * Copyright (C) 2007 The Android Open Source Project
3*38e8c45fSAndroid Build Coastguard Worker *
4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*38e8c45fSAndroid Build Coastguard Worker *
8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*38e8c45fSAndroid Build Coastguard Worker *
10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License.
15*38e8c45fSAndroid Build Coastguard Worker */
16*38e8c45fSAndroid Build Coastguard Worker
17*38e8c45fSAndroid Build Coastguard Worker #define LOG_TAG "GraphicBuffer"
18*38e8c45fSAndroid Build Coastguard Worker #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19*38e8c45fSAndroid Build Coastguard Worker
20*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicBuffer.h>
21*38e8c45fSAndroid Build Coastguard Worker
22*38e8c45fSAndroid Build Coastguard Worker #include <cutils/atomic.h>
23*38e8c45fSAndroid Build Coastguard Worker
24*38e8c45fSAndroid Build Coastguard Worker #include <grallocusage/GrallocUsageConversion.h>
25*38e8c45fSAndroid Build Coastguard Worker #include <sync/sync.h>
26*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicBufferAllocator.h>
27*38e8c45fSAndroid Build Coastguard Worker #include <ui/GraphicBufferMapper.h>
28*38e8c45fSAndroid Build Coastguard Worker #include <utils/Trace.h>
29*38e8c45fSAndroid Build Coastguard Worker
30*38e8c45fSAndroid Build Coastguard Worker namespace android {
31*38e8c45fSAndroid Build Coastguard Worker
32*38e8c45fSAndroid Build Coastguard Worker // ===========================================================================
33*38e8c45fSAndroid Build Coastguard Worker // Buffer and implementation of ANativeWindowBuffer
34*38e8c45fSAndroid Build Coastguard Worker // ===========================================================================
35*38e8c45fSAndroid Build Coastguard Worker
getUniqueId()36*38e8c45fSAndroid Build Coastguard Worker static uint64_t getUniqueId() {
37*38e8c45fSAndroid Build Coastguard Worker static volatile int32_t nextId = 0;
38*38e8c45fSAndroid Build Coastguard Worker uint64_t id = static_cast<uint64_t>(getpid()) << 32;
39*38e8c45fSAndroid Build Coastguard Worker id |= static_cast<uint32_t>(android_atomic_inc(&nextId));
40*38e8c45fSAndroid Build Coastguard Worker return id;
41*38e8c45fSAndroid Build Coastguard Worker }
42*38e8c45fSAndroid Build Coastguard Worker
resolveLegacyByteLayoutFromPlaneLayout(const std::vector<ui::PlaneLayout> & planeLayouts,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)43*38e8c45fSAndroid Build Coastguard Worker static void resolveLegacyByteLayoutFromPlaneLayout(const std::vector<ui::PlaneLayout>& planeLayouts,
44*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerPixel,
45*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerStride) {
46*38e8c45fSAndroid Build Coastguard Worker if (planeLayouts.empty()) return;
47*38e8c45fSAndroid Build Coastguard Worker if (outBytesPerPixel) {
48*38e8c45fSAndroid Build Coastguard Worker int32_t bitsPerPixel = planeLayouts.front().sampleIncrementInBits;
49*38e8c45fSAndroid Build Coastguard Worker for (const auto& planeLayout : planeLayouts) {
50*38e8c45fSAndroid Build Coastguard Worker if (bitsPerPixel != planeLayout.sampleIncrementInBits) {
51*38e8c45fSAndroid Build Coastguard Worker bitsPerPixel = -1;
52*38e8c45fSAndroid Build Coastguard Worker }
53*38e8c45fSAndroid Build Coastguard Worker }
54*38e8c45fSAndroid Build Coastguard Worker if (bitsPerPixel >= 0 && bitsPerPixel % 8 == 0) {
55*38e8c45fSAndroid Build Coastguard Worker *outBytesPerPixel = bitsPerPixel / 8;
56*38e8c45fSAndroid Build Coastguard Worker } else {
57*38e8c45fSAndroid Build Coastguard Worker *outBytesPerPixel = -1;
58*38e8c45fSAndroid Build Coastguard Worker }
59*38e8c45fSAndroid Build Coastguard Worker }
60*38e8c45fSAndroid Build Coastguard Worker if (outBytesPerStride) {
61*38e8c45fSAndroid Build Coastguard Worker int32_t bytesPerStride = planeLayouts.front().strideInBytes;
62*38e8c45fSAndroid Build Coastguard Worker for (const auto& planeLayout : planeLayouts) {
63*38e8c45fSAndroid Build Coastguard Worker if (bytesPerStride != planeLayout.strideInBytes) {
64*38e8c45fSAndroid Build Coastguard Worker bytesPerStride = -1;
65*38e8c45fSAndroid Build Coastguard Worker }
66*38e8c45fSAndroid Build Coastguard Worker }
67*38e8c45fSAndroid Build Coastguard Worker if (bytesPerStride >= 0) {
68*38e8c45fSAndroid Build Coastguard Worker *outBytesPerStride = bytesPerStride;
69*38e8c45fSAndroid Build Coastguard Worker } else {
70*38e8c45fSAndroid Build Coastguard Worker *outBytesPerStride = -1;
71*38e8c45fSAndroid Build Coastguard Worker }
72*38e8c45fSAndroid Build Coastguard Worker }
73*38e8c45fSAndroid Build Coastguard Worker }
74*38e8c45fSAndroid Build Coastguard Worker
from(ANativeWindowBuffer * anwb)75*38e8c45fSAndroid Build Coastguard Worker sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {
76*38e8c45fSAndroid Build Coastguard Worker return static_cast<GraphicBuffer *>(anwb);
77*38e8c45fSAndroid Build Coastguard Worker }
78*38e8c45fSAndroid Build Coastguard Worker
fromAHardwareBuffer(AHardwareBuffer * buffer)79*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer* buffer) {
80*38e8c45fSAndroid Build Coastguard Worker return reinterpret_cast<GraphicBuffer*>(buffer);
81*38e8c45fSAndroid Build Coastguard Worker }
82*38e8c45fSAndroid Build Coastguard Worker
fromAHardwareBuffer(AHardwareBuffer const * buffer)83*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer const* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer const* buffer) {
84*38e8c45fSAndroid Build Coastguard Worker return reinterpret_cast<GraphicBuffer const*>(buffer);
85*38e8c45fSAndroid Build Coastguard Worker }
86*38e8c45fSAndroid Build Coastguard Worker
toAHardwareBuffer()87*38e8c45fSAndroid Build Coastguard Worker AHardwareBuffer* GraphicBuffer::toAHardwareBuffer() {
88*38e8c45fSAndroid Build Coastguard Worker return reinterpret_cast<AHardwareBuffer*>(this);
89*38e8c45fSAndroid Build Coastguard Worker }
90*38e8c45fSAndroid Build Coastguard Worker
toAHardwareBuffer() const91*38e8c45fSAndroid Build Coastguard Worker AHardwareBuffer const* GraphicBuffer::toAHardwareBuffer() const {
92*38e8c45fSAndroid Build Coastguard Worker return reinterpret_cast<AHardwareBuffer const*>(this);
93*38e8c45fSAndroid Build Coastguard Worker }
94*38e8c45fSAndroid Build Coastguard Worker
GraphicBuffer()95*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::GraphicBuffer()
96*38e8c45fSAndroid Build Coastguard Worker : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
97*38e8c45fSAndroid Build Coastguard Worker mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
98*38e8c45fSAndroid Build Coastguard Worker {
99*38e8c45fSAndroid Build Coastguard Worker width =
100*38e8c45fSAndroid Build Coastguard Worker height =
101*38e8c45fSAndroid Build Coastguard Worker stride =
102*38e8c45fSAndroid Build Coastguard Worker format =
103*38e8c45fSAndroid Build Coastguard Worker usage_deprecated = 0;
104*38e8c45fSAndroid Build Coastguard Worker usage = 0;
105*38e8c45fSAndroid Build Coastguard Worker layerCount = 0;
106*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
107*38e8c45fSAndroid Build Coastguard Worker }
108*38e8c45fSAndroid Build Coastguard Worker
109*38e8c45fSAndroid Build Coastguard Worker // deprecated
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inUsage,std::string requestorName)110*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
111*38e8c45fSAndroid Build Coastguard Worker PixelFormat inFormat, uint32_t inUsage, std::string requestorName)
112*38e8c45fSAndroid Build Coastguard Worker : GraphicBuffer(inWidth, inHeight, inFormat, 1, static_cast<uint64_t>(inUsage), requestorName)
113*38e8c45fSAndroid Build Coastguard Worker {
114*38e8c45fSAndroid Build Coastguard Worker }
115*38e8c45fSAndroid Build Coastguard Worker
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,std::string requestorName)116*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
117*38e8c45fSAndroid Build Coastguard Worker uint32_t inLayerCount, uint64_t inUsage, std::string requestorName)
118*38e8c45fSAndroid Build Coastguard Worker : GraphicBuffer() {
119*38e8c45fSAndroid Build Coastguard Worker mInitCheck = initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage,
120*38e8c45fSAndroid Build Coastguard Worker std::move(requestorName));
121*38e8c45fSAndroid Build Coastguard Worker }
122*38e8c45fSAndroid Build Coastguard Worker
123*38e8c45fSAndroid Build Coastguard Worker // deprecated
GraphicBuffer(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint32_t inUsage,uint32_t inStride,native_handle_t * inHandle,bool keepOwnership)124*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
125*38e8c45fSAndroid Build Coastguard Worker PixelFormat inFormat, uint32_t inLayerCount, uint32_t inUsage,
126*38e8c45fSAndroid Build Coastguard Worker uint32_t inStride, native_handle_t* inHandle, bool keepOwnership)
127*38e8c45fSAndroid Build Coastguard Worker : GraphicBuffer(inHandle, keepOwnership ? TAKE_HANDLE : WRAP_HANDLE,
128*38e8c45fSAndroid Build Coastguard Worker inWidth, inHeight, inFormat, inLayerCount, static_cast<uint64_t>(inUsage),
129*38e8c45fSAndroid Build Coastguard Worker inStride)
130*38e8c45fSAndroid Build Coastguard Worker {
131*38e8c45fSAndroid Build Coastguard Worker }
132*38e8c45fSAndroid Build Coastguard Worker
GraphicBuffer(const native_handle_t * inHandle,HandleWrapMethod method,uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,uint32_t inStride)133*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::GraphicBuffer(const native_handle_t* inHandle, HandleWrapMethod method,
134*38e8c45fSAndroid Build Coastguard Worker uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
135*38e8c45fSAndroid Build Coastguard Worker uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride)
136*38e8c45fSAndroid Build Coastguard Worker : GraphicBuffer() {
137*38e8c45fSAndroid Build Coastguard Worker mInitCheck = initWithHandle(inHandle, method, inWidth, inHeight, inFormat, inLayerCount,
138*38e8c45fSAndroid Build Coastguard Worker inUsage, inStride);
139*38e8c45fSAndroid Build Coastguard Worker }
140*38e8c45fSAndroid Build Coastguard Worker
GraphicBuffer(const GraphicBufferAllocator::AllocationRequest & request)141*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::GraphicBuffer(const GraphicBufferAllocator::AllocationRequest& request)
142*38e8c45fSAndroid Build Coastguard Worker : GraphicBuffer() {
143*38e8c45fSAndroid Build Coastguard Worker GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
144*38e8c45fSAndroid Build Coastguard Worker auto result = allocator.allocate(request);
145*38e8c45fSAndroid Build Coastguard Worker mInitCheck = result.status;
146*38e8c45fSAndroid Build Coastguard Worker if (result.status == NO_ERROR) {
147*38e8c45fSAndroid Build Coastguard Worker handle = result.handle;
148*38e8c45fSAndroid Build Coastguard Worker stride = result.stride;
149*38e8c45fSAndroid Build Coastguard Worker
150*38e8c45fSAndroid Build Coastguard Worker mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
151*38e8c45fSAndroid Build Coastguard Worker
152*38e8c45fSAndroid Build Coastguard Worker width = static_cast<int>(request.width);
153*38e8c45fSAndroid Build Coastguard Worker height = static_cast<int>(request.height);
154*38e8c45fSAndroid Build Coastguard Worker format = request.format;
155*38e8c45fSAndroid Build Coastguard Worker layerCount = request.layerCount;
156*38e8c45fSAndroid Build Coastguard Worker usage = request.usage;
157*38e8c45fSAndroid Build Coastguard Worker usage_deprecated = int(usage);
158*38e8c45fSAndroid Build Coastguard Worker }
159*38e8c45fSAndroid Build Coastguard Worker }
160*38e8c45fSAndroid Build Coastguard Worker
~GraphicBuffer()161*38e8c45fSAndroid Build Coastguard Worker GraphicBuffer::~GraphicBuffer()
162*38e8c45fSAndroid Build Coastguard Worker {
163*38e8c45fSAndroid Build Coastguard Worker ATRACE_CALL();
164*38e8c45fSAndroid Build Coastguard Worker if (handle) {
165*38e8c45fSAndroid Build Coastguard Worker free_handle();
166*38e8c45fSAndroid Build Coastguard Worker }
167*38e8c45fSAndroid Build Coastguard Worker for (auto& [callback, context] : mDeathCallbacks) {
168*38e8c45fSAndroid Build Coastguard Worker callback(context, mId);
169*38e8c45fSAndroid Build Coastguard Worker }
170*38e8c45fSAndroid Build Coastguard Worker }
171*38e8c45fSAndroid Build Coastguard Worker
free_handle()172*38e8c45fSAndroid Build Coastguard Worker void GraphicBuffer::free_handle()
173*38e8c45fSAndroid Build Coastguard Worker {
174*38e8c45fSAndroid Build Coastguard Worker if (mOwner == ownHandle) {
175*38e8c45fSAndroid Build Coastguard Worker mBufferMapper.freeBuffer(handle);
176*38e8c45fSAndroid Build Coastguard Worker } else if (mOwner == ownData) {
177*38e8c45fSAndroid Build Coastguard Worker GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
178*38e8c45fSAndroid Build Coastguard Worker allocator.free(handle);
179*38e8c45fSAndroid Build Coastguard Worker }
180*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
181*38e8c45fSAndroid Build Coastguard Worker }
182*38e8c45fSAndroid Build Coastguard Worker
initCheck() const183*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::initCheck() const {
184*38e8c45fSAndroid Build Coastguard Worker return static_cast<status_t>(mInitCheck);
185*38e8c45fSAndroid Build Coastguard Worker }
186*38e8c45fSAndroid Build Coastguard Worker
dumpAllocationsToSystemLog()187*38e8c45fSAndroid Build Coastguard Worker void GraphicBuffer::dumpAllocationsToSystemLog()
188*38e8c45fSAndroid Build Coastguard Worker {
189*38e8c45fSAndroid Build Coastguard Worker GraphicBufferAllocator::dumpToSystemLog();
190*38e8c45fSAndroid Build Coastguard Worker }
191*38e8c45fSAndroid Build Coastguard Worker
getNativeBuffer() const192*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
193*38e8c45fSAndroid Build Coastguard Worker {
194*38e8c45fSAndroid Build Coastguard Worker return static_cast<ANativeWindowBuffer*>(
195*38e8c45fSAndroid Build Coastguard Worker const_cast<GraphicBuffer*>(this));
196*38e8c45fSAndroid Build Coastguard Worker }
197*38e8c45fSAndroid Build Coastguard Worker
getDataspace(ui::Dataspace * outDataspace) const198*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::getDataspace(ui::Dataspace* outDataspace) const {
199*38e8c45fSAndroid Build Coastguard Worker return mBufferMapper.getDataspace(handle, outDataspace);
200*38e8c45fSAndroid Build Coastguard Worker }
201*38e8c45fSAndroid Build Coastguard Worker
reallocate(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage)202*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::reallocate(uint32_t inWidth, uint32_t inHeight,
203*38e8c45fSAndroid Build Coastguard Worker PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
204*38e8c45fSAndroid Build Coastguard Worker {
205*38e8c45fSAndroid Build Coastguard Worker if (mOwner != ownData)
206*38e8c45fSAndroid Build Coastguard Worker return INVALID_OPERATION;
207*38e8c45fSAndroid Build Coastguard Worker
208*38e8c45fSAndroid Build Coastguard Worker if (handle &&
209*38e8c45fSAndroid Build Coastguard Worker static_cast<int>(inWidth) == width &&
210*38e8c45fSAndroid Build Coastguard Worker static_cast<int>(inHeight) == height &&
211*38e8c45fSAndroid Build Coastguard Worker inFormat == format &&
212*38e8c45fSAndroid Build Coastguard Worker inLayerCount == layerCount &&
213*38e8c45fSAndroid Build Coastguard Worker inUsage == usage)
214*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
215*38e8c45fSAndroid Build Coastguard Worker
216*38e8c45fSAndroid Build Coastguard Worker if (handle) {
217*38e8c45fSAndroid Build Coastguard Worker GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
218*38e8c45fSAndroid Build Coastguard Worker allocator.free(handle);
219*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
220*38e8c45fSAndroid Build Coastguard Worker }
221*38e8c45fSAndroid Build Coastguard Worker return initWithSize(inWidth, inHeight, inFormat, inLayerCount, inUsage, "[Reallocation]");
222*38e8c45fSAndroid Build Coastguard Worker }
223*38e8c45fSAndroid Build Coastguard Worker
needsReallocation(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage)224*38e8c45fSAndroid Build Coastguard Worker bool GraphicBuffer::needsReallocation(uint32_t inWidth, uint32_t inHeight,
225*38e8c45fSAndroid Build Coastguard Worker PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage)
226*38e8c45fSAndroid Build Coastguard Worker {
227*38e8c45fSAndroid Build Coastguard Worker if (static_cast<int>(inWidth) != width) return true;
228*38e8c45fSAndroid Build Coastguard Worker if (static_cast<int>(inHeight) != height) return true;
229*38e8c45fSAndroid Build Coastguard Worker if (inFormat != format) return true;
230*38e8c45fSAndroid Build Coastguard Worker if (inLayerCount != layerCount) return true;
231*38e8c45fSAndroid Build Coastguard Worker if ((usage & inUsage) != inUsage) return true;
232*38e8c45fSAndroid Build Coastguard Worker if ((usage & USAGE_PROTECTED) != (inUsage & USAGE_PROTECTED)) return true;
233*38e8c45fSAndroid Build Coastguard Worker return false;
234*38e8c45fSAndroid Build Coastguard Worker }
235*38e8c45fSAndroid Build Coastguard Worker
initWithSize(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,std::string requestorName)236*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::initWithSize(uint32_t inWidth, uint32_t inHeight,
237*38e8c45fSAndroid Build Coastguard Worker PixelFormat inFormat, uint32_t inLayerCount, uint64_t inUsage,
238*38e8c45fSAndroid Build Coastguard Worker std::string requestorName)
239*38e8c45fSAndroid Build Coastguard Worker {
240*38e8c45fSAndroid Build Coastguard Worker GraphicBufferAllocator& allocator = GraphicBufferAllocator::get();
241*38e8c45fSAndroid Build Coastguard Worker uint32_t outStride = 0;
242*38e8c45fSAndroid Build Coastguard Worker status_t err = allocator.allocate(inWidth, inHeight, inFormat, inLayerCount,
243*38e8c45fSAndroid Build Coastguard Worker inUsage, &handle, &outStride, mId,
244*38e8c45fSAndroid Build Coastguard Worker std::move(requestorName));
245*38e8c45fSAndroid Build Coastguard Worker if (err == NO_ERROR) {
246*38e8c45fSAndroid Build Coastguard Worker mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
247*38e8c45fSAndroid Build Coastguard Worker
248*38e8c45fSAndroid Build Coastguard Worker width = static_cast<int>(inWidth);
249*38e8c45fSAndroid Build Coastguard Worker height = static_cast<int>(inHeight);
250*38e8c45fSAndroid Build Coastguard Worker format = inFormat;
251*38e8c45fSAndroid Build Coastguard Worker layerCount = inLayerCount;
252*38e8c45fSAndroid Build Coastguard Worker usage = inUsage;
253*38e8c45fSAndroid Build Coastguard Worker usage_deprecated = int(usage);
254*38e8c45fSAndroid Build Coastguard Worker stride = static_cast<int>(outStride);
255*38e8c45fSAndroid Build Coastguard Worker }
256*38e8c45fSAndroid Build Coastguard Worker return err;
257*38e8c45fSAndroid Build Coastguard Worker }
258*38e8c45fSAndroid Build Coastguard Worker
initWithHandle(const native_handle_t * inHandle,HandleWrapMethod method,uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,uint32_t inStride)259*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::initWithHandle(const native_handle_t* inHandle, HandleWrapMethod method,
260*38e8c45fSAndroid Build Coastguard Worker uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
261*38e8c45fSAndroid Build Coastguard Worker uint32_t inLayerCount, uint64_t inUsage, uint32_t inStride) {
262*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::width = static_cast<int>(inWidth);
263*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::height = static_cast<int>(inHeight);
264*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::stride = static_cast<int>(inStride);
265*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::format = inFormat;
266*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::usage = inUsage;
267*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::usage_deprecated = int(inUsage);
268*38e8c45fSAndroid Build Coastguard Worker
269*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::layerCount = inLayerCount;
270*38e8c45fSAndroid Build Coastguard Worker
271*38e8c45fSAndroid Build Coastguard Worker mOwner = (method == WRAP_HANDLE) ? ownNone : ownHandle;
272*38e8c45fSAndroid Build Coastguard Worker
273*38e8c45fSAndroid Build Coastguard Worker if (method == TAKE_UNREGISTERED_HANDLE || method == CLONE_HANDLE) {
274*38e8c45fSAndroid Build Coastguard Worker buffer_handle_t importedHandle;
275*38e8c45fSAndroid Build Coastguard Worker status_t err = mBufferMapper.importBuffer(inHandle, inWidth, inHeight, inLayerCount,
276*38e8c45fSAndroid Build Coastguard Worker inFormat, inUsage, inStride, &importedHandle);
277*38e8c45fSAndroid Build Coastguard Worker if (err != NO_ERROR) {
278*38e8c45fSAndroid Build Coastguard Worker initWithHandle(nullptr, WRAP_HANDLE, 0, 0, 0, 0, 0, 0);
279*38e8c45fSAndroid Build Coastguard Worker
280*38e8c45fSAndroid Build Coastguard Worker return err;
281*38e8c45fSAndroid Build Coastguard Worker }
282*38e8c45fSAndroid Build Coastguard Worker
283*38e8c45fSAndroid Build Coastguard Worker if (method == TAKE_UNREGISTERED_HANDLE) {
284*38e8c45fSAndroid Build Coastguard Worker native_handle_close(inHandle);
285*38e8c45fSAndroid Build Coastguard Worker native_handle_delete(const_cast<native_handle_t*>(inHandle));
286*38e8c45fSAndroid Build Coastguard Worker }
287*38e8c45fSAndroid Build Coastguard Worker
288*38e8c45fSAndroid Build Coastguard Worker inHandle = importedHandle;
289*38e8c45fSAndroid Build Coastguard Worker mBufferMapper.getTransportSize(inHandle, &mTransportNumFds, &mTransportNumInts);
290*38e8c45fSAndroid Build Coastguard Worker }
291*38e8c45fSAndroid Build Coastguard Worker
292*38e8c45fSAndroid Build Coastguard Worker ANativeWindowBuffer::handle = inHandle;
293*38e8c45fSAndroid Build Coastguard Worker
294*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
295*38e8c45fSAndroid Build Coastguard Worker }
296*38e8c45fSAndroid Build Coastguard Worker
lock(uint32_t inUsage,void ** vaddr,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)297*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lock(uint32_t inUsage, void** vaddr, int32_t* outBytesPerPixel,
298*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerStride) {
299*38e8c45fSAndroid Build Coastguard Worker const Rect lockBounds(width, height);
300*38e8c45fSAndroid Build Coastguard Worker status_t res = lock(inUsage, lockBounds, vaddr, outBytesPerPixel, outBytesPerStride);
301*38e8c45fSAndroid Build Coastguard Worker return res;
302*38e8c45fSAndroid Build Coastguard Worker }
303*38e8c45fSAndroid Build Coastguard Worker
lock(uint32_t inUsage,const Rect & rect,void ** vaddr,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)304*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lock(uint32_t inUsage, const Rect& rect, void** vaddr,
305*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
306*38e8c45fSAndroid Build Coastguard Worker if (rect.left < 0 || rect.right > width ||
307*38e8c45fSAndroid Build Coastguard Worker rect.top < 0 || rect.bottom > height) {
308*38e8c45fSAndroid Build Coastguard Worker ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
309*38e8c45fSAndroid Build Coastguard Worker rect.left, rect.top, rect.right, rect.bottom,
310*38e8c45fSAndroid Build Coastguard Worker width, height);
311*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
312*38e8c45fSAndroid Build Coastguard Worker }
313*38e8c45fSAndroid Build Coastguard Worker
314*38e8c45fSAndroid Build Coastguard Worker return lockAsync(inUsage, rect, vaddr, -1, outBytesPerPixel, outBytesPerStride);
315*38e8c45fSAndroid Build Coastguard Worker }
316*38e8c45fSAndroid Build Coastguard Worker
lockYCbCr(uint32_t inUsage,android_ycbcr * ycbcr)317*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, android_ycbcr* ycbcr)
318*38e8c45fSAndroid Build Coastguard Worker {
319*38e8c45fSAndroid Build Coastguard Worker const Rect lockBounds(width, height);
320*38e8c45fSAndroid Build Coastguard Worker status_t res = lockYCbCr(inUsage, lockBounds, ycbcr);
321*38e8c45fSAndroid Build Coastguard Worker return res;
322*38e8c45fSAndroid Build Coastguard Worker }
323*38e8c45fSAndroid Build Coastguard Worker
lockYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr)324*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockYCbCr(uint32_t inUsage, const Rect& rect,
325*38e8c45fSAndroid Build Coastguard Worker android_ycbcr* ycbcr)
326*38e8c45fSAndroid Build Coastguard Worker {
327*38e8c45fSAndroid Build Coastguard Worker if (rect.left < 0 || rect.right > width ||
328*38e8c45fSAndroid Build Coastguard Worker rect.top < 0 || rect.bottom > height) {
329*38e8c45fSAndroid Build Coastguard Worker ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
330*38e8c45fSAndroid Build Coastguard Worker rect.left, rect.top, rect.right, rect.bottom,
331*38e8c45fSAndroid Build Coastguard Worker width, height);
332*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
333*38e8c45fSAndroid Build Coastguard Worker }
334*38e8c45fSAndroid Build Coastguard Worker return lockAsyncYCbCr(inUsage, rect, ycbcr, -1);
335*38e8c45fSAndroid Build Coastguard Worker }
336*38e8c45fSAndroid Build Coastguard Worker
unlock()337*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::unlock()
338*38e8c45fSAndroid Build Coastguard Worker {
339*38e8c45fSAndroid Build Coastguard Worker return unlockAsync(nullptr);
340*38e8c45fSAndroid Build Coastguard Worker }
341*38e8c45fSAndroid Build Coastguard Worker
lockAsync(uint32_t inUsage,void ** vaddr,int fenceFd,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)342*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockAsync(uint32_t inUsage, void** vaddr, int fenceFd,
343*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
344*38e8c45fSAndroid Build Coastguard Worker const Rect lockBounds(width, height);
345*38e8c45fSAndroid Build Coastguard Worker status_t res =
346*38e8c45fSAndroid Build Coastguard Worker lockAsync(inUsage, lockBounds, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
347*38e8c45fSAndroid Build Coastguard Worker return res;
348*38e8c45fSAndroid Build Coastguard Worker }
349*38e8c45fSAndroid Build Coastguard Worker
lockAsync(uint32_t inUsage,const Rect & rect,void ** vaddr,int fenceFd,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)350*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
351*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
352*38e8c45fSAndroid Build Coastguard Worker return lockAsync(inUsage, inUsage, rect, vaddr, fenceFd, outBytesPerPixel, outBytesPerStride);
353*38e8c45fSAndroid Build Coastguard Worker }
354*38e8c45fSAndroid Build Coastguard Worker
lockAsync(uint64_t inProducerUsage,uint64_t inConsumerUsage,const Rect & rect,void ** vaddr,int fenceFd,int32_t * outBytesPerPixel,int32_t * outBytesPerStride)355*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockAsync(uint64_t inProducerUsage, uint64_t inConsumerUsage,
356*38e8c45fSAndroid Build Coastguard Worker const Rect& rect, void** vaddr, int fenceFd,
357*38e8c45fSAndroid Build Coastguard Worker int32_t* outBytesPerPixel, int32_t* outBytesPerStride) {
358*38e8c45fSAndroid Build Coastguard Worker if (rect.left < 0 || rect.right > width ||
359*38e8c45fSAndroid Build Coastguard Worker rect.top < 0 || rect.bottom > height) {
360*38e8c45fSAndroid Build Coastguard Worker ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
361*38e8c45fSAndroid Build Coastguard Worker rect.left, rect.top, rect.right, rect.bottom,
362*38e8c45fSAndroid Build Coastguard Worker width, height);
363*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
364*38e8c45fSAndroid Build Coastguard Worker }
365*38e8c45fSAndroid Build Coastguard Worker
366*38e8c45fSAndroid Build Coastguard Worker // Resolve the bpp & bps before doing a lock in case this fails we don't have to worry about
367*38e8c45fSAndroid Build Coastguard Worker // doing an unlock
368*38e8c45fSAndroid Build Coastguard Worker int32_t legacyBpp = -1, legacyBps = -1;
369*38e8c45fSAndroid Build Coastguard Worker if (outBytesPerPixel || outBytesPerStride) {
370*38e8c45fSAndroid Build Coastguard Worker const auto mapperVersion = getBufferMapperVersion();
371*38e8c45fSAndroid Build Coastguard Worker // For gralloc2 we need to guess at the bpp & bps
372*38e8c45fSAndroid Build Coastguard Worker // For gralloc3 the lock() call will return it
373*38e8c45fSAndroid Build Coastguard Worker // For gralloc4 & later the PlaneLayout metadata query is vastly superior and we
374*38e8c45fSAndroid Build Coastguard Worker // resolve bpp & bps just for compatibility
375*38e8c45fSAndroid Build Coastguard Worker
376*38e8c45fSAndroid Build Coastguard Worker // TODO: See if we can't just remove gralloc2 support.
377*38e8c45fSAndroid Build Coastguard Worker if (mapperVersion == GraphicBufferMapper::GRALLOC_2) {
378*38e8c45fSAndroid Build Coastguard Worker legacyBpp = bytesPerPixel(format);
379*38e8c45fSAndroid Build Coastguard Worker if (legacyBpp > 0) {
380*38e8c45fSAndroid Build Coastguard Worker legacyBps = stride * legacyBpp;
381*38e8c45fSAndroid Build Coastguard Worker } else {
382*38e8c45fSAndroid Build Coastguard Worker legacyBpp = -1;
383*38e8c45fSAndroid Build Coastguard Worker }
384*38e8c45fSAndroid Build Coastguard Worker } else if (mapperVersion >= GraphicBufferMapper::GRALLOC_4) {
385*38e8c45fSAndroid Build Coastguard Worker auto planeLayout = getBufferMapper().getPlaneLayouts(handle);
386*38e8c45fSAndroid Build Coastguard Worker if (!planeLayout.has_value()) return planeLayout.asStatus();
387*38e8c45fSAndroid Build Coastguard Worker resolveLegacyByteLayoutFromPlaneLayout(planeLayout.value(), &legacyBpp, &legacyBps);
388*38e8c45fSAndroid Build Coastguard Worker }
389*38e8c45fSAndroid Build Coastguard Worker }
390*38e8c45fSAndroid Build Coastguard Worker
391*38e8c45fSAndroid Build Coastguard Worker const uint64_t usage = static_cast<uint64_t>(ANDROID_NATIVE_UNSIGNED_CAST(
392*38e8c45fSAndroid Build Coastguard Worker android_convertGralloc1To0Usage(inProducerUsage, inConsumerUsage)));
393*38e8c45fSAndroid Build Coastguard Worker
394*38e8c45fSAndroid Build Coastguard Worker auto result = getBufferMapper().lock(handle, usage, rect, base::unique_fd{fenceFd});
395*38e8c45fSAndroid Build Coastguard Worker
396*38e8c45fSAndroid Build Coastguard Worker if (!result.has_value()) {
397*38e8c45fSAndroid Build Coastguard Worker return result.error().asStatus();
398*38e8c45fSAndroid Build Coastguard Worker }
399*38e8c45fSAndroid Build Coastguard Worker auto value = result.value();
400*38e8c45fSAndroid Build Coastguard Worker *vaddr = value.address;
401*38e8c45fSAndroid Build Coastguard Worker
402*38e8c45fSAndroid Build Coastguard Worker if (outBytesPerPixel) {
403*38e8c45fSAndroid Build Coastguard Worker *outBytesPerPixel = legacyBpp != -1 ? legacyBpp : value.bytesPerPixel;
404*38e8c45fSAndroid Build Coastguard Worker }
405*38e8c45fSAndroid Build Coastguard Worker if (outBytesPerStride) {
406*38e8c45fSAndroid Build Coastguard Worker *outBytesPerStride = legacyBps != -1 ? legacyBps : value.bytesPerStride;
407*38e8c45fSAndroid Build Coastguard Worker }
408*38e8c45fSAndroid Build Coastguard Worker return OK;
409*38e8c45fSAndroid Build Coastguard Worker }
410*38e8c45fSAndroid Build Coastguard Worker
lockAsyncYCbCr(uint32_t inUsage,android_ycbcr * ycbcr,int fenceFd)411*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, android_ycbcr* ycbcr,
412*38e8c45fSAndroid Build Coastguard Worker int fenceFd)
413*38e8c45fSAndroid Build Coastguard Worker {
414*38e8c45fSAndroid Build Coastguard Worker const Rect lockBounds(width, height);
415*38e8c45fSAndroid Build Coastguard Worker status_t res = lockAsyncYCbCr(inUsage, lockBounds, ycbcr, fenceFd);
416*38e8c45fSAndroid Build Coastguard Worker return res;
417*38e8c45fSAndroid Build Coastguard Worker }
418*38e8c45fSAndroid Build Coastguard Worker
lockAsyncYCbCr(uint32_t inUsage,const Rect & rect,android_ycbcr * ycbcr,int fenceFd)419*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
420*38e8c45fSAndroid Build Coastguard Worker android_ycbcr* ycbcr, int fenceFd)
421*38e8c45fSAndroid Build Coastguard Worker {
422*38e8c45fSAndroid Build Coastguard Worker if (rect.left < 0 || rect.right > width ||
423*38e8c45fSAndroid Build Coastguard Worker rect.top < 0 || rect.bottom > height) {
424*38e8c45fSAndroid Build Coastguard Worker ALOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",
425*38e8c45fSAndroid Build Coastguard Worker rect.left, rect.top, rect.right, rect.bottom,
426*38e8c45fSAndroid Build Coastguard Worker width, height);
427*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
428*38e8c45fSAndroid Build Coastguard Worker }
429*38e8c45fSAndroid Build Coastguard Worker auto result = getBufferMapper().lockYCbCr(handle, static_cast<int64_t>(inUsage), rect,
430*38e8c45fSAndroid Build Coastguard Worker base::unique_fd{fenceFd});
431*38e8c45fSAndroid Build Coastguard Worker if (!result.has_value()) {
432*38e8c45fSAndroid Build Coastguard Worker return result.error().asStatus();
433*38e8c45fSAndroid Build Coastguard Worker }
434*38e8c45fSAndroid Build Coastguard Worker *ycbcr = result.value();
435*38e8c45fSAndroid Build Coastguard Worker return OK;
436*38e8c45fSAndroid Build Coastguard Worker }
437*38e8c45fSAndroid Build Coastguard Worker
unlockAsync(int * fenceFd)438*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::unlockAsync(int *fenceFd)
439*38e8c45fSAndroid Build Coastguard Worker {
440*38e8c45fSAndroid Build Coastguard Worker return getBufferMapper().unlockAsync(handle, fenceFd);
441*38e8c45fSAndroid Build Coastguard Worker }
442*38e8c45fSAndroid Build Coastguard Worker
isSupported(uint32_t inWidth,uint32_t inHeight,PixelFormat inFormat,uint32_t inLayerCount,uint64_t inUsage,bool * outSupported) const443*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::isSupported(uint32_t inWidth, uint32_t inHeight, PixelFormat inFormat,
444*38e8c45fSAndroid Build Coastguard Worker uint32_t inLayerCount, uint64_t inUsage,
445*38e8c45fSAndroid Build Coastguard Worker bool* outSupported) const {
446*38e8c45fSAndroid Build Coastguard Worker return mBufferMapper.isSupported(inWidth, inHeight, inFormat, inLayerCount, inUsage,
447*38e8c45fSAndroid Build Coastguard Worker outSupported);
448*38e8c45fSAndroid Build Coastguard Worker }
449*38e8c45fSAndroid Build Coastguard Worker
getFlattenedSize() const450*38e8c45fSAndroid Build Coastguard Worker size_t GraphicBuffer::getFlattenedSize() const {
451*38e8c45fSAndroid Build Coastguard Worker return static_cast<size_t>(13 + (handle ? mTransportNumInts : 0)) * sizeof(int);
452*38e8c45fSAndroid Build Coastguard Worker }
453*38e8c45fSAndroid Build Coastguard Worker
getFdCount() const454*38e8c45fSAndroid Build Coastguard Worker size_t GraphicBuffer::getFdCount() const {
455*38e8c45fSAndroid Build Coastguard Worker return static_cast<size_t>(handle ? mTransportNumFds : 0);
456*38e8c45fSAndroid Build Coastguard Worker }
457*38e8c45fSAndroid Build Coastguard Worker
flatten(void * & buffer,size_t & size,int * & fds,size_t & count) const458*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::flatten(void*& buffer, size_t& size, int*& fds, size_t& count) const {
459*38e8c45fSAndroid Build Coastguard Worker size_t sizeNeeded = GraphicBuffer::getFlattenedSize();
460*38e8c45fSAndroid Build Coastguard Worker if (size < sizeNeeded) return NO_MEMORY;
461*38e8c45fSAndroid Build Coastguard Worker
462*38e8c45fSAndroid Build Coastguard Worker size_t fdCountNeeded = GraphicBuffer::getFdCount();
463*38e8c45fSAndroid Build Coastguard Worker if (count < fdCountNeeded) return NO_MEMORY;
464*38e8c45fSAndroid Build Coastguard Worker
465*38e8c45fSAndroid Build Coastguard Worker int32_t* buf = static_cast<int32_t*>(buffer);
466*38e8c45fSAndroid Build Coastguard Worker buf[0] = 'GB01';
467*38e8c45fSAndroid Build Coastguard Worker buf[1] = width;
468*38e8c45fSAndroid Build Coastguard Worker buf[2] = height;
469*38e8c45fSAndroid Build Coastguard Worker buf[3] = stride;
470*38e8c45fSAndroid Build Coastguard Worker buf[4] = format;
471*38e8c45fSAndroid Build Coastguard Worker buf[5] = static_cast<int32_t>(layerCount);
472*38e8c45fSAndroid Build Coastguard Worker buf[6] = int(usage); // low 32-bits
473*38e8c45fSAndroid Build Coastguard Worker buf[7] = static_cast<int32_t>(mId >> 32);
474*38e8c45fSAndroid Build Coastguard Worker buf[8] = static_cast<int32_t>(mId & 0xFFFFFFFFull);
475*38e8c45fSAndroid Build Coastguard Worker buf[9] = static_cast<int32_t>(mGenerationNumber);
476*38e8c45fSAndroid Build Coastguard Worker buf[10] = 0;
477*38e8c45fSAndroid Build Coastguard Worker buf[11] = 0;
478*38e8c45fSAndroid Build Coastguard Worker buf[12] = int(usage >> 32); // high 32-bits
479*38e8c45fSAndroid Build Coastguard Worker
480*38e8c45fSAndroid Build Coastguard Worker if (handle) {
481*38e8c45fSAndroid Build Coastguard Worker buf[10] = int32_t(mTransportNumFds);
482*38e8c45fSAndroid Build Coastguard Worker buf[11] = int32_t(mTransportNumInts);
483*38e8c45fSAndroid Build Coastguard Worker memcpy(fds, handle->data, static_cast<size_t>(mTransportNumFds) * sizeof(int));
484*38e8c45fSAndroid Build Coastguard Worker memcpy(buf + 13, handle->data + handle->numFds,
485*38e8c45fSAndroid Build Coastguard Worker static_cast<size_t>(mTransportNumInts) * sizeof(int));
486*38e8c45fSAndroid Build Coastguard Worker }
487*38e8c45fSAndroid Build Coastguard Worker
488*38e8c45fSAndroid Build Coastguard Worker buffer = static_cast<void*>(static_cast<uint8_t*>(buffer) + sizeNeeded);
489*38e8c45fSAndroid Build Coastguard Worker size -= sizeNeeded;
490*38e8c45fSAndroid Build Coastguard Worker if (handle) {
491*38e8c45fSAndroid Build Coastguard Worker fds += mTransportNumFds;
492*38e8c45fSAndroid Build Coastguard Worker count -= static_cast<size_t>(mTransportNumFds);
493*38e8c45fSAndroid Build Coastguard Worker }
494*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
495*38e8c45fSAndroid Build Coastguard Worker }
496*38e8c45fSAndroid Build Coastguard Worker
unflatten(void const * & buffer,size_t & size,int const * & fds,size_t & count)497*38e8c45fSAndroid Build Coastguard Worker status_t GraphicBuffer::unflatten(void const*& buffer, size_t& size, int const*& fds,
498*38e8c45fSAndroid Build Coastguard Worker size_t& count) {
499*38e8c45fSAndroid Build Coastguard Worker // Check if size is not smaller than buf[0] is supposed to take.
500*38e8c45fSAndroid Build Coastguard Worker if (size < sizeof(int)) {
501*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
502*38e8c45fSAndroid Build Coastguard Worker }
503*38e8c45fSAndroid Build Coastguard Worker
504*38e8c45fSAndroid Build Coastguard Worker int const* buf = static_cast<int const*>(buffer);
505*38e8c45fSAndroid Build Coastguard Worker
506*38e8c45fSAndroid Build Coastguard Worker // NOTE: it turns out that some media code generates a flattened GraphicBuffer manually!!!!!
507*38e8c45fSAndroid Build Coastguard Worker // see H2BGraphicBufferProducer.cpp
508*38e8c45fSAndroid Build Coastguard Worker uint32_t flattenWordCount = 0;
509*38e8c45fSAndroid Build Coastguard Worker if (buf[0] == 'GB01') {
510*38e8c45fSAndroid Build Coastguard Worker // new version with 64-bits usage bits
511*38e8c45fSAndroid Build Coastguard Worker flattenWordCount = 13;
512*38e8c45fSAndroid Build Coastguard Worker } else if (buf[0] == 'GBFR') {
513*38e8c45fSAndroid Build Coastguard Worker // old version, when usage bits were 32-bits
514*38e8c45fSAndroid Build Coastguard Worker flattenWordCount = 12;
515*38e8c45fSAndroid Build Coastguard Worker } else {
516*38e8c45fSAndroid Build Coastguard Worker return BAD_TYPE;
517*38e8c45fSAndroid Build Coastguard Worker }
518*38e8c45fSAndroid Build Coastguard Worker
519*38e8c45fSAndroid Build Coastguard Worker if (size < 12 * sizeof(int)) {
520*38e8c45fSAndroid Build Coastguard Worker android_errorWriteLog(0x534e4554, "114223584");
521*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
522*38e8c45fSAndroid Build Coastguard Worker }
523*38e8c45fSAndroid Build Coastguard Worker
524*38e8c45fSAndroid Build Coastguard Worker const size_t numFds = static_cast<size_t>(buf[10]);
525*38e8c45fSAndroid Build Coastguard Worker const size_t numInts = static_cast<size_t>(buf[11]);
526*38e8c45fSAndroid Build Coastguard Worker
527*38e8c45fSAndroid Build Coastguard Worker // Limit the maxNumber to be relatively small. The number of fds or ints
528*38e8c45fSAndroid Build Coastguard Worker // should not come close to this number, and the number itself was simply
529*38e8c45fSAndroid Build Coastguard Worker // chosen to be high enough to not cause issues and low enough to prevent
530*38e8c45fSAndroid Build Coastguard Worker // overflow problems.
531*38e8c45fSAndroid Build Coastguard Worker const size_t maxNumber = 4096;
532*38e8c45fSAndroid Build Coastguard Worker if (numFds >= maxNumber || numInts >= (maxNumber - flattenWordCount)) {
533*38e8c45fSAndroid Build Coastguard Worker width = height = stride = format = usage_deprecated = 0;
534*38e8c45fSAndroid Build Coastguard Worker layerCount = 0;
535*38e8c45fSAndroid Build Coastguard Worker usage = 0;
536*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
537*38e8c45fSAndroid Build Coastguard Worker ALOGE("unflatten: numFds or numInts is too large: %zd, %zd", numFds, numInts);
538*38e8c45fSAndroid Build Coastguard Worker return BAD_VALUE;
539*38e8c45fSAndroid Build Coastguard Worker }
540*38e8c45fSAndroid Build Coastguard Worker
541*38e8c45fSAndroid Build Coastguard Worker const size_t sizeNeeded = (flattenWordCount + numInts) * sizeof(int);
542*38e8c45fSAndroid Build Coastguard Worker if (size < sizeNeeded) return NO_MEMORY;
543*38e8c45fSAndroid Build Coastguard Worker
544*38e8c45fSAndroid Build Coastguard Worker size_t fdCountNeeded = numFds;
545*38e8c45fSAndroid Build Coastguard Worker if (count < fdCountNeeded) return NO_MEMORY;
546*38e8c45fSAndroid Build Coastguard Worker
547*38e8c45fSAndroid Build Coastguard Worker if (handle) {
548*38e8c45fSAndroid Build Coastguard Worker // free previous handle if any
549*38e8c45fSAndroid Build Coastguard Worker free_handle();
550*38e8c45fSAndroid Build Coastguard Worker }
551*38e8c45fSAndroid Build Coastguard Worker
552*38e8c45fSAndroid Build Coastguard Worker if (numFds || numInts) {
553*38e8c45fSAndroid Build Coastguard Worker width = buf[1];
554*38e8c45fSAndroid Build Coastguard Worker height = buf[2];
555*38e8c45fSAndroid Build Coastguard Worker stride = buf[3];
556*38e8c45fSAndroid Build Coastguard Worker format = buf[4];
557*38e8c45fSAndroid Build Coastguard Worker layerCount = static_cast<uintptr_t>(buf[5]);
558*38e8c45fSAndroid Build Coastguard Worker usage_deprecated = buf[6];
559*38e8c45fSAndroid Build Coastguard Worker if (flattenWordCount == 13) {
560*38e8c45fSAndroid Build Coastguard Worker usage = (uint64_t(buf[12]) << 32) | uint32_t(buf[6]);
561*38e8c45fSAndroid Build Coastguard Worker } else {
562*38e8c45fSAndroid Build Coastguard Worker usage = uint64_t(ANDROID_NATIVE_UNSIGNED_CAST(usage_deprecated));
563*38e8c45fSAndroid Build Coastguard Worker }
564*38e8c45fSAndroid Build Coastguard Worker native_handle* h =
565*38e8c45fSAndroid Build Coastguard Worker native_handle_create(static_cast<int>(numFds), static_cast<int>(numInts));
566*38e8c45fSAndroid Build Coastguard Worker if (!h) {
567*38e8c45fSAndroid Build Coastguard Worker width = height = stride = format = usage_deprecated = 0;
568*38e8c45fSAndroid Build Coastguard Worker layerCount = 0;
569*38e8c45fSAndroid Build Coastguard Worker usage = 0;
570*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
571*38e8c45fSAndroid Build Coastguard Worker ALOGE("unflatten: native_handle_create failed");
572*38e8c45fSAndroid Build Coastguard Worker return NO_MEMORY;
573*38e8c45fSAndroid Build Coastguard Worker }
574*38e8c45fSAndroid Build Coastguard Worker memcpy(h->data, fds, numFds * sizeof(int));
575*38e8c45fSAndroid Build Coastguard Worker memcpy(h->data + numFds, buf + flattenWordCount, numInts * sizeof(int));
576*38e8c45fSAndroid Build Coastguard Worker handle = h;
577*38e8c45fSAndroid Build Coastguard Worker } else {
578*38e8c45fSAndroid Build Coastguard Worker width = height = stride = format = usage_deprecated = 0;
579*38e8c45fSAndroid Build Coastguard Worker layerCount = 0;
580*38e8c45fSAndroid Build Coastguard Worker usage = 0;
581*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
582*38e8c45fSAndroid Build Coastguard Worker }
583*38e8c45fSAndroid Build Coastguard Worker
584*38e8c45fSAndroid Build Coastguard Worker mId = static_cast<uint64_t>(buf[7]) << 32;
585*38e8c45fSAndroid Build Coastguard Worker mId |= static_cast<uint32_t>(buf[8]);
586*38e8c45fSAndroid Build Coastguard Worker
587*38e8c45fSAndroid Build Coastguard Worker mGenerationNumber = static_cast<uint32_t>(buf[9]);
588*38e8c45fSAndroid Build Coastguard Worker
589*38e8c45fSAndroid Build Coastguard Worker mOwner = ownHandle;
590*38e8c45fSAndroid Build Coastguard Worker
591*38e8c45fSAndroid Build Coastguard Worker if (handle != nullptr) {
592*38e8c45fSAndroid Build Coastguard Worker buffer_handle_t importedHandle;
593*38e8c45fSAndroid Build Coastguard Worker status_t err = mBufferMapper.importBuffer(handle, uint32_t(width), uint32_t(height),
594*38e8c45fSAndroid Build Coastguard Worker uint32_t(layerCount), format, usage, uint32_t(stride), &importedHandle);
595*38e8c45fSAndroid Build Coastguard Worker if (err != NO_ERROR) {
596*38e8c45fSAndroid Build Coastguard Worker width = height = stride = format = usage_deprecated = 0;
597*38e8c45fSAndroid Build Coastguard Worker layerCount = 0;
598*38e8c45fSAndroid Build Coastguard Worker usage = 0;
599*38e8c45fSAndroid Build Coastguard Worker handle = nullptr;
600*38e8c45fSAndroid Build Coastguard Worker ALOGE("unflatten: registerBuffer failed: %s (%d)", strerror(-err), err);
601*38e8c45fSAndroid Build Coastguard Worker return err;
602*38e8c45fSAndroid Build Coastguard Worker }
603*38e8c45fSAndroid Build Coastguard Worker
604*38e8c45fSAndroid Build Coastguard Worker native_handle_close(handle);
605*38e8c45fSAndroid Build Coastguard Worker native_handle_delete(const_cast<native_handle_t*>(handle));
606*38e8c45fSAndroid Build Coastguard Worker handle = importedHandle;
607*38e8c45fSAndroid Build Coastguard Worker mBufferMapper.getTransportSize(handle, &mTransportNumFds, &mTransportNumInts);
608*38e8c45fSAndroid Build Coastguard Worker }
609*38e8c45fSAndroid Build Coastguard Worker
610*38e8c45fSAndroid Build Coastguard Worker buffer = static_cast<void const*>(static_cast<uint8_t const*>(buffer) + sizeNeeded);
611*38e8c45fSAndroid Build Coastguard Worker size -= sizeNeeded;
612*38e8c45fSAndroid Build Coastguard Worker fds += numFds;
613*38e8c45fSAndroid Build Coastguard Worker count -= numFds;
614*38e8c45fSAndroid Build Coastguard Worker return NO_ERROR;
615*38e8c45fSAndroid Build Coastguard Worker }
616*38e8c45fSAndroid Build Coastguard Worker
addDeathCallback(GraphicBufferDeathCallback deathCallback,void * context)617*38e8c45fSAndroid Build Coastguard Worker void GraphicBuffer::addDeathCallback(GraphicBufferDeathCallback deathCallback, void* context) {
618*38e8c45fSAndroid Build Coastguard Worker mDeathCallbacks.emplace_back(deathCallback, context);
619*38e8c45fSAndroid Build Coastguard Worker }
620*38e8c45fSAndroid Build Coastguard Worker
621*38e8c45fSAndroid Build Coastguard Worker // ---------------------------------------------------------------------------
622*38e8c45fSAndroid Build Coastguard Worker
623*38e8c45fSAndroid Build Coastguard Worker }; // namespace android
624