diff --git a/src/python/boytacean/gb.py b/src/python/boytacean/gb.py
index ba224ef6fb79163c9641321dd0a64391060465d8..f471f5aea5e66215e5f2b7b1c892a35cfa183196 100644
--- a/src/python/boytacean/gb.py
+++ b/src/python/boytacean/gb.py
@@ -223,9 +223,7 @@ This is a [Game Boy](https://en.wikipedia.org/wiki/Game_Boy) emulator built usin
             self._video.save_frame(self.image(), self._frame_index)
             self._video.compute_next(self._frame_index)
 
-        # @TODO: this should be sample, meaning that not every
-        # single frame is sent to the display (performance)
-        if self._display != None:
+        if self._display != None and self._display.should_render(self._frame_index):
             from .graphics import Display
 
             cast(Display, self._display).render_frame(self.frame_buffer())
diff --git a/src/python/boytacean/graphics.py b/src/python/boytacean/graphics.py
index c6a98052f3f955c3695805bd9ae44683d00c4fc5..89fb480c7bdd8e32e1d32c06742ffbee734ffff1 100644
--- a/src/python/boytacean/graphics.py
+++ b/src/python/boytacean/graphics.py
@@ -1,3 +1,4 @@
+from math import ceil
 from typing import Union
 from sdl2 import (
     SDL_QUIT,
@@ -8,15 +9,18 @@ from sdl2 import (
     SDL_DestroyTexture,
     SDL_FreeSurface,
 )
-from sdl2.ext import Window, Renderer, Color, init as init_sdl, get_events
+from sdl2.ext import Window, Renderer, init as init_sdl, get_events
 
-from .boytacean import DISPLAY_WIDTH, DISPLAY_HEIGHT
+from .boytacean import DISPLAY_WIDTH, DISPLAY_HEIGHT, VISUAL_FREQ
 
 
 class Display:
     _width: int = DISPLAY_WIDTH
     _height: int = DISPLAY_HEIGHT
     _title: str = "Boytacean"
+    _scale: float = 3.0
+    _frame_gap: int = 60
+    _next_frame: int = 60
     _window: Union[Window, None] = None
     _renderer: Union[Renderer, None] = None
 
@@ -25,20 +29,32 @@ class Display:
         width: int = DISPLAY_WIDTH,
         height: int = DISPLAY_HEIGHT,
         title="Boytacean",
+        scale=3.0,
+        start_frame=0,
+        fps=5,
     ):
         self._width = width
         self._height = height
         self._title = title
+        self._scale = scale
+        self._frame_gap = ceil(VISUAL_FREQ / fps)
+        self._next_frame = start_frame + self._frame_gap
         self._window = None
         self._renderer = None
         self.build()
 
     def build(self):
         init_sdl()
-        self._window = Window(self._title, size=(self._width, self._height))
+        self._window = Window(
+            self._title,
+            size=(int(self._width * self._scale), int(self._height * self._scale)),
+        )
         self._window.show()
         self._renderer = Renderer(self._window)
 
+    def should_render(self, frame_index) -> bool:
+        return frame_index >= self._next_frame
+
     def render_frame(self, frame_buffer: bytes):
         if not self._window:
             raise RuntimeError("Window not initialized")
@@ -49,7 +65,7 @@ class Display:
         # we consider that every time there's a request for a new
         # frame draw the queue of SDL events should be flushed
         events = get_events()
-        for event in events:
+        for _ in events:
             pass
 
         surface = SDL_CreateRGBSurfaceFrom(
@@ -58,9 +74,9 @@ class Display:
             DISPLAY_HEIGHT,
             24,
             DISPLAY_WIDTH * 3,
-            0x000000ff,
-            0x0000ff00,
-            0x00ff0000,
+            0x000000FF,
+            0x0000FF00,
+            0x00FF0000,
             0x0,
         )
         texture = SDL_CreateTextureFromSurface(
@@ -72,9 +88,11 @@ class Display:
                 self._renderer.sdlrenderer,
                 texture,
                 None,
-                SDL_Rect(0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT),
+                None,
             )
             self._renderer.present()
         finally:
             SDL_DestroyTexture(texture)
             SDL_FreeSurface(surface)
+
+        self._next_frame += self._frame_gap