mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-30 06:32:42 +00:00
Improve performance flipping the dirty region only
This commit is contained in:
parent
8cc3cf3eb8
commit
de3d4c3662
@ -469,19 +469,23 @@ NonDisposableSurface* Alleg4Display::getSurface()
|
||||
return static_cast<NonDisposableSurface*>(m_surface);
|
||||
}
|
||||
|
||||
void Alleg4Display::flip()
|
||||
void Alleg4Display::flip(const gfx::Rect& bounds)
|
||||
{
|
||||
if (is_display_resize_awaiting())
|
||||
return;
|
||||
|
||||
BITMAP* bmp = reinterpret_cast<BITMAP*>(m_surface->nativeHandle());
|
||||
if (m_scale == 1) {
|
||||
blit(bmp, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
|
||||
blit(bmp, screen,
|
||||
bounds.x, bounds.y,
|
||||
bounds.x, bounds.y,
|
||||
bounds.w, bounds.h);
|
||||
}
|
||||
else {
|
||||
stretch_blit(bmp, screen,
|
||||
0, 0, bmp->w, bmp->h,
|
||||
0, 0, SCREEN_W, SCREEN_H);
|
||||
bounds.x, bounds.y, bounds.w, bounds.h,
|
||||
bounds.x*m_scale, bounds.y*m_scale,
|
||||
bounds.w*m_scale, bounds.h*m_scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace she {
|
||||
void setScale(int scale) override;
|
||||
void recreateSurface();
|
||||
NonDisposableSurface* getSurface() override;
|
||||
void flip() override;
|
||||
void flip(const gfx::Rect& bounds) override;
|
||||
void maximize() override;
|
||||
bool isMaximized() const override;
|
||||
void setTitleBar(const std::string& title) override;
|
||||
|
@ -49,7 +49,7 @@ namespace she {
|
||||
virtual NonDisposableSurface* getSurface() = 0;
|
||||
|
||||
// Flips all graphics in the surface to the real display.
|
||||
virtual void flip() = 0;
|
||||
virtual void flip(const gfx::Rect& bounds) = 0;
|
||||
|
||||
virtual void maximize() = 0;
|
||||
virtual bool isMaximized() const = 0;
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "she/scoped_surface_lock.h"
|
||||
#include "she/surface.h"
|
||||
#include "she/system.h"
|
||||
#include "ui/manager.h"
|
||||
#include "ui/theme.h"
|
||||
|
||||
namespace ui {
|
||||
@ -34,6 +35,14 @@ Graphics::Graphics(she::Surface* surface, int dx, int dy)
|
||||
|
||||
Graphics::~Graphics()
|
||||
{
|
||||
// If we were drawing in the screen surface, we mark these regions
|
||||
// as dirty for the final flip.
|
||||
if (m_surface == she::instance()->defaultDisplay()->getSurface()) {
|
||||
gfx::Region& dirty = Manager::getDirtyRegion();
|
||||
Manager::getDirtyRegion().createUnion(
|
||||
Manager::getDirtyRegion(),
|
||||
gfx::Region(m_dirtyBounds));
|
||||
}
|
||||
}
|
||||
|
||||
int Graphics::width() const
|
||||
@ -84,40 +93,56 @@ gfx::Color Graphics::getPixel(int x, int y)
|
||||
|
||||
void Graphics::putPixel(gfx::Color color, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, 1));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->putPixel(color, m_dx+x, m_dy+y);
|
||||
}
|
||||
|
||||
void Graphics::drawHLine(gfx::Color color, int x, int y, int w)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, w, 1));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawHLine(color, m_dx+x, m_dy+y, w);
|
||||
}
|
||||
|
||||
void Graphics::drawVLine(gfx::Color color, int x, int y, int h)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, 1, h));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawVLine(color, m_dx+x, m_dy+y, h);
|
||||
}
|
||||
|
||||
void Graphics::drawLine(gfx::Color color, const gfx::Point& a, const gfx::Point& b)
|
||||
void Graphics::drawLine(gfx::Color color, const gfx::Point& _a, const gfx::Point& _b)
|
||||
{
|
||||
gfx::Point a(m_dx+_a.x, m_dy+_a.y);
|
||||
gfx::Point b(m_dx+_b.x, m_dy+_b.y);
|
||||
dirty(gfx::Rect(a, b));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawLine(color,
|
||||
gfx::Point(m_dx+a.x, m_dy+a.y),
|
||||
gfx::Point(m_dx+b.x, m_dy+b.y));
|
||||
dst->drawLine(color, a, b);
|
||||
}
|
||||
|
||||
void Graphics::drawRect(gfx::Color color, const gfx::Rect& rc)
|
||||
void Graphics::drawRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
{
|
||||
gfx::Rect rc(rcOrig);
|
||||
rc.offset(m_dx, m_dy);
|
||||
dirty(rc);
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawRect(color, gfx::Rect(rc).offset(m_dx, m_dy));
|
||||
dst->drawRect(color, rc);
|
||||
}
|
||||
|
||||
void Graphics::fillRect(gfx::Color color, const gfx::Rect& rc)
|
||||
void Graphics::fillRect(gfx::Color color, const gfx::Rect& rcOrig)
|
||||
{
|
||||
gfx::Rect rc(rcOrig);
|
||||
rc.offset(m_dx, m_dy);
|
||||
dirty(rc);
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->fillRect(color, gfx::Rect(rc).offset(m_dx, m_dy));
|
||||
dst->fillRect(color, rc);
|
||||
}
|
||||
|
||||
void Graphics::fillRegion(gfx::Color color, const gfx::Region& rgn)
|
||||
@ -140,6 +165,8 @@ void Graphics::fillAreaBetweenRects(gfx::Color color,
|
||||
|
||||
void Graphics::drawSurface(she::Surface* surface, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
||||
she::ScopedSurfaceLock src(surface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawSurface(src, m_dx+x, m_dy+y);
|
||||
@ -147,6 +174,8 @@ void Graphics::drawSurface(she::Surface* surface, int x, int y)
|
||||
|
||||
void Graphics::drawRgbaSurface(she::Surface* surface, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
||||
she::ScopedSurfaceLock src(surface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawRgbaSurface(src, m_dx+x, m_dy+y);
|
||||
@ -154,6 +183,8 @@ void Graphics::drawRgbaSurface(she::Surface* surface, int x, int y)
|
||||
|
||||
void Graphics::drawColoredRgbaSurface(she::Surface* surface, gfx::Color color, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+x, m_dy+y, surface->width(), surface->height()));
|
||||
|
||||
she::ScopedSurfaceLock src(surface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawColoredRgbaSurface(src, color, gfx::ColorNone,
|
||||
@ -162,6 +193,8 @@ void Graphics::drawColoredRgbaSurface(she::Surface* surface, gfx::Color color, i
|
||||
|
||||
void Graphics::blit(she::Surface* srcSurface, int srcx, int srcy, int dstx, int dsty, int w, int h)
|
||||
{
|
||||
dirty(gfx::Rect(m_dx+dstx, m_dy+dsty, w, h));
|
||||
|
||||
she::ScopedSurfaceLock src(srcSurface);
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
src->blitTo(dst, srcx, srcy, m_dx+dstx, m_dy+dsty, w, h);
|
||||
@ -174,14 +207,19 @@ void Graphics::setFont(she::Font* font)
|
||||
|
||||
void Graphics::drawChar(int chr, gfx::Color fg, gfx::Color bg, int x, int y)
|
||||
{
|
||||
dirty(gfx::Rect(gfx::Point(m_dx+x, m_dy+y), measureChar(chr)));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawChar(m_font, fg, bg, m_dx+x, m_dy+y, chr);
|
||||
}
|
||||
|
||||
void Graphics::drawString(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt)
|
||||
void Graphics::drawString(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& ptOrig)
|
||||
{
|
||||
gfx::Point pt(m_dx+ptOrig.x, m_dy+ptOrig.y);
|
||||
dirty(gfx::Rect(pt.x, pt.y, m_font->textLength(str), m_font->height()));
|
||||
|
||||
she::ScopedSurfaceLock dst(m_surface);
|
||||
dst->drawString(m_font, fg, bg, m_dx+pt.x, m_dy+pt.y, str);
|
||||
dst->drawString(m_font, fg, bg, pt.x, pt.y, str);
|
||||
}
|
||||
|
||||
void Graphics::drawUIString(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Point& pt,
|
||||
@ -207,11 +245,14 @@ void Graphics::drawUIString(const std::string& str, gfx::Color fg, gfx::Color bg
|
||||
++it;
|
||||
}
|
||||
|
||||
y += m_font->height();
|
||||
if (drawUnderscore && underscored_w > 0) {
|
||||
y += m_font->height();
|
||||
dst->fillRect(fg,
|
||||
gfx::Rect(underscored_x, y, underscored_w, guiscale()));
|
||||
y += guiscale();
|
||||
}
|
||||
|
||||
dirty(gfx::Rect(pt, gfx::Point(x, y)));
|
||||
}
|
||||
|
||||
void Graphics::drawAlignedUIString(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, int align)
|
||||
|
@ -92,11 +92,16 @@ namespace ui {
|
||||
private:
|
||||
gfx::Size doUIStringAlgorithm(const std::string& str, gfx::Color fg, gfx::Color bg, const gfx::Rect& rc, int align, bool draw);
|
||||
|
||||
void dirty(const gfx::Rect& bounds) {
|
||||
m_dirtyBounds |= bounds;
|
||||
}
|
||||
|
||||
she::Surface* m_surface;
|
||||
int m_dx;
|
||||
int m_dy;
|
||||
gfx::Rect m_clipBounds;
|
||||
she::Font* m_font;
|
||||
gfx::Rect m_dirtyBounds;
|
||||
};
|
||||
|
||||
// Class to draw directly in the screen.
|
||||
|
@ -61,6 +61,7 @@ typedef std::list<Message*> Messages;
|
||||
typedef std::list<Filter*> Filters;
|
||||
|
||||
Manager* Manager::m_defaultManager = NULL;
|
||||
gfx::Region Manager::m_dirtyRegion;
|
||||
|
||||
static WidgetsList new_windows; // Windows that we should show
|
||||
static WidgetsList mouse_widgets_list; // List of widgets to send mouse events
|
||||
@ -106,6 +107,8 @@ Manager::Manager()
|
||||
setBounds(gfx::Rect(0, 0, ui::display_w(), ui::display_h()));
|
||||
setVisible(true);
|
||||
|
||||
m_dirtyRegion = getBounds();
|
||||
|
||||
// Default manager is the first one (and is always visible).
|
||||
if (!m_defaultManager)
|
||||
m_defaultManager = this;
|
||||
@ -181,7 +184,17 @@ void Manager::flipDisplay()
|
||||
overlays->captureOverlappedAreas();
|
||||
overlays->drawOverlays();
|
||||
|
||||
m_display->flip();
|
||||
// Flip dirty region.
|
||||
{
|
||||
m_dirtyRegion.createIntersection(
|
||||
m_dirtyRegion,
|
||||
gfx::Region(gfx::Rect(0, 0, ui::display_w(), ui::display_h())));
|
||||
|
||||
for (auto& rc : m_dirtyRegion)
|
||||
m_display->flip(rc);
|
||||
|
||||
m_dirtyRegion.clear();
|
||||
}
|
||||
|
||||
overlays->restoreOverlappedAreas();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define UI_MANAGER_H_INCLUDED
|
||||
#pragma once
|
||||
|
||||
#include "gfx/region.h"
|
||||
#include "ui/message_type.h"
|
||||
#include "ui/mouse_buttons.h"
|
||||
#include "ui/widget.h"
|
||||
@ -30,6 +31,10 @@ namespace ui {
|
||||
return m_defaultManager;
|
||||
}
|
||||
|
||||
static gfx::Region& getDirtyRegion() {
|
||||
return m_dirtyRegion;
|
||||
}
|
||||
|
||||
Manager();
|
||||
~Manager();
|
||||
|
||||
@ -116,6 +121,7 @@ namespace ui {
|
||||
void broadcastKeyMsg(Message* msg);
|
||||
|
||||
static Manager* m_defaultManager;
|
||||
static gfx::Region m_dirtyRegion;
|
||||
|
||||
WidgetsList m_garbage;
|
||||
she::Display* m_display;
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Aseprite UI Library
|
||||
// Copyright (C) 2001-2013 David Capello
|
||||
// Copyright (C) 2001-2013, 2015 David Capello
|
||||
//
|
||||
// This file is released under the terms of the MIT license.
|
||||
// Read LICENSE.txt for more information.
|
||||
@ -62,6 +62,12 @@ void Overlay::drawOverlay(she::LockedSurface* screen)
|
||||
|
||||
she::ScopedSurfaceLock lockedSurface(m_surface);
|
||||
screen->drawRgbaSurface(lockedSurface, m_pos.x, m_pos.y);
|
||||
|
||||
Manager::getDirtyRegion().createUnion(
|
||||
Manager::getDirtyRegion(),
|
||||
gfx::Region(gfx::Rect(m_pos.x, m_pos.y,
|
||||
m_surface->width(),
|
||||
m_surface->height())));
|
||||
}
|
||||
|
||||
void Overlay::moveOverlay(const gfx::Point& newPos)
|
||||
@ -93,6 +99,12 @@ void Overlay::restoreOverlappedArea(she::LockedSurface* screen)
|
||||
she::ScopedSurfaceLock lock(m_overlap);
|
||||
lock->blitTo(screen, 0, 0, m_pos.x, m_pos.y,
|
||||
m_overlap->width(), m_overlap->height());
|
||||
|
||||
Manager::getDirtyRegion().createUnion(
|
||||
Manager::getDirtyRegion(),
|
||||
gfx::Region(gfx::Rect(m_pos.x, m_pos.y,
|
||||
m_overlap->width(),
|
||||
m_overlap->height())));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user