Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bitblt() is faster then SetDIBitsToDevice()?

1,707 views
Skip to first unread message

asm23

unread,
Sep 19, 2008, 10:05:51 AM9/19/08
to
In my application, I will periodically receive data from an external
device. The data is actually an two dimensional array, and it's storage
structure is just like raster data in an DIB image. such as

row0: RGBRGBRGB......
row1: RGBRGBRGB......
row2: RGBRGBRGB......
......


Now, I have two kinds of method to paint this *raw data* to a window.

I will demonstrate them in pseudo code:

First method, I will call SetDIBitsToDevice() directly.
/////////////////////////////////////////////////////////

int nSize = Rows * Columns * 3;
pBuffer = new char[nSize]; //allocate a buffer
BITMAPINFO bmi;
Fill bmi......

while(bRunning){
ReceiveFromDevice(pBuffer);
SetDIBitsToDevice(
targetDC,
....,
pBuffer,
&bmi,
DIB_RGB_COLORS );
}
////////////////////////////////////////////////////////


Second method, I use a Dibsection
///////////////////////////////////////////////////////

hBitmap = ::CreateDIBSection(...);
BITMAP = GetObject(hBitmap,...);
pBuffer = BITMAP.bmBits; // Get the pointer to buffer

while(bRunning){
ReceiveFromDevice(pBuffer);
CDC dcMem;
dcMem.CreateCompatibleDC(pdc);
dcMem.SelectObject(hBitmap);
pDC->Bitblt(...,&dcMem...);
......
}
//////////////////////////////////////////////////////

I don't know which method is the best, and runs faster?

I do find a web link talk about this issue:
http://msdn.microsoft.com/en-us/library/ms532354(VS.85).aspx

It suggest that bitblt is faster.

"......For example, a multimedia application that combines animated
graphics with sound would benefit from calling the BitBlt function
because it executes faster than SetDIBitsToDevice...."

But I don't know why? Thanks for any suggestions!

Giovanni Dicanio

unread,
Sep 19, 2008, 10:10:58 AM9/19/08
to
I think that in cases like this doing some benchmarking and test is the best
thing to do...

I would like to suggest also to try DirectDraw. DirectDraw can blit 2D
surfaces very fast, e.g. using IDirectDrawSurface::BltFast() method.

Giovanni


"asm23" <asmwa...@gmail.com> ha scritto nel messaggio
news:gb0bik$o1j$1...@aioe.org...

Joseph M. Newcomer

unread,
Sep 19, 2008, 11:51:29 AM9/19/08
to
Has it occurred to you that you can actually *measure* the time yourself?

Look at ::QueryPerformanceCounter and ::QueryPerformanceFrequency.

Why depend on secondary sources when you can get the raw data on your own?
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

asm23

unread,
Sep 19, 2008, 12:35:14 PM9/19/08
to
Joseph M. Newcomer wrote:
> Has it occurred to you that you can actually *measure* the time yourself?
>
> Look at ::QueryPerformanceCounter and ::QueryPerformanceFrequency.
>
Thanks, I think I can test it myself.

> Why depend on secondary sources when you can get the raw data on your own?

Sorry, Joe, I can't understand this sentence above. Do you mean that I
should depend on the source code supplied by the device manufacture?
Actually, they have some sample code that use the "second method of
painting the raw data", But sometimes I think the "first method" is more
simple way.

asm23

unread,
Sep 19, 2008, 12:38:20 PM9/19/08
to
Giovanni Dicanio wrote:
> I think that in cases like this doing some benchmarking and test is the
> best thing to do...
>
> I would like to suggest also to try DirectDraw. DirectDraw can blit 2D
> surfaces very fast, e.g. using IDirectDrawSurface::BltFast() method.
>
> Giovanni
>

Thanks, Giovanni, But I don't know whether learning DirectDraw is as
easy as learning GDI. But I do agree with you that DirectDraw can do it
in a more effective and fast way.

Giovanni Dicanio

unread,
Sep 19, 2008, 1:40:49 PM9/19/08
to

"asm23" <asmwa...@gmail.com> ha scritto nel messaggio
news:gb0kdo$esf$1...@news.cn99.com...

> Thanks, Giovanni, But I don't know whether learning DirectDraw is as easy
> as learning GDI. But I do agree with you that DirectDraw can do it in a
> more effective and fast way.

DirectDraw has a medium-level learning curve, neither trivial nor very
steep.
You should be familiar with COM *basic* concepts (i.e. what a COM interface
is, IUknown, reference counting using AddRef/Release, QueryInterface...);
you don't need to be a COM guru to be able to use DirectDraw in your C++
Win32/MFC apps.

Moreover, I recall that, with DirectX SDK 6, Microsoft provided some helpful
easy-to-use C++ helper classes (CDisplay and CSurface, IIRC), that wrapped
some of COM and DirectDraw lower level aspects, making the C++ development
process easier. Those classes were not adequate for every need, but they
sure were a good start.

However, I would suggest you to measure your performance with your existing
code (as Joe suggested, too): IMHO, if you are satisfied with your GDI code,
then you don't need to try the (harder) DirectDraw path.

Giovanni

Joseph M. Newcomer

unread,
Sep 19, 2008, 8:45:36 PM9/19/08
to
No, I mean that you do something like

LARGE_INTEGER start;
::QueryPerformanceCounter(&start);
... do computation
::QueryPerformanceCounter(&end);

LONGLONG delta = end.QuadPart - start.QuadPart;

do this for two different algorithms (you said you had already written them, so
instrumenting them requires the four lines above!) Look at the results. Make several
measurements and average them, of course.

You can convert the delta from relative information to absolute time by using the value
from QueryPerformanceFrequency.

It has nothing to do with source code or the device manufacturer. It has to do with
actually MEASURING the information you want to get, instead of trying to depend on
"secondary sources" such as Microsoft documentation or "opinions" not backed by actual
measurement information.
joe

asm23

unread,
Sep 21, 2008, 11:07:01 PM9/21/08
to
Joseph M. Newcomer wrote:
> No, I mean that you do something like
>
> LARGE_INTEGER start;
> ::QueryPerformanceCounter(&start);
> ... do computation
> ::QueryPerformanceCounter(&end);
>
> LONGLONG delta = end.QuadPart - start.QuadPart;
>
> do this for two different algorithms (you said you had already written them, so
> instrumenting them requires the four lines above!) Look at the results. Make several
> measurements and average them, of course.
>
> You can convert the delta from relative information to absolute time by using the value
> from QueryPerformanceFrequency.
>
> It has nothing to do with source code or the device manufacturer. It has to do with
> actually MEASURING the information you want to get, instead of trying to depend on
> "secondary sources" such as Microsoft documentation or "opinions" not backed by actual
> measurement information.
> joe
>
Thanks joe!
I have test My code in these two method. And that's the CTimer class I use.
/////////////////////////////////////////////////////
class CTimer
{
private:

LARGE_INTEGER m_base;
LARGE_INTEGER m_temp;
float m_resolution;

public:

CTimer::CTimer()
{
LARGE_INTEGER t_freq;
QueryPerformanceFrequency(&t_freq);
m_resolution = (float) (1.0f / (double) t_freq.QuadPart);
reset();
}

void CTimer::reset()
{
QueryPerformanceCounter(&m_base);
}

inline float time() {
QueryPerformanceCounter(&m_temp);
return (m_temp.QuadPart - m_base.QuadPart) * m_resolution * 1000.0f;
}

};
////////////////////////////////////////////////////////
This is the result on my system:

method 1 (using SetDIBitsToDevice())
the average of painting a 656*490 24bit image is : 1.63ms
method 2 (using bitblt()
the average painting time is : 1.64ms

So, I think they are just in the same speed.^_^.


asm23

unread,
Sep 22, 2008, 4:26:16 AM9/22/08
to
Giovanni Dicanio wrote:
> DirectDraw has a medium-level learning curve, neither trivial nor very
> steep.
> You should be familiar with COM *basic* concepts (i.e. what a COM
> interface is, IUknown, reference counting using AddRef/Release,
> QueryInterface...); you don't need to be a COM guru to be able to use
> DirectDraw in your C++ Win32/MFC apps.
>
> Moreover, I recall that, with DirectX SDK 6, Microsoft provided some
> helpful easy-to-use C++ helper classes (CDisplay and CSurface, IIRC),
> that wrapped some of COM and DirectDraw lower level aspects, making the
> C++ development process easier. Those classes were not adequate for
> every need, but they sure were a good start.
>
> However, I would suggest you to measure your performance with your
> existing code (as Joe suggested, too): IMHO, if you are satisfied with
> your GDI code, then you don't need to try the (harder) DirectDraw path.
>
> Giovanni
>

Thank you, Giovanni. Now, I have finished testing with the measuring
method Joe suggested. I think it is enough to use the GDI specific
code.(I post the result after joe' message)

So I don't decide to start learning DirectDraw. But I'm very appreciate
with your explanation on DirectDraw. I also gain a lot from your reply.

Thanks again!

Joseph M. Newcomer

unread,
Sep 22, 2008, 8:54:49 AM9/22/08
to
VERY GOOD! When in doubt, measure.

I spent 15 years doing performance measurement, and learned that if you ask a programmer
where the performance bottleneck is in the program, you will get the wrong answer. Always.
(In fact, there were never any exceptions to this the whole time I was doing performance
measurement). But once you've measured, you have facts. Then you can make informed
decisions.

Curious: why were you using float? double doesn't cost that much more...and floating
point arithmetic is about the same performance as integer arithmetic on modern processors
(you can measure this, also...except for floating divide, which like integer divide,
always sucks in performance, which is why high-performance floating point algorithms never
divide if they can help it...)
joe

asm23

unread,
Sep 22, 2008, 8:23:54 PM9/22/08
to
Joseph M. Newcomer wrote:
> VERY GOOD! When in doubt, measure.
>
> I spent 15 years doing performance measurement, and learned that if you ask a programmer
> where the performance bottleneck is in the program, you will get the wrong answer. Always.
> (In fact, there were never any exceptions to this the whole time I was doing performance
> measurement). But once you've measured, you have facts. Then you can make informed
> decisions.
>
> Curious: why were you using float? double doesn't cost that much more...and floating
> point arithmetic is about the same performance as integer arithmetic on modern processors
> (you can measure this, also...except for floating divide, which like integer divide,
> always sucks in performance, which is why high-performance floating point algorithms never
> divide if they can help it...)

Thanks Joe.
Your suggestion is constructive. I should use "double" instead of
"float". As I have learned some X86 assemble language, I recalled that
many floating point arithmetic instruction take one or two cycles.
Except the fdiv..(They take about 10 cycles and more)

Joseph M. Newcomer

unread,
Sep 22, 2008, 10:30:35 PM9/22/08
to
Most of the issues about performance of floating point predate the Pentium 4 series of
machines. While Intel doesn't publish instruction timings any longer, remember that on a
3GHz machine, a cycle is 350 picoseconds, so even if your code is saving two cycles, you
are saving less than a nanosecond.
joe

0 new messages