SuperImposedFrame.cc 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #include "SuperImposedFrame.hh"
  2. #include "PixelOperations.hh"
  3. #include "LineScalers.hh"
  4. #include "unreachable.hh"
  5. #include "vla.hh"
  6. #include "build-info.hh"
  7. #include <algorithm>
  8. #include <cstdint>
  9. #include <memory>
  10. namespace openmsx {
  11. template <typename Pixel>
  12. class SuperImposedFrameImpl final : public SuperImposedFrame
  13. {
  14. public:
  15. explicit SuperImposedFrameImpl(const PixelFormat& format);
  16. private:
  17. unsigned getLineWidth(unsigned line) const override;
  18. const void* getLineInfo(
  19. unsigned line, unsigned& width,
  20. void* buf, unsigned bufWidth) const override;
  21. PixelOperations<Pixel> pixelOps;
  22. };
  23. // class SuperImposedFrame
  24. std::unique_ptr<SuperImposedFrame> SuperImposedFrame::create(
  25. const PixelFormat& format)
  26. {
  27. #if HAVE_16BPP
  28. if (format.getBytesPerPixel() == 2) {
  29. return std::make_unique<SuperImposedFrameImpl<uint16_t>>(format);
  30. }
  31. #endif
  32. #if HAVE_32BPP
  33. if (format.getBytesPerPixel() == 4) {
  34. return std::make_unique<SuperImposedFrameImpl<uint32_t>>(format);
  35. }
  36. #endif
  37. UNREACHABLE; return nullptr; // avoid warning
  38. }
  39. SuperImposedFrame::SuperImposedFrame(const PixelFormat& format)
  40. : FrameSource(format)
  41. {
  42. }
  43. void SuperImposedFrame::init(
  44. const FrameSource* top_, const FrameSource* bottom_)
  45. {
  46. top = top_;
  47. bottom = bottom_;
  48. setHeight(std::max(top->getHeight(), bottom->getHeight()));
  49. }
  50. // class SuperImposedFrameImpl
  51. template <typename Pixel>
  52. SuperImposedFrameImpl<Pixel>::SuperImposedFrameImpl(
  53. const PixelFormat& format)
  54. : SuperImposedFrame(format)
  55. , pixelOps(format)
  56. {
  57. }
  58. template <typename Pixel>
  59. unsigned SuperImposedFrameImpl<Pixel>::getLineWidth(unsigned line) const
  60. {
  61. unsigned tNum = (getHeight() == top ->getHeight()) ? line : line / 2;
  62. unsigned bNum = (getHeight() == bottom->getHeight()) ? line : line / 2;
  63. unsigned tWidth = top ->getLineWidth(tNum);
  64. unsigned bWidth = bottom->getLineWidth(bNum);
  65. return std::max(tWidth, bWidth);
  66. }
  67. template <typename Pixel>
  68. const void* SuperImposedFrameImpl<Pixel>::getLineInfo(
  69. unsigned line, unsigned& width, void* buf, unsigned bufWidth) const
  70. {
  71. unsigned tNum = (getHeight() == top ->getHeight()) ? line : line / 2;
  72. unsigned bNum = (getHeight() == bottom->getHeight()) ? line : line / 2;
  73. unsigned tWidth = top ->getLineWidth(tNum);
  74. unsigned bWidth = bottom->getLineWidth(bNum);
  75. width = std::max(tWidth, bWidth); // as wide as the widest source
  76. width = std::min(width, bufWidth); // but no wider than the output buffer
  77. auto* tBuf = static_cast<Pixel*>(buf);
  78. VLA_SSE_ALIGNED(Pixel, bBuf, width);
  79. auto* tLine = top ->getLinePtr(tNum, width, tBuf);
  80. auto* bLine = bottom->getLinePtr(bNum, width, bBuf);
  81. AlphaBlendLines<Pixel> blend(pixelOps);
  82. blend(tLine, bLine, tBuf, width); // possibly tLine == tBuf
  83. return tBuf;
  84. }
  85. } // namespace openmsx