소스 검색

Initial work on graphics system abstraction
Fixed member order and access rights in the Pixel class
Pink FTW

Streetwalrus Einstein 10 년 전
부모
커밋
292ab06153

+ 24 - 20
platform/Graphics.h

@@ -1,44 +1,48 @@
 #ifndef INCLUDE_GRAPHICS_H
 #ifndef INCLUDE_GRAPHICS_H
 #define INCLUDE_GRAPHICS_H
 #define INCLUDE_GRAPHICS_H
 
 
+/*
+ * Graphics.h
+ * Graphics backend abstraction
+ */
+
 #include <cstdint>
 #include <cstdint>
+#include "render/Pixel.h"
 #include "utility/Rect.h"
 #include "utility/Rect.h"
 
 
 namespace WalrusRPG
 namespace WalrusRPG
 {
 {
     namespace Graphics
     namespace Graphics
     {
     {
+        void init();
+        void deinit();
+
         /*
         /*
-         * Buffer management
+         * Allows doing stuff before drawing, the GC requires this,
+         * and it's a nice to have
          */
          */
-
-        void buffer_allocate();
-        void buffer_free();
-        void buffer_swap_screen();
-        void buffer_swap_render();
-        void buffer_fill(uint16_t color);
-
+        void frame_begin();
 
 
         /*
         /*
-         * Misc LCD functions
+         * Signal the graphics system that we're done drawing so that
+         * the frame can be pushed to the screen
          */
          */
-        void vsync_isr();
-
+        void frame_end();
 
 
         /*
         /*
-         * Drawing
+         * Current prototype is the same as the nspire fb implementation
+         * for now, need to add a texture type and get rid of the Rect
+         * (not sure the GC supports drawing parts of a texture, but it
+         * may be worth trying
          */
          */
-
-        void draw_pixel(int x, int y, uint16_t color);
-        void draw_sprite_sheet(const uint16_t *sheet, int x, int y,
-                               const WalrusRPG::Utils::Rect &window);
-
+        void put_sprite(const uint16_t *sheet, int x, int y,
+                        const WalrusRPG::Utils::Rect &window);
 
 
         /*
         /*
-         * Sprite manipulation
+         * Set a background color or texture to be used by frame_begin()
+         * To be defined further
          */
          */
-
-        uint16_t sprite_pixel_get(const uint16_t *sprite, uint32_t x, uint32_t y);
+        void set_bg(const WalrusRPG::Graphics::Pixel &new_bg);
     }
     }
 }
 }
 
 

+ 144 - 0
platform/nspire/CXfb.cpp

@@ -0,0 +1,144 @@
+#include <cstdlib>
+#include <cstring>
+#include "CXfb.h"
+#include "utility/misc.h"
+
+#define GRAPHICS Nspire::CXfb
+
+#define LCD_CONTROLLER 0xC0000000
+volatile uint32_t *lcd_base = (uint32_t *) (LCD_CONTROLLER + 0x10);
+volatile uint32_t *lcd_ris = (uint32_t *) (LCD_CONTROLLER + 0x20);
+volatile uint32_t *lcd_icr = (uint32_t *) (LCD_CONTROLLER + 0x28);
+volatile uint32_t *lcd_control = (uint32_t *) (LCD_CONTROLLER + 0x18);
+uint32_t lcd_control_bkp;
+volatile uint32_t *lcd_imsc = (uint32_t *) (LCD_CONTROLLER + 0x1C);
+uint32_t lcd_imsc_bkp;
+
+#define BUFFER_SIZE 320 * 240 * 2
+uint16_t *buffer_screen = NULL, *buffer_render = NULL, *buffer_ready = NULL, *buffer_os;
+bool buffer_swap_ready;
+
+/*
+ * Buffer management
+ */
+
+void GRAPHICS::buffer_allocate()
+{
+    buffer_screen = (uint16_t *) malloc(BUFFER_SIZE);
+    buffer_render = (uint16_t *) malloc(BUFFER_SIZE);
+    buffer_ready = (uint16_t *) malloc(BUFFER_SIZE);
+
+    if (buffer_screen == NULL || buffer_render == NULL || buffer_ready == NULL)
+    {
+        free(buffer_screen);
+        free(buffer_render);
+        free(buffer_ready);
+        exit(0);
+    }
+
+    memset(buffer_screen, 0, BUFFER_SIZE);
+
+    buffer_os = (uint16_t *) *lcd_base;
+    *lcd_base = (uint32_t) buffer_screen;
+    buffer_swap_ready = false;
+
+    // Set up the controller in order to use vsync signals
+    lcd_control_bkp = *lcd_control;
+    *lcd_control &= ~(0b11 << 12);
+    *lcd_control |= 0b11 << 12;
+    lcd_imsc_bkp = *lcd_imsc;
+    *lcd_imsc = 1 << 3;
+}
+
+void GRAPHICS::buffer_free()
+{
+    free(buffer_screen);
+    free(buffer_render);
+    free(buffer_ready);
+
+    *lcd_base = (uint32_t) buffer_os;
+
+    *lcd_control = lcd_control_bkp;
+    *lcd_imsc = lcd_imsc_bkp;
+}
+
+void GRAPHICS::buffer_swap_screen()
+{
+    if (buffer_swap_ready)
+    {
+        uint16_t *buffer_screen_tmp = buffer_screen;
+        buffer_screen = buffer_ready;
+        buffer_ready = buffer_screen_tmp;
+
+        *lcd_base = (uint32_t) buffer_screen;
+        buffer_swap_ready = false;
+    }
+}
+
+void GRAPHICS::buffer_swap_render()
+{
+    uint16_t *buffer_ready_tmp = buffer_ready;
+    buffer_ready = buffer_render;
+    buffer_render = buffer_ready_tmp;
+    buffer_swap_ready = true;
+}
+
+void GRAPHICS::buffer_fill(uint16_t color)
+{
+    uint32_t *buffer_render_32 = (uint32_t *) buffer_render;
+    uint32_t color_32 = color << 16 | color; // To avoid stupid overflows
+    for (uint32_t i = 0; i < (BUFFER_SIZE / 4); i++)
+        buffer_render_32[i] = color_32;
+}
+
+
+/*
+ * Misc LCD functions
+ */
+
+void GRAPHICS::vsync_isr()
+{
+    buffer_swap_screen();
+    *lcd_icr = 1 << 3;
+}
+
+
+/*
+ * Drawing
+ */
+
+void GRAPHICS::draw_pixel(int x, int y, uint16_t color)
+{
+    buffer_render[x + (y * 320)] = color;
+}
+
+void GRAPHICS::draw_sprite_sheet(const uint16_t *sheet, int x, int y,
+                                 const WalrusRPG::Utils::Rect &window)
+{
+    uint16_t color;
+    int w = min(window.width + x, 320);
+    int h = min(window.height + y, 240);
+
+    for (int j = max(y, 0), l = window.y - min(y, 0); j < h; j++, l++)
+    {
+        for (int i = max(x, 0), k = window.x - min(x, 0); i < w; i++, k++)
+        {
+            color = sprite_pixel_get(sheet, k, l);
+            if (color != sheet[2])
+                draw_pixel(i, j, color);
+        }
+    }
+}
+
+
+/*
+ * Sprite manipulation
+ */
+
+uint16_t GRAPHICS::sprite_pixel_get(const uint16_t *sprite, uint32_t x, uint32_t y)
+{
+    if (x < sprite[0] && y < sprite[1])
+        return sprite[x + (y * sprite[0]) + 3];
+    else
+        return sprite[2];
+}

+ 45 - 0
platform/nspire/CXfb.h

@@ -0,0 +1,45 @@
+#ifndef INCLUDE_CXFB_H
+#define INCLUDE_CXFB_H
+
+#include <cstdint>
+#include "utility/Rect.h"
+
+namespace Nspire
+{
+    namespace CXfb
+    {
+        /*
+         * Buffer management
+         */
+
+        void buffer_allocate();
+        void buffer_free();
+        void buffer_swap_screen();
+        void buffer_swap_render();
+        void buffer_fill(uint16_t color);
+
+
+        /*
+         * Misc LCD functions
+         */
+        void vsync_isr();
+
+
+        /*
+         * Drawing
+         */
+
+        void draw_pixel(int x, int y, uint16_t color);
+        void draw_sprite_sheet(const uint16_t *sheet, int x, int y,
+                               const WalrusRPG::Utils::Rect &window);
+
+
+        /*
+         * Sprite manipulation
+         */
+
+        uint16_t sprite_pixel_get(const uint16_t *sprite, uint32_t x, uint32_t y);
+    }
+}
+
+#endif

+ 17 - 121
platform/nspire/Graphics.cpp

@@ -1,144 +1,40 @@
-#include <cstdlib>
-#include <cstring>
 #include "Graphics.h"
 #include "Graphics.h"
-#include "utility/misc.h"
+#include "CXfb.h"
+#include "stdio.h"
 
 
 #define GRAPHICS WalrusRPG::Graphics
 #define GRAPHICS WalrusRPG::Graphics
 
 
-#define LCD_CONTROLLER 0xC0000000
-volatile uint32_t *lcd_base = (uint32_t *) (LCD_CONTROLLER + 0x10);
-volatile uint32_t *lcd_ris = (uint32_t *) (LCD_CONTROLLER + 0x20);
-volatile uint32_t *lcd_icr = (uint32_t *) (LCD_CONTROLLER + 0x28);
-volatile uint32_t *lcd_control = (uint32_t *) (LCD_CONTROLLER + 0x18);
-uint32_t lcd_control_bkp;
-volatile uint32_t *lcd_imsc = (uint32_t *) (LCD_CONTROLLER + 0x1C);
-uint32_t lcd_imsc_bkp;
+using namespace Nspire;
 
 
-#define BUFFER_SIZE 320 * 240 * 2
-uint16_t *buffer_screen = NULL, *buffer_render = NULL, *buffer_ready = NULL, *buffer_os;
-bool buffer_swap_ready;
+GRAPHICS::Pixel bg(0);
 
 
-/*
- * Buffer management
- */
-
-void GRAPHICS::buffer_allocate()
-{
-    buffer_screen = (uint16_t *) malloc(BUFFER_SIZE);
-    buffer_render = (uint16_t *) malloc(BUFFER_SIZE);
-    buffer_ready = (uint16_t *) malloc(BUFFER_SIZE);
-
-    if (buffer_screen == NULL || buffer_render == NULL || buffer_ready == NULL)
-    {
-        free(buffer_screen);
-        free(buffer_render);
-        free(buffer_ready);
-        exit(0);
-    }
-
-    memset(buffer_screen, 0, BUFFER_SIZE);
-
-    buffer_os = (uint16_t *) *lcd_base;
-    *lcd_base = (uint32_t) buffer_screen;
-    buffer_swap_ready = false;
-
-    // Set up the controller in order to use vsync signals
-    lcd_control_bkp = *lcd_control;
-    *lcd_control &= ~(0b11 << 12);
-    *lcd_control |= 0b11 << 12;
-    lcd_imsc_bkp = *lcd_imsc;
-    *lcd_imsc = 1 << 3;
-}
-
-void GRAPHICS::buffer_free()
-{
-    free(buffer_screen);
-    free(buffer_render);
-    free(buffer_ready);
-
-    *lcd_base = (uint32_t) buffer_os;
-
-    *lcd_control = lcd_control_bkp;
-    *lcd_imsc = lcd_imsc_bkp;
-}
-
-void GRAPHICS::buffer_swap_screen()
-{
-    if (buffer_swap_ready)
-    {
-        uint16_t *buffer_screen_tmp = buffer_screen;
-        buffer_screen = buffer_ready;
-        buffer_ready = buffer_screen_tmp;
-
-        *lcd_base = (uint32_t) buffer_screen;
-        buffer_swap_ready = false;
-    }
-}
-
-void GRAPHICS::buffer_swap_render()
+void GRAPHICS::init()
 {
 {
-    uint16_t *buffer_ready_tmp = buffer_ready;
-    buffer_ready = buffer_render;
-    buffer_render = buffer_ready_tmp;
-    buffer_swap_ready = true;
+    CXfb::buffer_allocate();
 }
 }
 
 
-void GRAPHICS::buffer_fill(uint16_t color)
+void GRAPHICS::deinit()
 {
 {
-    uint32_t *buffer_render_32 = (uint32_t *) buffer_render;
-    uint32_t color_32 = color << 16 | color; // To avoid stupid overflows
-    for (uint32_t i = 0; i < (BUFFER_SIZE / 4); i++)
-        buffer_render_32[i] = color_32;
+    CXfb::buffer_free();
 }
 }
 
 
-
-/*
- * Misc LCD functions
- */
-
-void GRAPHICS::vsync_isr()
+void GRAPHICS::frame_begin()
 {
 {
-    buffer_swap_screen();
-    *lcd_icr = 1 << 3;
+    CXfb::buffer_fill(bg);
 }
 }
 
 
-
-/*
- * Drawing
- */
-
-void GRAPHICS::draw_pixel(int x, int y, uint16_t color)
+void GRAPHICS::frame_end()
 {
 {
-    buffer_render[x + (y * 320)] = color;
+    CXfb::buffer_swap_render();
 }
 }
 
 
-void GRAPHICS::draw_sprite_sheet(const uint16_t *sheet, int x, int y,
-                                 const WalrusRPG::Utils::Rect &window)
+void GRAPHICS::put_sprite(const uint16_t *sheet, int x, int y,
+                          const WalrusRPG::Utils::Rect &window)
 {
 {
-    uint16_t color;
-    int w = min(window.width + x, 320);
-    int h = min(window.height + y, 240);
-
-    for (int j = max(y, 0), l = window.y - min(y, 0); j < h; j++, l++)
-    {
-        for (int i = max(x, 0), k = window.x - min(x, 0); i < w; i++, k++)
-        {
-            color = sprite_pixel_get(sheet, k, l);
-            if (color != sheet[2])
-                draw_pixel(i, j, color);
-        }
-    }
+    CXfb::draw_sprite_sheet(sheet, x, y, window);
 }
 }
 
 
-
-/*
- * Sprite manipulation
- */
-
-uint16_t GRAPHICS::sprite_pixel_get(const uint16_t *sprite, uint32_t x, uint32_t y)
+void GRAPHICS::set_bg(const WalrusRPG::Graphics::Pixel &new_bg)
 {
 {
-    if (x < sprite[0] && y < sprite[1])
-        return sprite[x + (y * sprite[0]) + 3];
-    else
-        return sprite[2];
+    bg = new_bg;
 }
 }

+ 2 - 2
platform/nspire/Interrupts.cpp

@@ -1,5 +1,5 @@
 #include "Interrupts.h"
 #include "Interrupts.h"
-#include "Graphics.h"
+#include "CXfb.h"
 
 
 #define INTERRUPTS WalrusRPG::Interrupts
 #define INTERRUPTS WalrusRPG::Interrupts
 
 
@@ -59,5 +59,5 @@ void INTERRUPTS::off()
 void __attribute__((interrupt("IRQ"))) INTERRUPTS::isr()
 void __attribute__((interrupt("IRQ"))) INTERRUPTS::isr()
 {
 {
     if (*irq_status & (1 << 21))
     if (*irq_status & (1 << 21))
-        WalrusRPG::Graphics::vsync_isr();
+        Nspire::CXfb::vsync_isr();
 }
 }

+ 2 - 1
src/engine/StateMachine.cpp

@@ -51,13 +51,14 @@ void STATEMACHINE::run()
         {
         {
             frame_stamp = Timers::read(0);
             frame_stamp = Timers::read(0);
             frame_time = frame_stamp - last_frame;
             frame_time = frame_stamp - last_frame;
+            Graphics::frame_begin();
             stack.back()->render(frame_time);
             stack.back()->render(frame_time);
             last_frame = frame_stamp;
             last_frame = frame_stamp;
 
 
             Text::print_format(0, 0, "WalrusRPG test build %s", git_version);
             Text::print_format(0, 0, "WalrusRPG test build %s", git_version);
             Text::print_format(0, 240 - 8, "%ufps, %uups", TIMER_FREQ / frame_time,
             Text::print_format(0, 240 - 8, "%ufps, %uups", TIMER_FREQ / frame_time,
                                TIMER_FREQ / update_time);
                                TIMER_FREQ / update_time);
-            Graphics::buffer_swap_render();
+            Graphics::frame_end();
         }
         }
 
 
         if (isKeyPressed(KEY_NSPIRE_ESC))
         if (isKeyPressed(KEY_NSPIRE_ESC))

+ 6 - 2
src/engine/main.cpp

@@ -4,6 +4,7 @@
 #include "Interrupts.h"
 #include "Interrupts.h"
 #include "map/Map.h"
 #include "map/Map.h"
 #include "map/StateMap.h"
 #include "map/StateMap.h"
+#include "render/Pixel.h"
 #include "utility/misc.h"
 #include "utility/misc.h"
 
 
 using namespace WalrusRPG;
 using namespace WalrusRPG;
@@ -13,7 +14,10 @@ int main(int argc, char *argv[])
     UNUSED(argc);
     UNUSED(argc);
     UNUSED(argv);
     UNUSED(argv);
 
 
-    Graphics::buffer_allocate();
+    Graphics::init();
+    Graphics::Pixel bg(0xFF, 0x40, 0xD0);
+    Graphics::set_bg(bg);
+
     Timers::init(0);
     Timers::init(0);
     Interrupts::init();
     Interrupts::init();
 
 
@@ -81,6 +85,6 @@ int main(int argc, char *argv[])
 
 
     Interrupts::off();
     Interrupts::off();
     Timers::restore(0);
     Timers::restore(0);
-    Graphics::buffer_free();
+    Graphics::deinit();
     return 0;
     return 0;
 }
 }

+ 0 - 1
src/map/StateMap.cpp

@@ -33,7 +33,6 @@ void STATEMAP::update(unsigned dt)
 void STATEMAP::render(unsigned dt)
 void STATEMAP::render(unsigned dt)
 {
 {
     Pixel pix(Graphics::Green);
     Pixel pix(Graphics::Green);
-    Graphics::buffer_fill(pix);
     map.render(camera, dt);
     map.render(camera, dt);
 
 
     print_debug_camera_data(camera);
     print_debug_camera_data(camera);

+ 1 - 1
src/render/Pixel.cpp

@@ -11,7 +11,7 @@ PIXEL::Pixel(Pixel &pix) : value((std::uint8_t) pix)
 }
 }
 
 
 PIXEL::Pixel(std::uint8_t red, std::uint8_t green, std::uint8_t blue)
 PIXEL::Pixel(std::uint8_t red, std::uint8_t green, std::uint8_t blue)
-    : r(red >> 3), g(green >> 2), b(blue >> 3)
+    : b(blue >> 3), g(green >> 2), r(red >> 3)
 {
 {
 }
 }
 
 

+ 3 - 3
src/render/Pixel.h

@@ -12,6 +12,7 @@ namespace WalrusRPG
          */
          */
         class Pixel
         class Pixel
         {
         {
+          public:
             union
             union
             {
             {
                 std::uint16_t value;
                 std::uint16_t value;
@@ -19,13 +20,12 @@ namespace WalrusRPG
               public: // hack to be able to do pixel.r. Clever!
               public: // hack to be able to do pixel.r. Clever!
                 struct
                 struct
                 {
                 {
-                    unsigned r : 5;
-                    unsigned g : 6;
                     unsigned b : 5;
                     unsigned b : 5;
+                    unsigned g : 6;
+                    unsigned r : 5;
                 };
                 };
             };
             };
 
 
-          public:
             Pixel(std::uint16_t color);
             Pixel(std::uint16_t color);
 
 
             Pixel(Pixel &pix);
             Pixel(Pixel &pix);

+ 1 - 1
src/render/SpriteRenderer.cpp

@@ -17,5 +17,5 @@ void SPRITERENDERER::add_sprite(unsigned id, WalrusRPG::Utils::Rect rect)
 
 
 void SPRITERENDERER::render(const unsigned id, const Rect &rect)
 void SPRITERENDERER::render(const unsigned id, const Rect &rect)
 {
 {
-    Graphics::draw_sprite_sheet(tilesheet, rect.x, rect.y, sprites[id]);
+    Graphics::put_sprite(tilesheet, rect.x, rect.y, sprites[id]);
 }
 }

+ 2 - 2
src/render/Text.cpp

@@ -10,7 +10,7 @@ using namespace WalrusRPG::Utils;
 
 
 void TEXT::print_char(char c, unsigned x, unsigned y)
 void TEXT::print_char(char c, unsigned x, unsigned y)
 {
 {
-    draw_sprite_sheet(font, x, y, Rect((c % 16) * 8, (c / 16) * 8, 8, 8));
+    put_sprite(font, x, y, Rect((c % 16) * 8, (c / 16) * 8, 8, 8));
 }
 }
 
 
 void TEXT::print_string(const char *str, unsigned x, unsigned y)
 void TEXT::print_string(const char *str, unsigned x, unsigned y)
@@ -23,7 +23,7 @@ void TEXT::print_string(const char *str, unsigned x, unsigned y)
         char c = str[index];
         char c = str[index];
         rect.x = (c % 16) * 8;
         rect.x = (c % 16) * 8;
         rect.y = (c / 16) * 8;
         rect.y = (c / 16) * 8;
-        draw_sprite_sheet(font, x, y, rect);
+        put_sprite(font, x, y, rect);
         x += 8;
         x += 8;
     }
     }
 }
 }

+ 1 - 1
src/render/TileRenderer.cpp

@@ -15,7 +15,7 @@ void TILERENDERER::render(const unsigned id, const Rect &rect)
 {
 {
     unsigned num_tiles_x = tilesheet[0] / tile_width;
     unsigned num_tiles_x = tilesheet[0] / tile_width;
     // unsigned num_tiles_y = sheet_height / tile_height;
     // unsigned num_tiles_y = sheet_height / tile_height;
-    Graphics::draw_sprite_sheet(tilesheet, rect.x, rect.y,
+    Graphics::put_sprite(tilesheet, rect.x, rect.y,
                                 Rect(tile_width * (id % num_tiles_x),
                                 Rect(tile_width * (id % num_tiles_x),
                                      tile_height * (id / num_tiles_x), tile_width,
                                      tile_height * (id / num_tiles_x), tile_width,
                                      tile_height));
                                      tile_height));