openMSX
SDLVisibleSurface.cc
Go to the documentation of this file.
3#include "PNG.hh"
4#include "SDLSnow.hh"
6#include "OSDGUILayer.hh"
7#include "MSXException.hh"
8#include "unreachable.hh"
9#include "vla.hh"
10#include "build-info.hh"
11#include <cstdint>
12#include <memory>
13
14namespace openmsx {
15
17 int width, int height,
18 Display& display_,
19 RTScheduler& rtScheduler_,
20 EventDistributor& eventDistributor_,
21 InputEventGenerator& inputEventGenerator_,
22 CliComm& cliComm_,
23 VideoSystem& videoSystem_)
24 : SDLVisibleSurfaceBase(display_, rtScheduler_, eventDistributor_,
25 inputEventGenerator_, cliComm_, videoSystem_)
26{
27 int flags = 0;
28 createSurface(width, height, flags);
29
30 renderer.reset(SDL_CreateRenderer(window.get(), -1, 0));
31 if (!renderer) {
32 std::string_view err = SDL_GetError();
33 throw InitException("Could not create renderer: ", err);
34 }
35 SDL_RenderSetLogicalSize(renderer.get(), width, height);
36 setSDLRenderer(renderer.get());
37
38 surface.reset(SDL_CreateRGBSurface(
39 0, width, height, 32,
40 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000));
41 if (!surface) {
42 std::string_view err = SDL_GetError();
43 throw InitException("Could not create surface: ", err);
44 }
45 setSDLSurface(surface.get());
46
47 texture.reset(SDL_CreateTexture(
48 renderer.get(), SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING,
49 width, height));
50 if (!texture) {
51 std::string_view err = SDL_GetError();
52 throw InitException("Could not create texture: ", err);
53 }
54
55 setSDLPixelFormat(*surface->format);
56
57 // In the SDL renderer logical size is the same as physical size.
58 gl::ivec2 size(width, height);
60}
61
63{
64 SDL_Renderer* render = getSDLRenderer();
65 SDL_UpdateTexture(texture.get(), nullptr, surface->pixels, surface->pitch);
66 SDL_RenderClear(render);
67 SDL_RenderCopy(render, texture.get(), nullptr, nullptr);
68}
69
71{
72 SDL_RenderPresent(getSDLRenderer());
73}
74
75std::unique_ptr<Layer> SDLVisibleSurface::createSnowLayer()
76{
77 switch (getPixelFormat().getBytesPerPixel()) {
78#if HAVE_16BPP
79 case 2:
80 return std::make_unique<SDLSnow<uint16_t>>(*this, getDisplay());
81#endif
82#if HAVE_32BPP
83 case 4:
84 return std::make_unique<SDLSnow<uint32_t>>(*this, getDisplay());
85#endif
86 default:
87 UNREACHABLE; return nullptr;
88 }
89}
90
92 Reactor& reactor, CommandConsole& console)
93{
94 const bool openGL = false;
95 auto [width, height] = getLogicalSize();
96 return std::make_unique<OSDConsoleRenderer>(
97 reactor, console, width, height, openGL);
98}
99
101{
102 return std::make_unique<SDLOSDGUILayer>(gui);
103}
104
105std::unique_ptr<OutputSurface> SDLVisibleSurface::createOffScreenSurface()
106{
107 return std::make_unique<SDLOffScreenSurface>(*surface);
108}
109
110void SDLVisibleSurface::saveScreenshot(const std::string& filename)
111{
112 saveScreenshotSDL(*this, filename);
113}
114
116 const SDLOutputSurface& output, const std::string& filename)
117{
118 auto [width, height] = output.getLogicalSize();
119 VLA(const void*, rowPointers, height);
120 MemBuffer<uint8_t> buffer(3 * size_t(width) * size_t(height));
121 for (auto i : xrange(size_t(height))) {
122 rowPointers[i] = &buffer[3 * size_t(width) * i];
123 }
124 if (SDL_RenderReadPixels(
125 output.getSDLRenderer(), nullptr,
126 SDL_PIXELFORMAT_RGB24, buffer.data(), width * 3)) {
127 throw MSXException("Couldn't acquire screenshot pixels: ", SDL_GetError());
128 }
129 PNG::save(width, rowPointers, filename);
130}
131
133{
134 SDL_FillRect(surface.get(), nullptr, 0);
135}
136
138{
139 // nothing
140}
141
142} // namespace openmsx
void reset(SDL_Surface *surface_=nullptr)
SDL_Surface * get()
Represents the output window/screen of openMSX.
Definition: Display.hh:33
Thrown when a subsystem initialisation fails.
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:81
const PixelFormat & getPixelFormat() const
gl::ivec2 getLogicalSize() const
void calculateViewPort(gl::ivec2 logSize, gl::ivec2 physSize)
Definition: OutputSurface.cc:6
Contains the main loop of openMSX.
Definition: Reactor.hh:68
A frame buffer where pixels can be written to.
void setSDLSurface(SDL_Surface *surface_)
SDL_Renderer * getSDLRenderer() const
void setSDLPixelFormat(const SDL_PixelFormat &format)
void setSDLRenderer(SDL_Renderer *r)
Common functionality for the plain SDL and SDLGL VisibleSurface classes.
void createSurface(int width, int height, unsigned flags)
void finish() override
When a complete frame is finished, call this method.
void saveScreenshot(const std::string &filename) override
Save the content of this OutputSurface to a PNG file.
SDLVisibleSurface(int width, int height, Display &display, RTScheduler &rtScheduler, EventDistributor &eventDistributor, InputEventGenerator &inputEventGenerator, CliComm &cliComm, VideoSystem &videoSystem)
std::unique_ptr< Layer > createConsoleLayer(Reactor &reactor, CommandConsole &console) override
static void saveScreenshotSDL(const SDLOutputSurface &output, const std::string &filename)
std::unique_ptr< Layer > createSnowLayer() override
void flushFrameBuffer() override
Copy frame buffer to display buffer.
std::unique_ptr< OutputSurface > createOffScreenSurface() override
Create an off-screen OutputSurface which has similar properties as this VisibleSurface.
std::unique_ptr< Layer > createOSDGUILayer(OSDGUI &gui) override
void fullScreenUpdated(bool fullScreen) override
void clearScreen() override
Clear frame buffer (paint it black).
Video back-end system.
Definition: VideoSystem.hh:23
Display & getDisplay() const
This file implemented 3 utility functions:
Definition: Autofire.cc:9
size_t size(std::string_view utf8)
#define UNREACHABLE
Definition: unreachable.hh:38
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:12
constexpr auto xrange(T e)
Definition: xrange.hh:132