Hash :
124f78c2
Author :
Date :
2019-06-18T11:48:24
Remove gl::Context parameter from Observer functions. It was only used in exactly one instance in VertexArray. Instead we can cache a bool and avoid needing to pass it around. Will make signaling dirty easier in the Vulkan back-end. Bug: angleproject:3539 Change-Id: Ia570aec051a24a5280df49edc4345c54022b46ec Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1663838 Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Observer:
// Implements the Observer pattern for sending state change notifications
// from Subject objects to dependent Observer objects.
//
// See design document:
// https://docs.google.com/document/d/15Edfotqg6_l1skTEL8ADQudF_oIdNa7i8Po43k6jMd4/
#ifndef LIBANGLE_OBSERVER_H_
#define LIBANGLE_OBSERVER_H_
#include "common/FastVector.h"
#include "common/angleutils.h"
namespace angle
{
template <typename HaystackT, typename NeedleT>
bool IsInContainer(const HaystackT &haystack, const NeedleT &needle)
{
return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
}
using SubjectIndex = size_t;
// Messages are used to distinguish different Subject events that get sent to a single Observer.
// It could be possible to improve the handling by using different callback functions instead
// of a single handler function. But in some cases we want to share a single binding between
// Observer and Subject and handle different types of events.
enum class SubjectMessage
{
// Used by gl::VertexArray to notify gl::Context of a gl::Buffer binding count change. Triggers
// a validation cache update.
BindingChanged,
// Only the contents (pixels, bytes, etc) changed in this Subject. Distinct from the object
// storage.
ContentsChanged,
// Sent by gl::Sampler, gl::Texture, gl::Framebuffer and others to notifiy gl::Context. This
// flag indicates to call syncState before next use.
DirtyBitsFlagged,
// Generic state change message. Used in multiple places for different purposes.
SubjectChanged,
// Indicates a bound gl::Buffer is now mapped or unmapped. Passed from gl::Buffer, through
// gl::VertexArray, into gl::Context. Used to track validation.
SubjectMapped,
SubjectUnmapped,
};
// The observing class inherits from this interface class.
class ObserverInterface
{
public:
virtual ~ObserverInterface();
virtual void onSubjectStateChange(SubjectIndex index, SubjectMessage message) = 0;
};
class ObserverBindingBase
{
public:
ObserverBindingBase(ObserverInterface *observer, SubjectIndex subjectIndex)
: mObserver(observer), mIndex(subjectIndex)
{}
virtual ~ObserverBindingBase() {}
ObserverInterface *getObserver() const { return mObserver; }
SubjectIndex getSubjectIndex() const { return mIndex; }
virtual void onSubjectReset() {}
private:
ObserverInterface *mObserver;
SubjectIndex mIndex;
};
// Maintains a list of observer bindings. Sends update messages to the observer.
class Subject : NonCopyable
{
public:
Subject();
virtual ~Subject();
void onStateChange(SubjectMessage message) const;
bool hasObservers() const;
void resetObservers();
ANGLE_INLINE void addObserver(ObserverBindingBase *observer)
{
ASSERT(!IsInContainer(mObservers, observer));
mObservers.push_back(observer);
}
ANGLE_INLINE void removeObserver(ObserverBindingBase *observer)
{
ASSERT(IsInContainer(mObservers, observer));
mObservers.remove_and_permute(observer);
}
private:
// Keep a short list of observers so we can allocate/free them quickly. But since we support
// unlimited bindings, have a spill-over list of that uses dynamic allocation.
static constexpr size_t kMaxFixedObservers = 8;
angle::FastVector<ObserverBindingBase *, kMaxFixedObservers> mObservers;
};
// Keeps a binding between a Subject and Observer, with a specific subject index.
class ObserverBinding final : public ObserverBindingBase
{
public:
ObserverBinding(ObserverInterface *observer, SubjectIndex index);
~ObserverBinding() override;
ObserverBinding(const ObserverBinding &other);
ObserverBinding &operator=(const ObserverBinding &other);
void bind(Subject *subject);
ANGLE_INLINE void reset() { bind(nullptr); }
void onStateChange(SubjectMessage message) const;
void onSubjectReset() override;
ANGLE_INLINE const Subject *getSubject() const { return mSubject; }
ANGLE_INLINE void assignSubject(Subject *subject) { mSubject = subject; }
private:
Subject *mSubject;
};
} // namespace angle
#endif // LIBANGLE_OBSERVER_H_