Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / renderbuffer_manager.cc
blob03c37cbe2f6ea735343467763d4fe47fc2814c8e
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"
14 namespace gpu {
15 namespace gles2 {
17 RenderbufferManager::RenderbufferManager(
18 MemoryTracker* memory_tracker,
19 GLint max_renderbuffer_size,
20 GLint max_samples,
21 bool depth24_supported)
22 : memory_tracker_(
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),
29 have_context_(true) {
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() {
42 uint32 size = 0;
43 manager_->ComputeEstimatedRenderbufferSize(
44 width_, height_, samples_, internal_format_, &size);
45 return size;
48 void Renderbuffer::AddToSignature(
49 std::string* signature) const {
50 DCHECK(signature);
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,
57 GLuint client_id,
58 GLuint service_id)
59 : manager_(manager),
60 client_id_(client_id),
61 service_id_(service_id),
62 cleared_(true),
63 has_been_bound_(false),
64 samples_(0),
65 internal_format_(GL_RGBA4),
66 width_(0),
67 height_(0) {
68 manager_->StartTracking(this);
71 Renderbuffer::~Renderbuffer() {
72 if (manager_) {
73 if (manager_->have_context_) {
74 GLuint id = service_id();
75 glDeleteRenderbuffersEXT(1, &id);
77 manager_->StopTracking(this);
78 manager_ = NULL;
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,
116 bool cleared) {
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(
140 GLuint client_id) {
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,
155 int height,
156 int samples,
157 int internal_format,
158 uint32* size) const {
159 DCHECK(size);
161 uint32 temp = 0;
162 if (!SafeMultiplyUint32(width, height, &temp)) {
163 return false;
165 if (!SafeMultiplyUint32(temp, samples, &temp)) {
166 return false;
168 GLenum impl_format = InternalRenderbufferFormatToImplFormat(internal_format);
169 if (!SafeMultiplyUint32(
170 temp, GLES2Util::RenderbufferBytesPerPixel(impl_format), &temp)) {
171 return false;
173 *size = temp;
174 return true;
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;
183 case GL_RGBA4:
184 case GL_RGB5_A1:
185 return GL_RGBA;
186 case GL_RGB565:
187 return GL_RGB;
189 } else {
190 // Upgrade 16-bit depth to 24-bit if possible.
191 if (impl_format == GL_DEPTH_COMPONENT16 && depth24_supported_)
192 return GL_DEPTH_COMPONENT24;
194 return impl_format;
197 } // namespace gles2
198 } // namespace gpu