OutputSurface.hh 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #ifndef OUTPUTSURFACE_HH
  2. #define OUTPUTSURFACE_HH
  3. #include "PixelFormat.hh"
  4. #include "gl_vec.hh"
  5. #include <string>
  6. #include <cassert>
  7. #include <cstdint>
  8. namespace openmsx {
  9. /** A frame buffer where pixels can be written to.
  10. * It could be an in-memory buffer or a video buffer visible to the user
  11. * (see *OffScreenSurface and *VisibleSurface classes).
  12. *
  13. * The OutputSurface class itself knows about its dimensions and pixel format.
  14. * But the actual pixel storage is left for the subclasses.
  15. */
  16. class OutputSurface
  17. {
  18. public:
  19. OutputSurface(const OutputSurface&) = delete;
  20. OutputSurface& operator=(const OutputSurface&) = delete;
  21. virtual ~OutputSurface() = default;
  22. int getLogicalWidth() const { return m_logicalSize[0]; }
  23. int getLogicalHeight() const { return m_logicalSize[1]; }
  24. gl::ivec2 getLogicalSize() const { return m_logicalSize; }
  25. gl::ivec2 getPhysicalSize() const { return m_physSize; }
  26. gl::ivec2 getViewOffset() const { return m_viewOffset; }
  27. gl::ivec2 getViewSize() const { return m_viewSize; }
  28. gl::vec2 getViewScale() const { return m_viewScale; }
  29. bool isViewScaled() const { return m_viewScale != gl::vec2(1.0f); }
  30. const PixelFormat& getPixelFormat() const { return pixelFormat; }
  31. /** Returns the pixel value for the given RGB color.
  32. * No effort is made to ensure that the returned pixel value is not the
  33. * color key for this output surface.
  34. */
  35. uint32_t mapRGB(gl::vec3 rgb) const
  36. {
  37. return mapRGB255(gl::ivec3(rgb * 255.0f));
  38. }
  39. /** Same as mapRGB, but RGB components are in range [0..255].
  40. */
  41. uint32_t mapRGB255(gl::ivec3 rgb) const
  42. {
  43. auto [r, g, b] = rgb;
  44. return getPixelFormat().map(r, g, b);
  45. }
  46. /** Returns the color key for this output surface.
  47. */
  48. template<typename Pixel> inline Pixel getKeyColor() const
  49. {
  50. return sizeof(Pixel) == 2
  51. ? 0x0001 // lowest bit of 'some' color component is set
  52. : 0x00000000; // alpha = 0
  53. }
  54. /** Returns a color that is visually very close to the key color.
  55. * The returned color can be used as an alternative for pixels that would
  56. * otherwise have the key color.
  57. */
  58. template<typename Pixel> inline Pixel getKeyColorClash() const
  59. {
  60. assert(sizeof(Pixel) != 4); // shouldn't get clashes in 32bpp
  61. return 0; // is visually very close, practically
  62. // indistinguishable, from the actual KeyColor
  63. }
  64. /** Returns the pixel value for the given RGB color.
  65. * It is guaranteed that the returned pixel value is different from the
  66. * color key for this output surface.
  67. */
  68. template<typename Pixel> Pixel mapKeyedRGB255(gl::ivec3 rgb)
  69. {
  70. Pixel p = mapRGB255(rgb);
  71. if (sizeof(Pixel) == 2) {
  72. return (p != getKeyColor<Pixel>())
  73. ? p
  74. : getKeyColorClash<Pixel>();
  75. } else {
  76. assert(p != getKeyColor<Pixel>());
  77. return p;
  78. }
  79. }
  80. /** Returns the pixel value for the given RGB color.
  81. * It is guaranteed that the returned pixel value is different from the
  82. * color key for this output surface.
  83. */
  84. template<typename Pixel> Pixel mapKeyedRGB(gl::vec3 rgb)
  85. {
  86. return mapKeyedRGB255<Pixel>(gl::ivec3(rgb * 255.0f));
  87. }
  88. /** Save the content of this OutputSurface to a PNG file.
  89. * @throws MSXException If creating the PNG file fails.
  90. */
  91. virtual void saveScreenshot(const std::string& filename) = 0;
  92. protected:
  93. OutputSurface() = default;
  94. // These two _must_ be called from (each) subclass constructor.
  95. void calculateViewPort(gl::ivec2 logSize, gl::ivec2 physSize);
  96. void setPixelFormat(const PixelFormat& format) { pixelFormat = format; }
  97. void setOpenGlPixelFormat();
  98. private:
  99. PixelFormat pixelFormat;
  100. gl::ivec2 m_logicalSize;
  101. gl::ivec2 m_physSize;
  102. gl::ivec2 m_viewOffset;
  103. gl::ivec2 m_viewSize;
  104. gl::vec2 m_viewScale{1.0f};
  105. };
  106. } // namespace openmsx
  107. #endif