Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Resource manager

Credits go to X-G for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
Resource manager
Trezker
Member #1,739
December 2001
avatar

I need a resource manager.
It should handle images, animations, sound and music. Maybe more.

I've been searching for examples but haven't found any really good stuff.
I suspect this requires more than one design pattern to really get a good manager. Thoughts, links and example code, anything is welcome.

ReyBrujo
Moderator
January 2001
avatar

Something like an Allegro datafile?

--
RB
光子「あたしただ…奪う側に回ろうと思っただけよ」
Mitsuko's last words, Battle Royale

X-G
Member #856
December 2000
avatar

Here's the one I use. I'm quite fond of it.

Resource manager:

1////////////////////////////////////////////////////////////////////////////////
2#ifndef __resourcemanager_h__
3#define __resourcemanager_h__
4 
5////////////////////////////////////////////////////////////////////////////////
6#include <string>
7#include <map>
8#include <typeinfo>
9 
10#include "resource.h"
11#include "log.h"
12 
13////////////////////////////////////////////////////////////////////////////////
14typedef std::map<std::string, Resource *> ResourceMap;
15 
16////////////////////////////////////////////////////////////////////////////////
17extern Log gLog;
18 
19////////////////////////////////////////////////////////////////////////////////
20class ResourceManager
21{
22private:
23 ResourceMap resources;
24public:
25 ResourceManager();
26 ~ResourceManager();
27 
28 template <typename T> T *load(std::string fn)
29 {
30 std::string rscname = fn + "*" + typeid(T).name();
31 ResourceMap::iterator iter = resources.find(rscname);
32 if (iter != resources.end())
33 {
34 gLog.log(Log::vDebug, "Retrieved cached resource '%s'", rscname.c_str());
35 return (T*)(iter->second);
36 }
37
38 T *rsrc = new T;
39 if (!rsrc->load(fn))
40 {
41 delete rsrc;
42 return 0;
43 }
44
45 gLog.log(Log::vNotice, "Loaded resource '%s'", rscname.c_str());
46
47 resources[rscname] = rsrc;
48
49 return rsrc;
50 }
51};
52 
53////////////////////////////////////////////////////////////////////////////////
54#endif

1////////////////////////////////////////////////////////////////////////////////
2#include <string>
3#include <map>
4 
5#include "resource.h"
6#include "resourcemanager.h"
7 
8////////////////////////////////////////////////////////////////////////////////
9using namespace std;
10 
11////////////////////////////////////////////////////////////////////////////////
12ResourceManager::ResourceManager()
13{
14}
15 
16////////////////////////////////////////////////////////////////////////////////
17ResourceManager::~ResourceManager()
18{
19 for (ResourceMap::iterator i = resources.begin(); i != resources.end(); ++i)
20 delete (*i).second;
21}
22 
23////////////////////////////////////////////////////////////////////////////////

Resource interface:

1////////////////////////////////////////////////////////////////////////////////
2/*
3*
4*/
5////////////////////////////////////////////////////////////////////////////////
6#ifndef __resource_h__
7#define __resource_h__
8 
9////////////////////////////////////////////////////////////////////////////////
10#include <string>
11 
12////////////////////////////////////////////////////////////////////////////////
13/*
14* Resource interface as implementable by anything you want to load as a resource
15*/
16class Resource
17{
18public:
19 virtual ~Resource() { }
20 virtual bool load(std::string fn) = 0;
21};
22 
23////////////////////////////////////////////////////////////////////////////////
24 
25#endif

Example of a resource:

1/*
2* [ sprite.h ]
3*/
4 
5#ifndef __SPRITE_H__
6#define __SPRITE_H__
7 
8#include <allegro.h>
9#include <vector>
10#include <string>
11 
12#include "vector2d.h"
13#include "region2d.h"
14#include "resource.h"
15 
16class Sprite : public Resource
17{
18protected:
19 class Sequence
20 {
21 public:
22 class Frame
23 {
24 public:
25 vector2i hotspot;
26 region2i region;
27 };
28
29 int fps;
30 std::vector<Frame> frames;
31 };
32
33 std::vector<Sequence> sequences;
34
35 BITMAP *framedata;
36public:
37 Sprite();
38 ~Sprite();
39 
40 bool load(std::string fn);
41 
42 inline BITMAP *getFrameData() { return framedata; }
43 inline unsigned int getSequences() { return sequences.size(); }
44 inline unsigned int getSequenceFrames(unsigned int s) { ASSERT(s < sequences.size()); return sequences[s].frames.size(); }
45 inline unsigned int getSequenceFPS(unsigned int s) { ASSERT(s < sequences.size()); return sequences[s].fps; }
46
47 inline region2i getFrame(unsigned int s, unsigned int f)
48 {
49 ASSERT(s < sequences.size() && f < sequences[s].frames.size());
50 return sequences[s].frames[f].region;
51 }
52 inline vector2i getHotspot(unsigned int s, unsigned int f)
53 {
54 ASSERT(s < sequences.size() && f < sequences[s].frames.size());
55 return sequences[s].frames[f].hotspot;
56 }
57};
58 
59#endif /* __SPRITE_H__ */

1#include <allegro.h>
2#include "sprite.h"
3 
4using namespace std;
5 
6Sprite::Sprite() : framedata(NULL)
7{
8}
9 
10Sprite::~Sprite()
11{
12}
13 
14bool Sprite::load(string fn)
15{
16 PACKFILE *fp;
17 int q;
18 
19 fp = pack_fopen(fn.c_str(), "rb");
20 if (!fp)
21 return false;
22 
23 q = pack_igetw(fp); // magic number - should be 0x1339
24 if (q != 0x1339)
25 {
26 pack_fclose(fp);
27 return false;
28 }
29 int version = pack_getc(fp); // should be 2
30 if (version != 2)
31 return false;
32
33 int flags = pack_igetl(fp);
34
35 // read palette
36 PALETTE pal;
37 if (flags & 0x3 == 0x1)
38 {
39 for (int p = 0; p < 256; p++)
40 {
41 pal[p].r = pack_getc(fp);
42 pal[p].g = pack_getc(fp);
43 pal[p].b = pack_getc(fp);
44 }
45 }
46 
47 // construct frame data
48 int w = pack_igetw(fp);
49 int h = pack_igetw(fp);
50 framedata = create_bitmap(w, h);
51 for (int y = 0; y < h; y++)
52 {
53 for (int x = 0; x < w; x++)
54 {
55 if (flags & 0x03 == 0x01)
56 {
57 int i = pack_getc(fp);
58 putpixel(framedata, x, y, makecol((pal<i>.r << 2) + (pal<i>.r >> 4), (pal<i>.g << 2) + (pal<i>.g >> 4), (pal<i>.b << 2) + (pal<i>.b >> 4)));
59 }
60 else if (flags & 0x03 == 0x02)
61 {
62 }
63 else if (flags & 0x03 == 0x03)
64 putpixel(framedata, x, y, makecol(pack_getc(fp), pack_getc(fp), pack_getc(fp)));
65 }
66 }
67 
68 // load frame data
69 // number of sequences
70 int seqs = pack_igetw(fp);
71 sequences.resize(seqs);
72
73 // load them all
74 for (int s = 0; s < seqs; ++s)
75 {
76 // FPS
77 sequences[s].fps = pack_getc(fp);
78
79 // number of frames
80 int frames = pack_igetw(fp);
81 sequences[s].frames.resize(frames);
82
83 // load frames
84 for (int f = 0; f < frames; ++f)
85 {
86 int x = pack_igetw(fp);
87 int y = pack_igetw(fp);
88 int w = pack_igetw(fp);
89 int h = pack_igetw(fp);
90 sequences[s].frames[f].region = region2i(x, y, w, h);
91 x = pack_igetw(fp);
92 y = pack_igetw(fp);
93 sequences[s].frames[f].hotspot = vector2i(x, y);
94 }
95 }
96 
97 pack_fclose(fp);
98
99 return true;
100}

Usage example:

ResourceManager *gRsrc = new ResourceManager();
Sprite *ninja = gRsrc->load<Sprite>("data/ninja.spr");

It will cache already loaded data and will clean everything up when the ResourceManager dies. Just remember to delete it.

You may ignore references to gLog. Just remove them. This was copied straight from a project so references to other parts of it are still in there.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Trezker
Member #1,739
December 2001
avatar

Thanks X-G! Have a little fluffy dragon. :)

I'm putting it in my old singleton.

Now I just have to make those resources... work, work, work... ::)

[edit]
Wondering why you're doing this...
std::string rscname = fn + "*" + typeid(T).name();

X-G
Member #856
December 2000
avatar

Quote:

Wondering why you're doing this...
std::string rscname = fn + "*" + typeid(T).name();

So that you can load the same file twice as different types. For instance, a .png file might be used as a Texture or a Bitmap or perhaps both in the same program. It would not be good if you loaded it expecting one thing and got something else entirely back.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Trezker
Member #1,739
December 2001
avatar

Ahh, smart. I'll add a comment.

Johan Halmén
Member #1,550
September 2001

How about Grabber?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Years of thorough research have revealed that the red "x" that closes a window, really isn't red, but white on red background.

Years of thorough research have revealed that what people find beautiful about the Mandelbrot set is not the set itself, but all the rest.

Wetimer
Member #1,622
November 2001

So, your resource manager doesn't provide unloading unused objects? All objects are only deallocated at the end?

<code>if(Windows.State = Crash) Computer.halt();</code>

X-G
Member #856
December 2000
avatar

It's very easy to add such functionality. It's not in right now because I don't use it, but absolutely nothing keeps you from implementing it.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Erkle
Member #3,493
May 2003
avatar

Another thing I didn't know you could do with templates:).

Where do the spr files come from? Is it a standard file or is there an editor for it somewhere in the depot?

If the writing above has offended you, you've read it wrong.....fool.
And if you read that wrong it means 'All of the above is opinion and is only to be treated as such.'

X-G
Member #856
December 2000
avatar

It's not standard, it's my own. I would show the code, but it's several files and I'm too tired to do much right now.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Trezker
Member #1,739
December 2001
avatar

Hey, would you like to give me the right to use your code straight off?
It would feel dumb having to rewrite this thing when it's already so good.

X-G
Member #856
December 2000
avatar

Knock yourself out. Use it, change it, just don't say you wrote it. There's more where it came from too, if you'd like.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Richard Phipps
Member #1,632
November 2001
avatar

Keep going and you'll have a plug 'n' play game making kit for us all to use. :)

Trezker
Member #1,739
December 2001
avatar

You don't happen to have a trans+alpha blit function?

As I mentioned in the loadpng thread I want to blit a RGBA with extra trans. As I see it I have to get the pixels from the source, put together their alphavalue with the trans factor and mix them with the destination.

umperio
Member #3,474
April 2003
avatar

Hey Trezker, you're still connected to my IRC channel so you can ask Hammerbear and Zenogais about our resource manager. ;)

X-G
Member #856
December 2000
avatar

Afraid not. I use OpenGL for projects that require that sort of functionality.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

Trezker
Member #1,739
December 2001
avatar

Ok I've written a function now. But I guess it's not the best...
I should use the alpha write thingy so I only need to mess witht he alpha. Now I get all the components just to edit the alpha...

I just gotta figure out how to use the alpha channel...
It would be nice to take the function down to a lower level, but I don't have the knowledge...

1void DrawTransAlpha32(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h, float fact) {
2 /* Clip the image */
3 if (dst_x < 0) {
4 w += dst_x;
5 src_x -= dst_x;
6 dst_x = 0;
7 }
8 if (dst_y < 0) {
9 h += dst_y;
10 src_y -= dst_y;
11 dst_y = 0;
12 }
13 if (dst_x + w >= dst->w)
14 w -= dst_x + w - dst->w;
15 if (dst_y + h >= dst->h)
16 h -= dst_y + h - dst->h;
17 
18 /* Nothing to do? */
19 if (w < 1 || h < 1)
20 return;
21 
22 BITMAP *temp=create_bitmap(w, h);
23 
24 drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
25 
26 for (int y=0; y<src->h; y++) {
27 for (int x=0; x<src->w; x++) {
28 int c = _getpixel32(src, x, y);
29 int r=getr32(c), g=getg32(c), b=getb32(c), a=geta32(c);
30 a=int(a*fact);
31 _putpixel32(temp, x, y, makeacol(r, g, b, a));
32 }
33 }
34 
35 set_alpha_blender();
36 draw_trans_sprite(dst, temp, dst_x, dst_y);
37 
38 destroy_bitmap(temp);
39 solid_mode();
40}

[edit twice]
I've changed the pixel code a little.

  int c=((int *)src->line[y])[x];
  int a=int(geta32(c)*fact);
  a=(c&0xFFFFFF)|a<<24;
  ((int *)temp->line[y])[x]=a;

Some testing has also been performed.
I draw the bitmap and blit to screen, windowed 1024*768.
Using regular blit, ~60 fps.
DrawTransAlpha32, ~50 fps.

That's not so bad imho.

Fladimir da Gorf
Member #1,565
October 2001
avatar

You're creating a bitmap everytime you want to render the bitmap? You could try if this code using MMX gives you better results (I simply added my own blending routines to your function below):

1 
2// If you wish to process multiple pixels at once, use this function... //
3inline unsigned long BlendColorsNoEmms( unsigned long dst, unsigned long src, unsigned long factor ) {
4 static unsigned short INVERT_MASK[4] = { 0x00FF, 0x00FF, 0x00FF, 0x00FF };
5 unsigned long returnParam;
6 factor = 255 - factor;
7 asm(
8 "movd %1, %%mm0\n"
9 "movd %2, %%mm1\n"
10 "pxor %%mm2, %%mm2\n"
11 "punpcklbw %%mm2, %%mm0\n"
12 "punpcklbw %%mm2, %%mm1\n"
13
14 // Get the alpha value //
15 "movd %4, %%mm3\n"
16 "punpcklwd %%mm3, %%mm3\n"
17 "punpcklwd %%mm3, %%mm3\n"
18
19 // (alpha * (source + 255 - dest))/255 + dest - alpha //
20 "paddw (%3), %%mm0\n"
21 "psubw %%mm1, %%mm0\n"
22 "psrlw $1, %%mm0\n"
23 "pmullw %%mm3, %%mm0\n"
24 "psrlw $7, %%mm0\n"
25 "paddw %%mm1, %%mm0\n"
26 "psubw %%mm3, %%mm0\n"
27
28 "packuswb %%mm0, %%mm0\n"
29 "movd %%mm0, %0\n"
30 : "=&a" (returnParam)
31 : "rm" (dst), "rm" (src), "rm" (INVERT_MASK), "rm" (factor)
32 : "memory"
33 );
34 return returnParam;
35}
36 
37 
38// ... but remember to call this one before you use any floats or doubles //
39inline void CallEmms() {
40 asm(
41 "emms\n"
42 );
43}
44 
45 
46// This is a shorthand to blend single pixels at a time //
47inline unsigned long BlendColors( unsigned long dst, unsigned long src, unsigned long factor ) {
48 unsigned long returnParam = BlendColorsNoEmms( dst, src, factor );
49 CallEmms();
50 return returnParam;
51}
52 
53 
54void DrawTransAlpha32(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h, float fact) {
55 /* Clip the image */
56 if (dst_x < 0) {
57 w += dst_x;
58 src_x -= dst_x;
59 dst_x = 0;
60 }
61 if (dst_y < 0) {
62 h += dst_y;
63 src_y -= dst_y;
64 dst_y = 0;
65 }
66 if (dst_x + w >= dst->w)
67 w -= dst_x + w - dst->w;
68 if (dst_y + h >= dst->h)
69 h -= dst_y + h - dst->h;
70 
71 /* Nothing to do? */
72 if (w < 1 || h < 1)
73 return;
74 
75 for (int y=0; y<src->h; y++) {
76 for (int x=0; x<src->w; x++) {
77 unsgined long col = _getpixel32(src, x, y);
78 unsgined long fact = col >> 24;
79
80 _putpixel32( dst, x, y, BlendColorsNoEmms( _getpixel32( dst, col, fact ));
81 }
82 }
83 CallEmms(); // Remember this line after using BlendColorsNoEmms() and you're finished with the rendering!! //
84}

Even if it doesn't make a big difference now (the real CPU power is consumed somewhere else), at least you can use the function more often in your game without a serious slowdown.

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Trezker
Member #1,739
December 2001
avatar

that code has some errors in it.

unsgined two times
and too few arguments to function `long unsigned int BlendColorsNoEmms(long unsigned int, long unsigned int, long unsigned int)'

From this line.
_putpixel32( dst, x, y, BlendColorsNoEmms( _getpixel32( dst, col, fact ));

Fladimir da Gorf
Member #1,565
October 2001
avatar

Ouch, a big, evil copy paste error, and I managed to typo "unsigned" as "unsgined". I also forgot the fundamental: factor = (globalFactor * pixelAlpha) / 255; ;D:P

1 
2inline unsigned long BlendColorsNoEmms( unsigned long dst, unsigned long src, unsigned long factor ) {
3 static unsigned short INVERT_MASK[4] = { 0x00FF, 0x00FF, 0x00FF, 0x00FF };
4 unsigned long returnParam;
5 factor = 255 - factor;
6 asm(
7 "movd %1, %%mm0\n"
8 "movd %2, %%mm1\n"
9 "pxor %%mm2, %%mm2\n"
10 "punpcklbw %%mm2, %%mm0\n"
11 "punpcklbw %%mm2, %%mm1\n"
12
13 // Get the alpha value //
14 "movd %4, %%mm3\n"
15 "punpcklwd %%mm3, %%mm3\n"
16 "punpcklwd %%mm3, %%mm3\n"
17
18 // (alpha * (source + 255 - dest))/255 + dest - alpha //
19 "paddw (%3), %%mm0\n"
20 "psubw %%mm1, %%mm0\n"
21 "psrlw $1, %%mm0\n"
22 "pmullw %%mm3, %%mm0\n"
23 "psrlw $7, %%mm0\n"
24 "paddw %%mm1, %%mm0\n"
25 "psubw %%mm3, %%mm0\n"
26
27 "packuswb %%mm0, %%mm0\n"
28 "movd %%mm0, %0\n"
29 : "=&a" (returnParam)
30 : "rm" (dst), "rm" (src), "rm" (INVERT_MASK), "rm" (factor)
31 : "memory"
32 );
33 return returnParam;
34}
35 
36 
37// ... but remember to call this one before you use any floats or doubles //
38inline void CallEmms() {
39 asm(
40 "emms\n"
41 );
42}
43 
44 
45// This is a shorthand to blend single pixels at a time //
46inline unsigned long BlendColors( unsigned long dst, unsigned long src, unsigned long factor ) {
47 unsigned long returnParam = BlendColorsNoEmms( dst, src, factor );
48 CallEmms();
49 return returnParam;
50}
51 
52 
53void DrawTransAlpha32(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h, float fact) {
54 /* Clip the image */
55 if (dst_x < 0) {
56 w += dst_x;
57 src_x -= dst_x;
58 dst_x = 0;
59 }
60 if (dst_y < 0) {
61 h += dst_y;
62 src_y -= dst_y;
63 dst_y = 0;
64 }
65 if (dst_x + w >= dst->w)
66 w -= dst_x + w - dst->w;
67 if (dst_y + h >= dst->h)
68 h -= dst_y + h - dst->h;
69 
70 /* Nothing to do? */
71 if (w < 1 || h < 1)
72 return;
73 
74 for (int y=0; y<src->h; y++) {
75 for (int x=0; x<src->w; x++) {
76 unsigned long col = _getpixel32(src, x, y);
77 unsigned long fact = (factor * (col >> 24)) >> 8;
78
79 _putpixel32( dst, x, y, BlendColorsNoEmms( _getpixel32( dst, x, y ), col, fact ));
80 }
81 }
82 CallEmms(); // Remember this line after using BlendColorsNoEmms() and you're finished with the rendering!! //
83}

Also, this works only if the destination bitmap is 32-bit as well...

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Trezker
Member #1,739
December 2001
avatar

These were still wrong...
unsigned long col = _getpixel32(src, x, y);
unsigned long fact = int(factor * (col >> 24)) >> 8;

And it doesn't work... it's all black.

Fladimir da Gorf
Member #1,565
October 2001
avatar

Hmm... I was just testing it myself. Let's see where the problem is. It's my bad habit to write a post and edit it over and over, like if I'd save a text document and continue editing it :P

Just be patient ;)

EDIT: When I changed the function header to
void DrawTransAlpha32(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h, int factor )
with factor ranging from 0 to 255, it looks correct.

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

Trezker
Member #1,739
December 2001
avatar

I'm exited to see if it actually is better than my code :)
I bet it is, I just want to see it.

Though when I run it I only get 30 fps, my code gives 50.

Fladimir da Gorf
Member #1,565
October 2001
avatar

OK, see the edit. I bet it should be faster, at least it doesn't need to create a bitmap every call, processes each pixel only once, doesn't use allegro's slow blenders, uses MMX and doesn't need int->float->int conversions for each pixel. I'll test if there's a cause for the slowdown...

EDIT: I tested it and at least in my PC, it was a lot faster, though not several times faster as I would've expected.

EDIT2: OUCH! When I changed my code to use direct bitmap memory access, it became about 4x (!!) faster, taking only 15-20% of the time as your original function (not that it wasn't good code as well). Also, I needed to change "unsigned long" to "unsigned int", maybe because with my 64-bit processor they were 64-bit ints as well and thus slower (?)

1 
2inline unsigned long BlendColorsNoEmms( unsigned int dst, unsigned int src, unsigned int factor ) {
3 static unsigned short INVERT_MASK[4] = { 0x00FF, 0x00FF, 0x00FF, 0x00FF };
4 unsigned long returnParam;
5 factor = 255 - factor;
6 asm(
7 "movd %1, %%mm0\n"
8 "movd %2, %%mm1\n"
9 "pxor %%mm2, %%mm2\n"
10 "punpcklbw %%mm2, %%mm0\n"
11 "punpcklbw %%mm2, %%mm1\n"
12
13 // Get the alpha value //
14 "movd %4, %%mm3\n"
15 "punpcklwd %%mm3, %%mm3\n"
16 "punpcklwd %%mm3, %%mm3\n"
17
18 // (alpha * (source + 255 - dest))/255 + dest - alpha //
19 "paddw (%3), %%mm0\n"
20 "psubw %%mm1, %%mm0\n"
21 "psrlw $1, %%mm0\n"
22 "pmullw %%mm3, %%mm0\n"
23 "psrlw $7, %%mm0\n"
24 "paddw %%mm1, %%mm0\n"
25 "psubw %%mm3, %%mm0\n"
26
27 "packuswb %%mm0, %%mm0\n"
28 "movd %%mm0, %0\n"
29 : "=&a" (returnParam)
30 : "rm" (dst), "rm" (src), "rm" (INVERT_MASK), "rm" (factor)
31 : "memory"
32 );
33 return returnParam;
34}
35 
36 
37// ... but remember to call this one before you use any floats or doubles //
38inline void CallEmms() {
39 asm(
40 "emms\n"
41 );
42}
43 
44 
45// This is a shorthand to blend single pixels at a time //
46inline unsigned long BlendColors( unsigned int dst, unsigned int src, unsigned int factor ) {
47 unsigned long returnParam = BlendColorsNoEmms( dst, src, factor );
48 CallEmms();
49 return returnParam;
50}
51 
52 
53void DrawTransAlpha32(BITMAP *src, BITMAP *dst, int src_x, int src_y, int dst_x, int dst_y, int w, int h, int factor ) {
54 /* Clip the image */
55 if (dst_x < 0) {
56 w += dst_x;
57 src_x -= dst_x;
58 dst_x = 0;
59 }
60 if (dst_y < 0) {
61 h += dst_y;
62 src_y -= dst_y;
63 dst_y = 0;
64 }
65 if (dst_x + w >= dst->w)
66 w -= dst_x + w - dst->w;
67 if (dst_y + h >= dst->h)
68 h -= dst_y + h - dst->h;
69 
70 /* Nothing to do? */
71 if (w < 1 || h < 1)
72 return;
73 
74 for (int y=0; y<h; y++) {
75 unsigned int *srcPtr = ((unsigned int *) src->line[y + src_y]) + src_x;
76 unsigned int *dstPtr = ((unsigned int *) dst->line[y + dst_y]) + dst_x;
77 for (int x=0; x<w; x++) {
78 unsigned long col = *srcPtr;
79 unsigned long fact = (factor * (col >> 24)) >> 8;
80
81 *dstPtr = BlendColorsNoEmms( *dstPtr, col, fact );
82
83 srcPtr++;
84 dstPtr++;
85 }
86 }
87 CallEmms(); // Remember this line after using BlendColorsNoEmms() and you're finished with the rendering!! //
88}

Test results when drawing 1000 quite large bitmaps: Original: 14858 ms New: 2650 ms

OpenLayer has reached a random SVN version number ;) | Online manual | Installation video!| MSVC projects now possible with cmake | Now alvailable as a Dev-C++ Devpack! (Thanks to Kotori)

 1   2 


Go to: