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. 4 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" 13 14 namespace gpu { 15 namespace gles2 { 16 17 RenderbufferManager::RenderbufferManager( 18 MemoryTracker* memory_tracker, 19 GLint max_renderbuffer_size, 20 GLint max_samples) 21 : memory_tracker_( 22 new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), 23 max_renderbuffer_size_(max_renderbuffer_size), 24 max_samples_(max_samples), 25 num_uncleared_renderbuffers_(0), 26 renderbuffer_count_(0), 27 have_context_(true) { 28 } 29 30 RenderbufferManager::~RenderbufferManager() { 31 DCHECK(renderbuffers_.empty()); 32 // If this triggers, that means something is keeping a reference to 33 // a Renderbuffer belonging to this. 34 CHECK_EQ(renderbuffer_count_, 0u); 35 36 DCHECK_EQ(0, num_uncleared_renderbuffers_); 37 } 38 39 size_t Renderbuffer::EstimatedSize() { 40 uint32 size = 0; 41 RenderbufferManager::ComputeEstimatedRenderbufferSize( 42 width_, height_, samples_, internal_format_, &size); 43 return size; 44 } 45 46 void Renderbuffer::AddToSignature( 47 std::string* signature) const { 48 DCHECK(signature); 49 *signature += base::StringPrintf( 50 "|Renderbuffer|internal_format=%04x|samples=%d|width=%d|height=%d", 51 internal_format_, samples_, width_, height_); 52 } 53 54 Renderbuffer::Renderbuffer(RenderbufferManager* manager, 55 GLuint client_id, 56 GLuint service_id) 57 : manager_(manager), 58 client_id_(client_id), 59 service_id_(service_id), 60 cleared_(true), 61 has_been_bound_(false), 62 samples_(0), 63 internal_format_(GL_RGBA4), 64 width_(0), 65 height_(0) { 66 manager_->StartTracking(this); 67 } 68 69 Renderbuffer::~Renderbuffer() { 70 if (manager_) { 71 if (manager_->have_context_) { 72 GLuint id = service_id(); 73 glDeleteRenderbuffersEXT(1, &id); 74 } 75 manager_->StopTracking(this); 76 manager_ = NULL; 77 } 78 } 79 80 void RenderbufferManager::Destroy(bool have_context) { 81 have_context_ = have_context; 82 renderbuffers_.clear(); 83 DCHECK_EQ(0u, memory_tracker_->GetMemRepresented()); 84 } 85 86 void RenderbufferManager::StartTracking(Renderbuffer* /* renderbuffer */) { 87 ++renderbuffer_count_; 88 } 89 90 void RenderbufferManager::StopTracking(Renderbuffer* renderbuffer) { 91 --renderbuffer_count_; 92 if (!renderbuffer->cleared()) { 93 --num_uncleared_renderbuffers_; 94 } 95 memory_tracker_->TrackMemFree(renderbuffer->EstimatedSize()); 96 } 97 98 void RenderbufferManager::SetInfo( 99 Renderbuffer* renderbuffer, 100 GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) { 101 DCHECK(renderbuffer); 102 if (!renderbuffer->cleared()) { 103 --num_uncleared_renderbuffers_; 104 } 105 memory_tracker_->TrackMemFree(renderbuffer->EstimatedSize()); 106 renderbuffer->SetInfo(samples, internalformat, width, height); 107 memory_tracker_->TrackMemAlloc(renderbuffer->EstimatedSize()); 108 if (!renderbuffer->cleared()) { 109 ++num_uncleared_renderbuffers_; 110 } 111 } 112 113 void RenderbufferManager::SetCleared(Renderbuffer* renderbuffer, 114 bool cleared) { 115 DCHECK(renderbuffer); 116 if (!renderbuffer->cleared()) { 117 --num_uncleared_renderbuffers_; 118 } 119 renderbuffer->set_cleared(cleared); 120 if (!renderbuffer->cleared()) { 121 ++num_uncleared_renderbuffers_; 122 } 123 } 124 125 void RenderbufferManager::CreateRenderbuffer( 126 GLuint client_id, GLuint service_id) { 127 scoped_refptr<Renderbuffer> renderbuffer( 128 new Renderbuffer(this, client_id, service_id)); 129 std::pair<RenderbufferMap::iterator, bool> result = 130 renderbuffers_.insert(std::make_pair(client_id, renderbuffer)); 131 DCHECK(result.second); 132 if (!renderbuffer->cleared()) { 133 ++num_uncleared_renderbuffers_; 134 } 135 } 136 137 Renderbuffer* RenderbufferManager::GetRenderbuffer( 138 GLuint client_id) { 139 RenderbufferMap::iterator it = renderbuffers_.find(client_id); 140 return it != renderbuffers_.end() ? it->second.get() : NULL; 141 } 142 143 void RenderbufferManager::RemoveRenderbuffer(GLuint client_id) { 144 RenderbufferMap::iterator it = renderbuffers_.find(client_id); 145 if (it != renderbuffers_.end()) { 146 Renderbuffer* renderbuffer = it->second.get(); 147 renderbuffer->MarkAsDeleted(); 148 renderbuffers_.erase(it); 149 } 150 } 151 152 bool RenderbufferManager::ComputeEstimatedRenderbufferSize( 153 int width, int height, int samples, int internal_format, uint32* size) { 154 DCHECK(size); 155 156 uint32 temp = 0; 157 if (!SafeMultiplyUint32(width, height, &temp)) { 158 return false; 159 } 160 if (!SafeMultiplyUint32(temp, samples, &temp)) { 161 return false; 162 } 163 GLenum impl_format = InternalRenderbufferFormatToImplFormat(internal_format); 164 if (!SafeMultiplyUint32( 165 temp, GLES2Util::RenderbufferBytesPerPixel(impl_format), &temp)) { 166 return false; 167 } 168 *size = temp; 169 return true; 170 } 171 172 GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat( 173 GLenum impl_format) { 174 if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { 175 switch (impl_format) { 176 case GL_DEPTH_COMPONENT16: 177 return GL_DEPTH_COMPONENT; 178 case GL_RGBA4: 179 case GL_RGB5_A1: 180 return GL_RGBA; 181 case GL_RGB565: 182 return GL_RGB; 183 } 184 } 185 return impl_format; 186 } 187 188 } // namespace gles2 189 } // namespace gpu 190 191 192