TinyGPU
Loading...
Searching...
No Matches
DisplayDriverSDL.h
Go to the documentation of this file.
1#pragma once
2#include <SDL.h>
3
4#include <cstdint>
5#include <cstdlib>
6#include <vector>
7
8#include "TinyGPU/Drivers/DisplayDriver.h"
9#include "TinyGPU/Color/RGB565.h"
10
11namespace tinygpu {
12
13/**
14 * @brief Display class for rendering a Surface<RGB565> using the SDL2 library.
15 * This class can be used to display the contents of a TinyGPU Surface<RGB565>
16 * on a desktop environment for testing and debugging purposes.
17 *
18 * writeData() drains the SDL event queue on every call and exits the process
19 * on SDL_QUIT (i.e. the window's close button), since sketches that never
20 * touch a TouchDriverSDL - the only other place that pumps events - would
21 * otherwise leave the window unresponsive to being closed: with no one
22 * calling SDL_PollEvent, the window manager's close request just piles up in
23 * SDL's queue and the OS reports the window as hung.
24 */
25template <typename RGB_T = RGB565>
26class DisplayDriverSDL : public DisplayDriver<RGB_T> {
27 public:
28 DisplayDriverSDL(size_t width, size_t height) : w_(width), h_(height) {}
29 DisplayDriverSDL(const ISurface<RGB_T>& surface)
30 : w_(surface.width()), h_(surface.height()) {}
31
32 size_t width() const override { return w_; }
33 size_t height() const override { return h_; }
34
35 bool begin() override {
36 SDL_Init(SDL_INIT_VIDEO);
37 if (window_ == nullptr) {
38 window_ =
39 SDL_CreateWindow("RGB565 Display", SDL_WINDOWPOS_UNDEFINED,
40 SDL_WINDOWPOS_UNDEFINED, w_, h_, SDL_WINDOW_SHOWN);
41 if (window_ == nullptr) return false;
42 renderer_ = SDL_CreateRenderer(window_, -1, SDL_RENDERER_ACCELERATED);
43 if (renderer_ == nullptr) return false;
44 texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGB565,
45 SDL_TEXTUREACCESS_STREAMING, w_, h_);
46 if (texture_ == nullptr) return false;
47 }
48 return true;
49 }
50
51 public:
52 bool writeData(ISurface<RGB_T>& surface) override {
53 return writeData(surface, 0, 0);
54 }
55
56 bool writeData(ISurface<RGB_T>& surface, size_t x, size_t y) override {
57 static_assert(sizeof(RGB_T) == 2,
58 "DisplayDriverSDL assumes a 16bpp RGB_T (RGB565)");
59 SDL_Event event;
60 while (SDL_PollEvent(&event)) {
61 if (event.type == SDL_QUIT) {
62 exit(0);
63 }
64 }
65 setAddressWindow(x, y, surface.width(), surface.height());
66 SDL_Rect updateRect = {static_cast<int>(x), static_cast<int>(y),
67 static_cast<int>(surface.width()),
68 static_cast<int>(surface.height())};
69 // RGB_T (RGB565) values are stored byte-swapped to SPI/QSPI wire
70 // order (see RGB565.h), but SDL_PIXELFORMAT_RGB565 expects the
71 // conventional (native) bit layout - swap back into a scratch
72 // buffer before uploading, rather than mutating the surface itself.
73 const size_t n = surface.size();
74 if (scratch_.size() < n) scratch_.resize(n);
75 const uint16_t* src = reinterpret_cast<const uint16_t*>(surface.data());
76 uint16_t* dst = reinterpret_cast<uint16_t*>(scratch_.data());
77 const size_t pixelCount = n / sizeof(RGB_T);
78 for (size_t i = 0; i < pixelCount; ++i) {
79 dst[i] = RGB565::swapBytes(src[i]);
80 }
81 SDL_UpdateTexture(texture_, &updateRect, scratch_.data(),
82 surface.width() * sizeof(RGB_T));
83 SDL_Rect fullRect = {0, 0, static_cast<int>(w_), static_cast<int>(h_)};
84 SDL_RenderClear(renderer_);
85 SDL_RenderCopy(renderer_, texture_, NULL, &fullRect);
86 SDL_RenderPresent(renderer_);
87 return true;
88 }
89
90 void end() override {
91 SDL_DestroyTexture(texture_);
92 SDL_DestroyRenderer(renderer_);
93 SDL_DestroyWindow(window_);
94 SDL_Quit();
95 texture_ = nullptr;
96 renderer_ = nullptr;
97 window_ = nullptr;
98 }
99
100 protected:
103 SDL_Window* window_ = nullptr;
107
108 protected:
109 bool setAddressWindow(size_t x, size_t y, size_t w, size_t h) override {
110 return true;
111 }
112};
113
114} // namespace tinygpu
Display class for rendering a Surface<RGB565> using the SDL2 library. This class can be used to displ...
Definition: DisplayDriverSDL.h:26
size_t w_
Definition: DisplayDriverSDL.h:101
SDL_Texture * texture_
Definition: DisplayDriverSDL.h:105
DisplayDriverSDL(size_t width, size_t height)
Definition: DisplayDriverSDL.h:28
void end() override
Definition: DisplayDriverSDL.h:90
SDL_Window * window_
Definition: DisplayDriverSDL.h:103
size_t height() const override
Definition: DisplayDriverSDL.h:33
DisplayDriverSDL(const ISurface< RGB_T > &surface)
Definition: DisplayDriverSDL.h:29
std::vector< uint8_t > scratch_
Definition: DisplayDriverSDL.h:106
bool writeData(ISurface< RGB_T > &surface, size_t x, size_t y) override
Definition: DisplayDriverSDL.h:56
size_t h_
Definition: DisplayDriverSDL.h:102
size_t width() const override
Definition: DisplayDriverSDL.h:32
SDL_Renderer * renderer_
Definition: DisplayDriverSDL.h:104
bool begin() override
Definition: DisplayDriverSDL.h:35
bool setAddressWindow(size_t x, size_t y, size_t w, size_t h) override
Definition: DisplayDriverSDL.h:109
bool writeData(ISurface< RGB_T > &surface) override
Definition: DisplayDriverSDL.h:52
Definition: DisplayDriver.h:49
RGB color stored in 16-bit RGB565 format, byte-swapped from the conventional bit layout.
Definition: RGB565.h:24
Definition: DSIBusESP32.h:19