openMSX
PixelOperations.hh
Go to the documentation of this file.
1 #ifndef PIXELOPERATIONS_HH
2 #define PIXELOPERATIONS_HH
3 
4 #include "unreachable.hh"
5 #include "build-info.hh"
6 #include <SDL.h>
7 
8 namespace openmsx {
9 
10 template<typename Pixel> class PixelOpBase
11 {
12 public:
13  explicit PixelOpBase(const SDL_PixelFormat& format_)
14  : format(format_)
15  , blendMask(calcBlendMask())
16  {
17  }
18 
19  const SDL_PixelFormat& getSDLPixelFormat() const { return format; }
20 
21  inline int getRmask() const { return format.Rmask; }
22  inline int getGmask() const { return format.Gmask; }
23  inline int getBmask() const { return format.Bmask; }
24  inline int getAmask() const { return format.Amask; }
25  inline int getRshift() const { return format.Rshift; }
26  inline int getGshift() const { return format.Gshift; }
27  inline int getBshift() const { return format.Bshift; }
28  inline int getAshift() const { return format.Ashift; }
29  inline int getRloss() const { return format.Rloss; }
30  inline int getGloss() const { return format.Gloss; }
31  inline int getBloss() const { return format.Bloss; }
32  inline int getAloss() const { return format.Aloss; }
33 
41  inline Pixel getBlendMask() const { return blendMask; }
42 
47  static const bool IS_RGB565 = false;
48 
49 private:
50  inline Pixel calcBlendMask() const
51  {
52  int rBit = ~(getRmask() << 1) & getRmask();
53  int gBit = ~(getGmask() << 1) & getGmask();
54  int bBit = ~(getBmask() << 1) & getBmask();
55  return ~(rBit | gBit | bBit);
56  }
57 
58  const SDL_PixelFormat& format;
59 
66  const Pixel blendMask;
67 };
68 
69 // Specialization for 32bpp
70 // No need to store 'blendMask' in a member variable.
71 template<> class PixelOpBase<unsigned>
72 {
73 public:
74  explicit PixelOpBase(const SDL_PixelFormat& format_)
75  : format(format_) {}
76 
77  const SDL_PixelFormat& getSDLPixelFormat() const { return format; }
78 
79  inline int getRmask() const { return format.Rmask; }
80  inline int getGmask() const { return format.Gmask; }
81  inline int getBmask() const { return format.Bmask; }
82  inline int getAmask() const { return format.Amask; }
83  inline int getRshift() const { return format.Rshift; }
84  inline int getGshift() const { return format.Gshift; }
85  inline int getBshift() const { return format.Bshift; }
86  inline int getAshift() const { return format.Ashift; }
87  inline int getRloss() const { return 0; }
88  inline int getGloss() const { return 0; }
89  inline int getBloss() const { return 0; }
90  inline int getAloss() const { return 0; }
91 
92  inline unsigned getBlendMask() const { return 0xFEFEFEFE; }
93 
94  static const bool IS_RGB565 = false;
95 
96 private:
97  const SDL_PixelFormat& format;
98 };
99 
100 
101 #if PLATFORM_DINGUX
102 // Specialization for dingoo (16bpp)
103 // We know the exact pixel format for this platform. No need for any
104 // members in this class. All values can also be compile-time constant.
105 template<> class PixelOpBase<uint16_t>
106 {
107 public:
108  explicit PixelOpBase(const SDL_PixelFormat& /*format*/) {}
109 
110  const SDL_PixelFormat& getSDLPixelFormat() const
111  {
112  static SDL_PixelFormat format;
113  format.palette = nullptr;
114  format.BitsPerPixel = 16;
115  format.BytesPerPixel = 2;
116  format.Rloss = 3;
117  format.Gloss = 2;
118  format.Bloss = 3;
119  format.Aloss = 8;
120  format.Rshift = 0;
121  format.Gshift = 5;
122  format.Bshift = 11;
123  format.Ashift = 0;
124  format.Rmask = 0x001F;
125  format.Gmask = 0x07E0;
126  format.Bmask = 0xF800;
127  format.Amask = 0x0000;
128  return format;
129  }
130 
131  inline int getRmask() const { return 0x001F; }
132  inline int getGmask() const { return 0x07E0; }
133  inline int getBmask() const { return 0xF800; }
134  inline int getAmask() const { return 0x0000; }
135  inline int getRshift() const { return 0; }
136  inline int getGshift() const { return 5; }
137  inline int getBshift() const { return 11; }
138  inline int getAshift() const { return 0; }
139  inline int getRloss() const { return 3; }
140  inline int getGloss() const { return 2; }
141  inline int getBloss() const { return 3; }
142  inline int getAloss() const { return 8; }
143 
144  inline uint16_t getBlendMask() const { return 0xF7DE; }
145 
146  static const bool IS_RGB565 = true;
147 };
148 #endif
149 
150 
151 
152 template<typename Pixel> class PixelOperations : public PixelOpBase<Pixel>
153 {
154 public:
170 
171  explicit PixelOperations(const SDL_PixelFormat& format);
172 
175  inline unsigned red(Pixel p) const;
176  inline unsigned green(Pixel p) const;
177  inline unsigned blue(Pixel p) const;
178  inline unsigned alpha(Pixel p) const;
179 
180  // alpha is maximum
181  inline bool isFullyOpaque(Pixel p) const;
182  // alpha is minimum
183  inline bool isFullyTransparent(Pixel p) const;
184 
187  inline unsigned red256(Pixel p) const;
188  inline unsigned green256(Pixel p) const;
189  inline unsigned blue256(Pixel p) const;
190 
193  inline Pixel combine(unsigned r, unsigned g, unsigned b) const;
194  inline Pixel combine256(unsigned r, unsigned g, unsigned b) const;
195 
198  inline unsigned getMaxRed() const;
199  inline unsigned getMaxGreen() const;
200  inline unsigned getMaxBlue() const;
201 
206  template <unsigned w1, unsigned w2>
207  inline Pixel blend(Pixel p1, Pixel p2) const;
208  template <unsigned w1, unsigned w2, unsigned w3>
209  inline Pixel blend(Pixel p1, Pixel p2, Pixel p3) const;
210  template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
211  inline Pixel blend(Pixel p1, Pixel p2, Pixel p3, Pixel p4) const;
212  template <unsigned w1, unsigned w2, unsigned w3,
213  unsigned w4, unsigned w5, unsigned w6>
214  inline Pixel blend(Pixel p1, Pixel p2, Pixel p3,
215  Pixel p4, Pixel p5, Pixel p6) const;
216 
217  template <unsigned w1, unsigned w2>
218  inline Pixel blend2(const Pixel* p) const;
219  template <unsigned w1, unsigned w2, unsigned w3>
220  inline Pixel blend3(const Pixel* p) const;
221  template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
222  inline Pixel blend4(const Pixel* p) const;
223  template <unsigned w1, unsigned w2, unsigned w3,
224  unsigned w4, unsigned w5, unsigned w6>
225  inline Pixel blend6(const Pixel* p) const;
226 
235  static inline Pixel multiply(Pixel p, unsigned x);
236 
245  inline Pixel lerp(Pixel p1, Pixel p2, unsigned x) const;
246 
251  inline Pixel alphaBlend(Pixel p1, Pixel p2) const;
252 
253 private:
254  inline Pixel avgDown(Pixel p1, Pixel p2) const;
255  inline Pixel avgUp (Pixel p1, Pixel p2) const;
256 };
257 
258 
259 template <typename Pixel>
260 PixelOperations<Pixel>::PixelOperations(const SDL_PixelFormat& format_)
261  : PixelOpBase<Pixel>(format_)
262 {
263 }
264 
265 template <typename Pixel>
266 inline unsigned PixelOperations<Pixel>::red(Pixel p) const
267 {
268  if (sizeof(Pixel) == 4) {
269  return (p >> getRshift()) & 0xFF;
270  } else {
271  return (p & getRmask()) >> getRshift();
272  }
273 }
274 template <typename Pixel>
275 inline unsigned PixelOperations<Pixel>::green(Pixel p) const
276 {
277  if (sizeof(Pixel) == 4) {
278  return (p >> getGshift()) & 0xFF;
279  } else {
280  return (p & getGmask()) >> getGshift();
281  }
282 }
283 template <typename Pixel>
284 inline unsigned PixelOperations<Pixel>::blue(Pixel p) const
285 {
286  if (sizeof(Pixel) == 4) {
287  return (p >> getBshift()) & 0xFF;
288  } else {
289  return (p & getBmask()) >> getBshift();
290  }
291 }
292 template <typename Pixel>
293 inline unsigned PixelOperations<Pixel>::alpha(Pixel p) const
294 {
295  if (sizeof(Pixel) == 4) {
296  return (p >> getAshift()) & 0xFF;
297  } else {
298  UNREACHABLE; return 0;
299  //return (p & getAmask()) >> getAshift();
300  }
301 }
302 
303 template <typename Pixel>
305 {
306  if (sizeof(Pixel) == 4) {
307  return alpha(p) == 255;
308  } else {
309  return p != 0x0001;
310  }
311 }
312 template <typename Pixel>
314 {
315  if (sizeof(Pixel) == 4) {
316  return alpha(p) == 0;
317  } else {
318  return p == 0x0001;
319  }
320 }
321 
322 template <typename Pixel>
323 inline unsigned PixelOperations<Pixel>::red256(Pixel p) const
324 {
325  if (sizeof(Pixel) == 4) {
326  return (p >> getRshift()) & 0xFF;
327  } else {
328  return ((p >> getRshift()) << getRloss()) & 0xFF;
329  }
330 }
331 template <typename Pixel>
332 inline unsigned PixelOperations<Pixel>::green256(Pixel p) const
333 {
334  if (sizeof(Pixel) == 4) {
335  return (p >> getGshift()) & 0xFF;
336  } else {
337  return ((p >> getGshift()) << getGloss()) & 0xFF;
338  }
339 }
340 template <typename Pixel>
341 inline unsigned PixelOperations<Pixel>::blue256(Pixel p) const
342 {
343  if (sizeof(Pixel) == 4) {
344  return (p >> getBshift()) & 0xFF;
345  } else {
346  return ((p >> getBshift()) << getBloss()) & 0xFF;
347  }
348 }
349 
350 template <typename Pixel>
352  unsigned r, unsigned g, unsigned b) const
353 {
354  return Pixel((r << getRshift()) |
355  (g << getGshift()) |
356  (b << getBshift()));
357 }
358 
359 template <typename Pixel>
361  unsigned r, unsigned g, unsigned b) const
362 {
363  if (sizeof(Pixel) == 4) {
364  return Pixel((r << getRshift()) |
365  (g << getGshift()) |
366  (b << getBshift()));
367  } else {
368  return Pixel(((r >> getRloss()) << getRshift()) |
369  ((g >> getGloss()) << getGshift()) |
370  ((b >> getBloss()) << getBshift()));
371  }
372 }
373 
374 template <typename Pixel>
375 inline unsigned PixelOperations<Pixel>::getMaxRed() const
376 {
377  if (sizeof(Pixel) == 4) {
378  return 255;
379  } else {
380  return 255 >> getRloss();
381  }
382 }
383 template <typename Pixel>
384 inline unsigned PixelOperations<Pixel>::getMaxGreen() const
385 {
386  if (sizeof(Pixel) == 4) {
387  return 255;
388  } else {
389  return 255 >> getGloss();
390  }
391 }
392 template <typename Pixel>
393 inline unsigned PixelOperations<Pixel>::getMaxBlue() const
394 {
395  if (sizeof(Pixel) == 4) {
396  return 255;
397  } else {
398  return 255 >> getBloss();
399  }
400 }
401 
402 template<unsigned N> struct IsPow2 {
403  static const bool result = ((N & 1) == 0) && IsPow2<N / 2>::result;
404  static const unsigned log2 = 1 + IsPow2<N / 2>::log2;
405 };
406 template<> struct IsPow2<1> {
407  static const bool result = true;
408  static const unsigned log2 = 0;
409 };
410 
411 
412 template<typename Pixel>
414 {
415  // Average can be calculated as:
416  // floor((x + y) / 2.0) = (x & y) + (x ^ y) / 2
417  // see "Average of Integers" on http://aggregate.org/MAGIC/
418  return (p1 & p2) + (((p1 ^ p2) & getBlendMask()) >> 1);
419 }
420 template<typename Pixel>
421 inline Pixel PixelOperations<Pixel>::avgUp(Pixel p1, Pixel p2) const
422 {
423  // Similar to above, but rounds up
424  // ceil((x + y) / 2.0) = (x | y) - (x ^ y) / 2
425  return (p1 | p2) - (((p1 ^ p2) & getBlendMask()) >> 1);
426 }
427 
428 template<typename Pixel>
429 template<unsigned w1, unsigned w2>
431 {
432  static const unsigned total = w1 + w2;
433  if (w1 == 0) {
434  return p2;
435  } else if (w1 > w2) {
436  return blend<w2, w1>(p2, p1);
437 
438  } else if (w1 == w2) {
439  // <1,1>
440  return avgDown(p1, p2);
441  } else if ((3 * w1) == w2) {
442  // <1,3>
443  Pixel p11 = avgDown(p1, p2);
444  return avgUp(p11, p2);
445  } else if ((7 * w1) == w2) {
446  // <1,7>
447  Pixel p11 = avgDown(p1, p2);
448  Pixel p13 = avgDown(p11, p2);
449  return avgUp(p13, p2);
450  } else if ((5 * w1) == (3 * w2)) {
451  // <3,5> mix rounding up/down to get a more accurate result
452  Pixel p11 = avgUp (p1, p2);
453  Pixel p13 = avgDown(p11, p2);
454  return avgDown(p11, p13);
455 
456  } else if (!IsPow2<total>::result) {
457  // approximate with weights that sum to 256 (or 64)
458  // e.g. approximate <1,2> as <85,171> (or <21,43>)
459  // ww1 = round(256 * w1 / total) ww2 = 256 - ww1
460  static const unsigned newTotal = IS_RGB565 ? 64 : 256;
461  static const unsigned ww1 = (2 * w1 * newTotal + total) / (2 * total);
462  static const unsigned ww2 = 256 - ww1;
463  return blend<ww1, ww2>(p1, p2);
464 
465  } else if (sizeof(Pixel) == 4) {
466  unsigned l2 = IsPow2<total>::log2;
467  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
468  (p2 & 0x00FF00FF) * w2
469  ) >> l2) & 0x00FF00FF;
470  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
471  ((p2 & 0xFF00FF00) >> l2) * w2
472  ) & 0xFF00FF00;
473  return c1 | c2;
474 
475  } else if (IS_RGB565) {
476  if (total > 64) {
477  // reduce to maximum 6-bit
478  // note: DIV64 only exists to work around a
479  // division by zero in dead code
480  static const unsigned DIV64 = (total > 64) ? 64 : 1;
481  static const unsigned factor = total / DIV64;
482  static const unsigned round = factor / 2;
483  static const unsigned ww1 = (w1 + round) / factor;
484  static const unsigned ww2 = 64 - ww1;
485  return blend<ww1, ww2>(p1, p2);
486  } else {
487  unsigned l2 = IsPow2<total>::log2;
488  unsigned c1 = (((unsigned(p1) & 0xF81F) * w1) +
489  ((unsigned(p2) & 0xF81F) * w2)) & (0xF81F << l2);
490  unsigned c2 = (((unsigned(p1) & 0x07E0) * w1) +
491  ((unsigned(p2) & 0x07E0) * w2)) & (0x07E0 << l2);
492  return (c1 | c2) >> l2;
493  }
494 
495  } else {
496  // generic version
497  unsigned r = (red (p1) * w1 + red (p2) * w2) / total;
498  unsigned g = (green(p1) * w1 + green(p2) * w2) / total;
499  unsigned b = (blue (p1) * w1 + blue (p2) * w2) / total;
500  return combine(r, g, b);
501  }
502 }
503 
504 template <typename Pixel>
505 template <unsigned w1, unsigned w2, unsigned w3>
507 {
508  static const unsigned total = w1 + w2 + w3;
509  if ((sizeof(Pixel) == 4) && IsPow2<total>::result) {
510  unsigned l2 = IsPow2<total>::log2;
511  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
512  (p2 & 0x00FF00FF) * w2 +
513  (p3 & 0x00FF00FF) * w3) >> l2) & 0x00FF00FF;
514  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
515  ((p2 & 0xFF00FF00) >> l2) * w2 +
516  ((p3 & 0xFF00FF00) >> l2) * w3) & 0xFF00FF00;
517  return c1 | c2;
518  } else {
519  unsigned r = (red (p1) * w1 + red (p2) * w2 + red (p3) * w3) / total;
520  unsigned g = (green(p1) * w1 + green(p2) * w2 + green(p3) * w3) / total;
521  unsigned b = (blue (p1) * w1 + blue (p2) * w2 + blue (p3) * w3) / total;
522  return combine(r, g, b);
523  }
524 }
525 
526 template <typename Pixel>
527 template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
529  Pixel p1, Pixel p2, Pixel p3, Pixel p4) const
530 {
531  static const unsigned total = w1 + w2 + w3 + w4;
532  if ((sizeof(Pixel) == 4) && IsPow2<total>::result) {
533  unsigned l2 = IsPow2<total>::log2;
534  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
535  (p2 & 0x00FF00FF) * w2 +
536  (p3 & 0x00FF00FF) * w3 +
537  (p4 & 0x00FF00FF) * w4) >> l2) & 0x00FF00FF;
538  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
539  ((p2 & 0xFF00FF00) >> l2) * w2 +
540  ((p3 & 0xFF00FF00) >> l2) * w3 +
541  ((p4 & 0xFF00FF00) >> l2) * w4) & 0xFF00FF00;
542  return c1 | c2;
543  } else {
544  unsigned r = (red (p1) * w1 + red (p2) * w2 +
545  red (p3) * w3 + red (p4) * w4) / total;
546  unsigned g = (green(p1) * w1 + green(p2) * w2 +
547  green(p3) * w3 + green(p4) * w4) / total;
548  unsigned b = (blue (p1) * w1 + blue (p2) * w2 +
549  blue (p3) * w3 + blue (p4) * w4) / total;
550  return combine(r, g, b);
551  }
552 }
553 
554 template <typename Pixel>
555 template <unsigned w1, unsigned w2, unsigned w3,
556  unsigned w4, unsigned w5, unsigned w6>
558  Pixel p1, Pixel p2, Pixel p3, Pixel p4, Pixel p5, Pixel p6) const
559 {
560  static const unsigned total = w1 + w2 + w3 + w4 + w5 + w6;
561  if ((sizeof(Pixel) == 4) && IsPow2<total>::result) {
562  unsigned l2 = IsPow2<total>::log2;
563  unsigned c1 = (((p1 & 0x00FF00FF) * w1 +
564  (p2 & 0x00FF00FF) * w2 +
565  (p3 & 0x00FF00FF) * w3 +
566  (p4 & 0x00FF00FF) * w4 +
567  (p5 & 0x00FF00FF) * w5 +
568  (p6 & 0x00FF00FF) * w6) >> l2) & 0x00FF00FF;
569  unsigned c2 = (((p1 & 0xFF00FF00) >> l2) * w1 +
570  ((p2 & 0xFF00FF00) >> l2) * w2 +
571  ((p3 & 0xFF00FF00) >> l2) * w3 +
572  ((p4 & 0xFF00FF00) >> l2) * w4 +
573  ((p5 & 0xFF00FF00) >> l2) * w5 +
574  ((p6 & 0xFF00FF00) >> l2) * w6) & 0xFF00FF00;
575  return c1 | c2;
576  } else {
577  unsigned r = (red (p1) * w1 + red (p2) * w2 +
578  red (p3) * w3 + red (p4) * w4 +
579  red (p5) * w5 + red (p6) * w6) / total;
580  unsigned g = (green(p1) * w1 + green(p2) * w2 +
581  green(p3) * w3 + green(p4) * w4 +
582  green(p5) * w5 + green(p6) * w6) / total;
583  unsigned b = (blue (p1) * w1 + blue (p2) * w2 +
584  blue (p3) * w3 + blue (p4) * w4 +
585  blue (p5) * w5 + blue (p6) * w6) / total;
586  return combine(r, g, b);
587  }
588 }
589 
590 
591 template <typename Pixel>
592 template <unsigned w1, unsigned w2>
594 {
595  return blend<w1, w2>(p[0], p[1]);
596 }
597 
598 template <typename Pixel>
599 template <unsigned w1, unsigned w2, unsigned w3>
601 {
602  return blend<w1, w2, w3>(p[0], p[1], p[2]);
603 }
604 
605 template <typename Pixel>
606 template <unsigned w1, unsigned w2, unsigned w3, unsigned w4>
608 {
609  return blend<w1, w2, w3, w4>(p[0], p[1], p[2], p[3]);
610 }
611 
612 template <typename Pixel>
613 template <unsigned w1, unsigned w2, unsigned w3,
614  unsigned w4, unsigned w5, unsigned w6>
616 {
617  return blend<w1, w2, w3, w4, w5, w6>(p[0], p[1], p[2], p[3], p[4], p[5]);
618 }
619 
620 template <typename Pixel>
622 {
623  if (sizeof(Pixel) == 4) {
624  return ((((p & 0x00FF00FF) * x) & 0xFF00FF00) >> 8)
625  | ((((p >> 8) & 0x00FF00FF) * x) & 0xFF00FF00);
626  } else {
627  UNREACHABLE; return 0;
628  }
629 }
630 
631 template <typename Pixel>
632 inline Pixel PixelOperations<Pixel>::lerp(Pixel p1, Pixel p2, unsigned x) const
633 {
634  if (sizeof(Pixel) == 4) { // 32 bpp
635  unsigned rb1 = (p1 >> 0) & 0x00FF00FF;
636  unsigned ag1 = (p1 >> 8) & 0x00FF00FF;
637  unsigned rb2 = (p2 >> 0) & 0x00FF00FF;
638  unsigned ag2 = (p2 >> 8) & 0x00FF00FF;
639 
640  // Note: the subtraction for the lower component can 'borrow' from
641  // the higher component. Though in the full calculation this error
642  // magically cancels out.
643  unsigned trb = ((rb2 - rb1) * x) >> 8;
644  unsigned tag = ((ag2 - ag1) * x) >> 0;
645 
646  unsigned rb = ((trb + rb1) << 0) & 0x00FF00FF;
647  unsigned ag = (tag + (ag1 << 8)) & 0xFF00FF00;
648 
649  return rb | ag;
650 
651  } else if (IS_RGB565) {
652  unsigned rb1 = p1 & 0xF81F;
653  unsigned rb2 = p2 & 0xF81F;
654  unsigned g1 = p1 & 0x07E0;
655  unsigned g2 = p2 & 0x07E0;
656 
657  x >>= 2;
658  unsigned trb = ((rb2 - rb1) * x) >> 6;
659  unsigned tg = ((g2 - g1 ) * x) >> 6;
660 
661  unsigned rb = (trb + rb1) & 0xF81F;
662  unsigned g = (tg + g1 ) & 0x07E0;
663 
664  return rb | g;
665 
666  } else {
667  int r1 = red(p1), r2 = red(p2);
668  int g1 = green(p1), g2 = green(p2);
669  int b1 = blue(p1), b2 = blue(p2);
670 
671  // note: '/ 256' is not the same as '>> 8' for signed numbers
672  int r = ((r2 - r1) * x) / 256 + r1;
673  int g = ((g2 - g1) * x) / 256 + g1;
674  int b = ((b2 - b1) * x) / 256 + b1;
675 
676  return combine(r, g, b);
677  }
678 }
679 
680 template <typename Pixel>
682 {
683  if (sizeof(Pixel) == 2) {
684  // TODO keep magic value in sync with OutputSurface::getKeyColor()
685  return (p1 == 0x0001) ? p2 : p1;
686  } else {
687  unsigned a = alpha(p1);
688  // Note: 'a' is [0..255], while lerp() expects [0..256].
689  // We ignore this small error.
690  return lerp(p2, p1, a);
691  }
692 }
693 
694 } // namespace openmsx
695 
696 #endif
KeyCode combine(KeyCode key, KeyCode modifier)
Convenience method to create key combinations (hides ugly casts).
Definition: Keys.hh:317
Pixel getBlendMask() const
Returns a constant that is useful to calculate the average of two pixel values.
uint32_t Pixel
PixelOpBase(const SDL_PixelFormat &format_)
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
const SDL_PixelFormat & getSDLPixelFormat() const
PixelOperations(const SDL_PixelFormat &format)
const SDL_PixelFormat & getSDLPixelFormat() const
void format(SectorAccessibleDisk &disk, bool dos1)
Format the given disk (= a single partition).
PixelOpBase(const SDL_PixelFormat &format_)
static const bool IS_RGB565
Return true if it&#39;s statically known that the pixelformat has a 5-6-5 format (not specified wihich co...
#define UNREACHABLE
Definition: unreachable.hh:35