News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Graphics

Started by Jimg, February 16, 2009, 01:47:52 AM

Previous topic - Next topic

Jimg

Well, getobject didn't work.  It returned everything except bmBits which came back zero.  sigh.

donkey

Hi JimG,

Then you have not passed a valid handle to it, it will not work with a device dependent bitmap only a DIB section created with the CreateDIBSection function.

http://msdn.microsoft.com/en-us/library/aa932477.aspx

QuoteIf hgdiobj identifies a bitmap created by calling CreateDIBSection, and the specified buffer is large enough, the GetObject function returns a DIBSECTION structure. In addition, the bmBits member of the BITMAP structure contained within the DIBSECTION structure will contain a pointer to the bitmap's bit values.

If hgdiobj identifies a bitmap created by any other means, GetObject returns only the width, height, and color format information of the bitmap and the pointer to the bitmap's bit values will be NULL. You can only access the bitmap's bits if they are in a device-independent bitmap.

You can use the BITMAP structure for DIB sections as well, the bmBits will contain the pointer to the bit values.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

NightWare

donkey is right, the difference between DDB and DIB is the informations used, DDB use existing infos (essentially BITMAPINFO structure). DIB use his own informations. but here you have defined only 1 serie... there is a problem somewhere with your speed test...

plus, by looking of Setup1 proc, you create a COMPATIBLE BITMAP, so you know where all infos are, coz a bitmap is composed of [BITMAPFILEHEADER]+[BITMAPINFOHEADER]+[RGBQUAD x dup]+[Pixels]

donkey

This will create a bitmap that can be used with the GetObject function...

CreateIndependantBitmap FRAME hDC,SizeX,SizeY
LOCAL bmi :BITMAPINFO
LOCAL ppvBits :D

mov D[bmi.bmiHeader.biSize],SIZEOF BITMAPINFOHEADER
mov eax,[SizeX]
mov [bmi.bmiHeader.biWidth],eax
mov eax,[SizeY]
mov D[bmi.bmiHeader.biHeight],eax
mov W[bmi.bmiHeader.biPlanes],1
mov W[bmi.bmiHeader.biBitCount],32
mov D[bmi.bmiHeader.biCompression],BI_RGB
invoke CreateDIBSection,[hDC],ADDR bmi,DIB_RGB_COLORS,ADDR ppvBits,NULL,NULL

push eax
invoke GdiFlush
pop eax
ret

ENDF
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Jimg

If you look at the code I posted, I was already using CreateDibSection to create a bitmap.  This is the one I tested against the compatible bitmap.  That's how I discovered how much slower the DIB was.

Mark Jones

Tried sDraw? Nice inc+lib. Ultrano mentioned it was also available on the asmcommunity forum.

http://www.masm32.com/board/index.php?topic=6514.0
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

Jimg

Quote from: NightWare on February 17, 2009, 04:31:52 AM
donkey is right, the difference between DDB and DIB is the informations used, DDB use existing infos (essentially BITMAPINFO structure). DIB use his own informations. but here you have defined only 1 serie... there is a problem somewhere with your speed test...
I don't understand what you mean when you say " here you have defined only 1 serie..."

Quoteplus, by looking of Setup1 proc, you create a COMPATIBLE BITMAP, so you know where all infos are, coz a bitmap is composed of [BITMAPFILEHEADER]+[BITMAPINFOHEADER]+[RGBQUAD x dup]+[Pixels]
When I create a compatible bitmap, all I get back are a handle.  If I feed the handle into GETOBJECT, I get back the correct information as to width,height,type,planes, and bitspixel.  For bmBits, I get back a zero, so I don't know the starting address.

I've come to the conclusion that this is all a colossal waste of time anyway.  If the procedure isn't clearly documented somewhere on MSDN, I don't really want to use it.   I'm sure my tests are correct, if not, please point out the mistaken instructions.  I apologize for my giant mess of a timing test, but it really helped me see what was actually going on.

Anyway, thanks all for your patience and time, I'll go crawl back in my hole now.

japheth

Quote from: Jimg on February 17, 2009, 05:23:50 PM
Quoteplus, by looking of Setup1 proc, you create a COMPATIBLE BITMAP, so you know where all infos are, coz a bitmap is composed of [BITMAPFILEHEADER]+[BITMAPINFOHEADER]+[RGBQUAD x dup]+[Pixels]
When I create a compatible bitmap, all I get back are a handle.  If I feed the handle into GETOBJECT, I get back the correct information as to width,height,type,planes, and bitspixel.  For bmBits, I get back a zero, so I don't know the starting address.
Yes, you won't get a pointer to the pixels of a DDB. AFAIK this is by design, because this abstraction level allowed GDI to support the old 4bit color-plane modes of the EGA/VGA without API extension.

As far as GDI is concerned there is one option which wasn't mentioned so far: one can use the SetDIBitsToDevice() function instead of CreateDIBSection() + BitBlt(). I've seen several programs using it, so I'm sure it isn't anything exotic, but I have no own experiences.


Jimg

p.s.  Thank you Donkey, PatBlt is absolutely faster than FillRect :thumbu

with GdiFlush after each test
        Clocks   Description
Test11  2349     fill background using FillRect with brush
Test12  1650     fill background using PatBlt with brush
Test13  96001    fill background using FillRect with brush on DIB
Test14  89930    fill background using direct access on DIB
Test15  95194    fill background using PatBlt with brush on DIB
Test21  2395     line using FillRect and Brush
Test22  1674     line using PatBlt and Brush
Test23  2228     line using FillRect and Brush on DIB
Test24  1586     line using PatBlt and Brush on DIB


without GdiFlush after each test
        Clocks   Description
Test11  134      fill background using FillRect with brush
Test12  64       fill background using PatBlt with brush
Test13  95720    fill background using FillRect with brush on DIB
Test14  89163    fill background using direct access on DIB
Test15  94868    fill background using PatBlt with brush on DIB
Test21  133      line using FillRect and Brush
Test22  64       line using PatBlt and Brush
Test23  1875     line using FillRect and Brush on DIB
Test24  1263     line using PatBlt and Brush on DIB

MichaelW

Jim,

The reason I asked why use a DIB was that your results show FillRect to be fast with a DDB. How about using a set pixel routine based on FillRect (specifying a one-pixel rectangle) on a DDB? If I assume a worst case of 133 cycles per call, and that the line in your tests is 500 pixels long, the resulting 66500 cycles is more than 11 times faster than using SetPixel on a DDB and more than 6 times faster than using SetPixel on a DIB. And since FillRect runs in 133 cycles for a 500-pixel line it could not have much overhead, so reducing the number of pixels drawn to one should speed it up considerably.

And now that I see your most recent results, read FillRect above as PatBlt.

eschew obfuscation

Jimg

Quote from: MichaelW on February 17, 2009, 06:30:35 PM
Jim,

The reason I asked why use a DIB was that your results show FillRect to be fast with a DDB. How about using a set pixel routine based on FillRect (specifying a one-pixel rectangle) on a DDB? If I assume a worst case of 133 cycles per call, and that the line in your tests is 500 pixels long, the resulting 66500 cycles is more than 11 times faster than using SetPixel on a DDB and more than 6 times faster than using SetPixel on a DIB. And since FillRect runs in 133 cycles for a 500-pixel line it could not have much overhead, so reducing the number of pixels drawn to one should speed it up considerably.

And now that I see your most recent results, read FillRect above as PatBlt.
If I understood your question correctly, the reason, and the only reason I considered using a DIB was to plot irregular curves.  Direct access to a DIB is much, much faster than setpixel in this case.  Every other operation seems to be faster on a DDB.  Since I will also be "plotting" a bunch of grid lines, I was concerned about how much slower it was on a DIB.  In reality, its insignificant if it takes 1800 cycles rather than 134 is for drawing each grid line.  I'm still unhappy that it takes 95000 cycles to fill the background on a DIB vs. worse case 2350 on a DDB, but again, in reality, it will never be noticed.  And I'm still unhappy that it takes 179000 cycles to blit a 100x500 DIB to the dialog vs. worse case 2300 for a DDB, but still again, it will never be noticed.  So what it boils down to, is that I'm letting the raw numbers bother me and not seeing reality.  Yes, DIB's are much slower than DDB's, regardless of what others have tried to tell me, but it Just Doesn't Matter.  If there is some way to make the DIB's faster, or to be able to put directly to a DDB, I would still like to know, but I'm done losing sleep over it :bg

p.s.  I'll run your one pixel test, but I don't have high hopes :wink

pps.  And here's the results
        Clocks   Description
Test31  741509   line using setpixel (on DDB)
Test34  475206   line using PatBlt one pixel at a time in place of setpixel (on DDB)
Test33  2304     line using direct access to bitmap on DIB
So yes, it's good to know that PatBlt is faster than setpixel, thanks.

ppps.  I've updated the test program in my first post for all new tests.

Jimg

I finally ran the tests on my old celeron laptop with minimal memory and graphics card. Unexpectedly, the results were similar to the amd.
cpu1: Mobile Intel(R) Celeron(R) CPU 2.00GHz (Family 15 Model 2 Step 7) SSE2                   
cpu2: AMD Athlon(tm) XP 3000+ (Family 7 Model 10 Step 0) SSE1                                 
                                                                                               
Method: Min                                                                                   
Iterations: 100                                                                               
        Clocks          Description                                                           
        cpu1    cpu2                                                                           
Test1   6640    1417    draw with pen                                                         
Test2   3444    2587    draw with pen on DIB                                                   
Test11  208     135     fill background using FillRect with brush                             
Test12  100     64      fill background using PatBlt with brush                               
Test13  157412  95606   fill background using FillRect with brush on DIB                       
Test14  112884  89161   fill background using direct access on DIB                             
Test15  144776  94870   fill background using PatBlt with brush on DIB                         
Test21  220     134     line using FillRect and Brush                                         
Test22  100     64      line using PatBlt and Brush                                           
Test23  3500    1864    line using FillRect and Brush on DIB                                   
Test24  1944    1258    line using PatBlt and Brush on DIB                                     
Test31  2298796 702092  line using setpixel                                                   
Test32  763076  370507  line using setpixel on DIB                                             
Test33  3992    1510    line using direct access to bitmap on DIB                             
Test34  1691708 477564  line using PatBlt one pixel at a time in place of setpixel             
Test41  5304    1988    bitblt from normal memory dc to dialog dc                             
Test42  325492  188096  bitblt from DIB dc to dialog dc                                       
Test51  127904  31328   DrawText                                                               
Test52  66420   50373   DrawText on DIB                                                       
Test54  1264    960     simple ExtTextOut                                                     
Test55  41984   34932   simple ExtTextOut on DIB                                               
Test57  1244    950     simple TextOut                                                         
Test58  40780   34844   simple TextOut on DIB                                                 
Test63  208     134     fill background using FillRect with brush                             
Test64  132     122     fill background using PatBlt with brush, SelectOBject in timing loop   


My apologies to anyone who downloaded the previous version of the program that didn't print results to the results file.


Jimg

After screwing around for a month and a half, I just discovered this whole thing was a waste of time.

To write directly to a device dependent bitmap, you just get the address and do it.  No need for a dib or dibsection.

Just do a GetObject.  The address of the  bits in in the parameter BITMAP.bmBits

Why didn't anyone tell me this when I was floundering around so badly?

dedndave

I would be interested in seeing some source to plot curves, Jim
I am new to 32-bit and would like to learn from your efforts

Jimg

That's actually my next step.  So far, anything that could go wrong, has.
Every time I run into a problem, it takes days to find a solution.
95% of my time is taken writing 2% of the code.
And EVERY time, it the windows api that is poorly documented or not documented at all.
The other 98% of the code is easy.
The actual graphing should be pretty easy (unless you want alpha blended smooth (blurry) curves  :lol)
I'll certainly post something when I have something worth posting.