Home | History | Annotate | Download | only in service
      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