| // Copyright (c) 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/command_buffer/client/readback_buffer_shadow_tracker.h" |
| |
| #include "base/memory/ptr_util.h" |
| #include "build/build_config.h" |
| #include "gpu/command_buffer/client/gles2_cmd_helper.h" |
| #include "gpu/command_buffer/client/mapped_memory.h" |
| |
| namespace gpu { |
| namespace gles2 { |
| |
| // ReadbackBufferShadowTracker::Buffer |
| |
| ReadbackBufferShadowTracker::Buffer::Buffer( |
| GLuint buffer_id, |
| ReadbackBufferShadowTracker* tracker) |
| : buffer_id_(buffer_id), tracker_(tracker) {} |
| |
| ReadbackBufferShadowTracker::Buffer::~Buffer() { |
| Free(); |
| } |
| |
| uint32_t ReadbackBufferShadowTracker::Buffer::Alloc(int32_t* shm_id, |
| uint32_t* shm_offset, |
| bool* already_allocated) { |
| *already_allocated = readback_shm_address_ != nullptr; |
| if (!readback_shm_address_) { |
| readback_shm_address_ = |
| tracker_->mapped_memory_->Alloc(size_, &shm_id_, &shm_offset_); |
| } |
| *shm_id = shm_id_; |
| *shm_offset = shm_offset_; |
| return size_; |
| } |
| |
| void ReadbackBufferShadowTracker::Buffer::Free() { |
| if (readback_shm_address_) { |
| tracker_->mapped_memory_->FreePendingToken( |
| readback_shm_address_, tracker_->helper_->InsertToken()); |
| } |
| readback_shm_address_ = nullptr; |
| } |
| |
| void* ReadbackBufferShadowTracker::Buffer::MapReadbackShm(uint32_t offset, |
| uint32_t map_size) { |
| DCHECK(!is_mapped_); |
| if (serial_of_readback_data_ != serial_of_last_write_) { |
| return nullptr; |
| } |
| if (!readback_shm_address_) { |
| return nullptr; |
| } |
| if (map_size > size_) { |
| return nullptr; |
| } |
| DCHECK_GE(size_, map_size); |
| if (offset > size_ - map_size) { |
| return nullptr; |
| } |
| is_mapped_ = true; |
| return &static_cast<uint8_t*>(readback_shm_address_)[offset]; |
| } |
| |
| bool ReadbackBufferShadowTracker::Buffer::UnmapReadbackShm() { |
| Free(); |
| |
| bool was_mapped = is_mapped_; |
| is_mapped_ = false; |
| return was_mapped; |
| } |
| |
| void ReadbackBufferShadowTracker::Buffer::UpdateSerialTo(uint64_t serial) { |
| DCHECK_LT(serial_of_readback_data_, serial); |
| serial_of_readback_data_ = serial; |
| } |
| |
| // ReadbackBufferShadowTracker |
| |
| ReadbackBufferShadowTracker::ReadbackBufferShadowTracker( |
| MappedMemoryManager* mapped_memory, |
| GLES2CmdHelper* helper) |
| : mapped_memory_(mapped_memory), helper_(helper) {} |
| |
| ReadbackBufferShadowTracker::~ReadbackBufferShadowTracker() {} |
| |
| ReadbackBufferShadowTracker::Buffer* |
| ReadbackBufferShadowTracker::GetOrCreateBuffer(GLuint id, GLuint size) { |
| Buffer* buffer = GetBuffer(id); |
| if (buffer) { |
| buffer->Free(); |
| } else { |
| buffer = new Buffer(id, this); |
| buffers_.emplace(id, base::WrapUnique(buffer)); |
| } |
| buffer->size_ = size; |
| OnBufferWrite(id); |
| |
| return buffer; |
| } |
| |
| void ReadbackBufferShadowTracker::OnBufferWrite(GLuint id) { |
| Buffer* buffer = GetBuffer(id); |
| if (!buffer) { |
| // Buffer is not tracked by the ReadbackBufferShadowTracker. |
| return; |
| } |
| |
| DCHECK(buffer->serial_of_last_write_ <= buffer_shadow_serial_); |
| buffer->serial_of_last_write_ = buffer_shadow_serial_; |
| |
| for (const auto& b : buffers_written_but_not_fenced_) { |
| if (b.get() == buffer) { |
| return; |
| } |
| } |
| buffers_written_but_not_fenced_.push_back(buffer->AsWeakPtr()); |
| } |
| |
| ReadbackBufferShadowTracker::BufferList |
| ReadbackBufferShadowTracker::TakeUnfencedBufferList() { |
| BufferList buffers; |
| std::swap(buffers, buffers_written_but_not_fenced_); |
| return buffers; |
| } |
| |
| } // namespace gles2 |
| } // namespace gpu |