• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 #pragma once
18 
19 #ifndef LOG_TAG
20 #warning "Gralloc0Hal.h included without LOG_TAG"
21 #endif
22 
23 #include <cstring>  // for strerror
24 
25 #include <allocator-hal/2.0/AllocatorHal.h>
26 #include <hardware/gralloc.h>
27 #include <log/log.h>
28 #include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
29 
30 namespace android {
31 namespace hardware {
32 namespace graphics {
33 namespace allocator {
34 namespace V2_0 {
35 namespace passthrough {
36 
37 namespace detail {
38 
39 using mapper::V2_0::BufferDescriptor;
40 using mapper::V2_0::Error;
41 using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
42 
43 // Gralloc0HalImpl implements V2_*::hal::AllocatorHal on top of gralloc0
44 template <typename Hal>
45 class Gralloc0HalImpl : public Hal {
46    public:
~Gralloc0HalImpl()47     ~Gralloc0HalImpl() {
48         if (mDevice) {
49             gralloc_close(mDevice);
50         }
51     }
52 
initWithModule(const hw_module_t * module)53     bool initWithModule(const hw_module_t* module) {
54         int result = gralloc_open(module, &mDevice);
55         if (result) {
56             ALOGE("failed to open gralloc0 device: %s", strerror(-result));
57             mDevice = nullptr;
58             return false;
59         }
60 
61         return true;
62     }
63 
dumpDebugInfo()64     std::string dumpDebugInfo() override {
65         char buf[4096] = {};
66         if (mDevice->dump) {
67             mDevice->dump(mDevice, buf, sizeof(buf));
68             buf[sizeof(buf) - 1] = '\0';
69         }
70 
71         return buf;
72     }
73 
allocateBuffers(const BufferDescriptor & descriptor,uint32_t count,uint32_t * outStride,std::vector<const native_handle_t * > * outBuffers)74     Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
75                           std::vector<const native_handle_t*>* outBuffers) override {
76         mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
77         if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
78             return Error::BAD_DESCRIPTOR;
79         }
80 
81         Error error = Error::NONE;
82         uint32_t stride = 0;
83         std::vector<const native_handle_t*> buffers;
84         buffers.reserve(count);
85 
86         // allocate the buffers
87         for (uint32_t i = 0; i < count; i++) {
88             const native_handle_t* tmpBuffer;
89             uint32_t tmpStride;
90             error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
91             if (error != Error::NONE) {
92                 break;
93             }
94 
95             buffers.push_back(tmpBuffer);
96 
97             if (stride == 0) {
98                 stride = tmpStride;
99             } else if (stride != tmpStride) {
100                 // non-uniform strides
101                 error = Error::UNSUPPORTED;
102                 break;
103             }
104         }
105 
106         if (error != Error::NONE) {
107             freeBuffers(buffers);
108             return error;
109         }
110 
111         *outStride = stride;
112         *outBuffers = std::move(buffers);
113 
114         return Error::NONE;
115     }
116 
freeBuffers(const std::vector<const native_handle_t * > & buffers)117     void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
118         for (auto buffer : buffers) {
119             int result = mDevice->free(mDevice, buffer);
120             if (result != 0) {
121                 ALOGE("failed to free buffer %p: %d", buffer, result);
122             }
123         }
124     }
125 
126    protected:
allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo & info,const native_handle_t ** outBuffer,uint32_t * outStride)127     Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
128                             const native_handle_t** outBuffer, uint32_t* outStride) {
129         if (info.layerCount > 1 || (info.usage >> 32) != 0) {
130             return Error::BAD_VALUE;
131         }
132 
133         const native_handle_t* buffer = nullptr;
134         int stride = 0;
135         int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
136                                     info.usage, &buffer, &stride);
137         switch (result) {
138             case 0:
139                 *outBuffer = buffer;
140                 *outStride = stride;
141                 return Error::NONE;
142             case -EINVAL:
143                 return Error::BAD_VALUE;
144             default:
145                 return Error::NO_RESOURCES;
146         }
147     }
148 
149     alloc_device_t* mDevice = nullptr;
150 };
151 
152 }  // namespace detail
153 
154 using Gralloc0Hal = detail::Gralloc0HalImpl<hal::AllocatorHal>;
155 
156 }  // namespace passthrough
157 }  // namespace V2_0
158 }  // namespace allocator
159 }  // namespace graphics
160 }  // namespace hardware
161 }  // namespace android
162