I'm working on a blink comparator, it switches between two images at a set interval for comparison.
The problem is - I'm not able blit the full image fast enough.
The attached program doesn't use actual images, it just blinks between two colors by bliting from one memory dc or the other, one gray, one orange.
.elseif eax==WM_PAINT
inv BeginPaint,hWnd,ADDR ps
mov hdc,eax
neg toggle
.if sign?
inv BitBlt,hdc,0,0,mwidth,mheight,mdc,0,0,SRCCOPY
.else
inv BitBlt,hdc,0,0,mwidth,mheight,mdc2,0,0,SRCCOPY
.endif
inv EndPaint,hWnd,ADDR ps
I've tried all the limited number of things I can find to do with no success.
If you run the program, you will probably be able to see where the vertical retrace occurs. I added Michaels vertical blanking routine. To active it, press a key, to deactivate, press a key again. Activating the retrace code makes the problem stand still on the screen, but it is still there.
What is the proper way to avoid this problem?
.nolist
include \masm32\include\masm32rt.inc
.list
.data?
hInst dd ?
.code
.data
ClassName DB "StdWindow",0
szAppName DB "test",0
align 4
wc WNDCLASS <CS_HREDRAW or CS_VREDRAW,WndProc,0,0,0,0,0,0,0,ClassName>
.data?
message MSG <>
hwindow dd ?
hMenu dd ?
SWidth dd ? ; screen width
SHeight dd ? ; screen height
.code
inv equ invoke
Program:
inv InitCommonControls
inv GetModuleHandle,0
mov hInst,eax
mov wc.hInstance,eax ; save for later
inv LoadIcon, 0, IDI_APPLICATION
mov wc.hIcon,eax
inv LoadCursor, 0, IDC_ARROW
mov wc.hCursor,eax
inv RegisterClass, addr wc
;inv LoadMenu, hInst, MNU
mov hMenu,0;eax
call GetScreenSetup
inv CreateWindowEx,WS_EX_CLIENTEDGE,addr ClassName,addr szAppName,WS_OVERLAPPEDWINDOW,
0,0,SWidth,SHeight,0,hMenu,hInst,0
mov hwindow,eax
inv ShowWindow, hwindow, SW_SHOWNORMAL
inv UpdateWindow, hwindow
.repeat
inv GetMessage,addr message,0,0,0
.break .if !eax
inv TranslateMessage,addr message
inv DispatchMessage,addr message
.until 0
inv ExitProcess,message.wParam
GetScreenSetup proc
inv GetSystemMetrics,SM_CXSCREEN ; screen width
mov SWidth,eax
inv GetSystemMetrics,SM_CYSCREEN
mov SHeight,eax
ret
GetScreenSetup endp
.data?
hWin dd ? ; dialog handle
hdc dd ? ; temp dc of dialog
mdc dd ? ; memory dc of hidden buffer
mdc2 dd ? ; scratch for loading images
hbm1 dd ? ; bitmap for hidden buffer mdc
hbm2 dd ? ; mdc2
crect RECT <>
mwidth equ crect.right ; total width of client rectangle in pixels
mheight equ crect.bottom ; total height in pixels
hbrush1 dd ?
hbrush2 dd ?
usevert dd ?
.data
toggle dd 1
.code
TimerProc proc hwnd,imsg,tid,ctime ; timer callback routine.
inv InvalidateRect,hWin,0,0
ret
TimerProc endp
WndProc Proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
local ps:PAINTSTRUCT
mov eax,uMsg
.if eax==WM_COMMAND
.elseif eax==WM_ERASEBKGND
mov eax,1
jmp WndRet
.elseif eax==WM_LBUTTONDOWN
inv InvalidateRect,hWin,0,0
.elseif eax==WM_PAINT
inv BeginPaint,hWnd,ADDR ps
mov hdc,eax
.if usevert
.if VblankOk
call WaitForVerticalBlank
.endif
.endif
neg toggle
.if sign?
inv BitBlt,hdc,0,0,mwidth,mheight,mdc,0,0,SRCCOPY
.else
inv BitBlt,hdc,0,0,mwidth,mheight,mdc2,0,0,SRCCOPY
.endif
inv EndPaint,hWnd,ADDR ps
.elseif eax==WM_SIZE
.if mdc==0
inv GetClientRect,hWin,addr crect ; get the size needed for the bitmap
inv GetDC,hWin ; get dc's
mov hdc,eax
inv CreateCompatibleDC,hdc ; create dc for hidden buffer
mov mdc,eax
inv SetBkMode,mdc,TRANSPARENT
inv CreateCompatibleBitmap,hdc, mwidth, mheight ; make a hidden buffer of the appropriate size
mov hbm1,eax
inv SelectObject, mdc,hbm1
inv DeleteObject,eax ; delete old bitmap
inv CreateSolidBrush,002492ffh
mov hbrush1,eax
inv SelectObject,mdc,eax
inv CreateCompatibleDC,hdc ; create dc for hidden buffer
mov mdc2,eax
inv SetBkMode,mdc2,TRANSPARENT
inv CreateCompatibleBitmap,hdc, mwidth, mheight ; make a hidden buffer of the appropriate size
mov hbm2,eax
inv SelectObject, mdc2, hbm2
inv DeleteObject,eax ; delete old bitmap
inv CreateSolidBrush,00818181h
mov hbrush2,eax
inv SelectObject,mdc2,eax
inv FillRect,mdc,addr crect,hbrush1
inv FillRect,mdc2,addr crect,hbrush2
inv ReleaseDC,hWin,hdc
inv SetTimer,hWin,999,150,addr TimerProc
.endif
.elseif eax==WM_KEYDOWN
not usevert
.elseif eax==WM_CREATE
m2m hWin,hWnd
call StartDD ; set up for vertical blanking
.elseif eax==WM_DESTROY
inv PostQuitMessage,0
mov eax,wParam
jmp WndRet
.endif
LpExit:
inv DefWindowProc, hWnd, uMsg, wParam, lParam
WndRet:
ret
WndProc endp
;-----code to get vertical blanking to prevent flicker from MichaelW------------
uselib ddraw ; to find vertical blanking to prevent flicker
DDO_GetScanLine EQU 64
DDERR_VERTICALBLANKINPROGRESS EQU ((1 shl 31)or(876h shl 16)or(537))
.data
lpdd_1 dd 0
scanLine dd 0
VblankOk dd 0 ; flag that it is ok to wait for vertical blanking
.code
StartDD proc
invoke DirectDrawCreate,0,ADDR lpdd_1,0 ; Create a default DirectDraw object.
or eax,eax
jnz DDNoGood
call DDGetScanLine ; Make sure DDGetScanLine doesn't have any obvious problems.
or eax,eax
jnz DDNoGood
mov VblankOk,1 ; ok to use
DDNoGood:
ret
StartDD EndP
DDGetScanLine proc
push offset scanLine
push lpdd_1
mov eax, lpdd_1
mov eax, [eax]
call DWORD PTR[eax+DDO_GetScanLine]
ret
DDGetScanLine endp
WaitForVerticalBlank proc
.repeat
call DDGetScanLine
.until eax != DDERR_VERTICALBLANKINPROGRESS
.repeat
call DDGetScanLine
.until eax == DDERR_VERTICALBLANKINPROGRESS
ret
WaitForVerticalBlank endp
end Program
[attachment deleted by admin]
Usually, after I post something like this, a dozen different things occur to me to try. This time, the only thing I can think of is to do true video double buffering like the old days. Perhaps junk gdi entirely and do it in DirectX. Unfortunately, I haven't found any directx double buffering code I could make enough sense of to convert it to masm. How do I set up two actual video buffers and then tell the hardware to just switch, when I want, from one to the other rather then copying all those bits each time?
If I stick with GDI, is there some way to tell a window to use this DC or that DC without blitting?
Perhaps I could make two full windows, and make one or the other visible or not?
Any other ideas?
old ways, are generally better :wink
http://www.masm32.com/board/index.php?topic=10624.0, it's easy to understand (maybe you should transform the calls to standard, for an easier understanding). use SetDIBitsToDevice instead of BitBlt, plus here i use double buffer only for the case where you read data of the current screen (fliker effect here), otherwise with SetDIBitsToDevice there is no flicker effect, so no need of double buffer... AND IT'S FAST !
It's beyond me how SetDIBitsToDevice could possibly be faster than a simple bitblt, but I'll try it. I have to say I'm a little overwhelmed by your code however. Thanks.
Hi Jim,
I've made a simple gradient example before:
http://www.masm32.com/board/index.php?topic=5944.0 (http://www.masm32.com/board/index.php?topic=5944.0)
I think it has a simple double buffering in there. Hopefully, it may help you.
Cheers,
-chris
Thanks gwapo, I'll give it a look.
Okay, I've look the two over.
I don't see how Chris's program helps at all. Now if you could switch between the two screens without tearing, that would help.
NightWare's program is just too much for my old brain to follow at the moment.
I'm going to try SetDIBits from scratch, but if anyone else has suggestions, I'd appreciate it.
According to Microsoft http://msdn.microsoft.com/en-us/library/dd183562(VS.85).aspx,
QuoteTo repeatedly redraw a bitmap in a window, however, the application should use the BitBlt function. For example, a multimedia application that combines animated graphics with sound would benefit from calling the BitBlt function because it executes faster than SetDIBitsToDevice.
Quote from: Jimg on February 27, 2009, 03:52:04 PM
According to Microsoft http://msdn.microsoft.com/en-us/library/dd183562(VS.85).aspx,
QuoteTo repeatedly redraw a bitmap in a window, however, the application should use the BitBlt function. For example, a multimedia application that combines animated graphics with sound would benefit from calling the BitBlt function because it executes faster than SetDIBitsToDevice.
The accent is on repeatedly - for drawing the same unchanged bitmap, BitBlt is probably faster. But if I remember well, you wanted to change the bits, right?
Well, yes, I want to change All the bits repeatedly rather than a small band or rectangle.
I found a post http://www.asmcommunity.net/board/index.php?topic=28403.0
I made a little comparing tool which compares some blit operations, results are:
BitBlt 900
SetDIBitsToDevice 6000
StretchBlt 9000
DrawDIB 50000
Does someone have a SIMPLE example of showing a graphic image in a standard (resizable, movable, titlebar,etc.) window using DirectDraw?
By Simple I mean something less than say 2000 lines of code counting all non-masm32 include files?
If this isn't going to work with standard GDI, I'd better get started learning DirectDraw, but initially, I'm overwhelmed.
I found something that looked promising on Japeth's site (http://www.japheth.de/Download/ShowBmp.zip), but was totally unable to get it to assemble (I don't seem to have dxguid.lib or be able to find it anywhere).
It's been several days and probably 30 hours of searching the web, trying to assemble and run examples, and general frustration. Just as there is something about C that just won't click in my brain, there's something that just won't click about DirectDraw either.
I looked at OpenGL which makes a small bit more sense to me, but I don't see how to flip back and forth between two buffers.
Both are just way, way too much code to accomplish anything in my opinion, and they are just rubbing me the wrong way to the point of needing to scream and pull out my hair.
So I need to decide which one can do what I want and just learn one.
Rather than blitting the whole image each time which doesn't seem to be able to happen before the vertical retrace puts an obvious tear in the picture, at least with GDI, which one is better for creating two images, just flipping back and forth between the two by telling the system just display this one or that one? I wish I could have tested both to see, but I can't get either to work so far.
Just so you know, I'm not trying to hide anything. I agreed to do this simple app for a set amount of money. I was totally surprised that GDI couldn't do something so simple. So I'm going to end up making about $2.00/hour before this is done, and any code or examples or suggestions have to be unencumbered by anti-commercial licensing agreements, a problem with virtually all example OpenGL or Directdraw code I've found.
After I finish this, I'm going to be doing some plotting. Which one is better suited for this, or should I just drop back to GDI?
I really need to pick one. Any suggestions will be greatly appreciated.
:bg last attempt, jimg, severals things...
1. for SetDIBitsToDevice you send a memory area (pixels) + infos (not a DC) to the display (a DC), so you can use your own functions.
for BitBlt you copy a src DC to another DC ! but if you have a DC as src, you MUST use microsoft's APIs (and gdi is well known to be very fast ::) ...) to alterate the content. it's a question a choice.
2. i've no idea of how you DO your speed tests, but here the algos DON'T do the same thing, i even suspect that BitBlt simply swap pointers here, after some test... (so yes it can be fast here, except that you have to use gdi's functions to set/alterate the content, before :lol), plus without infos on the alignment your results are inconsistant.
and i don't speak of the branch/variables that could affect the results...
3. if you want to test speed, mesure the result in FPS (the reality, and for the same visual result, not a black/background screen). note : the fps is NOT the number of screen seen (your gfx board simply can't), but the number of screen you have calculated/made and sent to the display.
4. direct draw also use DC (originally based on gdi), but it's more a rectangular face texturing than a screen draw... and here again, you will be the slave of the dedicated functions.
Quote from: Jimg on February 27, 2009, 07:35:11 PM
By Simple I mean something less than say 2000 lines of code counting all non-masm32 include files
it's the problem ? then why don't you see that as API (temporary) ? when you use gdi functions do you look/examine the algos used ?
Quote from: Jimg on February 26, 2009, 11:06:12 PM
I'm working on a blink comparator
Let me try to understand: A blink comparator is used in astrology for finding moving stars, right? If I remember well, it takes two bitmaps, and they must be drawn on the DC in a given interval. That sounds like a straightforward case for BitBlt... either with two source DCs, or one source DC with two bitmaps selected in alternatively.
So what does make your code so slow? A huge screen resolution?
Regarding the vertical retrace putting a tear in the picture, if you are updating the screen from top to bottom, by starting the update at the correct time, you can have almost two vertical frames to complete the update. As far as I know, that was the purpose of providing GetScanLine. I have never worked this out completely, but I think that by comparing the vertical refresh rate to the update rate you can determine which scan line to start on. If the update moves slower than the vertical scan, then you start the update when the scan reaches the second line from the top. If the update moves faster than the vertical scan, then you start the update somewhere close to the end of vertical blank.
Quote from: Jimg on February 27, 2009, 07:35:11 PM
Does someone have a SIMPLE example of showing a graphic image in a standard (resizable, movable, titlebar,etc.) window using DirectDraw?
By Simple I mean something less than say 2000 lines of code counting all non-masm32 include files?
If this isn't going to work with standard GDI, I'd better get started learning DirectDraw, but initially, I'm overwhelmed.
I found something that looked promising on Japeth's site (http://www.japheth.de/Download/ShowBmp.zip), but was totally unable to get it to assemble (I don't seem to have dxguid.lib or be able to find it anywhere).
dxguid.lib is part of the platform SDK, but you'll find in in Open Watcom as well. However, what's used from this lib is just the DirectDraw2 IID - you can define it on your own in the source and so skip any need for dxguid.lib:
IID_IDirectDraw2 GUID <0B3A6F3E0h,2B43h,11CFh,<0A2h,0DEh,00h,0AAh,00h,0B9h,33h,56h>>
Quote
Just so you know, I'm not trying to hide anything. I agreed to do this simple app for a set amount of money. I was totally surprised that GDI couldn't do something so simple. So I'm going to end up making about $2.00/hour before this is done, and any code or examples or suggestions have to be unencumbered by anti-commercial licensing agreements, a problem with virtually all example OpenGL or Directdraw code I've found.
Don't worry, this DD sample is Public Domain :toothy
Michael-
QuoteRegarding the vertical retrace putting a tear in the picture, if you are updating the screen from top to bottom, by starting the update at the correct time, you can have almost two vertical frames to complete the update. As far as I know, that was the purpose of providing GetScanLine. I have never worked this out completely, but I think that by comparing the vertical refresh rate to the update rate you can determine which scan line to start on. If the update moves slower than the vertical scan, then you start the update when the scan reaches the second line from the top. If the update moves faster than the vertical scan, then you start the update somewhere close to the end of vertical blank.
I am using a 1680 x 1050 screen for my test. With the blit synced to scanline 750, I just start to see a second break at the top of the picture. These two move down the screen as I increase the scanline I sync on, until the bottom one rolls off the bottom (line 1050) at which point there is only one break. Of course, I can't determine the appropriate number in the program since every screen/video card is different.
Ok, re-reading, I see what you are saying about starting from the bottom, but I don't immediately know how to do that with bitblt, and my brain tells me that would cut the available time down to 1/2 frame as me drawing from the bottom collided with the screen refreshing from the top and we met in the middle. I'll have to think a little more about it.
JJ-
QuoteLet me try to understand: A blink comparator is used in astrology for finding moving stars, right? If I remember well, it takes two bitmaps, and they must be drawn on the DC in a given interval. That sounds like a straightforward case for BitBlt... either with two source DCs, or one source DC with two bitmaps selected in alternatively.
So what does make your code so slow? A huge screen resolution?
You are correct. In the initial case, it will be two 1024 x 1024 technical bitmaps, not of stars however, but will be used for many other things as well. Did you try the code I posted above? Do you not get the tearing effect? Is it only my computer that has this problem? How do you load two bitmaps into one DC and switch between them? I missed that API somehow.
Japeth-
Quotedxguid.lib is part of the platform SDK, but you'll find in in Open Watcom as well. However, what's used from this lib is just the DirectDraw2 IID - you can define it on your own in the source and so skip any need for dxguid.lib:
IID_IDirectDraw2 GUID <0B3A6F3E0h,2B43h,11CFh,<0A2h,0DEh,00h,0AAh,00h,0B9h,33h,56h>>
Thank you. I feel much better having that rather than an unknown library from an unknown source. And it actually works! I'll look at it some more when I have more time. Vielen Dank.
NightWare-
Quotewhen you use gdi functions do you look/examine the algos used ?
Actally I did try to trace them. But Microsoft is the only one I have to accept. Everything else I scrutinize mercilessly until I understand it and know exactly what is happening. Which is probably why it takes me so long to do anything.
I'm going to try again in a full implementation and let you know the results. I certainly hope you are right. Basically I only care that it is not obvious visually. And Thank You also for your undeserved patience.
Quote from: Jimg on March 03, 2009, 03:00:17 PM
JJ-
...
Do you not get the tearing effect? Is it only my computer that has this problem?
I see an orange and a grey screen alternating about 4 times a second. Not sure what you mean with "tearing" - the screens look ok, there is a scan line that may be visible for some milliseconds at about 2/3 of the screen, but it might as well be my eyes that produce this effect.
I am a bit surprised why this is so slow: 4 times per second is very slow compared to what you browser has to perform when updating a page.
Quote
How do you load two bitmaps into one DC and switch between them? I missed that API somehow.
Not simultaneously, but you switch your selection: inv SelectObject, mdc2, hbm2
I doubt, though, that it's any faster than using two separate DCs.
That's about right, it's set in the timer-
inv SetTimer,hWin,999,150,addr TimerProc
to 150 ms. Just for this test, it's adjustable in the real program. Set it to 15 ms and the problem should be more visible when not synced to the retrace.
To me, it's really obvious that I'm seeing the top 1/4 in orange and the bottom 3/4's in grey, and on the next paint, it's the top 1/4 in gray and bottom 3/4's in orange.
Windows is doing the screen refresh when the blit has transfered only part of the pixels. By selecting the scan line to sync on, I can get about the top 1/8th in orange, the middle 6/8's in gray and the bottom 1/8th in orange, and just the opposite on the next paint. Very disturbing when your'e trying to detect or compare fine details.
I'll put in the time if necessary to learn directdraw or opengl if I can get assurances one of them is necessary and sufficient. But I'd much prefer to use gdi if I can. I'm going to try NightWare's method next and hope for the best.
OK, I got it. On my screen, the tear is at about 8% from the top, and pretty constant.
Here is a post saying Tearing-free drawing with GDI (http://www.codeproject.com/KB/GDI/tearingfreedrawing.aspx) can be done by exact timing; on the other hand, MSDN says (http://msdn.microsoft.com/en-us/library/aa911354.aspx)
QuoteIn a preemptive multithreaded environment, it is unlikely that the IDirectDraw::WaitForVerticalBlank method can synchronize with the vertical-blank interval. Instead, use appropriate wait flags to time blits and flips
GetVerticalBlankStatus is sometimes mentioned, too. The general idea seems to do the blitting some microseconds before the vertical blank occurs, i.e. to use QPC etc to finetune the start of the BitBlt...
Good luck :thumbu
Thanks. Like I mentioned above, I've tried syncing everywhere throughout the frame, and some places I see two breaks, so there doesn't exist a place where the whole frame can be blitted and displayed using what I doing now.
If the update takes more than two vertical frames, I can't see any way to eliminate the tearing.
Jim, good news: I have tested it on my other puter now, and there is no tear at all. Tell your clients they need a recent model :bg
15 ms it's too low for me (and my puter is only 1 year old...), with 17 or + it's ok...
1000/17=58,82 fps... not enough for your need ?
Mine can't handle it at any speed, it always tears.
Okay, I created a couple of dibsections and drew on them, in this case, I just filled them with color ---
.data?
hWin dd ? ; window handle
hdc dd ? ; temp dc of dialog
dib1 dd ? ; dibs
dib2 dd ?
mbits1 dd 0 ; address of bits
mbits2 dd 0
crect RECT <>
mwidth equ crect.right ; total width of client rectangle in pixels
mheight equ crect.bottom ; total height in pixels
.data
bih BITMAPINFOHEADER <sizeof BITMAPINFOHEADER, \
0, \;biWidth
0, \;biHeight
1, \;biPlanes WORD
32, \;biBitCount WORD
BI_RGB, \;biCompression
0, \;biSizeImage
0, \;biXPelsPerMeter
0, \;biYPelsPerMeter
0, \;biClrUsed
0 > ;biClrImportant
.code
SetupDibs proc
pusha
inv GetClientRect,hWin,addr crect ; get the size needed for the bitmap
inv GetDC,hWin ; get dc's
mov hdc,eax
m2m bih.biWidth,mwidth ; set width and height in bitmapinfoheader
mov eax,mheight
neg eax
mov bih.biHeight,eax
inv CreateDIBSection,hdc,addr bih,DIB_RGB_COLORS,addr mbits1,0,0
mov dib1,eax
inv CreateDIBSection,hdc,addr bih,DIB_RGB_COLORS,addr mbits2,0,0
mov dib2,eax
inv ReleaseDC,hWin,hdc
mov eax,mwidth
imul eax,mheight ; get total number of bits
push eax ; save
mov ecx,eax
mov edi,mbits1
mov eax,002492ffh ; fill with color
rep stosd
pop ecx ; get back total number of bits
mov edi,mbits2
mov eax,00818181h ; fill with color
rep stosd
inv GdiFlush
sdret:
popa
ret
SetupDibs endp
Now to do the SetDIBitsToDevice, I need a BitmapInfo structure.
inv SetDIBitsToDevice,dib1,0,0,mwidth,mheight,0,0,0,mheight,
mbits2,addr bi ,DIB_RGB_COLORS
I can't find how to create a BitmapInfo structure from the DibSection I already have, or alternately, tell SetDIBitsToDevice to just use the section and header.
I'm really struggling over this array of RGBQUAD structure that the system should already know about. What's the best way to get over this next step?
the rgbquad structures are not always exist... it depends if the bitmap use a palette of colors or directly use the colors as pixels.
if you have loaded a bmp file, in BITMAPINFOHEADER.biSize you have SIZEOF BITMAPCOREHEADER if the bmp use a BITMAPINFOHEADER structure, otherwise it use a BITMAPCOREHEADER structure. you just need to get width and height and put them in your BITMAPINFOHEADER to create the appropriate dib.
once you have the width/heidht, you allocate the corresponding mem area (aligned 16, if possible). here you have your pixels area.
once you've made all your manipulation, just send the area to the DC of the display SetDIBitsToDevice,HDC,...
(GetDC from the handler obtained by CreateWindowEx), and use your bih for the bitmapinfo structure, coz here you have defined 32 bits, there is no palette here, so the BITMAPINFO structure it's just a BITMAPINFOHEADER structure, no RGBQUADs
note : keep the HDC you have defined, you define it at the beginnig of the app, and delete it at the end, just before ExitProcess
note2 : why have you created dib sections ? just allocate the memory area for your 2 pixels area, all the infos needed after that are in bih.
note3: no need of GetClientRect, GdiFlush,etc ... coz SetDIBitsToDevice do the FINAL transformation to the DC of the display (including format conversion, if needed...) so you don't need ANY other gdi functions...
Excellent, thanks.
So I got it working, the tearing seems about the same or possibly slightly better, it's hard to tell.
After further testing, I'd say it's about twice as fast. Maybe even fast enough, if I can just figure out which line to sync on for all cases programatically.
edit: removed test, better one below.
haven't tested it yet (i need to make few change to make it work with masm32 v8), but you don't need vertical blanks
I'm still getting significant tearing until I get up to about scan line 300, so I'll need to check the vertical blanking. I have an idea for optimizing it, I'll have to check it out.
Here's an update to the test. It prints out in the title bar of the window, the starting scan line, the ending scanline, and the number of scan lines that it takes to do the SetDIBitsToDevice for each paint.
It increments the starting scan line by 5 for each paint so I can see where the vertical retrace shows up on the screen based on starting scan line. On my computer, it takes about 550 scan lines to do the update, on a 1680 x 1050 screen.
I lowered the delay between paints to 50 ms. to make the progression happen faster.
NightWare-
You have may sincerest apologies for doubting you, and my thanks for your patience. Every test I ran said SetDIBitsToDevice was slower except the one that actually mattered, how it worked on the screen.
[attachment deleted by admin]
On my system, with a 1024x768 screen, it takes only about 30 scan lines to do the update, the tearing starts when the starting scan line reaches about 740, and ends somewhere around 0.
I probably should have added that one reason for the low number of scan lines per update, beyond the lower number of pixels per row, is my 60Hz refresh rate.
796/180, needed 616 (on my fast machine).
The exe hangs apparently, I have to kill it manually.
A tear line slowly meanders down the screen on my AMD x64 4000+/XP SP3/1280x1024 with a GeForce 8600GTS. This rig should easily be able to do 100FPS. Is WaitForScanline not working as expected?
Hi Mark-
No, that is what it is supposed to do. In the title bar, it show what scan line it waited for before starting the setdibitstodevice.
It is incremented each time by 5 scanlines, so you can see what is the optimum scan line to start the drawing operation (when the tear disappears).
Also it shows how many scanlines it took to complete the operation (as long as it doesn't exceed the a full page, it's very crude).
Quote from: Jimg on March 04, 2009, 04:42:04 AM
You have may sincerest apologies for doubting you
:lol not needed, plus it's essential to not blindly trust someone else, especially in asm :wink