StretchScalerOutput.cc 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. #include "StretchScalerOutput.hh"
  2. #include "DirectScalerOutput.hh"
  3. #include "LineScalers.hh"
  4. #include "PixelOperations.hh"
  5. #include "MemoryOps.hh"
  6. #include "build-info.hh"
  7. #include <cstdint>
  8. #include <memory>
  9. #include <vector>
  10. using std::unique_ptr;
  11. namespace openmsx {
  12. template<typename Pixel>
  13. class StretchScalerOutputBase : public ScalerOutput<Pixel>
  14. {
  15. public:
  16. StretchScalerOutputBase(unique_ptr<ScalerOutput<Pixel>> output,
  17. PixelOperations<Pixel> pixelOps);
  18. ~StretchScalerOutputBase() override;
  19. unsigned getWidth() const override;
  20. unsigned getHeight() const override;
  21. Pixel* acquireLine(unsigned y) override;
  22. void fillLine (unsigned y, Pixel color) override;
  23. protected:
  24. Pixel* releasePre(unsigned y, Pixel* buf);
  25. void releasePost(unsigned y, Pixel* dstLine);
  26. const PixelOperations<Pixel> pixelOps;
  27. private:
  28. unique_ptr<ScalerOutput<Pixel>> output;
  29. std::vector<Pixel*> pool;
  30. };
  31. template<typename Pixel>
  32. class StretchScalerOutput : public StretchScalerOutputBase<Pixel>
  33. {
  34. public:
  35. StretchScalerOutput(unique_ptr<ScalerOutput<Pixel>> output,
  36. PixelOperations<Pixel> pixelOps,
  37. unsigned inWidth);
  38. void releaseLine(unsigned y, Pixel* buf) override;
  39. private:
  40. unsigned inWidth;
  41. };
  42. template<typename Pixel, unsigned IN_WIDTH, typename SCALE>
  43. class StretchScalerOutputN : public StretchScalerOutputBase<Pixel>
  44. {
  45. public:
  46. StretchScalerOutputN(unique_ptr<ScalerOutput<Pixel>> output,
  47. PixelOperations<Pixel> pixelOps);
  48. void releaseLine(unsigned y, Pixel* buf) override;
  49. };
  50. template<typename Pixel>
  51. class StretchScalerOutput256
  52. : public StretchScalerOutputN<Pixel, 256, Scale_4on5<Pixel>>
  53. {
  54. public:
  55. StretchScalerOutput256(unique_ptr<ScalerOutput<Pixel>> output,
  56. PixelOperations<Pixel> pixelOps);
  57. };
  58. template<typename Pixel>
  59. class StretchScalerOutput272
  60. : public StretchScalerOutputN<Pixel, 272, Scale_17on20<Pixel>>
  61. {
  62. public:
  63. StretchScalerOutput272(unique_ptr<ScalerOutput<Pixel>> output,
  64. PixelOperations<Pixel> pixelOps);
  65. };
  66. template<typename Pixel>
  67. class StretchScalerOutput280
  68. : public StretchScalerOutputN<Pixel, 280, Scale_7on8<Pixel>>
  69. {
  70. public:
  71. StretchScalerOutput280(unique_ptr<ScalerOutput<Pixel>> output,
  72. PixelOperations<Pixel> pixelOps);
  73. };
  74. template<typename Pixel>
  75. class StretchScalerOutput288
  76. : public StretchScalerOutputN<Pixel, 288, Scale_9on10<Pixel>>
  77. {
  78. public:
  79. StretchScalerOutput288(unique_ptr<ScalerOutput<Pixel>> output,
  80. PixelOperations<Pixel> pixelOps);
  81. };
  82. // class StretchScalerOutputBase
  83. template<typename Pixel>
  84. StretchScalerOutputBase<Pixel>::StretchScalerOutputBase(
  85. unique_ptr<ScalerOutput<Pixel>> output_,
  86. PixelOperations<Pixel> pixelOps_)
  87. : pixelOps(std::move(pixelOps_))
  88. , output(std::move(output_))
  89. {
  90. }
  91. template<typename Pixel>
  92. StretchScalerOutputBase<Pixel>::~StretchScalerOutputBase()
  93. {
  94. for (auto& p : pool) {
  95. MemoryOps::freeAligned(p);
  96. }
  97. }
  98. template<typename Pixel>
  99. unsigned StretchScalerOutputBase<Pixel>::getWidth() const
  100. {
  101. return output->getWidth();
  102. }
  103. template<typename Pixel>
  104. unsigned StretchScalerOutputBase<Pixel>::getHeight() const
  105. {
  106. return output->getHeight();
  107. }
  108. template<typename Pixel>
  109. Pixel* StretchScalerOutputBase<Pixel>::acquireLine(unsigned /*y*/)
  110. {
  111. if (!pool.empty()) {
  112. Pixel* buf = pool.back();
  113. pool.pop_back();
  114. return buf;
  115. } else {
  116. unsigned size = sizeof(Pixel) * output->getWidth();
  117. return static_cast<Pixel*>(MemoryOps::mallocAligned(64, size));
  118. }
  119. }
  120. template<typename Pixel>
  121. Pixel* StretchScalerOutputBase<Pixel>::releasePre(unsigned y, Pixel* buf)
  122. {
  123. pool.push_back(buf);
  124. return output->acquireLine(y);
  125. }
  126. template<typename Pixel>
  127. void StretchScalerOutputBase<Pixel>::releasePost(unsigned y, Pixel* dstLine)
  128. {
  129. output->releaseLine(y, dstLine);
  130. }
  131. template<typename Pixel>
  132. void StretchScalerOutputBase<Pixel>::fillLine(unsigned y, Pixel color)
  133. {
  134. Pixel* dstLine = output->acquireLine(y);
  135. MemoryOps::MemSet<Pixel> memset;
  136. memset(dstLine, output->getWidth(), color);
  137. output->releaseLine(y, dstLine);
  138. }
  139. // class StretchScalerOutput
  140. template<typename Pixel>
  141. StretchScalerOutput<Pixel>::StretchScalerOutput(
  142. unique_ptr<ScalerOutput<Pixel>> output_,
  143. PixelOperations<Pixel> pixelOps_,
  144. unsigned inWidth_)
  145. : StretchScalerOutputBase<Pixel>(std::move(output_), std::move(pixelOps_))
  146. , inWidth(inWidth_)
  147. {
  148. }
  149. template<typename Pixel>
  150. void StretchScalerOutput<Pixel>::releaseLine(unsigned y, Pixel* buf)
  151. {
  152. Pixel* dstLine = this->releasePre(y, buf);
  153. unsigned dstWidth = StretchScalerOutputBase<Pixel>::getWidth();
  154. unsigned srcWidth = (dstWidth / 320) * inWidth;
  155. unsigned srcOffset = (dstWidth - srcWidth) / 2;
  156. ZoomLine<Pixel> zoom(this->pixelOps);
  157. zoom(buf + srcOffset, srcWidth, dstLine, dstWidth);
  158. this->releasePost(y, dstLine);
  159. }
  160. // class StretchScalerOutputN
  161. template<typename Pixel, unsigned IN_WIDTH, typename SCALE>
  162. StretchScalerOutputN<Pixel, IN_WIDTH, SCALE>::StretchScalerOutputN(
  163. unique_ptr<ScalerOutput<Pixel>> output_,
  164. PixelOperations<Pixel> pixelOps_)
  165. : StretchScalerOutputBase<Pixel>(std::move(output_), std::move(pixelOps_))
  166. {
  167. }
  168. template<typename Pixel, unsigned IN_WIDTH, typename SCALE>
  169. void StretchScalerOutputN<Pixel, IN_WIDTH, SCALE>::releaseLine(unsigned y, Pixel* buf)
  170. {
  171. Pixel* dstLine = this->releasePre(y, buf);
  172. unsigned dstWidth = StretchScalerOutputBase<Pixel>::getWidth();
  173. unsigned srcWidth = (dstWidth / 320) * IN_WIDTH;
  174. unsigned srcOffset = (dstWidth - srcWidth) / 2;
  175. SCALE scale(this->pixelOps);
  176. scale(buf + srcOffset, dstLine, dstWidth);
  177. this->releasePost(y, dstLine);
  178. }
  179. // class StretchScalerOutput256
  180. template<typename Pixel>
  181. StretchScalerOutput256<Pixel>::StretchScalerOutput256(
  182. unique_ptr<ScalerOutput<Pixel>> output_,
  183. PixelOperations<Pixel> pixelOps_)
  184. : StretchScalerOutputN<Pixel, 256, Scale_4on5<Pixel>>(
  185. std::move(output_), std::move(pixelOps_))
  186. {
  187. }
  188. // class StretchScalerOutput272
  189. template<typename Pixel>
  190. StretchScalerOutput272<Pixel>::StretchScalerOutput272(
  191. unique_ptr<ScalerOutput<Pixel>> output_,
  192. PixelOperations<Pixel> pixelOps_)
  193. : StretchScalerOutputN<Pixel, 272, Scale_17on20<Pixel>>(
  194. std::move(output_), std::move(pixelOps_))
  195. {
  196. }
  197. // class StretchScalerOutput280
  198. template<typename Pixel>
  199. StretchScalerOutput280<Pixel>::StretchScalerOutput280(
  200. unique_ptr<ScalerOutput<Pixel>> output_,
  201. PixelOperations<Pixel> pixelOps_)
  202. : StretchScalerOutputN<Pixel, 280, Scale_7on8<Pixel>>(
  203. std::move(output_), std::move(pixelOps_))
  204. {
  205. }
  206. // class StretchScalerOutput288
  207. template<typename Pixel>
  208. StretchScalerOutput288<Pixel>::StretchScalerOutput288(
  209. unique_ptr<ScalerOutput<Pixel>> output_,
  210. PixelOperations<Pixel> pixelOps_)
  211. : StretchScalerOutputN<Pixel, 288, Scale_9on10<Pixel>>(
  212. std::move(output_), std::move(pixelOps_))
  213. {
  214. }
  215. // class StretchScalerOutputFactory
  216. template<typename Pixel>
  217. unique_ptr<ScalerOutput<Pixel>> StretchScalerOutputFactory<Pixel>::create(
  218. SDLOutputSurface& output,
  219. PixelOperations<Pixel> pixelOps,
  220. unsigned inWidth)
  221. {
  222. auto direct = std::make_unique<DirectScalerOutput<Pixel>>(output);
  223. switch (inWidth) {
  224. case 320:
  225. return direct;
  226. case 288:
  227. return std::make_unique<StretchScalerOutput288<Pixel>>(
  228. std::move(direct), std::move(pixelOps));
  229. case 280:
  230. return std::make_unique<StretchScalerOutput280<Pixel>>(
  231. std::move(direct), std::move(pixelOps));
  232. case 272:
  233. return std::make_unique<StretchScalerOutput272<Pixel>>(
  234. std::move(direct), std::move(pixelOps));
  235. case 256:
  236. return std::make_unique<StretchScalerOutput256<Pixel>>(
  237. std::move(direct), std::move(pixelOps));
  238. default:
  239. return std::make_unique<StretchScalerOutput<Pixel>>(
  240. std::move(direct), std::move(pixelOps), inWidth);
  241. }
  242. }
  243. // Force template instantiation.
  244. #if HAVE_16BPP
  245. template struct StretchScalerOutputFactory<uint16_t>;
  246. #endif
  247. #if HAVE_32BPP
  248. template struct StretchScalerOutputFactory<uint32_t>;
  249. #endif
  250. } // namespace openmsx