• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RenderbufferManager(MemoryTracker * memory_tracker,GLint max_renderbuffer_size,GLint max_samples,bool depth24_supported)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 
~RenderbufferManager()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 
EstimatedSize()41 size_t Renderbuffer::EstimatedSize() {
42   uint32 size = 0;
43   manager_->ComputeEstimatedRenderbufferSize(
44       width_, height_, samples_, internal_format_, &size);
45   return size;
46 }
47 
AddToSignature(std::string * signature) const48 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 
Renderbuffer(RenderbufferManager * manager,GLuint client_id,GLuint service_id)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 
~Renderbuffer()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 
Destroy(bool have_context)82 void RenderbufferManager::Destroy(bool have_context) {
83   have_context_ = have_context;
84   renderbuffers_.clear();
85   DCHECK_EQ(0u, memory_tracker_->GetMemRepresented());
86 }
87 
StartTracking(Renderbuffer *)88 void RenderbufferManager::StartTracking(Renderbuffer* /* renderbuffer */) {
89   ++renderbuffer_count_;
90 }
91 
StopTracking(Renderbuffer * renderbuffer)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 
SetInfo(Renderbuffer * renderbuffer,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height)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 
SetCleared(Renderbuffer * renderbuffer,bool cleared)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 
CreateRenderbuffer(GLuint client_id,GLuint service_id)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 
GetRenderbuffer(GLuint client_id)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 
RemoveRenderbuffer(GLuint client_id)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 
ComputeEstimatedRenderbufferSize(int width,int height,int samples,int internal_format,uint32 * size) const154 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 
InternalRenderbufferFormatToImplFormat(GLenum impl_format) const177 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