1 /* 2 * Copyright (C) 2007 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 #define LOG_TAG "GraphicBufferMapper" 18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS 19 //#define LOG_NDEBUG 0 20 21 #include <stdint.h> 22 #include <errno.h> 23 24 // We would eliminate the non-conforming zero-length array, but we can't since 25 // this is effectively included from the Linux kernel 26 #pragma clang diagnostic push 27 #pragma clang diagnostic ignored "-Wzero-length-array" 28 #include <sync/sync.h> 29 #pragma clang diagnostic pop 30 31 #include <utils/Errors.h> 32 #include <utils/Log.h> 33 #include <utils/Trace.h> 34 35 #include <ui/Gralloc1On0Adapter.h> 36 #include <ui/GraphicBufferMapper.h> 37 #include <ui/Rect.h> 38 39 #include <system/graphics.h> 40 41 namespace android { 42 // --------------------------------------------------------------------------- 43 44 ANDROID_SINGLETON_STATIC_INSTANCE( GraphicBufferMapper ) 45 46 GraphicBufferMapper::GraphicBufferMapper() 47 : mLoader(std::make_unique<Gralloc1::Loader>()), 48 mDevice(mLoader->getDevice()) {} 49 50 51 52 status_t GraphicBufferMapper::registerBuffer(buffer_handle_t handle) 53 { 54 ATRACE_CALL(); 55 56 gralloc1_error_t error = mDevice->retain(handle); 57 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d", 58 handle, error); 59 60 return error; 61 } 62 63 status_t GraphicBufferMapper::registerBuffer(const GraphicBuffer* buffer) 64 { 65 ATRACE_CALL(); 66 67 gralloc1_error_t error = mDevice->retain(buffer); 68 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "registerBuffer(%p) failed: %d", 69 buffer->getNativeBuffer()->handle, error); 70 71 return error; 72 } 73 74 status_t GraphicBufferMapper::unregisterBuffer(buffer_handle_t handle) 75 { 76 ATRACE_CALL(); 77 78 gralloc1_error_t error = mDevice->release(handle); 79 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "unregisterBuffer(%p): failed %d", 80 handle, error); 81 82 return error; 83 } 84 85 static inline gralloc1_rect_t asGralloc1Rect(const Rect& rect) { 86 gralloc1_rect_t outRect{}; 87 outRect.left = rect.left; 88 outRect.top = rect.top; 89 outRect.width = rect.width(); 90 outRect.height = rect.height(); 91 return outRect; 92 } 93 94 status_t GraphicBufferMapper::lock(buffer_handle_t handle, uint32_t usage, 95 const Rect& bounds, void** vaddr) 96 { 97 return lockAsync(handle, usage, bounds, vaddr, -1); 98 } 99 100 status_t GraphicBufferMapper::lockYCbCr(buffer_handle_t handle, uint32_t usage, 101 const Rect& bounds, android_ycbcr *ycbcr) 102 { 103 return lockAsyncYCbCr(handle, usage, bounds, ycbcr, -1); 104 } 105 106 status_t GraphicBufferMapper::unlock(buffer_handle_t handle) 107 { 108 int32_t fenceFd = -1; 109 status_t error = unlockAsync(handle, &fenceFd); 110 if (error == NO_ERROR) { 111 sync_wait(fenceFd, -1); 112 close(fenceFd); 113 } 114 return error; 115 } 116 117 status_t GraphicBufferMapper::lockAsync(buffer_handle_t handle, 118 uint32_t usage, const Rect& bounds, void** vaddr, int fenceFd) 119 { 120 ATRACE_CALL(); 121 122 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds); 123 sp<Fence> fence = new Fence(fenceFd); 124 gralloc1_error_t error = mDevice->lock(handle, 125 static_cast<gralloc1_producer_usage_t>(usage), 126 static_cast<gralloc1_consumer_usage_t>(usage), 127 &accessRegion, vaddr, fence); 128 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lock(%p, ...) failed: %d", handle, 129 error); 130 131 return error; 132 } 133 134 static inline bool isValidYCbCrPlane(const android_flex_plane_t& plane) { 135 if (plane.bits_per_component != 8) { 136 ALOGV("Invalid number of bits per component: %d", 137 plane.bits_per_component); 138 return false; 139 } 140 if (plane.bits_used != 8) { 141 ALOGV("Invalid number of bits used: %d", plane.bits_used); 142 return false; 143 } 144 145 bool hasValidIncrement = plane.h_increment == 1 || 146 (plane.component != FLEX_COMPONENT_Y && plane.h_increment == 2); 147 hasValidIncrement = hasValidIncrement && plane.v_increment > 0; 148 if (!hasValidIncrement) { 149 ALOGV("Invalid increment: h %d v %d", plane.h_increment, 150 plane.v_increment); 151 return false; 152 } 153 154 return true; 155 } 156 157 status_t GraphicBufferMapper::lockAsyncYCbCr(buffer_handle_t handle, 158 uint32_t usage, const Rect& bounds, android_ycbcr *ycbcr, int fenceFd) 159 { 160 ATRACE_CALL(); 161 162 gralloc1_rect_t accessRegion = asGralloc1Rect(bounds); 163 sp<Fence> fence = new Fence(fenceFd); 164 165 if (mDevice->hasCapability(GRALLOC1_CAPABILITY_ON_ADAPTER)) { 166 gralloc1_error_t error = mDevice->lockYCbCr(handle, 167 static_cast<gralloc1_producer_usage_t>(usage), 168 static_cast<gralloc1_consumer_usage_t>(usage), 169 &accessRegion, ycbcr, fence); 170 ALOGW_IF(error != GRALLOC1_ERROR_NONE, "lockYCbCr(%p, ...) failed: %d", 171 handle, error); 172 return error; 173 } 174 175 uint32_t numPlanes = 0; 176 gralloc1_error_t error = mDevice->getNumFlexPlanes(handle, &numPlanes); 177 if (error != GRALLOC1_ERROR_NONE) { 178 ALOGV("Failed to retrieve number of flex planes: %d", error); 179 return error; 180 } 181 if (numPlanes < 3) { 182 ALOGV("Not enough planes for YCbCr (%u found)", numPlanes); 183 return GRALLOC1_ERROR_UNSUPPORTED; 184 } 185 186 std::vector<android_flex_plane_t> planes(numPlanes); 187 android_flex_layout_t flexLayout{}; 188 flexLayout.num_planes = numPlanes; 189 flexLayout.planes = planes.data(); 190 191 error = mDevice->lockFlex(handle, 192 static_cast<gralloc1_producer_usage_t>(usage), 193 static_cast<gralloc1_consumer_usage_t>(usage), 194 &accessRegion, &flexLayout, fence); 195 if (error != GRALLOC1_ERROR_NONE) { 196 ALOGW("lockFlex(%p, ...) failed: %d", handle, error); 197 return error; 198 } 199 if (flexLayout.format != FLEX_FORMAT_YCbCr) { 200 ALOGV("Unable to convert flex-format buffer to YCbCr"); 201 unlock(handle); 202 return GRALLOC1_ERROR_UNSUPPORTED; 203 } 204 205 // Find planes 206 auto yPlane = planes.cend(); 207 auto cbPlane = planes.cend(); 208 auto crPlane = planes.cend(); 209 for (auto planeIter = planes.cbegin(); planeIter != planes.cend(); 210 ++planeIter) { 211 if (planeIter->component == FLEX_COMPONENT_Y) { 212 yPlane = planeIter; 213 } else if (planeIter->component == FLEX_COMPONENT_Cb) { 214 cbPlane = planeIter; 215 } else if (planeIter->component == FLEX_COMPONENT_Cr) { 216 crPlane = planeIter; 217 } 218 } 219 if (yPlane == planes.cend()) { 220 ALOGV("Unable to find Y plane"); 221 unlock(handle); 222 return GRALLOC1_ERROR_UNSUPPORTED; 223 } 224 if (cbPlane == planes.cend()) { 225 ALOGV("Unable to find Cb plane"); 226 unlock(handle); 227 return GRALLOC1_ERROR_UNSUPPORTED; 228 } 229 if (crPlane == planes.cend()) { 230 ALOGV("Unable to find Cr plane"); 231 unlock(handle); 232 return GRALLOC1_ERROR_UNSUPPORTED; 233 } 234 235 // Validate planes 236 if (!isValidYCbCrPlane(*yPlane)) { 237 ALOGV("Y plane is invalid"); 238 unlock(handle); 239 return GRALLOC1_ERROR_UNSUPPORTED; 240 } 241 if (!isValidYCbCrPlane(*cbPlane)) { 242 ALOGV("Cb plane is invalid"); 243 unlock(handle); 244 return GRALLOC1_ERROR_UNSUPPORTED; 245 } 246 if (!isValidYCbCrPlane(*crPlane)) { 247 ALOGV("Cr plane is invalid"); 248 unlock(handle); 249 return GRALLOC1_ERROR_UNSUPPORTED; 250 } 251 if (cbPlane->v_increment != crPlane->v_increment) { 252 ALOGV("Cb and Cr planes have different step (%d vs. %d)", 253 cbPlane->v_increment, crPlane->v_increment); 254 unlock(handle); 255 return GRALLOC1_ERROR_UNSUPPORTED; 256 } 257 if (cbPlane->h_increment != crPlane->h_increment) { 258 ALOGV("Cb and Cr planes have different stride (%d vs. %d)", 259 cbPlane->h_increment, crPlane->h_increment); 260 unlock(handle); 261 return GRALLOC1_ERROR_UNSUPPORTED; 262 } 263 264 // Pack plane data into android_ycbcr struct 265 ycbcr->y = yPlane->top_left; 266 ycbcr->cb = cbPlane->top_left; 267 ycbcr->cr = crPlane->top_left; 268 ycbcr->ystride = static_cast<size_t>(yPlane->v_increment); 269 ycbcr->cstride = static_cast<size_t>(cbPlane->v_increment); 270 ycbcr->chroma_step = static_cast<size_t>(cbPlane->h_increment); 271 272 return error; 273 } 274 275 status_t GraphicBufferMapper::unlockAsync(buffer_handle_t handle, int *fenceFd) 276 { 277 ATRACE_CALL(); 278 279 sp<Fence> fence = Fence::NO_FENCE; 280 gralloc1_error_t error = mDevice->unlock(handle, &fence); 281 if (error != GRALLOC1_ERROR_NONE) { 282 ALOGE("unlock(%p) failed: %d", handle, error); 283 return error; 284 } 285 286 *fenceFd = fence->dup(); 287 return error; 288 } 289 290 // --------------------------------------------------------------------------- 291 }; // namespace android 292