1 #include "include/private/dvr/buffer_hub_queue_producer.h" 2 3 #include <dvr/dvr_api.h> 4 #include <inttypes.h> 5 #include <log/log.h> 6 #include <system/window.h> 7 8 namespace android { 9 namespace dvr { 10 11 /* static */ 12 sp<BufferHubQueueProducer> BufferHubQueueProducer::Create() { 13 sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer; 14 auto config = ProducerQueueConfigBuilder() 15 .SetMetadata<DvrNativeBufferMetadata>() 16 .Build(); 17 producer->queue_ = ProducerQueue::Create(config, UsagePolicy{}); 18 return producer; 19 } 20 21 /* static */ 22 sp<BufferHubQueueProducer> BufferHubQueueProducer::Create( 23 const std::shared_ptr<ProducerQueue>& queue) { 24 if (queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) { 25 ALOGE( 26 "BufferHubQueueProducer::Create producer's metadata size is different " 27 "than the size of DvrNativeBufferMetadata"); 28 return nullptr; 29 } 30 31 sp<BufferHubQueueProducer> producer = new BufferHubQueueProducer; 32 producer->queue_ = queue; 33 return producer; 34 } 35 36 status_t BufferHubQueueProducer::requestBuffer(int slot, 37 sp<GraphicBuffer>* buf) { 38 ALOGD_IF(TRACE, "requestBuffer: slot=%d", slot); 39 40 std::unique_lock<std::mutex> lock(mutex_); 41 42 if (connected_api_ == kNoConnectedApi) { 43 ALOGE("requestBuffer: BufferHubQueueProducer has no connected producer"); 44 return NO_INIT; 45 } 46 47 if (slot < 0 || slot >= max_buffer_count_) { 48 ALOGE("requestBuffer: slot index %d out of range [0, %d)", slot, 49 max_buffer_count_); 50 return BAD_VALUE; 51 } else if (!buffers_[slot].mBufferState.isDequeued()) { 52 ALOGE("requestBuffer: slot %d is not owned by the producer (state = %s)", 53 slot, buffers_[slot].mBufferState.string()); 54 return BAD_VALUE; 55 } else if (buffers_[slot].mGraphicBuffer != nullptr) { 56 ALOGE("requestBuffer: slot %d is not empty.", slot); 57 return BAD_VALUE; 58 } else if (buffers_[slot].mBufferProducer == nullptr) { 59 ALOGE("requestBuffer: slot %d is not dequeued.", slot); 60 return BAD_VALUE; 61 } 62 63 const auto& buffer_producer = buffers_[slot].mBufferProducer; 64 sp<GraphicBuffer> graphic_buffer = buffer_producer->buffer()->buffer(); 65 66 buffers_[slot].mGraphicBuffer = graphic_buffer; 67 buffers_[slot].mRequestBufferCalled = true; 68 69 *buf = graphic_buffer; 70 return NO_ERROR; 71 } 72 73 status_t BufferHubQueueProducer::setMaxDequeuedBufferCount( 74 int max_dequeued_buffers) { 75 ALOGD_IF(TRACE, "setMaxDequeuedBufferCount: max_dequeued_buffers=%d", 76 max_dequeued_buffers); 77 78 std::unique_lock<std::mutex> lock(mutex_); 79 80 if (max_dequeued_buffers <= 0 || 81 max_dequeued_buffers > 82 static_cast<int>(BufferHubQueue::kMaxQueueCapacity - 83 kDefaultUndequeuedBuffers)) { 84 ALOGE("setMaxDequeuedBufferCount: %d out of range (0, %zu]", 85 max_dequeued_buffers, BufferHubQueue::kMaxQueueCapacity); 86 return BAD_VALUE; 87 } 88 89 // The new dequeued_buffers count should not be violated by the number 90 // of currently dequeued buffers. 91 int dequeued_count = 0; 92 for (const auto& buf : buffers_) { 93 if (buf.mBufferState.isDequeued()) { 94 dequeued_count++; 95 } 96 } 97 if (dequeued_count > max_dequeued_buffers) { 98 ALOGE( 99 "setMaxDequeuedBufferCount: the requested dequeued_buffers" 100 "count (%d) exceeds the current dequeued buffer count (%d)", 101 max_dequeued_buffers, dequeued_count); 102 return BAD_VALUE; 103 } 104 105 max_dequeued_buffer_count_ = max_dequeued_buffers; 106 return NO_ERROR; 107 } 108 109 status_t BufferHubQueueProducer::setAsyncMode(bool async) { 110 if (async) { 111 // TODO(b/36724099) BufferHubQueue's consumer end always acquires the buffer 112 // automatically and behaves differently from IGraphicBufferConsumer. Thus, 113 // android::BufferQueue's async mode (a.k.a. allocating an additional buffer 114 // to prevent dequeueBuffer from being blocking) technically does not apply 115 // here. 116 // 117 // In Daydream, non-blocking producer side dequeue is guaranteed by careful 118 // buffer consumer implementations. In another word, BufferHubQueue based 119 // dequeueBuffer should never block whether setAsyncMode(true) is set or 120 // not. 121 // 122 // See: IGraphicBufferProducer::setAsyncMode and 123 // BufferQueueProducer::setAsyncMode for more about original implementation. 124 ALOGW( 125 "BufferHubQueueProducer::setAsyncMode: BufferHubQueue should always be " 126 "asynchronous. This call makes no effact."); 127 return NO_ERROR; 128 } 129 return NO_ERROR; 130 } 131 132 status_t BufferHubQueueProducer::dequeueBuffer( 133 int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height, 134 PixelFormat format, uint64_t usage, uint64_t* /*outBufferAge*/, 135 FrameEventHistoryDelta* /* out_timestamps */) { 136 ALOGD_IF(TRACE, "dequeueBuffer: w=%u, h=%u, format=%d, usage=%" PRIu64, width, 137 height, format, usage); 138 139 status_t ret; 140 std::unique_lock<std::mutex> lock(mutex_); 141 142 if (connected_api_ == kNoConnectedApi) { 143 ALOGE("dequeueBuffer: BufferQueue has no connected producer"); 144 return NO_INIT; 145 } 146 147 const uint32_t kLayerCount = 1; 148 if (static_cast<int32_t>(queue_->capacity()) < 149 max_dequeued_buffer_count_ + kDefaultUndequeuedBuffers) { 150 // Lazy allocation. When the capacity of |queue_| has not reached 151 // |max_dequeued_buffer_count_|, allocate new buffer. 152 // TODO(jwcai) To save memory, the really reasonable thing to do is to go 153 // over existing slots and find first existing one to dequeue. 154 ret = AllocateBuffer(width, height, kLayerCount, format, usage); 155 if (ret < 0) 156 return ret; 157 } 158 159 size_t slot; 160 std::shared_ptr<BufferProducer> buffer_producer; 161 162 for (size_t retry = 0; retry < BufferHubQueue::kMaxQueueCapacity; retry++) { 163 LocalHandle fence; 164 auto buffer_status = queue_->Dequeue(dequeue_timeout_ms_, &slot, &fence); 165 if (!buffer_status) 166 return NO_MEMORY; 167 168 buffer_producer = buffer_status.take(); 169 if (!buffer_producer) 170 return NO_MEMORY; 171 172 if (width == buffer_producer->width() && 173 height == buffer_producer->height() && 174 static_cast<uint32_t>(format) == buffer_producer->format()) { 175 // The producer queue returns a buffer producer matches the request. 176 break; 177 } 178 179 // Needs reallocation. 180 // TODO(jwcai) Consider use VLOG instead if we find this log is not useful. 181 ALOGI( 182 "dequeueBuffer: requested buffer (w=%u, h=%u, format=%u) is different " 183 "from the buffer returned at slot: %zu (w=%u, h=%u, format=%u). Need " 184 "re-allocattion.", 185 width, height, format, slot, buffer_producer->width(), 186 buffer_producer->height(), buffer_producer->format()); 187 // Mark the slot as reallocating, so that later we can set 188 // BUFFER_NEEDS_REALLOCATION when the buffer actually get dequeued. 189 buffers_[slot].mIsReallocating = true; 190 191 // Remove the old buffer once the allocation before allocating its 192 // replacement. 193 RemoveBuffer(slot); 194 195 // Allocate a new producer buffer with new buffer configs. Note that if 196 // there are already multiple buffers in the queue, the next one returned 197 // from |queue_->Dequeue| may not be the new buffer we just reallocated. 198 // Retry up to BufferHubQueue::kMaxQueueCapacity times. 199 ret = AllocateBuffer(width, height, kLayerCount, format, usage); 200 if (ret < 0) 201 return ret; 202 } 203 204 // With the BufferHub backed solution. Buffer slot returned from 205 // |queue_->Dequeue| is guaranteed to avaiable for producer's use. 206 // It's either in free state (if the buffer has never been used before) or 207 // in queued state (if the buffer has been dequeued and queued back to 208 // BufferHubQueue). 209 LOG_ALWAYS_FATAL_IF( 210 (!buffers_[slot].mBufferState.isFree() && 211 !buffers_[slot].mBufferState.isQueued()), 212 "dequeueBuffer: slot %zu is not free or queued, actual state: %s.", slot, 213 buffers_[slot].mBufferState.string()); 214 215 buffers_[slot].mBufferState.freeQueued(); 216 buffers_[slot].mBufferState.dequeue(); 217 ALOGD_IF(TRACE, "dequeueBuffer: slot=%zu", slot); 218 219 // TODO(jwcai) Handle fence properly. |BufferHub| has full fence support, we 220 // just need to exopose that through |BufferHubQueue| once we need fence. 221 *out_fence = Fence::NO_FENCE; 222 *out_slot = slot; 223 ret = NO_ERROR; 224 225 if (buffers_[slot].mIsReallocating) { 226 ret |= BUFFER_NEEDS_REALLOCATION; 227 buffers_[slot].mIsReallocating = false; 228 } 229 230 return ret; 231 } 232 233 status_t BufferHubQueueProducer::detachBuffer(int /* slot */) { 234 ALOGE("BufferHubQueueProducer::detachBuffer not implemented."); 235 return INVALID_OPERATION; 236 } 237 238 status_t BufferHubQueueProducer::detachNextBuffer( 239 sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */) { 240 ALOGE("BufferHubQueueProducer::detachNextBuffer not implemented."); 241 return INVALID_OPERATION; 242 } 243 244 status_t BufferHubQueueProducer::attachBuffer( 245 int* /* out_slot */, const sp<GraphicBuffer>& /* buffer */) { 246 // With this BufferHub backed implementation, we assume (for now) all buffers 247 // are allocated and owned by the BufferHub. Thus the attempt of transfering 248 // ownership of a buffer to the buffer queue is intentionally unsupported. 249 LOG_ALWAYS_FATAL("BufferHubQueueProducer::attachBuffer not supported."); 250 return INVALID_OPERATION; 251 } 252 253 status_t BufferHubQueueProducer::queueBuffer(int slot, 254 const QueueBufferInput& input, 255 QueueBufferOutput* output) { 256 ALOGD_IF(TRACE, "queueBuffer: slot %d", slot); 257 258 if (output == nullptr) { 259 return BAD_VALUE; 260 } 261 262 int64_t timestamp; 263 bool is_auto_timestamp; 264 android_dataspace dataspace; 265 Rect crop(Rect::EMPTY_RECT); 266 int scaling_mode; 267 uint32_t transform; 268 sp<Fence> fence; 269 270 input.deflate(×tamp, &is_auto_timestamp, &dataspace, &crop, 271 &scaling_mode, &transform, &fence); 272 273 // Check input scaling mode is valid. 274 switch (scaling_mode) { 275 case NATIVE_WINDOW_SCALING_MODE_FREEZE: 276 case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW: 277 case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP: 278 case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP: 279 break; 280 default: 281 ALOGE("queueBuffer: unknown scaling mode %d", scaling_mode); 282 return BAD_VALUE; 283 } 284 285 // Check input fence is valid. 286 if (fence == nullptr) { 287 ALOGE("queueBuffer: fence is NULL"); 288 return BAD_VALUE; 289 } 290 291 status_t ret; 292 std::unique_lock<std::mutex> lock(mutex_); 293 294 if (connected_api_ == kNoConnectedApi) { 295 ALOGE("queueBuffer: BufferQueue has no connected producer"); 296 return NO_INIT; 297 } 298 299 if (slot < 0 || slot >= max_buffer_count_) { 300 ALOGE("queueBuffer: slot index %d out of range [0, %d)", slot, 301 max_buffer_count_); 302 return BAD_VALUE; 303 } else if (!buffers_[slot].mBufferState.isDequeued()) { 304 ALOGE("queueBuffer: slot %d is not owned by the producer (state = %s)", 305 slot, buffers_[slot].mBufferState.string()); 306 return BAD_VALUE; 307 } else if ((!buffers_[slot].mRequestBufferCalled || 308 buffers_[slot].mGraphicBuffer == nullptr)) { 309 ALOGE( 310 "queueBuffer: slot %d is not requested (mRequestBufferCalled=%d, " 311 "mGraphicBuffer=%p)", 312 slot, buffers_[slot].mRequestBufferCalled, 313 buffers_[slot].mGraphicBuffer.get()); 314 return BAD_VALUE; 315 } 316 317 // Post the buffer producer with timestamp in the metadata. 318 const auto& buffer_producer = buffers_[slot].mBufferProducer; 319 320 // Check input crop is not out of boundary of current buffer. 321 Rect buffer_rect(buffer_producer->width(), buffer_producer->height()); 322 Rect cropped_rect(Rect::EMPTY_RECT); 323 crop.intersect(buffer_rect, &cropped_rect); 324 if (cropped_rect != crop) { 325 ALOGE("queueBuffer: slot %d has out-of-boundary crop.", slot); 326 return BAD_VALUE; 327 } 328 329 LocalHandle fence_fd(fence->isValid() ? fence->dup() : -1); 330 331 DvrNativeBufferMetadata meta_data; 332 meta_data.timestamp = timestamp; 333 meta_data.is_auto_timestamp = static_cast<int32_t>(is_auto_timestamp); 334 meta_data.dataspace = static_cast<int32_t>(dataspace); 335 meta_data.crop_left = crop.left; 336 meta_data.crop_top = crop.top; 337 meta_data.crop_right = crop.right; 338 meta_data.crop_bottom = crop.bottom; 339 meta_data.scaling_mode = static_cast<int32_t>(scaling_mode); 340 meta_data.transform = static_cast<int32_t>(transform); 341 342 buffer_producer->PostAsync(&meta_data, fence_fd); 343 buffers_[slot].mBufferState.queue(); 344 345 output->width = buffer_producer->width(); 346 output->height = buffer_producer->height(); 347 output->transformHint = 0; // default value, we don't use it yet. 348 349 // |numPendingBuffers| counts of the number of buffers that has been enqueued 350 // by the producer but not yet acquired by the consumer. Due to the nature 351 // of BufferHubQueue design, this is hard to trace from the producer's client 352 // side, but it's safe to assume it's zero. 353 output->numPendingBuffers = 0; 354 355 // Note that we are not setting nextFrameNumber here as it seems to be only 356 // used by surface flinger. See more at b/22802885, ag/791760. 357 output->nextFrameNumber = 0; 358 359 return NO_ERROR; 360 } 361 362 status_t BufferHubQueueProducer::cancelBuffer(int slot, 363 const sp<Fence>& fence) { 364 ALOGD_IF(TRACE, __FUNCTION__); 365 366 std::unique_lock<std::mutex> lock(mutex_); 367 368 if (connected_api_ == kNoConnectedApi) { 369 ALOGE("cancelBuffer: BufferQueue has no connected producer"); 370 return NO_INIT; 371 } 372 373 if (slot < 0 || slot >= max_buffer_count_) { 374 ALOGE("cancelBuffer: slot index %d out of range [0, %d)", slot, 375 max_buffer_count_); 376 return BAD_VALUE; 377 } else if (!buffers_[slot].mBufferState.isDequeued()) { 378 ALOGE("cancelBuffer: slot %d is not owned by the producer (state = %s)", 379 slot, buffers_[slot].mBufferState.string()); 380 return BAD_VALUE; 381 } else if (fence == nullptr) { 382 ALOGE("cancelBuffer: fence is NULL"); 383 return BAD_VALUE; 384 } 385 386 auto buffer_producer = buffers_[slot].mBufferProducer; 387 queue_->Enqueue(buffer_producer, slot, 0ULL); 388 buffers_[slot].mBufferState.cancel(); 389 buffers_[slot].mFence = fence; 390 ALOGD_IF(TRACE, "cancelBuffer: slot %d", slot); 391 392 return NO_ERROR; 393 } 394 395 status_t BufferHubQueueProducer::query(int what, int* out_value) { 396 ALOGD_IF(TRACE, __FUNCTION__); 397 398 std::unique_lock<std::mutex> lock(mutex_); 399 400 if (out_value == nullptr) { 401 ALOGE("query: out_value was NULL"); 402 return BAD_VALUE; 403 } 404 405 int value = 0; 406 switch (what) { 407 case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS: 408 // TODO(b/36187402) This should be the maximum number of buffers that this 409 // producer queue's consumer can acquire. Set to be at least one. Need to 410 // find a way to set from the consumer side. 411 value = kDefaultUndequeuedBuffers; 412 break; 413 case NATIVE_WINDOW_BUFFER_AGE: 414 value = 0; 415 break; 416 case NATIVE_WINDOW_WIDTH: 417 value = queue_->default_width(); 418 break; 419 case NATIVE_WINDOW_HEIGHT: 420 value = queue_->default_height(); 421 break; 422 case NATIVE_WINDOW_FORMAT: 423 value = queue_->default_format(); 424 break; 425 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: 426 // BufferHubQueue is always operating in async mode, thus semantically 427 // consumer can never be running behind. See BufferQueueCore.cpp core 428 // for more information about the original meaning of this flag. 429 value = 0; 430 break; 431 case NATIVE_WINDOW_CONSUMER_USAGE_BITS: 432 // TODO(jwcai) This is currently not implement as we don't need 433 // IGraphicBufferConsumer parity. 434 value = 0; 435 break; 436 case NATIVE_WINDOW_DEFAULT_DATASPACE: 437 // TODO(jwcai) Return the default value android::BufferQueue is using as 438 // there is no way dvr::ConsumerQueue can set it. 439 value = 0; // HAL_DATASPACE_UNKNOWN 440 break; 441 case NATIVE_WINDOW_STICKY_TRANSFORM: 442 // TODO(jwcai) Return the default value android::BufferQueue is using as 443 // there is no way dvr::ConsumerQueue can set it. 444 value = 0; 445 break; 446 case NATIVE_WINDOW_CONSUMER_IS_PROTECTED: 447 // In Daydream's implementation, the consumer end (i.e. VR Compostior) 448 // knows how to handle protected buffers. 449 value = 1; 450 break; 451 default: 452 return BAD_VALUE; 453 } 454 455 ALOGD_IF(TRACE, "query: key=%d, v=%d", what, value); 456 *out_value = value; 457 return NO_ERROR; 458 } 459 460 status_t BufferHubQueueProducer::connect( 461 const sp<IProducerListener>& /* listener */, int api, 462 bool /* producer_controlled_by_app */, QueueBufferOutput* output) { 463 // Consumer interaction are actually handled by buffer hub, and we need 464 // to maintain consumer operations here. We only need to perform basic input 465 // parameter checks here. 466 ALOGD_IF(TRACE, __FUNCTION__); 467 468 if (output == nullptr) { 469 return BAD_VALUE; 470 } 471 472 std::unique_lock<std::mutex> lock(mutex_); 473 474 if (connected_api_ != kNoConnectedApi) { 475 return BAD_VALUE; 476 } 477 478 switch (api) { 479 case NATIVE_WINDOW_API_EGL: 480 case NATIVE_WINDOW_API_CPU: 481 case NATIVE_WINDOW_API_MEDIA: 482 case NATIVE_WINDOW_API_CAMERA: 483 connected_api_ = api; 484 485 output->width = queue_->default_width(); 486 output->height = queue_->default_height(); 487 488 // default values, we don't use them yet. 489 output->transformHint = 0; 490 output->numPendingBuffers = 0; 491 output->nextFrameNumber = 0; 492 output->bufferReplaced = false; 493 494 break; 495 default: 496 ALOGE("BufferHubQueueProducer::connect: unknow API %d", api); 497 return BAD_VALUE; 498 } 499 500 return NO_ERROR; 501 } 502 503 status_t BufferHubQueueProducer::disconnect(int api, DisconnectMode /*mode*/) { 504 // Consumer interaction are actually handled by buffer hub, and we need 505 // to maintain consumer operations here. We only need to perform basic input 506 // parameter checks here. 507 ALOGD_IF(TRACE, __FUNCTION__); 508 509 std::unique_lock<std::mutex> lock(mutex_); 510 511 if (kNoConnectedApi == connected_api_) { 512 return NO_INIT; 513 } else if (api != connected_api_) { 514 return BAD_VALUE; 515 } 516 517 FreeAllBuffers(); 518 connected_api_ = kNoConnectedApi; 519 return NO_ERROR; 520 } 521 522 status_t BufferHubQueueProducer::setSidebandStream( 523 const sp<NativeHandle>& stream) { 524 if (stream != nullptr) { 525 // TODO(jwcai) Investigate how is is used, maybe use BufferHubBuffer's 526 // metadata. 527 ALOGE("SidebandStream is not currently supported."); 528 return INVALID_OPERATION; 529 } 530 return NO_ERROR; 531 } 532 533 void BufferHubQueueProducer::allocateBuffers(uint32_t /* width */, 534 uint32_t /* height */, 535 PixelFormat /* format */, 536 uint64_t /* usage */) { 537 // TODO(jwcai) |allocateBuffers| aims to preallocate up to the maximum number 538 // of buffers permitted by the current BufferQueue configuration (aka 539 // |max_buffer_count_|). 540 ALOGE("BufferHubQueueProducer::allocateBuffers not implemented."); 541 } 542 543 status_t BufferHubQueueProducer::allowAllocation(bool /* allow */) { 544 ALOGE("BufferHubQueueProducer::allowAllocation not implemented."); 545 return INVALID_OPERATION; 546 } 547 548 status_t BufferHubQueueProducer::setGenerationNumber( 549 uint32_t generation_number) { 550 ALOGD_IF(TRACE, __FUNCTION__); 551 552 std::unique_lock<std::mutex> lock(mutex_); 553 generation_number_ = generation_number; 554 return NO_ERROR; 555 } 556 557 String8 BufferHubQueueProducer::getConsumerName() const { 558 // BufferHub based implementation could have one to many producer/consumer 559 // relationship, thus |getConsumerName| from the producer side does not 560 // make any sense. 561 ALOGE("BufferHubQueueProducer::getConsumerName not supported."); 562 return String8("BufferHubQueue::DummyConsumer"); 563 } 564 565 status_t BufferHubQueueProducer::setSharedBufferMode(bool shared_buffer_mode) { 566 if (shared_buffer_mode) { 567 ALOGE( 568 "BufferHubQueueProducer::setSharedBufferMode(true) is not supported."); 569 // TODO(b/36373181) Front buffer mode for buffer hub queue as ANativeWindow. 570 return INVALID_OPERATION; 571 } 572 // Setting to default should just work as a no-op. 573 return NO_ERROR; 574 } 575 576 status_t BufferHubQueueProducer::setAutoRefresh(bool auto_refresh) { 577 if (auto_refresh) { 578 ALOGE("BufferHubQueueProducer::setAutoRefresh(true) is not supported."); 579 return INVALID_OPERATION; 580 } 581 // Setting to default should just work as a no-op. 582 return NO_ERROR; 583 } 584 585 status_t BufferHubQueueProducer::setDequeueTimeout(nsecs_t timeout) { 586 ALOGD_IF(TRACE, __FUNCTION__); 587 588 std::unique_lock<std::mutex> lock(mutex_); 589 dequeue_timeout_ms_ = static_cast<int>(timeout / (1000 * 1000)); 590 return NO_ERROR; 591 } 592 593 status_t BufferHubQueueProducer::getLastQueuedBuffer( 594 sp<GraphicBuffer>* /* out_buffer */, sp<Fence>* /* out_fence */, 595 float /*out_transform_matrix*/[16]) { 596 ALOGE("BufferHubQueueProducer::getLastQueuedBuffer not implemented."); 597 return INVALID_OPERATION; 598 } 599 600 void BufferHubQueueProducer::getFrameTimestamps( 601 FrameEventHistoryDelta* /*outDelta*/) { 602 ALOGE("BufferHubQueueProducer::getFrameTimestamps not implemented."); 603 } 604 605 status_t BufferHubQueueProducer::getUniqueId(uint64_t* out_id) const { 606 ALOGD_IF(TRACE, __FUNCTION__); 607 608 *out_id = unique_id_; 609 return NO_ERROR; 610 } 611 612 status_t BufferHubQueueProducer::getConsumerUsage(uint64_t* out_usage) const { 613 ALOGD_IF(TRACE, __FUNCTION__); 614 615 // same value as returned by querying NATIVE_WINDOW_CONSUMER_USAGE_BITS 616 *out_usage = 0; 617 return NO_ERROR; 618 } 619 620 status_t BufferHubQueueProducer::AllocateBuffer(uint32_t width, uint32_t height, 621 uint32_t layer_count, 622 PixelFormat format, 623 uint64_t usage) { 624 auto status = 625 queue_->AllocateBuffer(width, height, layer_count, format, usage); 626 if (!status) { 627 ALOGE( 628 "BufferHubQueueProducer::AllocateBuffer: Failed to allocate buffer: %s", 629 status.GetErrorMessage().c_str()); 630 return NO_MEMORY; 631 } 632 633 size_t slot = status.get(); 634 auto buffer_producer = queue_->GetBuffer(slot); 635 636 LOG_ALWAYS_FATAL_IF(buffer_producer == nullptr, 637 "Failed to get buffer producer at slot: %zu", slot); 638 639 buffers_[slot].mBufferProducer = buffer_producer; 640 641 return NO_ERROR; 642 } 643 644 status_t BufferHubQueueProducer::RemoveBuffer(size_t slot) { 645 auto status = queue_->RemoveBuffer(slot); 646 if (!status) { 647 ALOGE("BufferHubQueueProducer::RemoveBuffer: Failed to remove buffer: %s", 648 status.GetErrorMessage().c_str()); 649 return INVALID_OPERATION; 650 } 651 652 // Reset in memory objects related the the buffer. 653 buffers_[slot].mBufferProducer = nullptr; 654 buffers_[slot].mGraphicBuffer = nullptr; 655 buffers_[slot].mBufferState.detachProducer(); 656 return NO_ERROR; 657 } 658 659 status_t BufferHubQueueProducer::FreeAllBuffers() { 660 for (size_t slot = 0; slot < BufferHubQueue::kMaxQueueCapacity; slot++) { 661 // Reset in memory objects related the the buffer. 662 buffers_[slot].mGraphicBuffer = nullptr; 663 buffers_[slot].mBufferState.reset(); 664 buffers_[slot].mRequestBufferCalled = false; 665 buffers_[slot].mBufferProducer = nullptr; 666 buffers_[slot].mFence = Fence::NO_FENCE; 667 } 668 669 auto status = queue_->FreeAllBuffers(); 670 if (!status) { 671 ALOGE( 672 "BufferHubQueueProducer::FreeAllBuffers: Failed to free all buffers on " 673 "the queue: %s", 674 status.GetErrorMessage().c_str()); 675 } 676 677 if (queue_->capacity() != 0 || queue_->count() != 0) { 678 LOG_ALWAYS_FATAL( 679 "BufferHubQueueProducer::FreeAllBuffers: Not all buffers are freed."); 680 } 681 682 return NO_ERROR; 683 } 684 685 } // namespace dvr 686 } // namespace android 687