renderbuffer_manager.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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
14namespace gpu {
15namespace gles2 {
16
17RenderbufferManager::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
30RenderbufferManager::~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
39size_t Renderbuffer::EstimatedSize() {
40  uint32 size = 0;
41  RenderbufferManager::ComputeEstimatedRenderbufferSize(
42      width_, height_, samples_, internal_format_, &size);
43  return size;
44}
45
46void 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
54Renderbuffer::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
69Renderbuffer::~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
80void RenderbufferManager::Destroy(bool have_context) {
81  have_context_ = have_context;
82  renderbuffers_.clear();
83  DCHECK_EQ(0u, memory_tracker_->GetMemRepresented());
84}
85
86void RenderbufferManager::StartTracking(Renderbuffer* /* renderbuffer */) {
87  ++renderbuffer_count_;
88}
89
90void RenderbufferManager::StopTracking(Renderbuffer* renderbuffer) {
91  --renderbuffer_count_;
92  if (!renderbuffer->cleared()) {
93    --num_uncleared_renderbuffers_;
94  }
95  memory_tracker_->TrackMemFree(renderbuffer->EstimatedSize());
96}
97
98void 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
113void 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
125void 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
137Renderbuffer* 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
143void 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
152bool 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
172GLenum 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