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 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) { 30 } 31 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); 37 38 DCHECK_EQ(0, num_uncleared_renderbuffers_); 39 } 40 41 size_t Renderbuffer::EstimatedSize() { 42 uint32 size = 0; 43 manager_->ComputeEstimatedRenderbufferSize( 44 width_, height_, samples_, internal_format_, &size); 45 return size; 46 } 47 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_); 54 } 55 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); 69 } 70 71 Renderbuffer::~Renderbuffer() { 72 if (manager_) { 73 if (manager_->have_context_) { 74 GLuint id = service_id(); 75 glDeleteRenderbuffersEXT(1, &id); 76 } 77 manager_->StopTracking(this); 78 manager_ = NULL; 79 } 80 } 81 82 void RenderbufferManager::Destroy(bool have_context) { 83 have_context_ = have_context; 84 renderbuffers_.clear(); 85 DCHECK_EQ(0u, memory_tracker_->GetMemRepresented()); 86 } 87 88 void RenderbufferManager::StartTracking(Renderbuffer* /* renderbuffer */) { 89 ++renderbuffer_count_; 90 } 91 92 void RenderbufferManager::StopTracking(Renderbuffer* renderbuffer) { 93 --renderbuffer_count_; 94 if (!renderbuffer->cleared()) { 95 --num_uncleared_renderbuffers_; 96 } 97 memory_tracker_->TrackMemFree(renderbuffer->EstimatedSize()); 98 } 99 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_; 106 } 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_; 112 } 113 } 114 115 void RenderbufferManager::SetCleared(Renderbuffer* renderbuffer, 116 bool cleared) { 117 DCHECK(renderbuffer); 118 if (!renderbuffer->cleared()) { 119 --num_uncleared_renderbuffers_; 120 } 121 renderbuffer->set_cleared(cleared); 122 if (!renderbuffer->cleared()) { 123 ++num_uncleared_renderbuffers_; 124 } 125 } 126 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_; 136 } 137 } 138 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; 143 } 144 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); 151 } 152 } 153 154 bool RenderbufferManager::ComputeEstimatedRenderbufferSize(int width, 155 int height, 156 int samples, 157 int internal_format, 158 uint32* size) const { 159 DCHECK(size); 160 161 uint32 temp = 0; 162 if (!SafeMultiplyUint32(width, height, &temp)) { 163 return false; 164 } 165 if (!SafeMultiplyUint32(temp, samples, &temp)) { 166 return false; 167 } 168 GLenum impl_format = InternalRenderbufferFormatToImplFormat(internal_format); 169 if (!SafeMultiplyUint32( 170 temp, GLES2Util::RenderbufferBytesPerPixel(impl_format), &temp)) { 171 return false; 172 } 173 *size = temp; 174 return true; 175 } 176 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; 188 } 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; 193 } 194 return impl_format; 195 } 196 197 } // namespace gles2 198 } // namespace gpu 199 200 201