123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- #ifndef OUTPUTSURFACE_HH
- #define OUTPUTSURFACE_HH
- #include "PixelFormat.hh"
- #include "gl_vec.hh"
- #include <string>
- #include <cassert>
- #include <cstdint>
- namespace openmsx {
- /** A frame buffer where pixels can be written to.
- * It could be an in-memory buffer or a video buffer visible to the user
- * (see *OffScreenSurface and *VisibleSurface classes).
- *
- * The OutputSurface class itself knows about its dimensions and pixel format.
- * But the actual pixel storage is left for the subclasses.
- */
- class OutputSurface
- {
- public:
- OutputSurface(const OutputSurface&) = delete;
- OutputSurface& operator=(const OutputSurface&) = delete;
- virtual ~OutputSurface() = default;
- int getLogicalWidth() const { return m_logicalSize[0]; }
- int getLogicalHeight() const { return m_logicalSize[1]; }
- gl::ivec2 getLogicalSize() const { return m_logicalSize; }
- gl::ivec2 getPhysicalSize() const { return m_physSize; }
- gl::ivec2 getViewOffset() const { return m_viewOffset; }
- gl::ivec2 getViewSize() const { return m_viewSize; }
- gl::vec2 getViewScale() const { return m_viewScale; }
- bool isViewScaled() const { return m_viewScale != gl::vec2(1.0f); }
- const PixelFormat& getPixelFormat() const { return pixelFormat; }
- /** Returns the pixel value for the given RGB color.
- * No effort is made to ensure that the returned pixel value is not the
- * color key for this output surface.
- */
- uint32_t mapRGB(gl::vec3 rgb) const
- {
- return mapRGB255(gl::ivec3(rgb * 255.0f));
- }
- /** Same as mapRGB, but RGB components are in range [0..255].
- */
- uint32_t mapRGB255(gl::ivec3 rgb) const
- {
- auto [r, g, b] = rgb;
- return getPixelFormat().map(r, g, b);
- }
- /** Returns the color key for this output surface.
- */
- template<typename Pixel> inline Pixel getKeyColor() const
- {
- return sizeof(Pixel) == 2
- ? 0x0001 // lowest bit of 'some' color component is set
- : 0x00000000; // alpha = 0
- }
- /** Returns a color that is visually very close to the key color.
- * The returned color can be used as an alternative for pixels that would
- * otherwise have the key color.
- */
- template<typename Pixel> inline Pixel getKeyColorClash() const
- {
- assert(sizeof(Pixel) != 4); // shouldn't get clashes in 32bpp
- return 0; // is visually very close, practically
- // indistinguishable, from the actual KeyColor
- }
- /** Returns the pixel value for the given RGB color.
- * It is guaranteed that the returned pixel value is different from the
- * color key for this output surface.
- */
- template<typename Pixel> Pixel mapKeyedRGB255(gl::ivec3 rgb)
- {
- Pixel p = mapRGB255(rgb);
- if (sizeof(Pixel) == 2) {
- return (p != getKeyColor<Pixel>())
- ? p
- : getKeyColorClash<Pixel>();
- } else {
- assert(p != getKeyColor<Pixel>());
- return p;
- }
- }
- /** Returns the pixel value for the given RGB color.
- * It is guaranteed that the returned pixel value is different from the
- * color key for this output surface.
- */
- template<typename Pixel> Pixel mapKeyedRGB(gl::vec3 rgb)
- {
- return mapKeyedRGB255<Pixel>(gl::ivec3(rgb * 255.0f));
- }
- /** Save the content of this OutputSurface to a PNG file.
- * @throws MSXException If creating the PNG file fails.
- */
- virtual void saveScreenshot(const std::string& filename) = 0;
- protected:
- OutputSurface() = default;
- // These two _must_ be called from (each) subclass constructor.
- void calculateViewPort(gl::ivec2 logSize, gl::ivec2 physSize);
- void setPixelFormat(const PixelFormat& format) { pixelFormat = format; }
- void setOpenGlPixelFormat();
- private:
- PixelFormat pixelFormat;
- gl::ivec2 m_logicalSize;
- gl::ivec2 m_physSize;
- gl::ivec2 m_viewOffset;
- gl::ivec2 m_viewSize;
- gl::vec2 m_viewScale{1.0f};
- };
- } // namespace openmsx
- #endif
|