12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CC_RESOURCES_PRIORITIZED_RESOURCE_H_
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CC_RESOURCES_PRIORITIZED_RESOURCE_H_
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/cc_export.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/priority_calculator.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/resource.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/resources/resource_provider.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/vector2d.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PrioritizedResourceManager;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Proxy;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CC_EXPORT PrioritizedResource {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static scoped_ptr<PrioritizedResource>
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Create(PrioritizedResourceManager* manager, gfx::Size size, GLenum format) {
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return make_scoped_ptr(new PrioritizedResource(manager, size, format));
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static scoped_ptr<PrioritizedResource> Create(
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PrioritizedResourceManager* manager) {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return make_scoped_ptr(new PrioritizedResource(manager, gfx::Size(), 0));
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~PrioritizedResource();
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Texture properties. Changing these causes the backing texture to be lost.
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setting these to the same value is a no-op.
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetTextureManager(PrioritizedResourceManager* manager);
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrioritizedResourceManager* resource_manager() { return manager_; }
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetDimensions(gfx::Size size, GLenum format);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLenum format() const { return format_; }
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size size() const { return size_; }
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t bytes() const { return bytes_; }
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool contents_swizzled() const { return contents_swizzled_; }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set priority for the requested texture.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_request_priority(int priority) { priority_ = priority; }
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int request_priority() const { return priority_; }
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // After PrioritizedResource::PrioritizeTextures() is called, this returns
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the the request succeeded and this texture can be acquired for use.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool can_acquire_backing_texture() const { return is_above_priority_cutoff_; }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This returns whether we still have a backing texture. This can continue
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to be true even after CanAcquireBackingTexture() becomes false. In this
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // case the texture can be used but shouldn't be updated since it will get
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // taken away "soon".
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool have_backing_texture() const { return !!backing(); }
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool BackingResourceWasEvicted() const;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If CanAcquireBackingTexture() is true AcquireBackingTexture() will acquire
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a backing texture for use. Call this whenever the texture is actually
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // needed.
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AcquireBackingTexture(ResourceProvider* resource_provider);
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(epenner): Request late is really a hack for when we are totally out of
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // memory (all textures are visible) but we can still squeeze into the limit
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // by not painting occluded textures. In this case the manager refuses all
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // visible textures and RequestLate() will enable CanAcquireBackingTexture()
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // on a call-order basis. We might want to just remove this in the future
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (carefully) and just make sure we don't regress OOMs situations.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool RequestLate();
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update pixels of backing resource from image. This functions will aquire
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the backing if needed.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetPixels(ResourceProvider* resource_provider,
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 const uint8_t* image,
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 gfx::Rect image_rect,
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 gfx::Rect source_rect,
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 gfx::Vector2d dest_offset);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResourceProvider::ResourceId resource_id() const {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return backing_ ? backing_->id() : 0;
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Self-managed textures are accounted for when prioritizing other textures,
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // but they are not allocated/recycled/deleted, so this needs to be done
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // externally. CanAcquireBackingTexture() indicates if the texture would have
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // been allowed given its priority.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_is_self_managed(bool is_self_managed) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_self_managed_ = is_self_managed;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_self_managed() { return is_self_managed_; }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetToSelfManagedMemoryPlaceholder(size_t bytes);
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ReturnBackingTexture();
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class PrioritizedResourceManager;
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class PrioritizedResourceTest;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class Backing : public Resource {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Backing(unsigned id,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ResourceProvider* resource_provider,
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            gfx::Size size,
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            GLenum format);
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ~Backing();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void UpdatePriority();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void UpdateInDrawingImplTree();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrioritizedResource* owner() { return owner_; }
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool CanBeRecycled() const;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int request_priority_at_last_priority_update() const {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return priority_at_last_priority_update_;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool was_above_priority_cutoff_at_last_priority_update() const {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return was_above_priority_cutoff_at_last_priority_update_;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool in_drawing_impl_tree() const { return in_drawing_impl_tree_; }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void DeleteResource(ResourceProvider* resource_provider);
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool ResourceHasBeenDeleted() const;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   private:
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Proxy* proxy() const;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    friend class PrioritizedResource;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    friend class PrioritizedResourceManager;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PrioritizedResource* owner_;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int priority_at_last_priority_update_;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool was_above_priority_cutoff_at_last_priority_update_;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Set if this is currently-drawing impl tree.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool in_drawing_impl_tree_;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool resource_has_been_deleted_;
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NDEBUG
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResourceProvider* resource_provider_;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DISALLOW_COPY_AND_ASSIGN(Backing);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrioritizedResource(PrioritizedResourceManager* resource_manager,
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      gfx::Size size,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      GLenum format);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_above_priority_cutoff() { return is_above_priority_cutoff_; }
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_above_priority_cutoff(bool is_above_priority_cutoff) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    is_above_priority_cutoff_ = is_above_priority_cutoff;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_manager_internal(PrioritizedResourceManager* manager) {
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_ = manager;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Backing* backing() const { return backing_; }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Link(Backing* backing);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Unlink();
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size size_;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GLenum format_;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t bytes_;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool contents_swizzled_;
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int priority_;
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_above_priority_cutoff_;
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_self_managed_;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Backing* backing_;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PrioritizedResourceManager* manager_;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PrioritizedResource);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // CC_RESOURCES_PRIORITIZED_RESOURCE_H_
181