mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-20 00:45:10 +00:00
SWORD25: Optimize graphics drawing code
This commit is contained in:
parent
6548104b96
commit
0a0b2f397b
@ -170,7 +170,7 @@ void Animation::setFrame(uint nr) {
|
||||
forceRefresh();
|
||||
}
|
||||
|
||||
bool Animation::doRender() {
|
||||
bool Animation::doRender(RectangleList *updateRects) {
|
||||
AnimationDescription *animationDescriptionPtr = getAnimationDescription();
|
||||
assert(animationDescriptionPtr);
|
||||
assert(_currentFrame < animationDescriptionPtr->getFrameCount());
|
||||
@ -191,12 +191,14 @@ bool Animation::doRender() {
|
||||
result = pBitmapResource->blit(_absoluteX, _absoluteY,
|
||||
(animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) |
|
||||
(animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0),
|
||||
0, _modulationColor, _width, _height);
|
||||
0, _modulationColor, _width, _height,
|
||||
updateRects);
|
||||
} else {
|
||||
result = pBitmapResource->blit(_absoluteX, _absoluteY,
|
||||
(animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) |
|
||||
(animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0),
|
||||
0, _modulationColor, -1, -1);
|
||||
0, _modulationColor, -1, -1,
|
||||
updateRects);
|
||||
}
|
||||
|
||||
// Resource freigeben
|
||||
|
@ -151,7 +151,7 @@ public:
|
||||
void setCallbacks();
|
||||
|
||||
protected:
|
||||
virtual bool doRender();
|
||||
virtual bool doRender(RectangleList *updateRects);
|
||||
|
||||
private:
|
||||
enum Direction {
|
||||
|
@ -123,9 +123,10 @@ public:
|
||||
int flipping = FLIP_NONE,
|
||||
Common::Rect *pSrcPartRect = NULL,
|
||||
uint color = BS_ARGB(255, 255, 255, 255),
|
||||
int width = -1, int height = -1) {
|
||||
int width = -1, int height = -1,
|
||||
RectangleList *updateRects = 0) {
|
||||
assert(_pImage);
|
||||
return _pImage->blit(posX, posY, flipping, pSrcPartRect, color, width, height);
|
||||
return _pImage->blit(posX, posY, flipping, pSrcPartRect, color, width, height, updateRects);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,6 +203,11 @@ public:
|
||||
return _pImage->isColorModulationAllowed();
|
||||
}
|
||||
|
||||
bool isSolid() {
|
||||
assert(_pImage);
|
||||
return _pImage->isSolid();
|
||||
}
|
||||
|
||||
private:
|
||||
Image *_pImage;
|
||||
};
|
||||
|
@ -53,10 +53,13 @@ DynamicBitmap::DynamicBitmap(InputPersistenceBlock &reader, RenderObjectPtr<Rend
|
||||
bool DynamicBitmap::createRenderedImage(uint width, uint height) {
|
||||
bool result = false;
|
||||
_image.reset(new RenderedImage(width, height, result));
|
||||
|
||||
|
||||
_originalWidth = _width = width;
|
||||
_originalHeight = _height = height;
|
||||
|
||||
_image->setIsTransparent(false);
|
||||
_isSolid = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -70,10 +73,12 @@ uint DynamicBitmap::getPixel(int x, int y) const {
|
||||
return _image->getPixel(x, y);
|
||||
}
|
||||
|
||||
bool DynamicBitmap::doRender() {
|
||||
bool DynamicBitmap::doRender(RectangleList *updateRects) {
|
||||
// Get the frame buffer object
|
||||
GraphicEngine *pGfx = Kernel::getInstance()->getGfx();
|
||||
assert(pGfx);
|
||||
|
||||
//return true;//DEBUG
|
||||
|
||||
// Draw the bitmap
|
||||
bool result;
|
||||
@ -85,7 +90,8 @@ bool DynamicBitmap::doRender() {
|
||||
result = _image->blit(_absoluteX, _absoluteY,
|
||||
(_flipV ? BitmapResource::FLIP_V : 0) |
|
||||
(_flipH ? BitmapResource::FLIP_H : 0),
|
||||
0, _modulationColor, -1, -1);
|
||||
0, _modulationColor, -1, -1,
|
||||
updateRects);
|
||||
#else
|
||||
// WIP: A bit faster code
|
||||
|
||||
@ -103,13 +109,15 @@ bool DynamicBitmap::doRender() {
|
||||
result = _image->blit(_absoluteX, _absoluteY,
|
||||
(_flipV ? BitmapResource::FLIP_V : 0) |
|
||||
(_flipH ? BitmapResource::FLIP_H : 0),
|
||||
0, _modulationColor, _width, _height);
|
||||
0, _modulationColor, _width, _height,
|
||||
updateRects);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DynamicBitmap::setContent(const byte *pixeldata, uint size, uint offset, uint stride) {
|
||||
++_version; // Update version to display the new video image
|
||||
return _image->setContent(pixeldata, size, offset, stride);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
virtual bool unpersist(InputPersistenceBlock &reader);
|
||||
|
||||
protected:
|
||||
virtual bool doRender();
|
||||
virtual bool doRender(RectangleList *updateRects);
|
||||
|
||||
private:
|
||||
DynamicBitmap(RenderObjectPtr<RenderObject> parentPtr, uint width, uint height);
|
||||
|
@ -216,7 +216,6 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) {
|
||||
}
|
||||
}
|
||||
|
||||
g_system->copyRectToScreen(_backSurface.getBasePtr(rect.left, rect.top), _backSurface.pitch, rect.left, rect.top, rect.width(), rect.height());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -46,6 +46,8 @@
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
class RectangleList;
|
||||
|
||||
class Image {
|
||||
public:
|
||||
virtual ~Image() {}
|
||||
@ -129,7 +131,8 @@ public:
|
||||
int flipping = FLIP_NONE,
|
||||
Common::Rect *pPartRect = NULL,
|
||||
uint color = BS_ARGB(255, 255, 255, 255),
|
||||
int width = -1, int height = -1) = 0;
|
||||
int width = -1, int height = -1,
|
||||
RectangleList *updateRects = 0) = 0;
|
||||
|
||||
/**
|
||||
@brief fills a rectangular section of the image with a color.
|
||||
@ -202,6 +205,8 @@ public:
|
||||
@brief Returns true, if the content of the BS_Image is allowed to be replaced by call of SetContent().
|
||||
*/
|
||||
virtual bool isSetContentAllowed() const = 0;
|
||||
|
||||
virtual bool isSolid() const { return false; }
|
||||
|
||||
//@}
|
||||
};
|
||||
|
@ -38,6 +38,8 @@
|
||||
#include "sword25/gfx/image/imgloader.h"
|
||||
#include "sword25/gfx/image/renderedimage.h"
|
||||
|
||||
#include "sword25/gfx/renderobjectmanager.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Sword25 {
|
||||
@ -99,7 +101,8 @@ static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSiz
|
||||
RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
|
||||
_data(0),
|
||||
_width(0),
|
||||
_height(0) {
|
||||
_height(0),
|
||||
_isTransparent(true) {
|
||||
result = false;
|
||||
|
||||
PackageManager *pPackage = Kernel::getInstance()->getPackage();
|
||||
@ -142,6 +145,8 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
|
||||
|
||||
_doCleanup = true;
|
||||
|
||||
checkForTransparency();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -149,7 +154,8 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
|
||||
|
||||
RenderedImage::RenderedImage(uint width, uint height, bool &result) :
|
||||
_width(width),
|
||||
_height(height) {
|
||||
_height(height),
|
||||
_isTransparent(true) {
|
||||
|
||||
_data = new byte[width * height * 4];
|
||||
Common::fill(_data, &_data[width * height * 4], 0);
|
||||
@ -162,7 +168,7 @@ RenderedImage::RenderedImage(uint width, uint height, bool &result) :
|
||||
return;
|
||||
}
|
||||
|
||||
RenderedImage::RenderedImage() : _width(0), _height(0), _data(0) {
|
||||
RenderedImage::RenderedImage() : _width(0), _height(0), _data(0), _isTransparent(true) {
|
||||
_backSurface = Kernel::getInstance()->getGfx()->getSurface();
|
||||
|
||||
_doCleanup = false;
|
||||
@ -219,7 +225,7 @@ uint RenderedImage::getPixel(int x, int y) {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) {
|
||||
bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, RectangleList *updateRects) {
|
||||
int ca = (color >> 24) & 0xff;
|
||||
|
||||
// Check if we need to draw anything at all
|
||||
@ -282,156 +288,175 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
|
||||
img = &srcImage;
|
||||
}
|
||||
|
||||
// Handle off-screen clipping
|
||||
if (posY < 0) {
|
||||
img->h = MAX(0, (int)img->h - -posY);
|
||||
img->pixels = (byte *)img->pixels + img->pitch * -posY;
|
||||
posY = 0;
|
||||
}
|
||||
|
||||
if (posX < 0) {
|
||||
img->w = MAX(0, (int)img->w - -posX);
|
||||
img->pixels = (byte *)img->pixels + (-posX * 4);
|
||||
posX = 0;
|
||||
}
|
||||
|
||||
img->w = CLIP((int)img->w, 0, (int)MAX((int)_backSurface->w - posX, 0));
|
||||
img->h = CLIP((int)img->h, 0, (int)MAX((int)_backSurface->h - posY, 0));
|
||||
|
||||
if ((img->w > 0) && (img->h > 0)) {
|
||||
int xp = 0, yp = 0;
|
||||
|
||||
int inStep = 4;
|
||||
int inoStep = img->pitch;
|
||||
if (flipping & Image::FLIP_V) {
|
||||
inStep = -inStep;
|
||||
xp = img->w - 1;
|
||||
for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) {
|
||||
const Common::Rect &clipRect = *it;
|
||||
|
||||
int skipLeft = 0, skipTop = 0;
|
||||
int drawX = posX, drawY = posY;
|
||||
int drawWidth = img->w;
|
||||
int drawHeight = img->h;
|
||||
|
||||
// Handle clipping
|
||||
if (drawY < clipRect.top) {
|
||||
skipTop = clipRect.top - drawY;
|
||||
drawHeight = MAX(0, (int)drawHeight - (clipRect.top - drawY));
|
||||
drawY = clipRect.top;
|
||||
}
|
||||
|
||||
if (flipping & Image::FLIP_H) {
|
||||
inoStep = -inoStep;
|
||||
yp = img->h - 1;
|
||||
|
||||
if (drawX < clipRect.left) {
|
||||
skipLeft = clipRect.left - drawX;
|
||||
drawWidth = MAX(0, (int)drawWidth - skipLeft);
|
||||
drawX = clipRect.left;
|
||||
}
|
||||
|
||||
if (drawX + drawWidth >= clipRect.right)
|
||||
drawWidth = clipRect.right - drawX;
|
||||
|
||||
if (drawY + drawHeight >= clipRect.bottom)
|
||||
drawHeight = clipRect.bottom - drawY;
|
||||
|
||||
if ((drawWidth > 0) && (drawHeight > 0)) {
|
||||
int xp = 0, yp = 0;
|
||||
|
||||
int inStep = 4;
|
||||
int inoStep = img->pitch;
|
||||
if (flipping & Image::FLIP_V) {
|
||||
inStep = -inStep;
|
||||
xp = img->w - 1 - skipLeft;
|
||||
} else {
|
||||
xp = skipLeft;
|
||||
}
|
||||
|
||||
if (flipping & Image::FLIP_H) {
|
||||
inoStep = -inoStep;
|
||||
yp = img->h - 1 - skipTop;
|
||||
} else {
|
||||
yp = skipTop;
|
||||
}
|
||||
|
||||
byte *ino = (byte *)img->getBasePtr(xp, yp);
|
||||
byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY);
|
||||
|
||||
byte *ino = (byte *)img->getBasePtr(xp, yp);
|
||||
byte *outo = (byte *)_backSurface->getBasePtr(posX, posY);
|
||||
byte *in, *out;
|
||||
|
||||
for (int i = 0; i < img->h; i++) {
|
||||
out = outo;
|
||||
in = ino;
|
||||
for (int j = 0; j < img->w; j++) {
|
||||
uint32 pix = *(uint32 *)in;
|
||||
int b = (pix >> 0) & 0xff;
|
||||
int g = (pix >> 8) & 0xff;
|
||||
int r = (pix >> 16) & 0xff;
|
||||
int a = (pix >> 24) & 0xff;
|
||||
in += inStep;
|
||||
|
||||
if (ca != 255) {
|
||||
a = a * ca >> 8;
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
// Simple memcpy if the source bitmap doesn't have transparent pixels and the drawing transparency is 255
|
||||
// NOTE Only possible with LE-machines at the moment, maybe it would be feasible to convert the bitmap pixels at loading time?
|
||||
if (!_isTransparent && ca == 255) {
|
||||
for (int i = 0; i < drawHeight; i++) {
|
||||
memcpy(outo, ino, drawWidth * 4);
|
||||
outo += _backSurface->pitch;
|
||||
ino += inoStep;
|
||||
}
|
||||
|
||||
switch (a) {
|
||||
case 0: // Full transparency
|
||||
out += 4;
|
||||
break;
|
||||
case 255: // Full opacity
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
byte *in, *out;
|
||||
for (int i = 0; i < drawHeight; i++) {
|
||||
out = outo;
|
||||
in = ino;
|
||||
for (int j = 0; j < drawWidth; j++) {
|
||||
uint32 pix = *(uint32 *)in;
|
||||
int a = (pix >> 24) & 0xff;
|
||||
in += inStep;
|
||||
|
||||
if (a == 0) {
|
||||
// Full transparency
|
||||
out += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ca != 255) {
|
||||
a = a * ca >> 8;
|
||||
}
|
||||
|
||||
int b = (pix >> 0) & 0xff;
|
||||
int g = (pix >> 8) & 0xff;
|
||||
int r = (pix >> 16) & 0xff;
|
||||
|
||||
if (a == 255) {
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
if (cb != 255)
|
||||
*out++ = (b * cb) >> 8;
|
||||
else
|
||||
*out++ = b;
|
||||
|
||||
if (cg != 255)
|
||||
*out++ = (g * cg) >> 8;
|
||||
else
|
||||
*out++ = g;
|
||||
|
||||
if (cr != 255)
|
||||
*out++ = (r * cr) >> 8;
|
||||
else
|
||||
*out++ = r;
|
||||
|
||||
*out++ = a;
|
||||
if (cb != 255)
|
||||
b = (b * cb) >> 8;
|
||||
if (cg != 255)
|
||||
g = (g * cg) >> 8;
|
||||
if (cr != 255)
|
||||
r = (r * cr) >> 8;
|
||||
*(uint32 *)out = (255 << 24) | (r << 16) | (g << 8) | b;
|
||||
out += 4;
|
||||
#else
|
||||
*out++ = a;
|
||||
|
||||
if (cr != 255)
|
||||
*out++ = (r * cr) >> 8;
|
||||
else
|
||||
*out++ = r;
|
||||
|
||||
if (cg != 255)
|
||||
*out++ = (g * cg) >> 8;
|
||||
else
|
||||
*out++ = g;
|
||||
|
||||
if (cb != 255)
|
||||
*out++ = (b * cb) >> 8;
|
||||
else
|
||||
*out++ = b;
|
||||
*out++ = a;
|
||||
if (cr != 255)
|
||||
*out++ = (r * cr) >> 8;
|
||||
else
|
||||
*out++ = r;
|
||||
if (cg != 255)
|
||||
*out++ = (g * cg) >> 8;
|
||||
else
|
||||
*out++ = g;
|
||||
if (cb != 255)
|
||||
*out++ = (b * cb) >> 8;
|
||||
else
|
||||
*out++ = b;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default: // alpha blending
|
||||
} else {
|
||||
#if defined(SCUMM_LITTLE_ENDIAN)
|
||||
if (cb == 0)
|
||||
*out = 0;
|
||||
else if (cb != 255)
|
||||
*out += ((b - *out) * a * cb) >> 16;
|
||||
else
|
||||
*out += ((b - *out) * a) >> 8;
|
||||
out++;
|
||||
if (cg == 0)
|
||||
*out = 0;
|
||||
else if (cg != 255)
|
||||
*out += ((g - *out) * a * cg) >> 16;
|
||||
else
|
||||
*out += ((g - *out) * a) >> 8;
|
||||
out++;
|
||||
if (cr == 0)
|
||||
*out = 0;
|
||||
else if (cr != 255)
|
||||
*out += ((r - *out) * a * cr) >> 16;
|
||||
else
|
||||
*out += ((r - *out) * a) >> 8;
|
||||
out++;
|
||||
*out = 255;
|
||||
out++;
|
||||
pix = *(uint32 *)out;
|
||||
int outb = (pix >> 0) & 0xff;
|
||||
int outg = (pix >> 8) & 0xff;
|
||||
int outr = (pix >> 16) & 0xff;
|
||||
if (cb == 0)
|
||||
outb = 0;
|
||||
else if (cb != 255)
|
||||
outb += ((b - outb) * a * cb) >> 16;
|
||||
else
|
||||
outb += ((b - outb) * a) >> 8;
|
||||
if (cg == 0)
|
||||
outg = 0;
|
||||
else if (cg != 255)
|
||||
outg += ((g - outg) * a * cg) >> 16;
|
||||
else
|
||||
outg += ((g - outg) * a) >> 8;
|
||||
if (cr == 0)
|
||||
outr = 0;
|
||||
else if (cr != 255)
|
||||
outr += ((r - outr) * a * cr) >> 16;
|
||||
else
|
||||
outr += ((r - outr) * a) >> 8;
|
||||
*(uint32 *)out = (255 << 24) | (outr << 16) | (outg << 8) | outb;
|
||||
out += 4;
|
||||
#else
|
||||
*out = 255;
|
||||
out++;
|
||||
if (cr == 0)
|
||||
*out = 0;
|
||||
else if (cr != 255)
|
||||
*out += ((r - *out) * a * cr) >> 16;
|
||||
else
|
||||
*out += ((r - *out) * a) >> 8;
|
||||
out++;
|
||||
if (cg == 0)
|
||||
*out = 0;
|
||||
else if (cg != 255)
|
||||
*out += ((g - *out) * a * cg) >> 16;
|
||||
else
|
||||
*out += ((g - *out) * a) >> 8;
|
||||
out++;
|
||||
if (cb == 0)
|
||||
*out = 0;
|
||||
else if (cb != 255)
|
||||
*out += ((b - *out) * a * cb) >> 16;
|
||||
else
|
||||
*out += ((b - *out) * a) >> 8;
|
||||
out++;
|
||||
*out = 255;
|
||||
out++;
|
||||
if (cr == 0)
|
||||
*out = 0;
|
||||
else if (cr != 255)
|
||||
*out += ((r - *out) * a * cr) >> 16;
|
||||
else
|
||||
*out += ((r - *out) * a) >> 8;
|
||||
out++;
|
||||
if (cg == 0)
|
||||
*out = 0;
|
||||
else if (cg != 255)
|
||||
*out += ((g - *out) * a * cg) >> 16;
|
||||
else
|
||||
*out += ((g - *out) * a) >> 8;
|
||||
out++;
|
||||
if (cb == 0)
|
||||
*out = 0;
|
||||
else if (cb != 255)
|
||||
*out += ((b - *out) * a * cb) >> 16;
|
||||
else
|
||||
*out += ((b - *out) * a) >> 8;
|
||||
out++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
outo += _backSurface->pitch;
|
||||
ino += inoStep;
|
||||
}
|
||||
}
|
||||
outo += _backSurface->pitch;
|
||||
ino += inoStep;
|
||||
}
|
||||
|
||||
g_system->copyRectToScreen(_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
|
||||
img->w, img->h);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (imgScaled) {
|
||||
@ -467,6 +492,20 @@ void RenderedImage::copyDirectly(int posX, int posY) {
|
||||
g_system->copyRectToScreen(data, _backSurface->pitch, posX, posY, w, h);
|
||||
}
|
||||
|
||||
void RenderedImage::checkForTransparency() {
|
||||
// Check if the source bitmap has any transparent pixels at all
|
||||
_isTransparent = false;
|
||||
byte *data = _data;
|
||||
for (int i = 0; i < _height; i++) {
|
||||
for (int j = 0; j < _width; j++) {
|
||||
_isTransparent = data[3] != 0xff;
|
||||
if (_isTransparent)
|
||||
return;
|
||||
data += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales a passed surface, creating a new surface with the result
|
||||
* @param srcImage Source image to scale
|
||||
|
@ -75,7 +75,8 @@ public:
|
||||
int flipping = Image::FLIP_NONE,
|
||||
Common::Rect *pPartRect = NULL,
|
||||
uint color = BS_ARGB(255, 255, 255, 255),
|
||||
int width = -1, int height = -1);
|
||||
int width = -1, int height = -1,
|
||||
RectangleList *updateRects = 0);
|
||||
virtual bool fill(const Common::Rect *pFillRect, uint color);
|
||||
virtual bool setContent(const byte *pixeldata, uint size, uint offset = 0, uint stride = 0);
|
||||
void replaceContent(byte *pixeldata, int width, int height);
|
||||
@ -105,14 +106,19 @@ public:
|
||||
|
||||
static Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
|
||||
|
||||
void setIsTransparent(bool isTransparent) { _isTransparent = isTransparent; }
|
||||
virtual bool isSolid() const { return !_isTransparent; }
|
||||
|
||||
private:
|
||||
byte *_data;
|
||||
int _width;
|
||||
int _height;
|
||||
bool _doCleanup;
|
||||
bool _isTransparent;
|
||||
|
||||
Graphics::Surface *_backSurface;
|
||||
|
||||
void checkForTransparency();
|
||||
static int *scaleLine(int size, int srcSize);
|
||||
};
|
||||
|
||||
|
@ -79,7 +79,8 @@ bool SWImage::blit(int posX, int posY,
|
||||
int flipping,
|
||||
Common::Rect *pPartRect,
|
||||
uint color,
|
||||
int width, int height) {
|
||||
int width, int height,
|
||||
RectangleList *updateRects) {
|
||||
error("Blit() is not supported.");
|
||||
return false;
|
||||
}
|
||||
|
@ -58,7 +58,8 @@ public:
|
||||
int flipping = Image::FLIP_NONE,
|
||||
Common::Rect *pPartRect = NULL,
|
||||
uint color = BS_ARGB(255, 255, 255, 255),
|
||||
int width = -1, int height = -1);
|
||||
int width = -1, int height = -1,
|
||||
RectangleList *updateRects = 0);
|
||||
virtual bool fill(const Common::Rect *fillRectPtr, uint color);
|
||||
virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride);
|
||||
virtual uint getPixel(int x, int y);
|
||||
|
@ -602,7 +602,8 @@ bool VectorImage::blit(int posX, int posY,
|
||||
int flipping,
|
||||
Common::Rect *pPartRect,
|
||||
uint color,
|
||||
int width, int height) {
|
||||
int width, int height,
|
||||
RectangleList *updateRects) {
|
||||
static VectorImage *oldThis = 0;
|
||||
static int oldWidth = -2;
|
||||
static int oldHeight = -2;
|
||||
@ -623,7 +624,7 @@ bool VectorImage::blit(int posX, int posY,
|
||||
RenderedImage *rend = new RenderedImage();
|
||||
|
||||
rend->replaceContent(_pixelData, width, height);
|
||||
rend->blit(posX, posY, flipping, pPartRect, color, width, height);
|
||||
rend->blit(posX, posY, flipping, pPartRect, color, width, height, updateRects);
|
||||
|
||||
delete rend;
|
||||
|
||||
|
@ -212,7 +212,8 @@ public:
|
||||
int flipping = FLIP_NONE,
|
||||
Common::Rect *pPartRect = NULL,
|
||||
uint color = BS_ARGB(255, 255, 255, 255),
|
||||
int width = -1, int height = -1);
|
||||
int width = -1, int height = -1,
|
||||
RectangleList *updateRects = 0);
|
||||
|
||||
class SWFBitStream;
|
||||
|
||||
|
164
engines/sword25/gfx/microtiles.cpp
Normal file
164
engines/sword25/gfx/microtiles.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
/* 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 "sword25/gfx/microtiles.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
MicroTileArray::MicroTileArray(int16 width, int16 height) {
|
||||
_tilesW = (width / TileSize) + ((width % TileSize) > 0 ? 1 : 0);
|
||||
_tilesH = (height / TileSize) + ((height % TileSize) > 0 ? 1 : 0);
|
||||
_tiles = new BoundingBox[_tilesW * _tilesH];
|
||||
clear();
|
||||
}
|
||||
|
||||
MicroTileArray::~MicroTileArray() {
|
||||
delete[] _tiles;
|
||||
}
|
||||
|
||||
void MicroTileArray::addRect(Common::Rect r) {
|
||||
|
||||
int ux0, uy0, ux1, uy1;
|
||||
int tx0, ty0, tx1, ty1;
|
||||
int ix0, iy0, ix1, iy1;
|
||||
|
||||
r.clip(Common::Rect(0, 0, 799, 599));
|
||||
|
||||
ux0 = r.left / TileSize;
|
||||
uy0 = r.top / TileSize;
|
||||
ux1 = r.right / TileSize;
|
||||
uy1 = r.bottom / TileSize;
|
||||
|
||||
tx0 = r.left % TileSize;
|
||||
ty0 = r.top % TileSize;
|
||||
tx1 = r.right % TileSize;
|
||||
ty1 = r.bottom % TileSize;
|
||||
|
||||
for (int yc = uy0; yc <= uy1; yc++) {
|
||||
for (int xc = ux0; xc <= ux1; xc++) {
|
||||
ix0 = (xc == ux0) ? tx0 : 0;
|
||||
ix1 = (xc == ux1) ? tx1 : TileSize - 1;
|
||||
iy0 = (yc == uy0) ? ty0 : 0;
|
||||
iy1 = (yc == uy1) ? ty1 : TileSize - 1;
|
||||
updateBoundingBox(_tiles[xc + yc * _tilesW], ix0, iy0, ix1, iy1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MicroTileArray::clear() {
|
||||
memset(_tiles, 0, _tilesW * _tilesH * sizeof(BoundingBox));
|
||||
}
|
||||
|
||||
byte MicroTileArray::TileX0(const BoundingBox &boundingBox) {
|
||||
return (boundingBox >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
byte MicroTileArray::TileY0(const BoundingBox &boundingBox) {
|
||||
return (boundingBox >> 16) & 0xFF;
|
||||
}
|
||||
|
||||
byte MicroTileArray::TileX1(const BoundingBox &boundingBox) {
|
||||
return (boundingBox >> 8) & 0xFF;
|
||||
}
|
||||
|
||||
byte MicroTileArray::TileY1(const BoundingBox &boundingBox) {
|
||||
return boundingBox & 0xFF;
|
||||
}
|
||||
|
||||
bool MicroTileArray::isBoundingBoxEmpty(const BoundingBox &boundingBox) {
|
||||
return boundingBox == EmptyBoundingBox;
|
||||
}
|
||||
|
||||
bool MicroTileArray::isBoundingBoxFull(const BoundingBox &boundingBox) {
|
||||
return boundingBox == FullBoundingBox;
|
||||
}
|
||||
|
||||
void MicroTileArray::setBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1) {
|
||||
boundingBox = (x0 << 24) | (y0 << 16) | (x1 << 8) | y1;
|
||||
}
|
||||
|
||||
void MicroTileArray::updateBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1) {
|
||||
if (!isBoundingBoxEmpty(boundingBox)) {
|
||||
x0 = MIN(TileX0(boundingBox), x0);
|
||||
y0 = MIN(TileY0(boundingBox), y0);
|
||||
x1 = MAX(TileX1(boundingBox), x1);
|
||||
y1 = MAX(TileY1(boundingBox), y1);
|
||||
}
|
||||
setBoundingBox(boundingBox, x0, y0, x1, y1);
|
||||
}
|
||||
|
||||
RectangleList *MicroTileArray::getRectangles() {
|
||||
|
||||
RectangleList *rects = new RectangleList();
|
||||
|
||||
int x, y;
|
||||
int x0, y0, x1, y1;
|
||||
int i = 0;
|
||||
|
||||
for (y = 0; y < _tilesH; ++y) {
|
||||
for (x = 0; x < _tilesW; ++x) {
|
||||
|
||||
int start;
|
||||
int finish = 0;
|
||||
BoundingBox boundingBox = _tiles[i];
|
||||
|
||||
if (isBoundingBoxEmpty(boundingBox)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
x0 = (x * TileSize) + TileX0(boundingBox);
|
||||
y0 = (y * TileSize) + TileY0(boundingBox);
|
||||
y1 = (y * TileSize) + TileY1(boundingBox);
|
||||
|
||||
start = i;
|
||||
|
||||
if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) { // check if the tile continues
|
||||
while (!finish) {
|
||||
++x;
|
||||
++i;
|
||||
if (x == _tilesW || i >= _tilesW * _tilesH ||
|
||||
TileY0(_tiles[i]) != TileY0(boundingBox) ||
|
||||
TileY1(_tiles[i]) != TileY1(boundingBox) ||
|
||||
TileX0(_tiles[i]) != 0)
|
||||
{
|
||||
--x;
|
||||
--i;
|
||||
finish = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x1 = (x * TileSize) + TileX1(_tiles[i]);
|
||||
|
||||
rects->push_back(Common::Rect(x0, y0, x1 + 1, y1 + 1));
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return rects;
|
||||
}
|
||||
|
||||
} // End of namespace Sword25
|
65
engines/sword25/gfx/microtiles.h
Normal file
65
engines/sword25/gfx/microtiles.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* 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.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SWORD25_MICROTILES_H
|
||||
#define SWORD25_MICROTILES_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/list.h"
|
||||
#include "common/util.h"
|
||||
#include "common/rect.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
typedef uint32 BoundingBox;
|
||||
|
||||
const BoundingBox FullBoundingBox = 0x00001F1F;
|
||||
const BoundingBox EmptyBoundingBox = 0x00000000;
|
||||
const int TileSize = 32;
|
||||
|
||||
class RectangleList : public Common::List<Common::Rect> {
|
||||
};
|
||||
|
||||
class MicroTileArray {
|
||||
public:
|
||||
MicroTileArray(int16 width, int16 height);
|
||||
~MicroTileArray();
|
||||
void addRect(Common::Rect r);
|
||||
void clear();
|
||||
RectangleList *getRectangles();
|
||||
protected:
|
||||
BoundingBox *_tiles;
|
||||
int16 _tilesW, _tilesH;
|
||||
byte TileX0(const BoundingBox &boundingBox);
|
||||
byte TileY0(const BoundingBox &boundingBox);
|
||||
byte TileX1(const BoundingBox &boundingBox);
|
||||
byte TileY1(const BoundingBox &boundingBox);
|
||||
bool isBoundingBoxEmpty(const BoundingBox &boundingBox);
|
||||
bool isBoundingBoxFull(const BoundingBox &boundingBox);
|
||||
void setBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1);
|
||||
void updateBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1);
|
||||
};
|
||||
|
||||
} // namespace Sword25
|
||||
|
||||
#endif // SWORD25_MICROTILES_H
|
@ -36,6 +36,8 @@
|
||||
#include "sword25/gfx/graphicengine.h"
|
||||
#include "sword25/gfx/image/image.h"
|
||||
|
||||
#include "sword25/gfx/renderobjectmanager.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
Panel::Panel(RenderObjectPtr<RenderObject> parentPtr, int width, int height, uint color) :
|
||||
@ -67,7 +69,7 @@ Panel::Panel(InputPersistenceBlock &reader, RenderObjectPtr<RenderObject> parent
|
||||
Panel::~Panel() {
|
||||
}
|
||||
|
||||
bool Panel::doRender() {
|
||||
bool Panel::doRender(RectangleList *updateRects) {
|
||||
// Falls der Alphawert 0 ist, ist das Panel komplett durchsichtig und es muss nichts gezeichnet werden.
|
||||
if (_color >> 24 == 0)
|
||||
return true;
|
||||
@ -75,7 +77,15 @@ bool Panel::doRender() {
|
||||
GraphicEngine *gfxPtr = Kernel::getInstance()->getGfx();
|
||||
assert(gfxPtr);
|
||||
|
||||
return gfxPtr->fill(&_bbox, _color);
|
||||
for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) {
|
||||
const Common::Rect &clipRect = *it;
|
||||
if (_bbox.intersects(clipRect)) {
|
||||
Common::Rect intersectionRect = _bbox.findIntersectingRect(clipRect);
|
||||
gfxPtr->fill(&intersectionRect, _color);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Panel::persist(OutputPersistenceBlock &writer) {
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
virtual bool unpersist(InputPersistenceBlock &reader);
|
||||
|
||||
protected:
|
||||
virtual bool doRender();
|
||||
virtual bool doRender(RectangleList *updateRects);
|
||||
|
||||
private:
|
||||
uint _color;
|
||||
|
@ -48,6 +48,8 @@
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
int RenderObject::_nextGlobalVersion = 0;
|
||||
|
||||
RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type, uint handle) :
|
||||
_managerPtr(0),
|
||||
_parentPtr(parentPtr),
|
||||
@ -65,7 +67,9 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type,
|
||||
_type(type),
|
||||
_initSuccess(false),
|
||||
_refreshForced(true),
|
||||
_handle(0) {
|
||||
_handle(0),
|
||||
_version(++_nextGlobalVersion),
|
||||
_isSolid(false) {
|
||||
|
||||
// Renderobject registrieren, abhängig vom Handle-Parameter entweder mit beliebigem oder vorgegebenen Handle.
|
||||
if (handle == 0)
|
||||
@ -106,7 +110,7 @@ RenderObject::~RenderObject() {
|
||||
RenderObjectRegistry::instance().deregisterObject(this);
|
||||
}
|
||||
|
||||
bool RenderObject::render() {
|
||||
bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ) {
|
||||
// Objektänderungen validieren
|
||||
validateObject();
|
||||
|
||||
@ -121,17 +125,39 @@ bool RenderObject::render() {
|
||||
}
|
||||
|
||||
// Objekt zeichnen.
|
||||
doRender();
|
||||
bool needRender = false;
|
||||
int index = 0;
|
||||
|
||||
// Only draw if the bounding box intersects any update rectangle and
|
||||
// the object is in front of the minimum Z value.
|
||||
for (RectangleList::iterator rectIt = updateRects->begin(); !needRender && rectIt != updateRects->end(); ++rectIt, ++index)
|
||||
needRender = (_bbox.contains(*rectIt) || _bbox.intersects(*rectIt)) && getAbsoluteZ() >= updateRectsMinZ[index];
|
||||
|
||||
if (needRender)
|
||||
doRender(updateRects);
|
||||
|
||||
// Dann müssen die Kinder gezeichnet werden
|
||||
RENDEROBJECT_ITER it = _children.begin();
|
||||
for (; it != _children.end(); ++it)
|
||||
if (!(*it)->render())
|
||||
if (!(*it)->render(updateRects, updateRectsMinZ))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderObject::collectRenderQueue(RenderObjectQueue *renderQueue) {
|
||||
|
||||
if (!_visible)
|
||||
return;
|
||||
|
||||
renderQueue->add(this);
|
||||
|
||||
RENDEROBJECT_ITER it = _children.begin();
|
||||
for (; it != _children.end(); ++it)
|
||||
(*it)->collectRenderQueue(renderQueue);
|
||||
|
||||
}
|
||||
|
||||
void RenderObject::validateObject() {
|
||||
// Die Veränderungen in den Objektvariablen aufheben
|
||||
_oldBbox = _bbox;
|
||||
@ -157,6 +183,8 @@ bool RenderObject::updateObjectState() {
|
||||
|
||||
// Die Bounding-Box neu berechnen und Update-Regions registrieren.
|
||||
updateBoxes();
|
||||
|
||||
++_version;
|
||||
|
||||
// Änderungen Validieren
|
||||
validateObject();
|
||||
@ -289,6 +317,13 @@ void RenderObject::setZ(int z) {
|
||||
_z = z;
|
||||
}
|
||||
|
||||
int RenderObject::getAbsoluteZ() const {
|
||||
if (_parentPtr.isValid())
|
||||
return _parentPtr->getAbsoluteZ() + _z;
|
||||
else
|
||||
return _z;
|
||||
}
|
||||
|
||||
void RenderObject::setVisible(bool visible) {
|
||||
_visible = visible;
|
||||
}
|
||||
|
@ -53,6 +53,8 @@ namespace Sword25 {
|
||||
|
||||
class Kernel;
|
||||
class RenderObjectManager;
|
||||
class RenderObjectQueue;
|
||||
class RectangleList;
|
||||
class Bitmap;
|
||||
class Animation;
|
||||
class AnimationTemplate;
|
||||
@ -218,7 +220,10 @@ public:
|
||||
Dieses kann entweder direkt geschehen oder durch den Aufruf von UpdateObjectState() an einem Vorfahren-Objekt.<br>
|
||||
Diese Methode darf nur von BS_RenderObjectManager aufgerufen werden.
|
||||
*/
|
||||
bool render();
|
||||
bool render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ);
|
||||
|
||||
void collectRenderQueue(RenderObjectQueue *renderQueue);
|
||||
|
||||
/**
|
||||
@brief Bereitet das Objekt und alle seine Unterobjekte auf einen Rendervorgang vor.
|
||||
Hierbei werden alle Dirty-Rectangles berechnet und die Renderreihenfolge aktualisiert.
|
||||
@ -230,7 +235,7 @@ public:
|
||||
@brief Löscht alle Kinderobjekte.
|
||||
*/
|
||||
void deleteAllChildren();
|
||||
|
||||
|
||||
// Accessor-Methoden
|
||||
// -----------------
|
||||
/**
|
||||
@ -299,6 +304,9 @@ public:
|
||||
int getZ() const {
|
||||
return _z;
|
||||
}
|
||||
|
||||
int getAbsoluteZ() const;
|
||||
|
||||
/**
|
||||
@brief Gibt die Breite des Objektes zurück.
|
||||
*/
|
||||
@ -352,6 +360,15 @@ public:
|
||||
return _handle;
|
||||
}
|
||||
|
||||
// Get the RenderObjects current version
|
||||
int getVersion() const {
|
||||
return _version;
|
||||
}
|
||||
|
||||
bool isSolid() const {
|
||||
return _isSolid;
|
||||
}
|
||||
|
||||
// Persistenz-Methoden
|
||||
// -------------------
|
||||
virtual bool persist(OutputPersistenceBlock &writer);
|
||||
@ -388,6 +405,13 @@ protected:
|
||||
int _oldZ;
|
||||
bool _oldVisible;
|
||||
|
||||
static int _nextGlobalVersion;
|
||||
|
||||
int _version;
|
||||
|
||||
// This should be set to true if the RenderObject is NOT alpha-blended to optimize drawing
|
||||
bool _isSolid;
|
||||
|
||||
/// Ein Pointer auf den BS_RenderObjektManager, der das Objekt verwaltet.
|
||||
RenderObjectManager *_managerPtr;
|
||||
|
||||
@ -402,7 +426,7 @@ protected:
|
||||
@return Gibt false zurück, falls das Rendern fehlgeschlagen ist.
|
||||
@remark
|
||||
*/
|
||||
virtual bool doRender() = 0; // { return true; }
|
||||
virtual bool doRender(RectangleList *updateRects) = 0; // { return true; }
|
||||
|
||||
// RenderObject-Baum Variablen
|
||||
// ---------------------------
|
||||
|
@ -41,17 +41,37 @@
|
||||
#include "sword25/gfx/timedrenderobject.h"
|
||||
#include "sword25/gfx/rootrenderobject.h"
|
||||
|
||||
#include "common/system.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
void RenderObjectQueue::add(RenderObject *renderObject) {
|
||||
push_back(RenderObjectQueueItem(renderObject, renderObject->getBbox(), renderObject->getVersion()));
|
||||
}
|
||||
|
||||
bool RenderObjectQueue::exists(const RenderObjectQueueItem &renderObjectQueueItem) {
|
||||
for (RenderObjectQueue::iterator it = begin(); it != end(); ++it)
|
||||
if ((*it)._renderObject == renderObjectQueueItem._renderObject &&
|
||||
(*it)._version == renderObjectQueueItem._version)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderObjectManager::RenderObjectManager(int width, int height, int framebufferCount) :
|
||||
_frameStarted(false) {
|
||||
// Wurzel des BS_RenderObject-Baumes erzeugen.
|
||||
_rootPtr = (new RootRenderObject(this, width, height))->getHandle();
|
||||
_uta = new MicroTileArray(width, height);
|
||||
_currQueue = new RenderObjectQueue();
|
||||
_prevQueue = new RenderObjectQueue();
|
||||
}
|
||||
|
||||
RenderObjectManager::~RenderObjectManager() {
|
||||
// Die Wurzel des Baumes löschen, damit werden alle BS_RenderObjects mitgelöscht.
|
||||
_rootPtr.erase();
|
||||
delete _uta;
|
||||
delete _currQueue;
|
||||
delete _prevQueue;
|
||||
}
|
||||
|
||||
void RenderObjectManager::startFrame() {
|
||||
@ -76,7 +96,62 @@ bool RenderObjectManager::render() {
|
||||
_frameStarted = false;
|
||||
|
||||
// Die Render-Methode der Wurzel aufrufen. Dadurch wird das rekursive Rendern der Baumelemente angestoßen.
|
||||
return _rootPtr->render();
|
||||
|
||||
uint32 renderDuration = g_system->getMillis();
|
||||
|
||||
_currQueue->clear();
|
||||
_rootPtr->collectRenderQueue(_currQueue);
|
||||
|
||||
_uta->clear();
|
||||
// Add rectangles of objects which don't exist in this frame any more
|
||||
for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it)
|
||||
if (!_currQueue->exists(*it))
|
||||
_uta->addRect((*it)._bbox);
|
||||
// Add rectangles of objects which are different from the previous frame
|
||||
for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it)
|
||||
if (!_prevQueue->exists(*it))
|
||||
_uta->addRect((*it)._bbox);
|
||||
|
||||
RectangleList *updateRects = _uta->getRectangles();
|
||||
Common::Array<int> updateRectsMinZ;
|
||||
|
||||
updateRectsMinZ.reserve(updateRects->size());
|
||||
|
||||
// Calculate the minimum drawing Z value of each update rectangle
|
||||
// Solid bitmaps with a Z order less than the value calculated here would be overdrawn again and
|
||||
// so don't need to be drawn in the first place which speeds things up a bit.
|
||||
for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
|
||||
int minZ = 0;
|
||||
for (RenderObjectQueue::iterator it = _currQueue->reverse_begin(); it != _currQueue->end(); --it) {
|
||||
if ((*it)._renderObject->isVisible() && (*it)._renderObject->isSolid() &&
|
||||
(*it)._renderObject->getBbox().contains(*rectIt)) {
|
||||
minZ = (*it)._renderObject->getAbsoluteZ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
updateRectsMinZ.push_back(minZ);
|
||||
}
|
||||
|
||||
if (_rootPtr->render(updateRects, updateRectsMinZ)) {
|
||||
// Copy updated rectangles to the video screen
|
||||
Graphics::Surface *backSurface = Kernel::getInstance()->getGfx()->getSurface();
|
||||
for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
|
||||
const int x = (*rectIt).left;
|
||||
const int y = (*rectIt).top;
|
||||
const int width = (*rectIt).width();
|
||||
const int height = (*rectIt).height();
|
||||
g_system->copyRectToScreen(backSurface->getBasePtr(x, y), backSurface->pitch, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
delete updateRects;
|
||||
|
||||
SWAP(_currQueue, _prevQueue);
|
||||
|
||||
renderDuration = g_system->getMillis() - renderDuration;
|
||||
//debug("renderDuration: %3.5f", renderDuration / 1000.0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderObjectManager::attatchTimedRenderObject(RenderObjectPtr<TimedRenderObject> renderObjectPtr) {
|
||||
|
@ -47,11 +47,28 @@
|
||||
#include "sword25/gfx/renderobjectptr.h"
|
||||
#include "sword25/kernel/persistable.h"
|
||||
|
||||
#include "sword25/gfx/microtiles.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
class Kernel;
|
||||
class RenderObject;
|
||||
class TimedRenderObject;
|
||||
class RenderObjectManager;
|
||||
|
||||
struct RenderObjectQueueItem {
|
||||
RenderObject *_renderObject;
|
||||
Common::Rect _bbox;
|
||||
int _version;
|
||||
RenderObjectQueueItem(RenderObject *renderObject, const Common::Rect &bbox, int version)
|
||||
: _renderObject(renderObject), _bbox(bbox), _version(version) {}
|
||||
};
|
||||
|
||||
class RenderObjectQueue : public Common::List<RenderObjectQueueItem> {
|
||||
public:
|
||||
void add(RenderObject *renderObject);
|
||||
bool exists(const RenderObjectQueueItem &renderObjectQueueItem);
|
||||
};
|
||||
|
||||
/**
|
||||
@brief Diese Klasse ist für die Verwaltung von BS_RenderObjects zuständig.
|
||||
@ -114,6 +131,9 @@ private:
|
||||
typedef Common::Array<RenderObjectPtr<TimedRenderObject> > RenderObjectList;
|
||||
RenderObjectList _timedRenderObjects;
|
||||
|
||||
MicroTileArray *_uta;
|
||||
RenderObjectQueue *_currQueue, *_prevQueue;
|
||||
|
||||
// RenderObject-Tree Variablen
|
||||
// ---------------------------
|
||||
// Der Baum legt die hierachische Ordnung der BS_RenderObjects fest.
|
||||
|
@ -59,7 +59,7 @@ private:
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool doRender() {
|
||||
virtual bool doRender(RectangleList *updateRects) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -71,6 +71,8 @@ bool StaticBitmap::initBitmapResource(const Common::String &filename) {
|
||||
// RenderObject Eigenschaften aktualisieren
|
||||
_originalWidth = _width = bitmapPtr->getWidth();
|
||||
_originalHeight = _height = bitmapPtr->getHeight();
|
||||
|
||||
_isSolid = bitmapPtr->isSolid();
|
||||
|
||||
// Bild-Resource freigeben
|
||||
bitmapPtr->release();
|
||||
@ -81,7 +83,7 @@ bool StaticBitmap::initBitmapResource(const Common::String &filename) {
|
||||
StaticBitmap::~StaticBitmap() {
|
||||
}
|
||||
|
||||
bool StaticBitmap::doRender() {
|
||||
bool StaticBitmap::doRender(RectangleList *updateRects) {
|
||||
// Bitmap holen
|
||||
Resource *resourcePtr = Kernel::getInstance()->getResourceManager()->requestResource(_resourceFilename);
|
||||
assert(resourcePtr);
|
||||
@ -98,12 +100,14 @@ bool StaticBitmap::doRender() {
|
||||
result = bitmapResourcePtr->blit(_absoluteX, _absoluteY,
|
||||
(_flipV ? BitmapResource::FLIP_V : 0) |
|
||||
(_flipH ? BitmapResource::FLIP_H : 0),
|
||||
0, _modulationColor, -1, -1);
|
||||
0, _modulationColor, -1, -1,
|
||||
updateRects);
|
||||
} else {
|
||||
result = bitmapResourcePtr->blit(_absoluteX, _absoluteY,
|
||||
(_flipV ? BitmapResource::FLIP_V : 0) |
|
||||
(_flipH ? BitmapResource::FLIP_H : 0),
|
||||
0, _modulationColor, _width, _height);
|
||||
0, _modulationColor, _width, _height,
|
||||
updateRects);
|
||||
}
|
||||
|
||||
// Resource freigeben
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
virtual bool unpersist(InputPersistenceBlock &reader);
|
||||
|
||||
protected:
|
||||
virtual bool doRender();
|
||||
virtual bool doRender(RectangleList *updateRects);
|
||||
|
||||
private:
|
||||
Common::String _resourceFilename;
|
||||
|
@ -129,7 +129,7 @@ void Text::setAutoWrapThreshold(uint autoWrapThreshold) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Text::doRender() {
|
||||
bool Text::doRender(RectangleList *updateRects) {
|
||||
// Font-Resource locken.
|
||||
FontResource *fontPtr = lockFontResource();
|
||||
if (!fontPtr)
|
||||
@ -171,7 +171,7 @@ bool Text::doRender() {
|
||||
|
||||
Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height());
|
||||
renderRect.translate(curRect.left - curX, curRect.top - curY);
|
||||
result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor);
|
||||
result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects);
|
||||
if (!result)
|
||||
break;
|
||||
|
||||
|
@ -136,7 +136,7 @@ public:
|
||||
virtual bool unpersist(InputPersistenceBlock &reader);
|
||||
|
||||
protected:
|
||||
virtual bool doRender();
|
||||
virtual bool doRender(RectangleList *updateRects);
|
||||
|
||||
private:
|
||||
Text(RenderObjectPtr<RenderObject> parentPtr);
|
||||
|
@ -16,6 +16,7 @@ MODULE_OBJS := \
|
||||
gfx/fontresource.o \
|
||||
gfx/graphicengine.o \
|
||||
gfx/graphicengine_script.o \
|
||||
gfx/microtiles.o \
|
||||
gfx/panel.o \
|
||||
gfx/renderobject.o \
|
||||
gfx/renderobjectmanager.o \
|
||||
|
Loading…
x
Reference in New Issue
Block a user