From 433a2daa6a42b4cca3a715d4461a893be17ef61a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 10 Mar 2016 21:49:42 -0500 Subject: GRAPHICS: Added ManagedSurface and Screen classes --- graphics/managed_surface.cpp | 258 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 graphics/managed_surface.cpp (limited to 'graphics/managed_surface.cpp') diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp new file mode 100644 index 0000000000..45db0bc52e --- /dev/null +++ b/graphics/managed_surface.cpp @@ -0,0 +1,258 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "graphics/managed_surface.h" +#include "common/algorithm.h" +#include "common/textconsole.h" + +namespace Graphics { + +const int SCALE_THRESHOLD = 0x100; + +ManagedSurface::ManagedSurface() : + w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), + _isManaged(false), _owner(nullptr) { +} + +ManagedSurface::ManagedSurface(const ManagedSurface &surf) : + w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), + _isManaged(false), _owner(nullptr) { + *this = surf; +} + +ManagedSurface::ManagedSurface(int width, int height) : + w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), + _isManaged(false), _owner(nullptr) { + create(width, height); +} + +ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) : + w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), + _isManaged(false), _owner(nullptr) { + create(width, height, format); +} + +ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) : + w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), + _isManaged(false), _owner(nullptr) { + create(surf, bounds); +} + +ManagedSurface::~ManagedSurface() { + free(); +} + +ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) { + if (surf._isManaged) { + // Create a new surface and copy the pixels from the source surface + create(surf.w, surf.h, surf.format); + Common::copy((const byte *)surf.getPixels(), (const byte *)surf.getPixels() + + surf.w * surf.h * surf.format.bytesPerPixel, (byte *)this->getPixels()); + } else { + // Source isn't managed, so simply copy it's fields + _isManaged = false; + _owner = surf._owner; + _offsetFromOwner = surf._offsetFromOwner; + + void *srcPixels = (void *)surf._innerSurface.getPixels(); + _innerSurface.setPixels(srcPixels); + _innerSurface.w = surf.w; + _innerSurface.h = surf.h; + _innerSurface.pitch = surf.pitch; + this->format = surf.format; + } + + return *this; +} + +void ManagedSurface::setPixels(void *newPixels) { + free(); + _innerSurface.setPixels(newPixels); +} + +void ManagedSurface::create(uint16 width, uint16 height) { + create(width, height, PixelFormat::createFormatCLUT8()); +} + +void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixelFormat) { + free(); + _innerSurface.create(width, height, pixelFormat); + + _isManaged = true; + markAllDirty(); +} + +void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) { + free(); + + _offsetFromOwner = Common::Point(bounds.left, bounds.top); + _innerSurface.setPixels(surf.getBasePtr(bounds.left, bounds.top)); + _innerSurface.pitch = surf.pitch; + _innerSurface.format = surf.format; + _innerSurface.w = bounds.width(); + _innerSurface.h = bounds.height(); + _owner = &surf; + _isManaged = false; +} + +void ManagedSurface::free() { + if (_isManaged) + _innerSurface.free(); + + _isManaged = false; + _owner = nullptr; + _offsetFromOwner = Common::Point(0, 0); +} + +bool ManagedSurface::clip(Common::Rect &srcBounds, Common::Rect &destBounds) { + if (destBounds.left >= this->w || destBounds.top >= this->h || + destBounds.right <= 0 || destBounds.bottom <= 0) + return false; + + // Clip the bounds if necessary to fit on-screen + if (destBounds.right > this->w) { + srcBounds.right -= destBounds.right - this->w; + destBounds.right = this->w; + } + + if (destBounds.bottom > this->h) { + srcBounds.bottom -= destBounds.bottom - this->h; + destBounds.bottom = this->h; + } + + if (destBounds.top < 0) { + srcBounds.top += -destBounds.top; + destBounds.top = 0; + } + + if (destBounds.left < 0) { + srcBounds.left += -destBounds.left; + destBounds.left = 0; + } + + return true; +} + +void ManagedSurface::blitFrom(const Surface &src) { + blitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Point(0, 0)); +} + +void ManagedSurface::blitFrom(const Surface &src, const Common::Point &destPos) { + blitFrom(src, Common::Rect(0, 0, src.w, src.h), destPos); +} + +void ManagedSurface::blitFrom(const Surface &src, const Common::Rect &srcRect, + const Common::Point &destPos) { + Common::Rect srcBounds = srcRect; + Common::Rect destBounds(destPos.x, destPos.y, destPos.x + srcRect.width(), + destPos.y + srcRect.height()); + assert(src.format.bytesPerPixel == format.bytesPerPixel); + + if (!srcRect.isValidRect() || !clip(srcBounds, destBounds)) + return; + + for (int y = 0; y < srcBounds.height(); ++y) { + const byte *srcP = (const byte *)src.getBasePtr(srcBounds.left, srcBounds.top + y); + byte *destP = (byte *)getBasePtr(destBounds.left, destBounds.top + y); + Common::copy(srcP, srcP + srcBounds.width() * format.bytesPerPixel, destP); + } + + addDirtyRect(Common::Rect(0, 0, this->w, this->h)); +} + +void ManagedSurface::transBlitFrom(const Surface &src, uint transColor, bool flipped, uint overrideColor) { + transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(0, 0, this->w, this->h), + transColor, false, overrideColor); +} + +void ManagedSurface::transBlitFrom(const Surface &src, const Common::Point &destPos, + uint transColor, bool flipped, uint overrideColor) { + transBlitFrom(src, Common::Rect(0, 0, src.w, src.h), Common::Rect(destPos.x, destPos.y, + destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor); +} + +void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect, + const Common::Point &destPos, uint transColor, bool flipped, uint overrideColor) { + transBlitFrom(src, srcRect, Common::Rect(destPos.x, destPos.y, + destPos.x + src.w, destPos.y + src.h), transColor, false, overrideColor); +} + +template +void transBlit(const Surface &src, const Common::Rect &srcRect, const Surface *dest, const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) { + int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width(); + int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height(); + + // Loop through drawing output lines + for (int destY = destRect.top, scaleYCtr = 0; destY < destRect.bottom; ++destY, scaleYCtr += scaleY) { + if (destY < 0 || destY >= dest->h) + continue; + const T *srcLine = (const T *)src.getBasePtr(0, scaleYCtr / SCALE_THRESHOLD); + T *destLine = (T *)dest->getBasePtr(destRect.left, destY); + + // Loop through drawing the pixels of the row + for (int destX = destRect.left, xCtr = 0, scaleXCtr = 0; destX < destRect.right; ++destX, ++xCtr, scaleXCtr += scaleX) { + if (destX < 0 || destX >= dest->w) + continue; + + T srcVal = srcLine[flipped ? src.w - scaleXCtr / SCALE_THRESHOLD - 1 : scaleXCtr / SCALE_THRESHOLD]; + if (srcVal != transColor) { + destLine[xCtr] = overrideColor ? overrideColor : srcVal; + } + } + } +} + +void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRect, + const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) { + if (src.w == 0 || src.h == 0 || destRect.width() == 0 || destRect.height() == 0) + return; + + if (format.bytesPerPixel == 1) + transBlit(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor); + else if (format.bytesPerPixel == 2) + transBlit(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor); + else if (format.bytesPerPixel == 4) + transBlit(src, srcRect, &_innerSurface, destRect, transColor, flipped, overrideColor); + else + error("Surface::transBlitFrom: bytesPerPixel must be 1, 2, or 4"); + + // Mark the affected area + addDirtyRect(destRect); +} + +void ManagedSurface::markAllDirty() { + addDirtyRect(Common::Rect(0, 0, this->w, this->h)); +} + +void ManagedSurface::addDirtyRect(const Common::Rect &r) { + if (_owner) { + Common::Rect bounds = r; + bounds.translate(_offsetFromOwner.x, _offsetFromOwner.y); + _owner->addDirtyRect(bounds); + } +} + +void ManagedSurface::clear(uint color) { + fillRect(getBounds(), color); +} + +} // End of namespace Graphics -- cgit v1.2.3 From 390487aa43e5507d4d0fb4ae57e7cf726a94f4c1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 17 Mar 2016 18:35:17 -0400 Subject: GRAPHICS: Cleanup of ManagedSurface and Screen classes --- graphics/managed_surface.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'graphics/managed_surface.cpp') diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp index 45db0bc52e..e493ab9f4e 100644 --- a/graphics/managed_surface.cpp +++ b/graphics/managed_surface.cpp @@ -30,30 +30,30 @@ const int SCALE_THRESHOLD = 0x100; ManagedSurface::ManagedSurface() : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), - _isManaged(false), _owner(nullptr) { + _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { } ManagedSurface::ManagedSurface(const ManagedSurface &surf) : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), - _isManaged(false), _owner(nullptr) { + _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { *this = surf; } ManagedSurface::ManagedSurface(int width, int height) : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), - _isManaged(false), _owner(nullptr) { + _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { create(width, height); } ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), - _isManaged(false), _owner(nullptr) { + _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { create(width, height, format); } ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), - _isManaged(false), _owner(nullptr) { + _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { create(surf, bounds); } @@ -62,17 +62,18 @@ ManagedSurface::~ManagedSurface() { } ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) { - if (surf._isManaged) { + // Free any current surface + free(); + + if (surf._disposeAfterUse == DisposeAfterUse::YES) { // Create a new surface and copy the pixels from the source surface create(surf.w, surf.h, surf.format); Common::copy((const byte *)surf.getPixels(), (const byte *)surf.getPixels() + surf.w * surf.h * surf.format.bytesPerPixel, (byte *)this->getPixels()); } else { - // Source isn't managed, so simply copy it's fields - _isManaged = false; + // Source isn't managed, so simply copy its fields _owner = surf._owner; _offsetFromOwner = surf._offsetFromOwner; - void *srcPixels = (void *)surf._innerSurface.getPixels(); _innerSurface.setPixels(srcPixels); _innerSurface.w = surf.w; @@ -97,7 +98,7 @@ void ManagedSurface::create(uint16 width, uint16 height, const PixelFormat &pixe free(); _innerSurface.create(width, height, pixelFormat); - _isManaged = true; + _disposeAfterUse = DisposeAfterUse::YES; markAllDirty(); } @@ -111,14 +112,14 @@ void ManagedSurface::create(ManagedSurface &surf, const Common::Rect &bounds) { _innerSurface.w = bounds.width(); _innerSurface.h = bounds.height(); _owner = &surf; - _isManaged = false; + _disposeAfterUse = DisposeAfterUse::NO; } void ManagedSurface::free() { - if (_isManaged) + if (_disposeAfterUse == DisposeAfterUse::YES) _innerSurface.free(); - _isManaged = false; + _disposeAfterUse = DisposeAfterUse::NO; _owner = nullptr; _offsetFromOwner = Common::Point(0, 0); } @@ -246,6 +247,7 @@ void ManagedSurface::markAllDirty() { void ManagedSurface::addDirtyRect(const Common::Rect &r) { if (_owner) { Common::Rect bounds = r; + bounds.clip(Common::Rect(0, 0, this->w, this->h)); bounds.translate(_offsetFromOwner.x, _offsetFromOwner.y); _owner->addDirtyRect(bounds); } -- cgit v1.2.3 From 14ba851d32bae17d1cdc7ef9dd05c645611c005d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 20 Mar 2016 16:37:19 -0400 Subject: GRAPHICS: Fix MangaedSurface pixel casting errors --- graphics/managed_surface.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'graphics/managed_surface.cpp') diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp index e493ab9f4e..9dcea12836 100644 --- a/graphics/managed_surface.cpp +++ b/graphics/managed_surface.cpp @@ -33,7 +33,7 @@ ManagedSurface::ManagedSurface() : _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { } -ManagedSurface::ManagedSurface(const ManagedSurface &surf) : +ManagedSurface::ManagedSurface(ManagedSurface &surf) : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { *this = surf; @@ -61,7 +61,7 @@ ManagedSurface::~ManagedSurface() { free(); } -ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) { +ManagedSurface &ManagedSurface::operator=(ManagedSurface &surf) { // Free any current surface free(); @@ -74,7 +74,7 @@ ManagedSurface &ManagedSurface::operator=(const ManagedSurface &surf) { // Source isn't managed, so simply copy its fields _owner = surf._owner; _offsetFromOwner = surf._offsetFromOwner; - void *srcPixels = (void *)surf._innerSurface.getPixels(); + void *srcPixels = surf._innerSurface.getPixels(); _innerSurface.setPixels(srcPixels); _innerSurface.w = surf.w; _innerSurface.h = surf.h; @@ -198,7 +198,7 @@ void ManagedSurface::transBlitFrom(const Surface &src, const Common::Rect &srcRe } template -void transBlit(const Surface &src, const Common::Rect &srcRect, const Surface *dest, const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) { +void transBlit(const Surface &src, const Common::Rect &srcRect, Surface *dest, const Common::Rect &destRect, uint transColor, bool flipped, uint overrideColor) { int scaleX = SCALE_THRESHOLD * srcRect.width() / destRect.width(); int scaleY = SCALE_THRESHOLD * srcRect.height() / destRect.height(); -- cgit v1.2.3 From c382e179084d52656de7379822d89a5fe97ca988 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 20 Mar 2016 20:53:01 -0400 Subject: GRAPHICS: Fix create call in ManagedSurface constructor --- graphics/managed_surface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'graphics/managed_surface.cpp') diff --git a/graphics/managed_surface.cpp b/graphics/managed_surface.cpp index 9dcea12836..273b15de55 100644 --- a/graphics/managed_surface.cpp +++ b/graphics/managed_surface.cpp @@ -48,7 +48,7 @@ ManagedSurface::ManagedSurface(int width, int height) : ManagedSurface::ManagedSurface(int width, int height, const Graphics::PixelFormat &pixelFormat) : w(_innerSurface.w), h(_innerSurface.h), pitch(_innerSurface.pitch), format(_innerSurface.format), _disposeAfterUse(DisposeAfterUse::NO), _owner(nullptr) { - create(width, height, format); + create(width, height, pixelFormat); } ManagedSurface::ManagedSurface(ManagedSurface &surf, const Common::Rect &bounds) : -- cgit v1.2.3