Elim cr-checkbox
[chromium-blink-merge.git] / gpu / command_buffer / service / renderbuffer_manager.cc
blob54c18bebbf3861b41160f8018a05bf2ea6f3c372
1 // Copyright (c) 2012 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.
5 #include "gpu/command_buffer/service/renderbuffer_manager.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/thread_task_runner_handle.h"
10 #include "base/trace_event/memory_dump_manager.h"
11 #include "base/trace_event/trace_event.h"
12 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
13 #include "gpu/command_buffer/service/feature_info.h"
14 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
15 #include "gpu/command_buffer/service/memory_tracking.h"
16 #include "ui/gl/gl_implementation.h"
17 #include "ui/gl/gl_version_info.h"
18 #include "ui/gl/trace_util.h"
20 namespace gpu {
21 namespace gles2 {
23 // This should contain everything to uniquely identify a Renderbuffer.
24 static const char RenderbufferTag[] = "|Renderbuffer|";
25 struct RenderbufferSignature {
26 GLenum internal_format_;
27 GLsizei samples_;
28 GLsizei width_;
29 GLsizei height_;
31 // Since we will be hashing this signature structure, the padding must be
32 // zero initialized. Although the C++11 specifications specify that this is
33 // true, we will use a constructor with a memset to further enforce it instead
34 // of relying on compilers adhering to this deep dark corner specification.
35 RenderbufferSignature(GLenum internal_format,
36 GLsizei samples,
37 GLsizei width,
38 GLsizei height) {
39 memset(this, 0, sizeof(RenderbufferSignature));
40 internal_format_ = internal_format;
41 samples_ = samples;
42 width_ = width;
43 height_ = height;
47 RenderbufferManager::RenderbufferManager(MemoryTracker* memory_tracker,
48 GLint max_renderbuffer_size,
49 GLint max_samples,
50 FeatureInfo* feature_info)
51 : memory_type_tracker_(
52 new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)),
53 memory_tracker_(memory_tracker),
54 max_renderbuffer_size_(max_renderbuffer_size),
55 max_samples_(max_samples),
56 feature_info_(feature_info),
57 num_uncleared_renderbuffers_(0),
58 renderbuffer_count_(0),
59 have_context_(true) {
60 // When created from InProcessCommandBuffer, we won't have a |memory_tracker_|
61 // so don't register a dump provider.
62 if (memory_tracker_) {
63 base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
64 this, base::ThreadTaskRunnerHandle::Get());
68 RenderbufferManager::~RenderbufferManager() {
69 DCHECK(renderbuffers_.empty());
70 // If this triggers, that means something is keeping a reference to
71 // a Renderbuffer belonging to this.
72 CHECK_EQ(renderbuffer_count_, 0u);
74 DCHECK_EQ(0, num_uncleared_renderbuffers_);
76 base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
77 this);
80 size_t Renderbuffer::EstimatedSize() {
81 uint32 size = 0;
82 manager_->ComputeEstimatedRenderbufferSize(
83 width_, height_, samples_, internal_format_, &size);
84 return size;
88 size_t Renderbuffer::GetSignatureSize() const {
89 return sizeof(RenderbufferTag) + sizeof(RenderbufferSignature);
92 void Renderbuffer::AddToSignature(std::string* signature) const {
93 DCHECK(signature);
94 RenderbufferSignature signature_data(internal_format_,
95 samples_,
96 width_,
97 height_);
99 signature->append(RenderbufferTag, sizeof(RenderbufferTag));
100 signature->append(reinterpret_cast<const char*>(&signature_data),
101 sizeof(signature_data));
104 Renderbuffer::Renderbuffer(RenderbufferManager* manager,
105 GLuint client_id,
106 GLuint service_id)
107 : manager_(manager),
108 client_id_(client_id),
109 service_id_(service_id),
110 cleared_(true),
111 has_been_bound_(false),
112 samples_(0),
113 internal_format_(GL_RGBA4),
114 width_(0),
115 height_(0) {
116 manager_->StartTracking(this);
119 Renderbuffer::~Renderbuffer() {
120 if (manager_) {
121 if (manager_->have_context_) {
122 GLuint id = service_id();
123 glDeleteRenderbuffersEXT(1, &id);
125 manager_->StopTracking(this);
126 manager_ = NULL;
130 void RenderbufferManager::Destroy(bool have_context) {
131 have_context_ = have_context;
132 renderbuffers_.clear();
133 DCHECK_EQ(0u, memory_type_tracker_->GetMemRepresented());
136 void RenderbufferManager::StartTracking(Renderbuffer* /* renderbuffer */) {
137 ++renderbuffer_count_;
140 void RenderbufferManager::StopTracking(Renderbuffer* renderbuffer) {
141 --renderbuffer_count_;
142 if (!renderbuffer->cleared()) {
143 --num_uncleared_renderbuffers_;
145 memory_type_tracker_->TrackMemFree(renderbuffer->EstimatedSize());
148 void RenderbufferManager::SetInfo(
149 Renderbuffer* renderbuffer,
150 GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
151 DCHECK(renderbuffer);
152 if (!renderbuffer->cleared()) {
153 --num_uncleared_renderbuffers_;
155 memory_type_tracker_->TrackMemFree(renderbuffer->EstimatedSize());
156 renderbuffer->SetInfo(samples, internalformat, width, height);
157 memory_type_tracker_->TrackMemAlloc(renderbuffer->EstimatedSize());
158 if (!renderbuffer->cleared()) {
159 ++num_uncleared_renderbuffers_;
163 void RenderbufferManager::SetCleared(Renderbuffer* renderbuffer,
164 bool cleared) {
165 DCHECK(renderbuffer);
166 if (!renderbuffer->cleared()) {
167 --num_uncleared_renderbuffers_;
169 renderbuffer->set_cleared(cleared);
170 if (!renderbuffer->cleared()) {
171 ++num_uncleared_renderbuffers_;
175 void RenderbufferManager::CreateRenderbuffer(
176 GLuint client_id, GLuint service_id) {
177 scoped_refptr<Renderbuffer> renderbuffer(
178 new Renderbuffer(this, client_id, service_id));
179 std::pair<RenderbufferMap::iterator, bool> result =
180 renderbuffers_.insert(std::make_pair(client_id, renderbuffer));
181 DCHECK(result.second);
182 if (!renderbuffer->cleared()) {
183 ++num_uncleared_renderbuffers_;
187 Renderbuffer* RenderbufferManager::GetRenderbuffer(
188 GLuint client_id) {
189 RenderbufferMap::iterator it = renderbuffers_.find(client_id);
190 return it != renderbuffers_.end() ? it->second.get() : NULL;
193 void RenderbufferManager::RemoveRenderbuffer(GLuint client_id) {
194 RenderbufferMap::iterator it = renderbuffers_.find(client_id);
195 if (it != renderbuffers_.end()) {
196 Renderbuffer* renderbuffer = it->second.get();
197 renderbuffer->MarkAsDeleted();
198 renderbuffers_.erase(it);
202 bool RenderbufferManager::ComputeEstimatedRenderbufferSize(int width,
203 int height,
204 int samples,
205 int internal_format,
206 uint32* size) const {
207 DCHECK(size);
209 uint32 temp = 0;
210 if (!SafeMultiplyUint32(width, height, &temp)) {
211 return false;
213 if (!SafeMultiplyUint32(temp, samples, &temp)) {
214 return false;
216 GLenum impl_format = InternalRenderbufferFormatToImplFormat(internal_format);
217 if (!SafeMultiplyUint32(
218 temp, GLES2Util::RenderbufferBytesPerPixel(impl_format), &temp)) {
219 return false;
221 *size = temp;
222 return true;
225 GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat(
226 GLenum impl_format) const {
227 if (!feature_info_->gl_version_info().BehavesLikeGLES()) {
228 switch (impl_format) {
229 case GL_DEPTH_COMPONENT16:
230 return GL_DEPTH_COMPONENT;
231 case GL_RGBA4:
232 case GL_RGB5_A1:
233 return GL_RGBA;
234 case GL_RGB565:
235 return GL_RGB;
237 } else {
238 // Upgrade 16-bit depth to 24-bit if possible.
239 if (impl_format == GL_DEPTH_COMPONENT16 &&
240 feature_info_->feature_flags().oes_depth24)
241 return GL_DEPTH_COMPONENT24;
243 return impl_format;
246 bool RenderbufferManager::OnMemoryDump(
247 const base::trace_event::MemoryDumpArgs& args,
248 base::trace_event::ProcessMemoryDump* pmd) {
249 int client_id = memory_tracker_->ClientId();
250 for (const auto& renderbuffer_entry : renderbuffers_) {
251 const auto& client_renderbuffer_id = renderbuffer_entry.first;
252 const auto& renderbuffer = renderbuffer_entry.second;
254 std::string dump_name =
255 base::StringPrintf("gpu/gl/renderbuffers/client_%d/renderbuffer_%d",
256 client_id, client_renderbuffer_id);
257 base::trace_event::MemoryAllocatorDump* dump =
258 pmd->CreateAllocatorDump(dump_name);
259 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
260 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
261 static_cast<uint64_t>(renderbuffer->EstimatedSize()));
263 auto guid = gfx::GetGLRenderbufferGUIDForTracing(
264 memory_tracker_->ShareGroupTracingGUID(), client_renderbuffer_id);
265 pmd->CreateSharedGlobalAllocatorDump(guid);
266 pmd->AddOwnershipEdge(dump->guid(), guid);
268 return true;
271 } // namespace gles2
272 } // namespace gpu