summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIra Rice <irarice@gmail.com>2009-03-17 20:18:41 -0600
committerIra Rice <irarice@gmail.com>2009-03-17 20:18:41 -0600
commit72daf0bf49c0ff994aeff357f6e52140887bce30 (patch)
tree6965511cc5bbede09526c115d43fc1465f39f7de /src
parenta1eb62126bae54557e03682cac70c8331e359e01 (diff)
downloadmana-72daf0bf49c0ff994aeff357f6e52140887bce30.tar.gz
mana-72daf0bf49c0ff994aeff357f6e52140887bce30.tar.bz2
mana-72daf0bf49c0ff994aeff357f6e52140887bce30.tar.xz
mana-72daf0bf49c0ff994aeff357f6e52140887bce30.zip
Added an image merge feature loosely based on a merge function found in
the open source project Wormux. To improve SDL performance, the number of layers that are pushed out to the hardware or software buffers should be reduced, which is where this function comes into play, as it combines two surfaces together so that the number of blit operations is reduced. This function is currently not used, but will be used once a good way to link each of the target systems is determined so that it only initiates when SDL is enabled, as well as making sure that each hook that uses this function is benefiting from it sufficiently. At the moment, it's suspected that the particle engine will likely be the most likely to benefit from this function, followed by tile drawing, then sprite drawing. Signed-off-by: Ira Rice <irarice@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/map.cpp12
-rw-r--r--src/openglgraphics.cpp1
-rw-r--r--src/particle.cpp44
-rw-r--r--src/resources/image.cpp79
-rw-r--r--src/resources/image.h10
5 files changed, 117 insertions, 29 deletions
diff --git a/src/map.cpp b/src/map.cpp
index bda618e2..877a8ba9 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -120,10 +120,8 @@ Image* MapLayer::getTile(int x, int y) const
return mTiles[x + y * mWidth];
}
-void MapLayer::draw(Graphics *graphics,
- int startX, int startY,
- int endX, int endY,
- int scrollX, int scrollY,
+void MapLayer::draw(Graphics *graphics, int startX, int startY,
+ int endX, int endY, int scrollX, int scrollY,
const Sprites &sprites) const
{
startX -= mX;
@@ -164,8 +162,10 @@ void MapLayer::draw(Graphics *graphics,
}
// Draw any remaining sprites
- if (mIsFringeLayer) {
- while (si != sprites.end()) {
+ if (mIsFringeLayer)
+ {
+ while (si != sprites.end())
+ {
(*si)->draw(graphics, -scrollX, -scrollY);
si++;
}
diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp
index 78b502ea..df8d264f 100644
--- a/src/openglgraphics.cpp
+++ b/src/openglgraphics.cpp
@@ -233,7 +233,6 @@ void OpenGLGraphics::drawImagePattern(Image *image, int x, int y, int w, int h)
glColor4ub(mColor.r, mColor.g, mColor.b, mColor.a);
}
-
void OpenGLGraphics::updateScreen()
{
glFlush();
diff --git a/src/particle.cpp b/src/particle.cpp
index e56435ed..0e412ada 100644
--- a/src/particle.cpp
+++ b/src/particle.cpp
@@ -177,7 +177,8 @@ bool Particle::update()
mVelocity *= mBounce;
mVelocity.z = -mVelocity.z;
}
- else {
+ else
+ {
mAlive = false;
}
}
@@ -185,16 +186,12 @@ bool Particle::update()
// Update child emitters
if ((mLifetimePast-1)%Particle::emitterSkip == 0)
{
- for ( EmitterIterator e = mChildEmitters.begin();
- e != mChildEmitters.end();
- e++
- )
+ for (EmitterIterator e = mChildEmitters.begin();
+ e != mChildEmitters.end(); e++)
{
Particles newParticles = (*e)->createParticles(mLifetimePast);
- for ( ParticleIterator p = newParticles.begin();
- p != newParticles.end();
- p++
- )
+ for (ParticleIterator p = newParticles.begin();
+ p != newParticles.end(); p++)
{
(*p)->moveBy(mPos);
mChildParticles.push_back (*p);
@@ -219,7 +216,9 @@ bool Particle::update()
if ((*p)->update())
{
p++;
- } else {
+ }
+ else
+ {
delete (*p);
p = mChildParticles.erase(p);
}
@@ -237,8 +236,7 @@ void Particle::moveBy(const Vector &change)
{
mPos += change;
for (ParticleIterator p = mChildParticles.begin();
- p != mChildParticles.end();
- p++)
+ p != mChildParticles.end(); p++)
{
if ((*p)->doesFollow())
{
@@ -279,20 +277,21 @@ Particle* Particle::addEffect(const std::string &particleEffectFile,
xmlNodePtr node;
// Animation
- if ((node = XML::findFirstChildByName(
- effectChildNode, "animation"))) {
+ if ((node = XML::findFirstChildByName(effectChildNode, "animation")))
+ {
newParticle = new AnimationParticle(mMap, node);
}
// Image
- else if ((node = XML::findFirstChildByName(
- effectChildNode, "image"))) {
+ else if ((node = XML::findFirstChildByName(effectChildNode, "image")))
+ {
Image *img= resman->getImage((const char*)
node->xmlChildrenNode->content);
newParticle = new ImageParticle(mMap, img);
}
// Other
- else {
+ else
+ {
newParticle = new Particle(mMap);
}
@@ -315,7 +314,8 @@ Particle* Particle::addEffect(const std::string &particleEffectFile,
continue;
ParticleEmitter *newEmitter;
- newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap, rotation);
+ newEmitter = new ParticleEmitter(emitterNode, newParticle, mMap,
+ rotation);
newParticle->addEmitter(newEmitter);
}
@@ -326,7 +326,8 @@ Particle* Particle::addEffect(const std::string &particleEffectFile,
}
Particle *Particle::addTextSplashEffect(const std::string &text, int x, int y,
- const gcn::Color *color, gcn::Font *font, bool outline)
+ const gcn::Color *color,
+ gcn::Font *font, bool outline)
{
Particle *newParticle = new TextParticle(mMap, text, color, font, outline);
newParticle->moveTo(x, y);
@@ -344,7 +345,10 @@ Particle *Particle::addTextSplashEffect(const std::string &text, int x, int y,
}
Particle *Particle::addTextRiseFadeOutEffect(const std::string &text,
- int x, int y, const gcn::Color *color, gcn::Font *font, bool outline){
+ int x, int y,
+ const gcn::Color *color,
+ gcn::Font *font, bool outline)
+{
Particle *newParticle = new TextParticle(mMap, text, color, font, outline);
newParticle->moveTo(x, y);
newParticle->setVelocity(0.0f, 0.0f, 0.5f);
diff --git a/src/resources/image.cpp b/src/resources/image.cpp
index 7a15b762..cff40197 100644
--- a/src/resources/image.cpp
+++ b/src/resources/image.cpp
@@ -26,6 +26,7 @@
#include "image.h"
#include "../log.h"
+#include "../position.h"
#ifdef USE_OPENGL
bool Image::mUseOpenGL = false;
@@ -47,8 +48,7 @@ Image::Image(SDL_Surface *image):
}
#ifdef USE_OPENGL
-Image::Image(GLuint glimage, int width, int height,
- int texWidth, int texHeight):
+Image::Image(GLuint glimage, int width, int height, int texWidth, int texHeight):
mGLImage(glimage),
mTexWidth(texWidth),
mTexHeight(texHeight),
@@ -316,6 +316,81 @@ void Image::setAlpha(float a)
}
}
+Image* Image::merge(Image* image, const Position& pos)
+{
+ SDL_Surface* surface = new SDL_Surface(*(image->mImage));
+
+ Uint32 surface_pix, cur_pix;
+ Uint8 r, g, b, a, p_r, p_g, p_b, p_a;
+ double f_a, f_ca, f_pa;
+ SDL_PixelFormat *current_fmt = mImage->format;
+ SDL_PixelFormat *surface_fmt = surface->format;
+ int current_offset, surface_offset;
+ Position offset(0, 0);
+
+ SDL_LockSurface(surface);
+ SDL_LockSurface(mImage);
+ // for each pixel lines of a source image
+ for (offset.x = (pos.x > 0 ? 0 : -pos.x); offset.x < image->getWidth() &&
+ pos.x + offset.x < getWidth(); offset.x++)
+ {
+ for (offset.y = (pos.y > 0 ? 0 : -pos.y); offset.y < image->getHeight()
+ && pos.y + offset.y < getHeight(); offset.y++)
+ {
+ // Computing offset on both images
+ current_offset = (pos.y + offset.y) * getWidth() + pos.x + offset.x;
+ surface_offset = offset.y * surface->w + offset.x;
+
+ // Retrieving a pixel to merge
+ surface_pix = ((Uint32*) surface->pixels)[surface_offset];
+ cur_pix = ((Uint32*) mImage->pixels)[current_offset];
+
+ // Retreiving each channel of the pixel using pixel format
+ r = (Uint8)(((surface_pix & surface_fmt->Rmask) >>
+ surface_fmt->Rshift) << surface_fmt->Rloss);
+ g = (Uint8)(((surface_pix & surface_fmt->Gmask) >>
+ surface_fmt->Gshift) << surface_fmt->Gloss);
+ b = (Uint8)(((surface_pix & surface_fmt->Bmask) >>
+ surface_fmt->Bshift) << surface_fmt->Bloss);
+ a = (Uint8)(((surface_pix & surface_fmt->Amask) >>
+ surface_fmt->Ashift) << surface_fmt->Aloss);
+
+ // Retreiving previous alpha value
+ p_a = (Uint8)(((cur_pix & current_fmt->Amask) >>
+ current_fmt->Ashift) << current_fmt->Aloss);
+
+ // new pixel with no alpha or nothing on previous pixel
+ if (a == SDL_ALPHA_OPAQUE || (p_a == 0 && a > 0))
+ ((Uint32 *)(surface->pixels))[current_offset] =
+ SDL_MapRGBA(current_fmt, r, g, b, a);
+ else if (a > 0)
+ { // alpha is lower => merge color with previous value
+ f_a = (double) a / 255.0;
+ f_ca = 1.0 - f_a;
+ f_pa = (double) p_a / 255.0;
+ p_r = (Uint8)(((cur_pix & current_fmt->Rmask) >>
+ current_fmt->Rshift) << current_fmt->Rloss);
+ p_g = (Uint8)(((cur_pix & current_fmt->Gmask) >>
+ current_fmt->Gshift) << current_fmt->Gloss);
+ p_b = (Uint8)(((cur_pix & current_fmt->Bmask) >>
+ current_fmt->Bshift) << current_fmt->Bloss);
+ r = (Uint8)((double) p_r * f_ca * f_pa + (double)r * f_a);
+ g = (Uint8)((double) p_g * f_ca * f_pa + (double)g * f_a);
+ b = (Uint8)((double) p_b * f_ca * f_pa + (double)b * f_a);
+ a = (a > p_a ? a : p_a);
+ ((Uint32 *)(surface->pixels))[current_offset] =
+ SDL_MapRGBA(current_fmt, r, g, b, a);
+ }
+ }
+ }
+ SDL_UnlockSurface(surface);
+ SDL_UnlockSurface(mImage);
+
+ Image* newImage = new Image(surface);
+
+ return newImage;
+}
+
float Image::getAlpha()
{
return mAlpha;
diff --git a/src/resources/image.h b/src/resources/image.h
index 596917ce..f6b77f26 100644
--- a/src/resources/image.h
+++ b/src/resources/image.h
@@ -41,6 +41,7 @@
#include "resource.h"
class Dye;
+class Position;
class SDL_Rect;
class SDL_Surface;
@@ -132,6 +133,15 @@ class Image : public Resource
static void setLoadAsOpenGL(bool useOpenGL);
#endif
+ /**
+ * Merges two image SDL_Surfaces together. This is for SDL use only, as
+ * reducing the number of surfaces that SDL has to render can cut down
+ * on the number of blit operations necessary, which in turn can help
+ * improve overall framerates. Don't use unless you are using it to
+ * reduce the number of overall layers that need to be drawn through SDL.
+ */
+ Image* merge(Image* image, const Position& pos);
+
protected:
/**
* Constructor.