• Advertisement

Archived

This topic is now archived and is closed to further replies.

Pixel ploting with Lock() is slow for me :(

This topic is 6205 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi , first im using DX7 im trying to fill my screen with some color , and im trying to do it with pixel ploting with the DX7 Lock() and UnLock() , but for some reason its sooooooo slow and it wont even finish to fill the screen , any ideas what could make it to be very slow? coz by what i have heared , pixel ploting with Lock() should work very fast . thanks a lot

- Goblineye Entertainment

Share this post


Link to post
Share on other sites
Advertisement
Heya Xeno,

Locking and unlocking the surfaces is SsssLLLlllOOOoooWWwww. Avoid it whenever you can. As well as locking and ulocking being slow, it''s also crawling to copy from video memory to system memory (and the other way around.

If you''re going to plot a bunch of pixels, do one lock, plot all of your pixels, and then unlock. If you''re writing an interface to doing all of this, then include a Lock and Unlock call so the user/programmer can do this whenever they need to.

Hope that helps

---
Wait, you mean I have to actually... THINK?!

Share this post


Link to post
Share on other sites
hi random
well , its exactly what im doing , every frame im just calling one time to lock , ploting all the pixels i need , and then unlock , and its still slllllllllllllloooooooooooowwwwwwwwwwwwwww hehe , i dont understnad why


- Goblineye Entertainment

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The pixel plotting functions are slow. You''ll need to find an alternative, or, if you NEED pixel plotting, use ASM to do it. Scaling down the resolution will also speed things up. If you''re running over 640x480, you''re running too high-res for this sort of thing, even if you do write it in ASM.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I just reread your post. If you only want to fill it with a single color then just use BltColorFill. It''s fast.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster

The pixel plotting functions are slow. You''ll need to find an alternative, or, if you NEED pixel plotting, use ASM to do it. Scaling down the resolution will also speed things up. If you''re running over 640x480, you''re running too high-res for this sort of thing, even if you do write it in ASM.


HUH?!?!?!?
by what i know , what u are saying is just cant be , coz , so how the hell windows doing the pixel ploting so fast? and how DDraw doing it so fast?! , by what i know DDraw written in ASM.




- Goblineye Entertainment

Share this post


Link to post
Share on other sites
I did this recently...

Tips:

1. Do your run time RGB conversation at load (i.e. don''t do a RGB conversion for every pixel for every frame...)

2. Use ASM optimised routines... namely memcpy, memset, etc.

3. Don''t do it... using DDraw surfaces and Blt''ing allows for the use of HARDWARE! Thus reducing the load on the cpu




Regards,
Nekosion

Share this post


Link to post
Share on other sites
Nekosion:
first tnx

1. i have a question , did u got it to run fast? , i mean , did u get it to run smoothly every frame? without flicker or something....

2. i didnt understand what u meant in the #3 sentence....


- Goblineye Entertainment

Share this post


Link to post
Share on other sites
I managed to get it to run at about 75 fps (my monitor refresh rate). With the the DDFLIP_NOVSYNC, it got upto 125fps.

It can run quite fast, but generally it''s not fast enough. It all depends on what you want to do. That was basically writing every pixel once on a 800x600 screen, and then 8 more images that were about 200x150 in size on top (using a slower method).

2. If you use DDRAW surfaces, DDRAW automatically utilises the capabilities of the graphics card, taking the burden off of the CPU.



Regards,
Nekosion

Share this post


Link to post
Share on other sites
If you want to fill the screen with a single color, just do a bltcolorfill! Maybe I''m missing something, but why do you need to plot pixels manually, when there''s a DDRAW function that will do what you want, but faster?

If what you mean is you want to get a screen pixel, get a source pixel, multiply or add them, and put that new value on the screen, then you will need to do pixel plotting. Here are two suggestions if that''s the case.

- Don''t use getlockedpixel. Use GetLockedArray.
- Do all your calculations once at load and use lookup tables. For example, instead of keeping your source surface in memory, load each pixel value into an array (maybe seperate R, G, and B arrays) and then unload the surface. This will cut down on the number of locks you need o do each frame.

Share this post


Link to post
Share on other sites
Here's some things that I've found about pixel plotting on a DirectDraw surface (I've been experimenting for a long time):

1. DON'T PLOT VERY MANY PIXELS ON A VIDEO MEMORY SURFACE!!!! Setting pixels in video memory is INCREDIBLY SLOW. If you still want to use video memory, do something like this:

BYTE tmp_line[WIDTH]; // (it's not in video memory)
// for every row: plot pixels to tmp_line and then
// memcpy the pixels back to the surface.

2. Use the correct memory direction. Go across rows and then down columns. Going the other way will go slow.

EX:
------->
------->
------->

Example code:
for (int y=0; y<480; y++) {
for (int x=0; x<640; x++) {
// set a pixel
}
}

Notice that the Y loop is on the outside.

3. If you are using translucency, make a color lookup table. Tell me if you need this because I have code.

4. I haven't used this method much, but if you are setting more than one pixel in a row, use a DWORD size. If normal pixels are 1 BYTE long, plotting a DWORD would set 4 pixels in a row with only one write.

I hope these methods help.

(By the way, getting pixels goes about 1000 times faster than setting them)

Dave2001,
MAILTO(Forrester6@msn.com);


Edited by - Dave2001 on February 19, 2001 2:53:27 PM

Share this post


Link to post
Share on other sites
ok , here the code for my PlotPixel() procedure:


void CGDisplay:lotPixel(int x,int y,COLORREF color)
{

BYTE *tmp_lpSurface;
DWORD offset;
DWORD new_color;
BYTE new_red;
BYTE new_green;
BYTE new_blue;
int bpp;

bpp = lock_info.ddpfPixelFormat.dwRGBBitCount / 8; // get the current bpp
tmp_lpSurface = (BYTE *)lock_info.lpSurface; // get the surface pointer
offset = y * lock_info.lPitch + x * bpp; // calculate the offset
tmp_lpSurface += offset; // go to the desired pixel




/* Color converting */
WORD MaskRBits;
WORD MaskGBits;
WORD MaskBBits;
WORD MaskPosRBits;
WORD MaskPosGBits;
WORD MaskPosBBits;

MaskRBits = GetMaskBitsNum(lock_info.ddpfPixelFormat.dwRBitMask);
MaskGBits = GetMaskBitsNum(lock_info.ddpfPixelFormat.dwGBitMask);
MaskBBits = GetMaskBitsNum(lock_info.ddpfPixelFormat.dwBBitMask);

MaskPosRBits = GetMaskPos(lock_info.ddpfPixelFormat.dwRBitMask);
MaskPosGBits = GetMaskPos(lock_info.ddpfPixelFormat.dwGBitMask);
MaskPosBBits = GetMaskPos(lock_info.ddpfPixelFormat.dwBBitMask);

new_red = GetRValue(color) >> (8 - MaskRBits);
new_green = GetGValue(color) >> (8 - MaskGBits);
new_blue = GetBValue(color) >> (8 - MaskBBits);

new_color = (new_color & (~lock_info.ddpfPixelFormat.dwRBitMask)) | (new_red << MaskPosRBits);
new_color = (new_color & (~lock_info.ddpfPixelFormat.dwGBitMask)) | (new_green << MaskPosGBits);
new_color = (new_color & (~lock_info.ddpfPixelFormat.dwBBitMask)) | (new_blue << MaskPosBBits);
/* End color conversation */

memcpy(tmp_lpSurface,(LPVOID)&new_color,sizeof(bpp)); // Put the new pixel

}



And im getting from it just 0-3 FPS!!!! , im just calling Lock() one time in every frame , and then call PlotPixel as many as i need.


- Goblineye Entertainment

Share this post


Link to post
Share on other sites
Holy shit! No wonder. All that code is getting called for every single pixel.
All of the colours should be pre-calculated for the surface.
memcpy should be replaced with a single write to memory
Calculating the memory address can also be pre-calculated

But the best speed up will be not to use a plotpixel routine in the first place. Just write your code to go direct to the surface memory incrementally (i.e. horizontal scanlines) if possible, and write the maximum amount you can in one go (i.e. a DWORD for non-MMX machines).

Share this post


Link to post
Share on other sites
Plotting single pixels like that won''t do any good. You are doing way too much in that function. You shouldn''t even be using a seperate function in the first place because it will slow it down. Calling functions takes longer than you think. Anyway, for filling the screen with a color, don''t set each individual pixel. Use Blt with DDBLT_COLORFILL. Once you get to something practical to do pixel setting on, tell me and I will give you some optimized code.

Also, doing pixel plotting, don''t convert colors. That is a really bad idea. You should load the surfaces into the correct bit depth from the start.

Dave2001,
MAILTO(Forrester6@msn.com);

Share this post


Link to post
Share on other sites
You guys dont get my point
sure i know i can fill the screen with Blt() and everything.

the reason im filling the screen with PlotPixel() is just to check the speed of the function

ok , i''ll try to do what u told , hopes it will work


- Goblineye Entertainment

Share this post


Link to post
Share on other sites
well , i tried to calculate the colors before the call to Lock() and PlotPixel() and everything... and its dont seem to help a lot , now i get 5 FPS , hehe


- Goblineye Entertainment

Share this post


Link to post
Share on other sites
If you really want to use a putpixel routine, then try writing one for a specific bit depth.
e.g. for 16 bit

WORD *wscrptr;
WORD *wscrptrLookup[screenHeight];

putpixel(int x, int y, WORD data)
{
wscrptr = wscrptrLookup[y] + x;
*wscrptr = data;
}

fill wscrptrLookup with the addresses of the screen for the start of each scanline.

This is by no means the fastest way, but much more like what you should be using.

And there''s probably bugs, I''ve been doing JAVA for a while, so I might have got my C crossed.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonypous Moster

This is by no means the fastest way, but much more like what you should be using.




i still dont see whats so slow in my function if i removing the color convertion part....




- Goblineye Entertainment

Share this post


Link to post
Share on other sites
Ok, here''s my 2 cents.

You are using OOP, right? In that case you could take advantage of polymorphism and write a separate setpixel for the different pixel formats. Then you could minimize your setpixel routine to just a few rows.

// 8 bit version
surface_8[x_pos + y_pos * surface_pitch] = color;

// 16 bit 5:6:5 version
surface_16[x_pos + y_pos * surface_pitch * 0.5] = (red << 11) | (green << 6) | blue;

// 32 bit 8:8:8:8 version
surface_8[x_pos + y_pos * surface_pitch * 4] = (red << 24) | (green << 16) | (blue << 8);

I''m not saying that this is a very fast method (ASM is prefered), but I bet it is faster than that huge function you supplied =)

// Poppeman

Share this post


Link to post
Share on other sites
quote:
Original post by Xeno

i still dont see whats so slow in my function if i removing the color convertion part....



Just take a look at what it''s doing. It''s calling memcpy for one thing just to write a couple of bytes!
Then there''s all that casting and multiplying and stuff at the start.
The more things you do, the longer it will take, that''s why my demo function was made small. There''s (roughly speaking) one read (which may or may not be faster as a calculation), one write and an add. It probably an order of magnitude faster than yours.

Share this post


Link to post
Share on other sites
You need to Lock and Unlock the surface only one time. When you have the pointer (it´s hard for me to explain in english) you can change the memory all time. Only call "WORD memory = (WORD *)DDSurfDesc.lpSurface;" and then you can change the memory. But on my computer it produced a mistake when fliping (the VSync I think) so you may need to use Blt or BltFast

Share this post


Link to post
Share on other sites
This is how I plot pixels in DX7-

  
//Lock Back-buffer

gpDDSBackBuffer->Lock ( NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL );

// Get pointer to Back-Buffer and pitch

video_buffer = ( USHORT * ) ddsd.lpSurface;
words_per_line = ( ddsd.lPitch >> 1);

...and then to plot a pixel-

int offset = x + ( y * words_per_line );
*(video_buffer + offset) = color;

...and DX7 has the D3DRGB macro to build your RGB color.

Share this post


Link to post
Share on other sites
I worked with this when I used DX7. I didn''t do anything special really and it was quite fast. Try using a profiler to see whats slowing it all down. Other then that I can just tell you to do everything in system memory then once each frame lock, copy the whole sysmem-buffer to vidmem and finally unlock. Maybe someone told you or you''re already doing that. I didn''t read ALL the replies

Share this post


Link to post
Share on other sites
Ok , now it really start to piss me off , i made the function to look like that:



void CGSurface:lotPixel(int x,int y,COLORREF color)
{
DWORD offset;
int bpp;

bpp = lock_info.ddpfPixelFormat.dwRGBBitCount >> 3; // get the current bpp
offset = y * lock_info.lPitch + x * bpp; // calculate the offset
*(LPDWORD)((DWORD)lock_info.lpSurface + offset) = color;
}



and i still get just 8 - 9 FPS!!!!
and im calling Lock() just ONE time every frame and im ploting the pixels to a system memory surface , what the hell im doing wrong?
maybe its just slow as it is? i dont understand

plz , can someone post his own code? , or post a link to a source code that he made for ploting pixels?

thanks.


- Goblineye Entertainment

Edited by - xeno on February 20, 2001 2:44:51 PM

Share this post


Link to post
Share on other sites

  • Advertisement