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/trace_event/trace_event.h"
10 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
11 #include "gpu/command_buffer/service/feature_info.h"
12 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
13 #include "gpu/command_buffer/service/memory_tracking.h"
14 #include "ui/gl/gl_implementation.h"
19 // This should contain everything to uniquely identify a Renderbuffer.
20 static const char RenderbufferTag
[] = "|Renderbuffer|";
21 struct RenderbufferSignature
{
22 GLenum internal_format_
;
27 // Since we will be hashing this signature structure, the padding must be
28 // zero initialized. Although the C++11 specifications specify that this is
29 // true, we will use a constructor with a memset to further enforce it instead
30 // of relying on compilers adhering to this deep dark corner specification.
31 RenderbufferSignature(GLenum internal_format
,
35 memset(this, 0, sizeof(RenderbufferSignature
));
36 internal_format_
= internal_format
;
43 RenderbufferManager::RenderbufferManager(
44 MemoryTracker
* memory_tracker
,
45 GLint max_renderbuffer_size
,
47 FeatureInfo
* feature_info
)
49 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
50 max_renderbuffer_size_(max_renderbuffer_size
),
51 max_samples_(max_samples
),
52 feature_info_(feature_info
),
53 num_uncleared_renderbuffers_(0),
54 renderbuffer_count_(0),
58 RenderbufferManager::~RenderbufferManager() {
59 DCHECK(renderbuffers_
.empty());
60 // If this triggers, that means something is keeping a reference to
61 // a Renderbuffer belonging to this.
62 CHECK_EQ(renderbuffer_count_
, 0u);
64 DCHECK_EQ(0, num_uncleared_renderbuffers_
);
67 size_t Renderbuffer::EstimatedSize() {
69 manager_
->ComputeEstimatedRenderbufferSize(
70 width_
, height_
, samples_
, internal_format_
, &size
);
75 size_t Renderbuffer::GetSignatureSize() const {
76 return sizeof(RenderbufferTag
) + sizeof(RenderbufferSignature
);
79 void Renderbuffer::AddToSignature(std::string
* signature
) const {
81 RenderbufferSignature
signature_data(internal_format_
,
86 signature
->append(RenderbufferTag
, sizeof(RenderbufferTag
));
87 signature
->append(reinterpret_cast<const char*>(&signature_data
),
88 sizeof(signature_data
));
91 Renderbuffer::Renderbuffer(RenderbufferManager
* manager
,
95 client_id_(client_id
),
96 service_id_(service_id
),
98 has_been_bound_(false),
100 internal_format_(GL_RGBA4
),
103 manager_
->StartTracking(this);
106 Renderbuffer::~Renderbuffer() {
108 if (manager_
->have_context_
) {
109 GLuint id
= service_id();
110 glDeleteRenderbuffersEXT(1, &id
);
112 manager_
->StopTracking(this);
117 void RenderbufferManager::Destroy(bool have_context
) {
118 have_context_
= have_context
;
119 renderbuffers_
.clear();
120 DCHECK_EQ(0u, memory_tracker_
->GetMemRepresented());
123 void RenderbufferManager::StartTracking(Renderbuffer
* /* renderbuffer */) {
124 ++renderbuffer_count_
;
127 void RenderbufferManager::StopTracking(Renderbuffer
* renderbuffer
) {
128 --renderbuffer_count_
;
129 if (!renderbuffer
->cleared()) {
130 --num_uncleared_renderbuffers_
;
132 memory_tracker_
->TrackMemFree(renderbuffer
->EstimatedSize());
135 void RenderbufferManager::SetInfo(
136 Renderbuffer
* renderbuffer
,
137 GLsizei samples
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
138 DCHECK(renderbuffer
);
139 if (!renderbuffer
->cleared()) {
140 --num_uncleared_renderbuffers_
;
142 memory_tracker_
->TrackMemFree(renderbuffer
->EstimatedSize());
143 renderbuffer
->SetInfo(samples
, internalformat
, width
, height
);
144 memory_tracker_
->TrackMemAlloc(renderbuffer
->EstimatedSize());
145 if (!renderbuffer
->cleared()) {
146 ++num_uncleared_renderbuffers_
;
150 void RenderbufferManager::SetCleared(Renderbuffer
* renderbuffer
,
152 DCHECK(renderbuffer
);
153 if (!renderbuffer
->cleared()) {
154 --num_uncleared_renderbuffers_
;
156 renderbuffer
->set_cleared(cleared
);
157 if (!renderbuffer
->cleared()) {
158 ++num_uncleared_renderbuffers_
;
162 void RenderbufferManager::CreateRenderbuffer(
163 GLuint client_id
, GLuint service_id
) {
164 scoped_refptr
<Renderbuffer
> renderbuffer(
165 new Renderbuffer(this, client_id
, service_id
));
166 std::pair
<RenderbufferMap::iterator
, bool> result
=
167 renderbuffers_
.insert(std::make_pair(client_id
, renderbuffer
));
168 DCHECK(result
.second
);
169 if (!renderbuffer
->cleared()) {
170 ++num_uncleared_renderbuffers_
;
174 Renderbuffer
* RenderbufferManager::GetRenderbuffer(
176 RenderbufferMap::iterator it
= renderbuffers_
.find(client_id
);
177 return it
!= renderbuffers_
.end() ? it
->second
.get() : NULL
;
180 void RenderbufferManager::RemoveRenderbuffer(GLuint client_id
) {
181 RenderbufferMap::iterator it
= renderbuffers_
.find(client_id
);
182 if (it
!= renderbuffers_
.end()) {
183 Renderbuffer
* renderbuffer
= it
->second
.get();
184 renderbuffer
->MarkAsDeleted();
185 renderbuffers_
.erase(it
);
189 bool RenderbufferManager::ComputeEstimatedRenderbufferSize(int width
,
193 uint32
* size
) const {
197 if (!SafeMultiplyUint32(width
, height
, &temp
)) {
200 if (!SafeMultiplyUint32(temp
, samples
, &temp
)) {
203 GLenum impl_format
= InternalRenderbufferFormatToImplFormat(internal_format
);
204 if (!SafeMultiplyUint32(
205 temp
, GLES2Util::RenderbufferBytesPerPixel(impl_format
), &temp
)) {
212 GLenum
RenderbufferManager::InternalRenderbufferFormatToImplFormat(
213 GLenum impl_format
) const {
214 if (!feature_info_
->gl_version_info().BehavesLikeGLES()) {
215 switch (impl_format
) {
216 case GL_DEPTH_COMPONENT16
:
217 return GL_DEPTH_COMPONENT
;
225 // Upgrade 16-bit depth to 24-bit if possible.
226 if (impl_format
== GL_DEPTH_COMPONENT16
&&
227 feature_info_
->feature_flags().oes_depth24
)
228 return GL_DEPTH_COMPONENT24
;