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     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