1 // Copyright (c) 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gpu/command_buffer/client/readback_buffer_shadow_tracker.h"
6 
7 #include "base/memory/ptr_util.h"
8 #include "build/build_config.h"
9 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
10 #include "gpu/command_buffer/client/mapped_memory.h"
11 
12 namespace gpu {
13 namespace gles2 {
14 
15 // ReadbackBufferShadowTracker::Buffer
16 
Buffer(GLuint buffer_id,ReadbackBufferShadowTracker * tracker)17 ReadbackBufferShadowTracker::Buffer::Buffer(
18     GLuint buffer_id,
19     ReadbackBufferShadowTracker* tracker)
20     : buffer_id_(buffer_id), tracker_(tracker) {}
21 
~Buffer()22 ReadbackBufferShadowTracker::Buffer::~Buffer() {
23   Free();
24 }
25 
Alloc(int32_t * shm_id,uint32_t * shm_offset,bool * already_allocated)26 uint32_t ReadbackBufferShadowTracker::Buffer::Alloc(int32_t* shm_id,
27                                                     uint32_t* shm_offset,
28                                                     bool* already_allocated) {
29   *already_allocated = readback_shm_address_ != nullptr;
30   if (!readback_shm_address_) {
31     readback_shm_address_ =
32         tracker_->mapped_memory_->Alloc(size_, &shm_id_, &shm_offset_);
33   }
34   *shm_id = shm_id_;
35   *shm_offset = shm_offset_;
36   return size_;
37 }
38 
Free()39 void ReadbackBufferShadowTracker::Buffer::Free() {
40   if (readback_shm_address_) {
41     tracker_->mapped_memory_->FreePendingToken(
42         readback_shm_address_, tracker_->helper_->InsertToken());
43   }
44   readback_shm_address_ = nullptr;
45 }
46 
MapReadbackShm(uint32_t offset,uint32_t map_size)47 void* ReadbackBufferShadowTracker::Buffer::MapReadbackShm(uint32_t offset,
48                                                           uint32_t map_size) {
49   DCHECK(!is_mapped_);
50   if (serial_of_readback_data_ != serial_of_last_write_) {
51     return nullptr;
52   }
53   if (!readback_shm_address_) {
54     return nullptr;
55   }
56   if (map_size > size_) {
57     return nullptr;
58   }
59   DCHECK_GE(size_, map_size);
60   if (offset > size_ - map_size) {
61     return nullptr;
62   }
63   is_mapped_ = true;
64   return &static_cast<uint8_t*>(readback_shm_address_)[offset];
65 }
66 
UnmapReadbackShm()67 bool ReadbackBufferShadowTracker::Buffer::UnmapReadbackShm() {
68   Free();
69 
70   bool was_mapped = is_mapped_;
71   is_mapped_ = false;
72   return was_mapped;
73 }
74 
UpdateSerialTo(uint64_t serial)75 void ReadbackBufferShadowTracker::Buffer::UpdateSerialTo(uint64_t serial) {
76   DCHECK_LT(serial_of_readback_data_, serial);
77   serial_of_readback_data_ = serial;
78 }
79 
80 // ReadbackBufferShadowTracker
81 
ReadbackBufferShadowTracker(MappedMemoryManager * mapped_memory,GLES2CmdHelper * helper)82 ReadbackBufferShadowTracker::ReadbackBufferShadowTracker(
83     MappedMemoryManager* mapped_memory,
84     GLES2CmdHelper* helper)
85     : mapped_memory_(mapped_memory), helper_(helper) {}
86 
~ReadbackBufferShadowTracker()87 ReadbackBufferShadowTracker::~ReadbackBufferShadowTracker() {}
88 
89 ReadbackBufferShadowTracker::Buffer*
GetOrCreateBuffer(GLuint id,GLuint size)90 ReadbackBufferShadowTracker::GetOrCreateBuffer(GLuint id, GLuint size) {
91   Buffer* buffer = GetBuffer(id);
92   if (buffer) {
93     buffer->Free();
94   } else {
95     buffer = new Buffer(id, this);
96     buffers_.emplace(id, base::WrapUnique(buffer));
97   }
98   buffer->size_ = size;
99   OnBufferWrite(id);
100 
101   return buffer;
102 }
103 
OnBufferWrite(GLuint id)104 void ReadbackBufferShadowTracker::OnBufferWrite(GLuint id) {
105   Buffer* buffer = GetBuffer(id);
106   if (!buffer) {
107     // Buffer is not tracked by the ReadbackBufferShadowTracker.
108     return;
109   }
110 
111   DCHECK(buffer->serial_of_last_write_ <= buffer_shadow_serial_);
112   buffer->serial_of_last_write_ = buffer_shadow_serial_;
113 
114   for (const auto& b : buffers_written_but_not_fenced_) {
115     if (b.get() == buffer) {
116       return;
117     }
118   }
119   buffers_written_but_not_fenced_.push_back(buffer->AsWeakPtr());
120 }
121 
122 ReadbackBufferShadowTracker::BufferList
TakeUnfencedBufferList()123 ReadbackBufferShadowTracker::TakeUnfencedBufferList() {
124   BufferList buffers;
125   std::swap(buffers, buffers_written_but_not_fenced_);
126   return buffers;
127 }
128 
129 }  // namespace gles2
130 }  // namespace gpu
131