Skip to content

Commit

Permalink
Fix rendering artifacts (#215)
Browse files Browse the repository at this point in the history
* Consider SDL.TextEditingEvent as an action event

* When a frame requires rendering, make sure the next one is also rendered to avoid artifacts. It still does not render every frame

* Fix lint

* Fix typo

* Update Changelog
  • Loading branch information
fjvallarino committed Oct 31, 2022
1 parent ba4da4b commit d1ddcc2
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 7 deletions.
11 changes: 11 additions & 0 deletions ChangeLog.md
@@ -1,3 +1,14 @@
## 1.5.1.0

### Fixed

- Fix rendering artifacts ([PR #215](https://github.com/fjvallarino/monomer/pull/215)).

### Changed

- Add "examples" flag to optionally build examples and tutorials ([PR #218](https://github.com/fjvallarino/monomer/pull/218)).
- Use pkg-config for glew linking ([PR #219](https://github.com/fjvallarino/monomer/pull/219)).

## 1.5.0.0

### Added
Expand Down
1 change: 1 addition & 0 deletions src/Monomer/Event/Core.hs
Expand Up @@ -36,6 +36,7 @@ isActionEvent :: SDL.EventPayload -> Bool
isActionEvent SDL.MouseButtonEvent{} = True
isActionEvent SDL.MouseWheelEvent{} = True
isActionEvent SDL.KeyboardEvent{} = True
isActionEvent SDL.TextEditingEvent{} = True
isActionEvent SDL.TextInputEvent{} = True
isActionEvent _ = False

Expand Down
33 changes: 27 additions & 6 deletions src/Monomer/Main/Core.hs
Expand Up @@ -270,6 +270,7 @@ mainLoop window fontManager config loopArgs = do
inputStatus <- use L.inputStatus
mousePos <- liftIO $ getCurrentMousePos epr
currWinSize <- liftIO $ getViewportSize window dpr
prevRenderNeeded <- use L.renderRequested

let Size rw rh = windowSize
let ts = startTs - _mlFrameStartTs
Expand Down Expand Up @@ -331,6 +332,8 @@ mainLoop window fontManager config loopArgs = do
| otherwise = Seq.Empty
let baseStep = (wenv, _mlWidgetRoot, Seq.empty)

L.renderRequested .= False

(rqWenv, rqRoot, _) <- handleRequests baseReqs baseStep
(wtWenv, wtRoot, _) <- handleWidgetTasks rqWenv rqRoot
(seWenv, seRoot, _) <- handleSystemEvents wtWenv wtRoot baseSystemEvents
Expand All @@ -346,11 +349,11 @@ mainLoop window fontManager config loopArgs = do
-- Rendering
renderCurrentReq <- checkRenderCurrent startTs _mlLatestRenderTs

let renderEvent = any isActionEvent eventsPayload
let winRedrawEvt = windowResized || windowExposed
let renderNeeded = winRedrawEvt || renderEvent || renderCurrentReq
let actionEvt = any isActionEvent eventsPayload
let windowRenderEvt = windowResized || any isWindowRenderEvent eventsPayload
let renderNeeded = windowRenderEvt || actionEvt || renderCurrentReq

when renderNeeded $ do
when (prevRenderNeeded || renderNeeded) $ do
renderMethod <- use L.renderMethod

case renderMethod of
Expand All @@ -361,8 +364,13 @@ mainLoop window fontManager config loopArgs = do

liftIO $ renderWidgets window dpr renderer bgColor newWenv newRoot

-- Used in the next rendering cycle
L.renderRequested .= windowResized
{-
Used in the next rendering cycle.
Temporary workaround: when rendering is needed, make sure to render the next
frame too in order to avoid visual artifacts.
-}
L.renderRequested .= renderNeeded

let fps = realToFrac _mlMaxFps
let frameLength = round (1000000 / fps)
Expand Down Expand Up @@ -455,6 +463,7 @@ handleRenderMsg window renderer fontMgr state (MsgRender tmpWenv newRoot) = do
let newWenv = tmpWenv
& L.fontManager .~ fontMgr
let color = newWenv ^. L.theme . L.clearColor

renderWidgets window dpr renderer color newWenv newRoot
return (RenderState dpr newWenv newRoot)
handleRenderMsg window renderer fontMgr state (MsgResize _) = do
Expand Down Expand Up @@ -564,6 +573,18 @@ isMouseEntered :: [SDL.EventPayload] -> Bool
isMouseEntered eventsPayload = not status where
status = null [ e | e@SDL.WindowGainedMouseFocusEvent {} <- eventsPayload ]

isWindowRenderEvent :: SDL.EventPayload -> Bool
isWindowRenderEvent SDL.WindowShownEvent{} = True
isWindowRenderEvent SDL.WindowExposedEvent{} = True
isWindowRenderEvent SDL.WindowMovedEvent{} = True
isWindowRenderEvent SDL.WindowResizedEvent{} = True
isWindowRenderEvent SDL.WindowSizeChangedEvent{} = True
isWindowRenderEvent SDL.WindowMaximizedEvent{} = True
isWindowRenderEvent SDL.WindowRestoredEvent{} = True
isWindowRenderEvent SDL.WindowGainedMouseFocusEvent{} = True
isWindowRenderEvent SDL.WindowGainedKeyboardFocusEvent{} = True
isWindowRenderEvent _ = False

getCurrentTimestamp :: MonadIO m => m Millisecond
getCurrentTimestamp = toMs <$> liftIO getCurrentTime
where
Expand Down
2 changes: 1 addition & 1 deletion src/Monomer/Main/Handlers.hs
Expand Up @@ -281,7 +281,7 @@ handleResizeWidgets previousStep = do
resizeRequests <- use L.resizeRequests
paths <- mapM getWidgetIdPath resizeRequests
let parts = Set.fromDistinctAscList . drop 1 . toList . Seq.inits
let sets = fold (parts <$> paths)
let sets = foldMap parts paths

return (`Set.member` sets)

Expand Down

0 comments on commit d1ddcc2

Please sign in to comment.