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  : VisibleSurface(display_, rtScheduler_, eventDistributor_,
24  inputEventGenerator_, cliComm_)
25 {
26  int flags = 0;
27  createSurface(width, height, flags);
28  const SDL_Surface* surf = getSDLSurface();
29  setSDLFormat(*surf->format);
30  setBufferPtr(static_cast<char*>(surf->pixels), surf->pitch);
31 
32  // In the SDL renderer logical size is the same as physical size.
34 }
35 
36 void SDLVisibleSurface::flushFrameBuffer()
37 {
38  unlock();
39  SDL_Surface* surf = getSDLSurface();
40  SDL_Renderer* render = getSDLRenderer();
41  SDL_UpdateTexture(texture.get(), nullptr, surf->pixels, surf->pitch);
42  SDL_RenderClear(render);
43  SDL_RenderCopy(render, texture.get(), nullptr, nullptr);
44 }
45 
46 void SDLVisibleSurface::finish()
47 {
48  SDL_RenderPresent(getSDLRenderer());
49 }
50 
51 std::unique_ptr<Layer> SDLVisibleSurface::createSnowLayer()
52 {
53  switch (getSDLFormat().BytesPerPixel) {
54 #if HAVE_16BPP
55  case 2:
56  return std::make_unique<SDLSnow<uint16_t>>(*this, getDisplay());
57 #endif
58 #if HAVE_32BPP
59  case 4:
60  return std::make_unique<SDLSnow<uint32_t>>(*this, getDisplay());
61 #endif
62  default:
63  UNREACHABLE; return nullptr;
64  }
65 }
66 
67 std::unique_ptr<Layer> SDLVisibleSurface::createConsoleLayer(
68  Reactor& reactor, CommandConsole& console)
69 {
70  const bool openGL = false;
71  return std::make_unique<OSDConsoleRenderer>(
72  reactor, console, getWidth(), getHeight(), openGL);
73 }
74 
75 std::unique_ptr<Layer> SDLVisibleSurface::createOSDGUILayer(OSDGUI& gui)
76 {
77  return std::make_unique<SDLOSDGUILayer>(gui);
78 }
79 
80 std::unique_ptr<OutputSurface> SDLVisibleSurface::createOffScreenSurface()
81 {
82  return std::make_unique<SDLOffScreenSurface>(*getSDLSurface());
83 }
84 
85 void SDLVisibleSurface::saveScreenshot(const std::string& filename)
86 {
87  saveScreenshotSDL(*this, filename);
88 }
89 
91  const OutputSurface& output, const std::string& filename)
92 {
93  unsigned width = output.getWidth();
94  unsigned height = output.getHeight();
95  VLA(const void*, rowPointers, height);
96  MemBuffer<uint8_t> buffer(width * height * 3);
97  for (unsigned i = 0; i < height; ++i) {
98  rowPointers[i] = &buffer[width * 3 * i];
99  }
100  if (SDL_RenderReadPixels(
101  output.getSDLRenderer(), nullptr,
102  SDL_PIXELFORMAT_RGB24, buffer.data(), width * 3)) {
103  throw MSXException("Couldn't acquire screenshot pixels: ", SDL_GetError());
104  }
105  PNG::save(width, height, rowPointers, filename);
106 }
107 
108 void SDLVisibleSurface::clearScreen()
109 {
110  unlock();
111  SDL_FillRect(getSDLSurface(), nullptr, 0);
112 }
113 
114 } // namespace openmsx
Contains the main loop of openMSX.
Definition: Reactor.hh:66
SDL_Renderer * getSDLRenderer() const
void setBufferPtr(char *data, unsigned pitch)
Represents the output window/screen of openMSX.
Definition: Display.hh:31
SDLVisibleSurface(unsigned width, unsigned height, Display &display, RTScheduler &rtScheduler, EventDistributor &eventDistributor, InputEventGenerator &inputEventGenerator, CliComm &cliComm)
gl::ivec2 getLogicalSize() const
A frame buffer where pixels can be written to.
Display & getDisplay() const
static void saveScreenshotSDL(const OutputSurface &output, const std::string &filename)
void setSDLFormat(const SDL_PixelFormat &format)
constexpr const char *const filename
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:90
An OutputSurface which is visible to the user, such as a window or a full screen display.
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
SDL_Surface * getSDLSurface() const
void unlock()
Unlock this OutputSurface.
void createSurface(int width, int height, unsigned flags)
void calculateViewPort(gl::ivec2 physSize)
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:10
const SDL_PixelFormat & getSDLFormat() const
#define UNREACHABLE
Definition: unreachable.hh:38