473,378 Members | 1,156 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Templates in blitter functions

Hi all,

Last year I posted a message regarding templates use in blitter functions, but
the single answer I got didn't help.

My problem is that I was writing blitter functions which takes a "Flag"
argument which may radically change the behavior of a function. I have read
that the best way to handle this particular issue was with meta-programming
using templates, as can be read on this page:

http://www.gapidraw.com/gapidraw-features.php
(in the section about templates)

I must now continue that project and I am faced with that same old problem with
an even larger increase in complexity. The number of possible flags for the
main "BltFast()" function alone is around 10, meaning that I either bloat and
slow the inner loop with tons of if/then/else, or I find a new way to manage
the complexity.

I'm working for devices with a very limited CPU in term of speed, so every
cycle count. Are templates a way to solve my problem?

Any information would be welcome. I spent quite a bit of time investigating
this, but still have no idea how templates can help me in this case.

--Eric
May 5 '06 #1
5 2242
On Thu, 04 May 2006 19:56:42 -0500, Eric Fortier wrote:
Hi all,

Last year I posted a message regarding templates use in blitter functions, but
the single answer I got didn't help.

My problem is that I was writing blitter functions which takes a "Flag"
argument which may radically change the behavior of a function. I have read
that the best way to handle this particular issue was with meta-programming
using templates, as can be read on this page:

http://www.gapidraw.com/gapidraw-features.php
(in the section about templates)

I must now continue that project and I am faced with that same old problem with
an even larger increase in complexity. The number of possible flags for the
main "BltFast()" function alone is around 10, meaning that I either bloat and
slow the inner loop with tons of if/then/else, or I find a new way to manage
the complexity.

I'm working for devices with a very limited CPU in term of speed, so every
cycle count. Are templates a way to solve my problem?


Are you familiar with the idea of a code smell[0]? Having one method do
more than one thing based on a flag value is a code smell. It doesn't
mean the design is wrong in and of itself, but it's a really good
indicator.

Without seeing any actual code, the number of suggestions anyone can offer
is strongly limited, but here's an idea:

Break the BltFast function into independent functions that perform one
part of the blt process and have no flags at all. Then consider either
the Decorator[1] or the Template Method[2] pattern for controlling which
of or which group of individual functions are composed into the final
function.

[0] <http://c2.com/cgi/wiki?CodeSmell>
[1] <http://c2.com/cgi/wiki?DecoratorPattern>
[2] This has nothing to do with C++ templates. See
<http://c2.com/cgi/wiki?TemplateMethodPattern>
May 5 '06 #2
Hi Owen, thanks for your reply.
Are you familiar with the idea of a code smell[0]? Having one method do
more than one thing based on a flag value is a code smell. It doesn't
You are right. I'm looking into cleaning that code.

Without seeing any actual code, the number of suggestions anyone can offer
is strongly limited.
Ok, here are a few examples (minus any setup code).

Normal (source copy) Blt loop:

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{
lpDest[x] = lpSrc[x];
}
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

Now a Blit with source color keying:

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{
if( ColorKey != lpSrc[x] )
{
lpDest[x] = lpSrc[x];
}
}
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

Now an Alpha blit:

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{
if( Alpha != 0 )
{
lpDest[x] = CALCULATE_ALPHA( src, dest );
}
}
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

(this is all unoptimized code for better understanding what it does)

Now, you can combine alpha with color keying which leads to one more if() check
in the inner loop. I am asked to add at least two other draw mode (multiply &
invert) that also must combine with normal, color keying and alpha blending.

The number of loops is quickly getting out of control. And this is without
mentioning the setup code which also weights in (in term of if()s).

And replicating code all over the place is also a smell I don't like! The
reason I use flags is to get an interface that closely mimics DirectX and other
graphics library which also use such an interface.

Break the BltFast function into independent functions that perform one
part of the blt process and have no flags at all. Then consider either
the Decorator[1] or the Template Method[2] pattern for controlling which
of or which group of individual functions are composed into the final
function.


I'd look into that but I can't view the pages you provided in either IE or
Firefox.

Thanks again,

--
Eric Fortier

May 5 '06 #3
On Thu, 04 May 2006 21:43:44 -0500, Eric Fortier wrote:
Without seeing any actual code, the number of suggestions anyone can offer
is strongly limited.
Ok, here are a few examples (minus any setup code).

Normal (source copy) Blt loop:

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{


/* Pixel function--> */
lpDest[x] = lpSrc[x];
/* <--Pixel function */
}
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

Now a Blit with source color keying:

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{
/* Pixel function--> */
if( ColorKey != lpSrc[x] )
{
lpDest[x] = lpSrc[x];
}
/* <--Pixel function */
}
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

Now an Alpha blit:

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{ /* Pixel function --> */ if( Alpha != 0 )
{
lpDest[x] = CALCULATE_ALPHA( src, dest );
} /* <-- Pixel function */ }
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

(this is all unoptimized code for better understanding what it does)

Now, you can combine alpha with color keying which leads to one more if() check
in the inner loop. I am asked to add at least two other draw mode (multiply &
invert) that also must combine with normal, color keying and alpha blending.


I've added /* Pixel function--> */ /* <--Pixel function */ markers to the
code to demarcate the parts of the three loops that are different. You
could write all three as

for( int y=0 ; y<h ; ++y )
{
for( int x=0 ; x<w ; ++x )
{
pixelFunction (lpDest[x], lpSource[x]);
}
lpDest += nPitchY;
lpSrc += nSrcWidth;
}

Then the question is, what type is pixelFunction? I did a bit of
experimentation and came up with something that both works and allows for
stateful functions like your alpha conversion function, which rely on
information specific to the function.

// BEGIN blitter.cpp
#include <iostream>

void passthrough (int &dest, const int &src) {
dest = src;
}

void invert (int &dest, const int &src) {
dest = ~src;
}

struct adder {
adder (int c):
constant (c)
{}

void operator () (int &dest, const int &src) {
dest = src + constant;
}

private:
const int constant;
};

template<typename Filter>
void arrayblit (int dest[], const int src[], std::size_t ints, Filter f) {
for (int i = 0; i < ints; ++i)
f(dest[i], src[i]);
}

int main () {
int src[] = {1, 2, 3, 4, 5};
int copied[5];
int flipped[5];
int added[5];

arrayblit (copied, src, 5, passthrough);
arrayblit (flipped, src, 5, invert);
arrayblit (added, src, 5, adder(2));

for (int i = 0; i < 5; ++i)
std::cout << src[i] << '\t'
<< copied[i] << '\t'
<< flipped[i] << '\t'
<< added[i] << std::endl;
}
// END blitter.cpp

With a bit of prodding I was able to get g++ to inline the first two pixel
functions into the template instantiations rather than invoking the pixel
function through a function pointer.
Break the BltFast function into independent functions that perform one
part of the blt process and have no flags at all. Then consider either
the Decorator[1] or the Template Method[2] pattern for controlling
which of or which group of individual functions are composed into the
final function.


I'd look into that but I can't view the pages you provided in either IE
or Firefox.


Weird. The c2 wiki contains the simplest HTML you'll probably find on the
internet at large. Any sign of an error message so I can at least let
them know what's wrong?

May 5 '06 #4
Owen,
Then the question is, what type is pixelFunction? I did a bit of
experimentation and came up with something that both works and allows for
stateful functions like your alpha conversion function, which rely on
information specific to the function.
I had to look at your code quite a bit in order to understand it. Since you
came up with this code on your own it's pretty clear that your skills surpass
mine by a fair bit.

void operator () (int &dest, const int &src)
I didn't knew you could override the function operator!

template<typename Filter>


And I sure didn't knew you could do THAT with templates.

After a bit of retooling, I was able to write a blit function that takes a
pixel shader class as input and have that shader inlined into the main loop. I
can now call the blit function like this:

ShaderBlit( CInvertPixelsShader(), x, y, Surface, Rect, Flags );

I can pass whatever arguments I need into the shader class and that ends up
inlined into the blit function too.

And along the way I was able to get rid of a whole level of abstraction into my
graphics engine. Thanks for taking some of your time on this, it helped me
solve a problem and learn quite a few things.

I'd look into that but I can't view the pages you provided in either IE
or Firefox.


Weird. The c2 wiki contains the simplest HTML you'll probably find on the
internet at large. Any sign of an error message so I can at least let
them know what's wrong?


I just get a blank white page in both browser and the page source is empty. I
don't have problems browsing anywhere else. Pretty weird.

Thanks again.

--
Eric Fortier

May 5 '06 #5
On Fri, 05 May 2006 00:26:27 -0500, Eric Fortier wrote:
void operator () (int &dest, const int &src)
I didn't knew you could override the function operator!


Oh, indeed. Functors -- objects that act like functions -- are incredibly
useful for a lot of things, not least STL-heavy programming. Most STL
algorithms take a function or functor.
After a bit of retooling, I was able to write a blit function that takes
a pixel shader class as input and have that shader inlined into the main
loop. I can now call the blit function like this:

ShaderBlit( CInvertPixelsShader(), x, y, Surface, Rect, Flags );

I can pass whatever arguments I need into the shader class and that ends
up inlined into the blit function too.
I see you still have 'Flags' as an argument; I assume this pattern lets
you reduce the number of flags but not, so far eliminate them entirely?
I'd be interested in seeing what else the flags control that could be
turned into a strategy function/functor.
And along the way I was able to get rid of a whole level of abstraction
into my graphics engine. Thanks for taking some of your time on this, it
helped me solve a problem and learn quite a few things.


No problem. It was an interesting challenge, actually; my own template
metaprogramming skills are a bit weak. Normally I'd implement this
pattern with an abstract base class for the functor interface and an
instance pointer/reference as an argument, because I'd find it clearer,
but for speed-intensive applications a version that's nearly as readable
that can be inlined by the compiler is handy.

Thanks for giving me the idea!
May 6 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Senthilraja | last post by:
I have the following program using templates. Someone please let me know the syntax to be used for defining the member functions push, pop etc. as non-inline functions. #include <iostream>...
5
by: Ray Gardener | last post by:
Would templates be necessary if C++ had all numeric types inherit from a base "number" class and had all types inherit from a base "object" class? (Sorry if this has already been discussed to...
2
by: kelvSYC | last post by:
I'm trying to program something along the lines of a "trading card" idea: I have a single copy of the "card" in the program, yet there may be multiple "instances" of the "card", with differing...
16
by: WittyGuy | last post by:
Hi, What is the major difference between function overloading and function templates? Thanks! http://www.gotw.ca/resources/clcm.htm for info about ]
11
by: Elpoca | last post by:
Hi: What rules govern the inlining of templated functions and templated class methods? It has always been my understanding that both templated functions and templated class methods were...
28
by: NewToCPP | last post by:
Hi, I am just trying to find out if there is any strong reason for not using Templates. When we use Templates it is going to replicate the code for different data types, thus increasing the...
2
by: jaggomiken | last post by:
Hi all, I'm working on a video acquisition project for industrial application. I need to capture, save and show 80 frames per second 800x1024 pixels YUV420/422 and RGB24 images. We are planning to...
3
by: Steven T. Hatton | last post by:
Has anybody here used explicit instantiation of templates? Has it worked well? Are there any issues to be aware of? -- NOUN:1. Money or property bequeathed to another by will. 2. Something...
104
by: JohnQ | last post by:
Well apparently not since one can step thru template code with a debugger. But if I was willing to make the concession on debugging, templates would be strictly a precompiler thing? I have a...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.