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"
6 #include "base/debug/trace_event.h"
7 #include "base/logging.h"
8 #include "base/strings/stringprintf.h"
9 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
10 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
11 #include "gpu/command_buffer/service/memory_tracking.h"
12 #include "ui/gl/gl_implementation.h"
17 RenderbufferManager::RenderbufferManager(
18 MemoryTracker
* memory_tracker
,
19 GLint max_renderbuffer_size
,
21 bool depth24_supported
)
23 new MemoryTypeTracker(memory_tracker
, MemoryTracker::kUnmanaged
)),
24 max_renderbuffer_size_(max_renderbuffer_size
),
25 max_samples_(max_samples
),
26 depth24_supported_(depth24_supported
),
27 num_uncleared_renderbuffers_(0),
28 renderbuffer_count_(0),
32 RenderbufferManager::~RenderbufferManager() {
33 DCHECK(renderbuffers_
.empty());
34 // If this triggers, that means something is keeping a reference to
35 // a Renderbuffer belonging to this.
36 CHECK_EQ(renderbuffer_count_
, 0u);
38 DCHECK_EQ(0, num_uncleared_renderbuffers_
);
41 size_t Renderbuffer::EstimatedSize() {
43 manager_
->ComputeEstimatedRenderbufferSize(
44 width_
, height_
, samples_
, internal_format_
, &size
);
48 void Renderbuffer::AddToSignature(
49 std::string
* signature
) const {
51 *signature
+= base::StringPrintf(
52 "|Renderbuffer|internal_format=%04x|samples=%d|width=%d|height=%d",
53 internal_format_
, samples_
, width_
, height_
);
56 Renderbuffer::Renderbuffer(RenderbufferManager
* manager
,
60 client_id_(client_id
),
61 service_id_(service_id
),
63 has_been_bound_(false),
65 internal_format_(GL_RGBA4
),
68 manager_
->StartTracking(this);
71 Renderbuffer::~Renderbuffer() {
73 if (manager_
->have_context_
) {
74 GLuint id
= service_id();
75 glDeleteRenderbuffersEXT(1, &id
);
77 manager_
->StopTracking(this);
82 void RenderbufferManager::Destroy(bool have_context
) {
83 have_context_
= have_context
;
84 renderbuffers_
.clear();
85 DCHECK_EQ(0u, memory_tracker_
->GetMemRepresented());
88 void RenderbufferManager::StartTracking(Renderbuffer
* /* renderbuffer */) {
89 ++renderbuffer_count_
;
92 void RenderbufferManager::StopTracking(Renderbuffer
* renderbuffer
) {
93 --renderbuffer_count_
;
94 if (!renderbuffer
->cleared()) {
95 --num_uncleared_renderbuffers_
;
97 memory_tracker_
->TrackMemFree(renderbuffer
->EstimatedSize());
100 void RenderbufferManager::SetInfo(
101 Renderbuffer
* renderbuffer
,
102 GLsizei samples
, GLenum internalformat
, GLsizei width
, GLsizei height
) {
103 DCHECK(renderbuffer
);
104 if (!renderbuffer
->cleared()) {
105 --num_uncleared_renderbuffers_
;
107 memory_tracker_
->TrackMemFree(renderbuffer
->EstimatedSize());
108 renderbuffer
->SetInfo(samples
, internalformat
, width
, height
);
109 memory_tracker_
->TrackMemAlloc(renderbuffer
->EstimatedSize());
110 if (!renderbuffer
->cleared()) {
111 ++num_uncleared_renderbuffers_
;
115 void RenderbufferManager::SetCleared(Renderbuffer
* renderbuffer
,
117 DCHECK(renderbuffer
);
118 if (!renderbuffer
->cleared()) {
119 --num_uncleared_renderbuffers_
;
121 renderbuffer
->set_cleared(cleared
);
122 if (!renderbuffer
->cleared()) {
123 ++num_uncleared_renderbuffers_
;
127 void RenderbufferManager::CreateRenderbuffer(
128 GLuint client_id
, GLuint service_id
) {
129 scoped_refptr
<Renderbuffer
> renderbuffer(
130 new Renderbuffer(this, client_id
, service_id
));
131 std::pair
<RenderbufferMap::iterator
, bool> result
=
132 renderbuffers_
.insert(std::make_pair(client_id
, renderbuffer
));
133 DCHECK(result
.second
);
134 if (!renderbuffer
->cleared()) {
135 ++num_uncleared_renderbuffers_
;
139 Renderbuffer
* RenderbufferManager::GetRenderbuffer(
141 RenderbufferMap::iterator it
= renderbuffers_
.find(client_id
);
142 return it
!= renderbuffers_
.end() ? it
->second
.get() : NULL
;
145 void RenderbufferManager::RemoveRenderbuffer(GLuint client_id
) {
146 RenderbufferMap::iterator it
= renderbuffers_
.find(client_id
);
147 if (it
!= renderbuffers_
.end()) {
148 Renderbuffer
* renderbuffer
= it
->second
.get();
149 renderbuffer
->MarkAsDeleted();
150 renderbuffers_
.erase(it
);
154 bool RenderbufferManager::ComputeEstimatedRenderbufferSize(int width
,
158 uint32
* size
) const {
162 if (!SafeMultiplyUint32(width
, height
, &temp
)) {
165 if (!SafeMultiplyUint32(temp
, samples
, &temp
)) {
168 GLenum impl_format
= InternalRenderbufferFormatToImplFormat(internal_format
);
169 if (!SafeMultiplyUint32(
170 temp
, GLES2Util::RenderbufferBytesPerPixel(impl_format
), &temp
)) {
177 GLenum
RenderbufferManager::InternalRenderbufferFormatToImplFormat(
178 GLenum impl_format
) const {
179 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2
) {
180 switch (impl_format
) {
181 case GL_DEPTH_COMPONENT16
:
182 return GL_DEPTH_COMPONENT
;
190 // Upgrade 16-bit depth to 24-bit if possible.
191 if (impl_format
== GL_DEPTH_COMPONENT16
&& depth24_supported_
)
192 return GL_DEPTH_COMPONENT24
;