2

I've got an OpenGL application with win32 api without glut etc...and I run into a problem with screen tearing in fullscreen. Basicly I have set WS_POPUP as a window style and resolution of my monitor as window size. I'm running on AMD radeon HD 7770 and I see terrible tearing! When I put WS_POPUPWINDOW style instead of WS_POPUP, the tearing is gone, however I have unwanted border around my scene. Another thing I noticed is fact, that the tearing disappears when the resolution is NOT native. So when I pass my_screen_resolution + 1 as size parameter, the tearing is gone.

RESx = 1920;
RESy = 1080;
hwnd = CreateWindowEx(NULL, NAME, NAME, WS_POPUP, 0, 0, RESx, RESy, NULL, NULL, hInstance, NULL);
SetWindowPos(hwnd, 0, -1, -1, RESx + 1, RESy + 1, 0); // With this function call, the tearing disappears!

What can I do to get rid of the tearing without having to run on not native resolution?

EDIT: (Hint: It's not V-sync)

ProXicT
  • 1,903
  • 3
  • 22
  • 46
  • I don't think you can avoid vsync to get rid of the tearing. There are plenty of potential solutions to limit input lag on the other hand. Like for example, run your app logic at 300 fps but only draw it at 60fps. Try to Google it for more details (or maybe ask another question here). – Jerem May 18 '15 at 08:48
  • I'm updating things on 60FPS and drawing on maximum as possible (I get around 600FPS). I know, I can avoid tearing since the last function (`SetWindowPos(hwnd, 0, -1, -1, RESx + 1, RESy + 1, 0);`) in my post does this. However I think this is not a proper solution. – ProXicT May 18 '15 at 08:53
  • 1
    "Hint: It's not V-sync"... well, thanks for the hint, but it actually is V-sync. The entire purpose of V-sync is to prevent tearing. That's all it does. V-sync does not have any other purpose. – Dietrich Epp May 18 '15 at 10:22
  • @DietrichEpp no, it's only a solution to a quirky problem. just because vsync is meant to prevent tearing, and tearing is his issue, doesn't NECESSARILY mean it's because you need vsync to fix it. because i can solve this just by using width+1 and there's no tearing. i can set the viewport with width and no issue at all. no need for vsync. why only when it maps the exact screen does it tear? an actual reason (answer) perhaps would be that it runs even faster mapped to the exact resolution? and hence vsync is perhaps the only way to solve that? – Puddle Mar 22 '19 at 23:22
  • @Puddle: With width+1 you may be going through the compositor, and maybe that will give you v-sync. – Dietrich Epp Mar 22 '19 at 23:25
  • @DietrichEpp also forgot to mention, if you bring up the start menu it stops tearing as well. simply proving the point that it's not tearing because of that size. so you're supposing it automatically uses vsync when not fullscreen? that might make sense. similar to my assumption that it just goes faster. – Puddle Mar 22 '19 at 23:27
  • @Puddle: What I'm saying is that there are two different ways your graphics end up on the screen. You can draw directly to the screen, or you can draw to an offscreen buffer, which the compositor will then put on the screen. The compositor uses V-sync. So, you will not see tearing when you are going through the compositor. It sounds like you can draw directly to the screen when your window is the exact size of the screen, and when there's nothing on top of your window. Resizing the window or putting something else in front means you are going through the compositor and getting v-sync. – Dietrich Epp Mar 22 '19 at 23:36
  • @DietrichEpp thanks for the quick replies to this old question, i'd be using vsync anyway. i just had to reply to your old response since that didn't quite explain it. the purpose of something that stops tearing is why there's tearing? lol – Puddle Mar 22 '19 at 23:46
  • @Puddle: The purpose of v-sync is to prevent tearing. The reason why there's tearing is because v-sync is off. – Dietrich Epp Mar 23 '19 at 00:00
  • @DietrichEpp oh god. – Puddle Mar 23 '19 at 02:35

2 Answers2

2

What can I do to get rid of the tearing without having to run on not native resolution?

EDIT: (Hint: It's not V-sync)

Yes it is V-Sync.

When you make a fullscreen window, it will bypass the DWM compositor.

If the window is not covering the full screen its contents are going through the DWM compositor. The DWM compositor itself makes itself a copy of the window's contents whenever something indicates, that it is done drawing (return from WM_PAINT handler, EndPaint or SwapBuffers called). The composition itself happens V-synced.

Thanks for your advice, but I want to aviod the tearing without vsync. With vsync I have terrible input lag.

Then you're doing something wrong in your input processing. Most likely your event loop only processes one input event at a time then does a redraw. If that's the case and your scene complexity goes up, then you're getting lag, that's proportional to your scene's drawing complexity. You don't want this to happen.

What you should do is accumulate all the input events that piled up between redraws and coalesce them into a single new drawing state. Ideally input events are collected until only just before the scene is set up for drawing to reflect the most recent state. If you want to get fancy you my add a Kalman filter to predict the input state at the moment the frame gets shown to the user and use that for drawing the scene.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • Thank you! Now I get it. I didn't know about DWM compositor, now it makes sense to me. Thanks for great explanation! :-) – ProXicT May 18 '15 at 10:28
1

To remove OpenGL tearing, you should have "enable" vsync. Follow this link for details: how to enable vertical sync in opengl?

Community
  • 1
  • 1
Ciprian Khlud
  • 434
  • 3
  • 6
  • Thanks for your advice, but I want to aviod the tearing without vsync. With vsync I have terrible input lag. – ProXicT May 17 '15 at 23:54
  • Very probably when you say "tearing dissapears when resolution is not native" is very likely that your video card will be able to touch 60 FPS, and if you don't do it, you will have something like 40-50 which gives the annoying tearing. I would still suggest to setup the swap interval code and make your application "lag aware". Some computers will lag from time to time when running your application, so is better to be prepared in advance. – Ciprian Khlud May 17 '15 at 23:58
  • No, I have about 600FPS – ProXicT May 18 '15 at 00:21
  • 3
    I think Windows prevents tearing when you are in windowed mode or when you can see the desktop behind because in this case your window is drawn by the DWM. Your app runs fast but the DWM only update the window at 60fps. – Jerem May 18 '15 at 08:26
  • That's exactly the type of answer I wanted to hear, thank you a lot for that. I don't know if it is as you say, because when I draw it in fullscreen and expand the window one pixel on each side, the tearing is gone. I've also read, the problem is caused by `WM_POPUP` style set in `CreateWindow` function...indeed when I remove that style, force the window to be in fullscreen (some terrible awful way) - the tearing is gone as well. – ProXicT May 18 '15 at 08:57
  • for anyone else wanting the quick answer `((BOOL(WINAPI*)(int))wglGetProcAddress("wglSwapIntervalEXT"))(1);` – Puddle Mar 22 '19 at 23:52