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#ifndef GPU_COMMAND_BUFFER_SERVICE_MEMORY_TRACKING_H_
6#define GPU_COMMAND_BUFFER_SERVICE_MEMORY_TRACKING_H_
7
8#include <string>
9#include "base/basictypes.h"
10#include "base/debug/trace_event.h"
11#include "base/logging.h"
12#include "base/memory/ref_counted.h"
13
14namespace gpu {
15namespace gles2 {
16
17// A MemoryTracker is used to propagate per-ContextGroup memory usage
18// statistics to the global GpuMemoryManager.
19class MemoryTracker : public base::RefCounted<MemoryTracker> {
20 public:
21   enum Pool {
22     kUnmanaged,
23     kManaged
24   };
25
26   virtual void TrackMemoryAllocatedChange(size_t old_size,
27                                           size_t new_size,
28                                           Pool pool) = 0;
29
30   // Ensure a certain amount of GPU memory is free. Returns true on success.
31   virtual bool EnsureGPUMemoryAvailable(size_t size_needed) = 0;
32
33 protected:
34  friend class base::RefCounted<MemoryTracker>;
35  MemoryTracker() {}
36  virtual ~MemoryTracker() {};
37
38 private:
39  DISALLOW_COPY_AND_ASSIGN(MemoryTracker);
40};
41
42// A MemoryTypeTracker tracks the use of a particular type of memory (buffer,
43// texture, or renderbuffer) and forward the result to a specified
44// MemoryTracker.
45class MemoryTypeTracker {
46 public:
47  MemoryTypeTracker(MemoryTracker* memory_tracker, MemoryTracker::Pool pool)
48    : memory_tracker_(memory_tracker),
49      pool_(pool),
50      has_done_update_(false),
51      mem_represented_(0),
52      mem_represented_at_last_update_(0) {
53    UpdateMemRepresented();
54  }
55
56  ~MemoryTypeTracker() {
57    UpdateMemRepresented();
58  }
59
60  void TrackMemAlloc(size_t bytes) {
61    mem_represented_ += bytes;
62    UpdateMemRepresented();
63  }
64
65  void TrackMemFree(size_t bytes) {
66    DCHECK(bytes <= mem_represented_);
67    mem_represented_ -= bytes;
68    UpdateMemRepresented();
69  }
70
71  size_t GetMemRepresented() const {
72    return mem_represented_at_last_update_;
73  }
74
75  // Ensure a certain amount of GPU memory is free. Returns true on success.
76  bool EnsureGPUMemoryAvailable(size_t size_needed) {
77    if (memory_tracker_) {
78      return memory_tracker_->EnsureGPUMemoryAvailable(size_needed);
79    }
80    return true;
81  }
82
83 private:
84  void UpdateMemRepresented() {
85    // Skip redundant updates only if we have already done an update.
86    if (!has_done_update_ &&
87        mem_represented_ == mem_represented_at_last_update_) {
88      return;
89    }
90    if (memory_tracker_) {
91      memory_tracker_->TrackMemoryAllocatedChange(
92        mem_represented_at_last_update_,
93        mem_represented_,
94        pool_);
95    }
96    has_done_update_ = true;
97    mem_represented_at_last_update_ = mem_represented_;
98  }
99
100  MemoryTracker* memory_tracker_;
101  MemoryTracker::Pool pool_;
102  bool has_done_update_;
103  size_t mem_represented_;
104  size_t mem_represented_at_last_update_;
105
106  DISALLOW_COPY_AND_ASSIGN(MemoryTypeTracker);
107};
108
109}  // namespace gles2
110}  // namespace gpu
111
112#endif  // GPU_COMMAND_BUFFER_SERVICE_MEMORY_TRACKING_H_
113