Hash :
ea84f6ff
Author :
Date :
2017-09-20T13:20:30
Pass Context to Framebuffer11 dirty callback. This allows us to call StateManager11::invalidateRenderTarget from the Framebuffer11::signal function, which will then trigger state refresh on the next draw call. This requires passing Context through a few more Renderbuffer methods, and reorganizing the RenderTarget signalling so that it doesn't signal dirty in the destructor. Instead they are signaled as they are destroyed in the containing classes. BUG=angleproject:2151 Change-Id: I4cf575e4a01b48275ff78d75bc55b2d1fced591d Reviewed-on: https://chromium-review.googlesource.com/673139 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Frank Henigman <fjhenigman@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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
//
// 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.
//
// signal_utils:
// Helper classes for tracking dependent state changes between objects.
// These changes are signaled to the dependent class via channels.
// See design document:
// https://docs.google.com/document/d/15Edfotqg6_l1skTEL8ADQudF_oIdNa7i8Po43k6jMd4/
#ifndef LIBANGLE_SIGNAL_UTILS_H_
#define LIBANGLE_SIGNAL_UTILS_H_
#include <set>
#include "common/angleutils.h"
#include "common/debug.h"
namespace angle
{
// Interface that the depending class inherits from.
template <typename ChannelID = uint32_t, typename... MessageT>
class SignalReceiver
{
public:
virtual ~SignalReceiver() = default;
virtual void signal(ChannelID channelID, MessageT... message) = 0;
};
template <typename ChannelID, typename... MessageT>
class ChannelBinding;
// The host class owns the channel. It uses the channel to fire signals to the receiver.
template <typename ChannelID = uint32_t, typename... MessageT>
class BroadcastChannel final : NonCopyable
{
public:
BroadcastChannel();
~BroadcastChannel();
void signal(MessageT... message) const;
void reset();
bool empty() const;
private:
// Only the ChannelBinding class should add or remove receivers.
friend class ChannelBinding<ChannelID, MessageT...>;
void addReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
void removeReceiver(ChannelBinding<ChannelID, MessageT...> *receiver);
std::vector<ChannelBinding<ChannelID, MessageT...> *> mReceivers;
};
template <typename ChannelID, typename... MessageT>
BroadcastChannel<ChannelID, MessageT...>::BroadcastChannel()
{
}
template <typename ChannelID, typename... MessageT>
BroadcastChannel<ChannelID, MessageT...>::~BroadcastChannel()
{
reset();
}
template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::addReceiver(
ChannelBinding<ChannelID, MessageT...> *receiver)
{
ASSERT(std::find(mReceivers.begin(), mReceivers.end(), receiver) == mReceivers.end());
mReceivers.push_back(receiver);
}
template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::removeReceiver(
ChannelBinding<ChannelID, MessageT...> *receiver)
{
auto iter = std::find(mReceivers.begin(), mReceivers.end(), receiver);
ASSERT(iter != mReceivers.end());
mReceivers.erase(iter);
}
template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::signal(MessageT... message) const
{
if (mReceivers.empty())
return;
for (const auto *receiver : mReceivers)
{
receiver->signal(message...);
}
}
template <typename ChannelID, typename... MessageT>
void BroadcastChannel<ChannelID, MessageT...>::reset()
{
for (auto receiver : mReceivers)
{
receiver->onChannelClosed();
}
mReceivers.clear();
}
template <typename ChannelID, typename... MessageT>
bool BroadcastChannel<ChannelID, MessageT...>::empty() const
{
return mReceivers.empty();
}
// The dependent class keeps bindings to the host's BroadcastChannel.
template <typename ChannelID = uint32_t, typename... MessageT>
class ChannelBinding final
{
public:
ChannelBinding(SignalReceiver<ChannelID, MessageT...> *receiver, ChannelID channelID);
~ChannelBinding();
ChannelBinding(const ChannelBinding &other) = default;
ChannelBinding &operator=(const ChannelBinding &other) = default;
void bind(BroadcastChannel<ChannelID, MessageT...> *channel);
void reset();
void signal(MessageT... message) const;
void onChannelClosed();
private:
BroadcastChannel<ChannelID, MessageT...> *mChannel;
SignalReceiver<ChannelID, MessageT...> *mReceiver;
ChannelID mChannelID;
};
template <typename ChannelID, typename... MessageT>
ChannelBinding<ChannelID, MessageT...>::ChannelBinding(
SignalReceiver<ChannelID, MessageT...> *receiver,
ChannelID channelID)
: mChannel(nullptr), mReceiver(receiver), mChannelID(channelID)
{
ASSERT(receiver);
}
template <typename ChannelID, typename... MessageT>
ChannelBinding<ChannelID, MessageT...>::~ChannelBinding()
{
reset();
}
template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::bind(BroadcastChannel<ChannelID, MessageT...> *channel)
{
ASSERT(mReceiver);
if (mChannel)
{
mChannel->removeReceiver(this);
}
mChannel = channel;
if (mChannel)
{
mChannel->addReceiver(this);
}
}
template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::reset()
{
bind(nullptr);
}
template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::signal(MessageT... message) const
{
mReceiver->signal(mChannelID, message...);
}
template <typename ChannelID, typename... MessageT>
void ChannelBinding<ChannelID, MessageT...>::onChannelClosed()
{
mChannel = nullptr;
}
} // namespace angle
#endif // LIBANGLE_SIGNAL_UTILS_H_