Repository: openai/gym

Issue:
CarRacing corrupt frames when not rendering visually
When using CarRacing-v0 and not using render() explicitly, the frames from step() are corrupt. Mainly it's always 4 quadrants with a green or gray L shape regardless of what steps I perform (Attached 2 examples).
I've tracked it down to the call to 'win.dispatch_events()' in the render() function of the CarRacing() class, which isn't called in case of mode="state_pixels".

Calling the dispatch_events() even once after creating the window seems to solve it.
Attached also notebook which shows the issue and workaround.

![corrupt2](https://user-images.githubusercontent.com/6597746/38364963-4cf30aa0-38e3-11e8-93ce-c4288f0caeae.png)
![corrupt1](https://user-images.githubusercontent.com/6597746/38364965-4d162a30-38e3-11e8-90ee-320f7573643f.png)
[car_race_consistency.zip](https://github.com/openai/gym/files/1879931/car_race_consistency.zip)



Discussion:
I am also having this problem.
Same problem here. Just opened a similar issue https://github.com/openai/gym/issues/990 before noticing this one. Sorry for that. Thanks for your solution :)
#MeToo
Proposed workaround--something like:

`if "dispatch_events_called" not in self.__dict__ and mode == 'state_pixels':  
   win.dispatch_events()  
   self.dispatch_events_called = True`

At line 354 of gym/envs/box2d/car_racing.py
I am having a similar problem [Issue #1267 ](https://github.com/openai/gym/issues/1267). I cannot figure out how to run the [modified SAC](https://github.com/WuXinyang2012/spinningup/blob/master/spinup/algos/sac/sac.py), which I think offers a solution to the problem. 

Resolving patch:
diff --git a/gym/envs/box2d/car_racing.py b/gym/envs/box2d/car_racing.py
--- a/gym/envs/box2d/car_racing.py
+++ b/gym/envs/box2d/car_racing.py
@@ -284,7 +284,6 @@ def reset(self):
         self.tile_visited_count = 0
         self.t = 0.0
         self.road_poly = []
-        self.human_render = False
 
         while True:
             success = self._create_track()
@@ -326,6 +325,7 @@ def step(self, action):
         return self.state, step_reward, done, {}
 
     def render(self, mode='human'):
+        assert mode in ['human', 'state_pixels', 'rgb_array']
         if self.viewer is None:
             from gym.envs.classic_control import rendering
             self.viewer = rendering.Viewer(WINDOW_W, WINDOW_H)
@@ -355,48 +355,42 @@ def render(self, mode='human'):
 
         arr = None
         win = self.viewer.window
-        if mode != 'state_pixels':
-            win.switch_to()
-            win.dispatch_events()
-        if mode=="rgb_array" or mode=="state_pixels":
-            win.clear()
-            t = self.transform
-            if mode=='rgb_array':
-                VP_W = VIDEO_W
-                VP_H = VIDEO_H
-            else:
-                VP_W = STATE_W
-                VP_H = STATE_H
-            gl.glViewport(0, 0, VP_W, VP_H)
-            t.enable()
-            self.render_road()
-            for geom in self.viewer.onetime_geoms:
-                geom.render()
-            t.disable()
-            self.render_indicators(WINDOW_W, WINDOW_H)  # TODO: find why 2x needed, wtf
-            image_data = pyglet.image.get_buffer_manager().get_color_buffer().get_image_data()
-            arr = np.fromstring(image_data.data, dtype=np.uint8, sep='')
-            arr = arr.reshape(VP_H, VP_W, 4)
-            arr = arr[::-1, :, 0:3]
-
-        if mode=="rgb_array" and not self.human_render: # agent can call or not call env.render() itself when recording video.
-            win.flip()
+        win.switch_to()
+        win.dispatch_events()
+
+        win.clear()
+        t = self.transform
+        if mode=='rgb_array':
+            VP_W = VIDEO_W
+            VP_H = VIDEO_H
+        elif mode == 'state_pixels':
+            VP_W = STATE_W
+            VP_H = STATE_H
+        else:
+            pixel_scale = 1
+            if hasattr(win.context, '_nscontext'):
+                pixel_scale = win.context._nscontext.view().backingScaleFactor()  # pylint: disable=protected-access
+            VP_W = pixel_scale * WINDOW_W
+            VP_H = pixel_scale * WINDOW_H
+
+        gl.glViewport(0, 0, VP_W, VP_H)
+        t.enable()
+        self.render_road()
+        for geom in self.viewer.onetime_geoms:
+            geom.render()
+        self.viewer.onetime_geoms = []
+        t.disable()
+        self.render_indicators(WINDOW_W, WINDOW_H)
 
-        if mode=='human':
-            self.human_render = True
-            win.clear()
-            t = self.transform
-            gl.glViewport(0, 0, WINDOW_W, WINDOW_H)
-            t.enable()
-            self.render_road()
-            for geom in self.viewer.onetime_geoms:
-                geom.render()
-            t.disable()
-            self.render_indicators(WINDOW_W, WINDOW_H)
+        if mode == 'human':
             win.flip()
             return self.viewer.isopen
 
-        self.viewer.onetime_geoms = []
+        image_data = pyglet.image.get_buffer_manager().get_color_buffer().get_image_data()
+        arr = np.fromstring(image_data.data, dtype=np.uint8, sep='')
+        arr = arr.reshape(VP_H, VP_W, 4)
+        arr = arr[::-1, :, 0:3]
+
         return arr
 
     def close(self):


Test patch: