mirror of https://github.com/odrling/Aegisub
Eliminate some pointless rerenders of the video display
If the frame number hasn't changed and none of the currently visible lines have changed, there's no need to rerender the subtitles and redisplay the frame. Mostly helps with very slow opengl implementations where actually painting the video display is expensive, as the rendering is done on a background thread anyway.
This commit is contained in:
parent
556d655c0b
commit
f38ba33fed
|
@ -140,10 +140,53 @@ void AsyncVideoProvider::RequestFrame(int new_frame, double new_time) throw() {
|
|||
});
|
||||
}
|
||||
|
||||
bool AsyncVideoProvider::NeedUpdate(std::vector<AssDialogueBase const*> const& visible_lines) {
|
||||
// Always need to render after a seek
|
||||
if (single_frame != NEW_SUBS_FILE || frame_number != last_rendered)
|
||||
return true;
|
||||
|
||||
// Obviously need to render if the number of visible lines has changed
|
||||
if (visible_lines.size() != last_lines.size())
|
||||
return true;
|
||||
|
||||
for (size_t i = 0; i < last_lines.size(); ++i) {
|
||||
auto const& last = last_lines[i];
|
||||
auto const& cur = *visible_lines[i];
|
||||
if (last.Layer != cur.Layer) return true;
|
||||
if (last.Margin != cur.Margin) return true;
|
||||
if (last.Style != cur.Style) return true;
|
||||
if (last.Effect != cur.Effect) return true;
|
||||
if (last.Text != cur.Text) return true;
|
||||
|
||||
// Changing the start/end time effects the appearance only if the
|
||||
// line is animated. This is obviously not a very accurate check for
|
||||
// animated lines, but false positives aren't the end of the world
|
||||
if ((last.Start != cur.Start || last.End != cur.End) &&
|
||||
(!cur.Effect.get().empty() || cur.Text.get().find('\\') != std::string::npos))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AsyncVideoProvider::ProcAsync(uint_fast32_t req_version) {
|
||||
// Only actually produce the frame if there's no queued changes waiting
|
||||
if (req_version < version || frame_number < 0) return;
|
||||
|
||||
std::vector<AssDialogueBase const*> visible_lines;
|
||||
for (auto const& line : subs->Events) {
|
||||
if (!line.Comment && !(line.Start > time || line.End <= time))
|
||||
visible_lines.push_back(&line);
|
||||
}
|
||||
|
||||
if (!NeedUpdate(visible_lines)) return;
|
||||
|
||||
last_lines.clear();
|
||||
last_lines.reserve(visible_lines.size());
|
||||
for (auto line : visible_lines)
|
||||
last_lines.push_back(*line);
|
||||
last_rendered = frame_number;
|
||||
|
||||
try {
|
||||
FrameReadyEvent *evt = new FrameReadyEvent(ProcFrame(frame_number, time), time);
|
||||
evt->SetEventType(EVT_FRAME_READY);
|
||||
|
|
|
@ -29,6 +29,7 @@ class AssFile;
|
|||
class SubtitlesProvider;
|
||||
class VideoProvider;
|
||||
class VideoProviderError;
|
||||
struct AssDialogueBase;
|
||||
struct VideoFrame;
|
||||
namespace agi {
|
||||
class BackgroundRunner;
|
||||
|
@ -58,6 +59,14 @@ class AsyncVideoProvider {
|
|||
/// currently loaded file is out of date.
|
||||
int single_frame = -1;
|
||||
|
||||
/// Last rendered frame number
|
||||
int last_rendered = -1;
|
||||
/// Last rendered subtitles on that frame
|
||||
std::vector<AssDialogueBase> last_lines;
|
||||
/// Check if we actually need to honor a frame request or if no visible
|
||||
/// lines have actually changed
|
||||
bool NeedUpdate(std::vector<AssDialogueBase const*> const& visible_lines);
|
||||
|
||||
std::shared_ptr<VideoFrame> ProcFrame(int frame, double time, bool raw = false);
|
||||
|
||||
/// Produce a frame if req_version is still the current version
|
||||
|
|
Loading…
Reference in New Issue