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"
23 // This should contain everything to uniquely identify a Renderbuffer.
24 static const char RenderbufferTag
[] = "|Renderbuffer|";
25 struct RenderbufferSignature
{
26 GLenum internal_format_
;
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
,
39 memset(this, 0, sizeof(RenderbufferSignature
));
40 internal_format_
= internal_format
;
47 RenderbufferManager::RenderbufferManager(MemoryTracker
* memory_tracker
,
48 GLint max_renderbuffer_size
,
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),
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(
80 size_t Renderbuffer::EstimatedSize() {
82 manager_
->ComputeEstimatedRenderbufferSize(
83 width_
, height_
, samples_
, internal_format_
, &size
);
88 size_t Renderbuffer::GetSignatureSize() const {
89 return sizeof(RenderbufferTag
) + sizeof(RenderbufferSignature
);
92 void Renderbuffer::AddToSignature(std::string
* signature
) const {
94 RenderbufferSignature
signature_data(internal_format_
,
99 signature
->append(RenderbufferTag
, sizeof(RenderbufferTag
));
100 signature
->append(reinterpret_cast<const char*>(&signature_data
),
101 sizeof(signature_data
));
104 Renderbuffer::Renderbuffer(RenderbufferManager
* manager
,
108 client_id_(client_id
),
109 service_id_(service_id
),
111 has_been_bound_(false),
113 internal_format_(GL_RGBA4
),
116 manager_
->StartTracking(this);
119 Renderbuffer::~Renderbuffer() {
121 if (manager_
->have_context_
) {
122 GLuint id
= service_id();
123 glDeleteRenderbuffersEXT(1, &id
);
125 manager_
->StopTracking(this);
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
,
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(
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
,
206 uint32
* size
) const {
210 if (!SafeMultiplyUint32(width
, height
, &temp
)) {
213 if (!SafeMultiplyUint32(temp
, samples
, &temp
)) {
216 GLenum impl_format
= InternalRenderbufferFormatToImplFormat(internal_format
);
217 if (!SafeMultiplyUint32(
218 temp
, GLES2Util::RenderbufferBytesPerPixel(impl_format
), &temp
)) {
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
;
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
;
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("gl/client_%d/renderbuffers/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_
->ClientTracingId(), client_renderbuffer_id
);
265 pmd
->CreateSharedGlobalAllocatorDump(guid
);
266 pmd
->AddOwnershipEdge(dump
->guid(), guid
);