openMSX
SDLVisibleSurface.cc
Go to the documentation of this file.
1 #include "SDLVisibleSurface.hh"
2 #include "SDLOffScreenSurface.hh"
3 #include "PNG.hh"
4 #include "SDLSnow.hh"
5 #include "OSDConsoleRenderer.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 
14 namespace openmsx {
15 
17  unsigned width, unsigned 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 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  0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000));
41  if (!surface) {
42  std::string 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_ARGB8888, SDL_TEXTUREACCESS_STREAMING,
49  width, height));
50  if (!texture) {
51  std::string 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 
75 std::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 
100 std::unique_ptr<Layer> SDLVisibleSurface::createOSDGUILayer(OSDGUI& gui)
101 {
102  return std::make_unique<SDLOSDGUILayer>(gui);
103 }
104 
105 std::unique_ptr<OutputSurface> SDLVisibleSurface::createOffScreenSurface()
106 {
107  return std::make_unique<SDLOffScreenSurface>(*surface);
108 }
109 
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(width * height * 3);
121  for (int i = 0; i < height; ++i) {
122  rowPointers[i] = &buffer[width * 3 * 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, height, rowPointers, filename);
130 }
131 
133 {
134  SDL_FillRect(surface.get(), nullptr, 0);
135 }
136 
137 } // namespace openmsx
SDLSnow.hh
openmsx::SDLVisibleSurface::saveScreenshotSDL
static void saveScreenshotSDL(const SDLOutputSurface &output, const std::string &filename)
Definition: SDLVisibleSurface.cc:115
openmsx::SDLVisibleSurfaceBase
Common functionality for the plain SDL and SDLGL VisibleSurface classes.
Definition: SDLVisibleSurfaceBase.hh:13
openmsx::OutputSurface::calculateViewPort
void calculateViewPort(gl::ivec2 logSize, gl::ivec2 physSize)
Definition: OutputSurface.cc:6
utf8::unchecked::size
size_t size(std::string_view utf8)
Definition: utf8_unchecked.hh:227
openmsx::InputEventGenerator
Definition: InputEventGenerator.hh:18
openmsx::SDLVisibleSurface::SDLVisibleSurface
SDLVisibleSurface(unsigned width, unsigned height, Display &display, RTScheduler &rtScheduler, EventDistributor &eventDistributor, InputEventGenerator &inputEventGenerator, CliComm &cliComm, VideoSystem &videoSystem)
Definition: SDLVisibleSurface.cc:16
openmsx::SDLVisibleSurface::flushFrameBuffer
void flushFrameBuffer() override
Copy frame buffer to display buffer.
Definition: SDLVisibleSurface.cc:62
MSXException.hh
openmsx::MSXException
Definition: MSXException.hh:10
openmsx::RTScheduler
Definition: RTScheduler.hh:20
openmsx::VideoSystem
Video back-end system.
Definition: VideoSystem.hh:21
openmsx::EventDistributor
Definition: EventDistributor.hh:17
openmsx::SDLVisibleSurface::createSnowLayer
std::unique_ptr< Layer > createSnowLayer() override
Definition: SDLVisibleSurface.cc:75
openmsx::SDLVisibleSurface::clearScreen
void clearScreen() override
Clear frame buffer (paint it black).
Definition: SDLVisibleSurface.cc:132
openmsx::SDLVisibleSurface::createOffScreenSurface
std::unique_ptr< OutputSurface > createOffScreenSurface() override
Create an off-screen OutputSurface which has similar properties as this VisibleSurface.
Definition: SDLVisibleSurface.cc:105
PNG.hh
gl::vecN
Definition: gl_vec.hh:36
openmsx::OutputSurface::getPixelFormat
const PixelFormat & getPixelFormat() const
Definition: OutputSurface.hh:37
openmsx::SDLVisibleSurface::saveScreenshot
void saveScreenshot(const std::string &filename) override
Save the content of this OutputSurface to a PNG file.
Definition: SDLVisibleSurface.cc:110
openmsx::Reactor
Contains the main loop of openMSX.
Definition: Reactor.hh:67
openmsx::OSDGUI
Definition: OSDGUI.hh:14
vla.hh
UNREACHABLE
#define UNREACHABLE
Definition: unreachable.hh:38
SDLVisibleSurface.hh
openmsx::MemBuffer< uint8_t >
OSDGUILayer.hh
openmsx::SDLOutputSurface
A frame buffer where pixels can be written to.
Definition: SDLOutputSurface.hh:30
openmsx::filename
constexpr const char *const filename
Definition: FirmwareSwitch.cc:10
openmsx::SDLOutputSurface::setSDLRenderer
void setSDLRenderer(SDL_Renderer *r)
Definition: SDLOutputSurface.hh:69
openmsx::SDLOutputSurface::setSDLPixelFormat
void setSDLPixelFormat(const SDL_PixelFormat &format)
Definition: SDLOutputSurface.cc:24
openmsx::InitException
Thrown when a subsystem initialisation fails.
Definition: InitException.hh:12
build-info.hh
openmsx::SDLVisibleSurfaceBase::createSurface
void createSurface(int width, int height, unsigned flags)
Definition: SDLVisibleSurfaceBase.cc:30
SDLSurfacePtr::get
SDL_Surface * get()
Definition: SDLSurfacePtr.hh:77
openmsx::SDLOutputSurface::getSDLRenderer
SDL_Renderer * getSDLRenderer() const
Definition: SDLOutputSurface.hh:36
openmsx::SDLVisibleSurfaceBase::window
SDLWindowPtr window
Definition: SDLVisibleSurfaceBase.hh:24
openmsx::SDLVisibleSurface::finish
void finish() override
When a complete frame is finished, call this method.
Definition: SDLVisibleSurface.cc:70
openmsx::SDLOutputSurface::setSDLSurface
void setSDLSurface(SDL_Surface *surface_)
Definition: SDLOutputSurface.hh:68
openmsx::Display
Represents the output window/screen of openMSX.
Definition: Display.hh:33
openmsx::MemBuffer::data
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:90
openmsx::CliComm
Definition: CliComm.hh:11
SDLSurfacePtr::reset
void reset(SDL_Surface *surface_=nullptr)
Definition: SDLSurfacePtr.hh:71
openmsx::SDLVisibleSurface::createConsoleLayer
std::unique_ptr< Layer > createConsoleLayer(Reactor &reactor, CommandConsole &console) override
Definition: SDLVisibleSurface.cc:91
unreachable.hh
openmsx::VisibleSurface::getDisplay
Display & getDisplay() const
Definition: VisibleSurface.hh:52
VLA
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:10
openmsx::SDLVisibleSurface::createOSDGUILayer
std::unique_ptr< Layer > createOSDGUILayer(OSDGUI &gui) override
Definition: SDLVisibleSurface.cc:100
OSDConsoleRenderer.hh
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
SDLOffScreenSurface.hh
openmsx::OutputSurface::getLogicalSize
gl::ivec2 getLogicalSize() const
Definition: OutputSurface.hh:29
openmsx::CommandConsole
Definition: CommandConsole.hh:66