openMSX
SDLRasterizer.cc
Go to the documentation of this file.
1 #include "SDLRasterizer.hh"
2 #include "VDP.hh"
3 #include "VDPVRAM.hh"
4 #include "RawFrame.hh"
5 #include "CharacterConverter.hh"
6 #include "BitmapConverter.hh"
7 #include "SpriteConverter.hh"
8 #include "MSXMotherBoard.hh"
9 #include "Display.hh"
10 #include "Renderer.hh"
11 #include "RenderSettings.hh"
12 #include "PostProcessor.hh"
13 #include "FloatSetting.hh"
14 #include "StringSetting.hh"
15 #include "MemoryOps.hh"
16 #include "VisibleSurface.hh"
17 #include "memory.hh"
18 #include "build-info.hh"
19 #include "components.hh"
20 #include <algorithm>
21 #include <cassert>
22 #include <cstdint>
23 
24 namespace openmsx {
25 
28 static const int TICKS_LEFT_BORDER = 100 + 102;
29 
34 static const int TICKS_VISIBLE_MIDDLE =
35  TICKS_LEFT_BORDER + (VDP::TICKS_PER_LINE - TICKS_LEFT_BORDER - 27) / 2;
36 
37 template <class Pixel>
38 inline int SDLRasterizer<Pixel>::translateX(int absoluteX, bool narrow)
39 {
40  int maxX = narrow ? 640 : 320;
41  if (absoluteX == VDP::TICKS_PER_LINE) return maxX;
42 
43  // Note: The ROUND_MASK forces the ticks to a pixel (2-tick) boundary.
44  // If this is not done, rounding errors will occur.
45  // This is especially tricky because division of a negative number
46  // is rounded towards zero instead of down.
47  const int ROUND_MASK = narrow ? ~1 : ~3;
48  int screenX =
49  ((absoluteX & ROUND_MASK) - (TICKS_VISIBLE_MIDDLE & ROUND_MASK))
50  / (narrow ? 2 : 4)
51  + maxX / 2;
52  return std::max(screenX, 0);
53 }
54 
55 template <class Pixel>
56 inline void SDLRasterizer<Pixel>::renderBitmapLine(Pixel* buf, unsigned vramLine)
57 {
58  if (vdp.getDisplayMode().isPlanar()) {
59  const byte* vramPtr0;
60  const byte* vramPtr1;
61  vram.bitmapCacheWindow.getReadAreaPlanar(
62  vramLine * 256, 256, vramPtr0, vramPtr1);
63  bitmapConverter->convertLinePlanar(buf, vramPtr0, vramPtr1);
64  } else {
65  const byte* vramPtr =
66  vram.bitmapCacheWindow.getReadArea(vramLine * 128, 128);
67  bitmapConverter->convertLine(buf, vramPtr);
68  }
69 }
70 
71 template <class Pixel>
73  VDP& vdp_, Display& display, VisibleSurface& screen_,
74  std::unique_ptr<PostProcessor> postProcessor_)
75  : vdp(vdp_), vram(vdp.getVRAM())
76  , screen(screen_)
77  , postProcessor(std::move(postProcessor_))
78  , workFrame(make_unique<RawFrame>(screen.getSDLFormat(), 640, 240))
79  , renderSettings(display.getRenderSettings())
80  , characterConverter(make_unique<CharacterConverter<Pixel>>(
81  vdp, palFg, palBg))
82  , bitmapConverter(make_unique<BitmapConverter<Pixel>>(
83  palFg, PALETTE256, V9958_COLORS))
84  , spriteConverter(make_unique<SpriteConverter<Pixel>>(
85  vdp.getSpriteChecker()))
86 {
87  // Init the palette.
88  precalcPalette();
89 
90  // Initialize palette (avoid UMR)
91  if (!vdp.isMSX1VDP()) {
92  for (int i = 0; i < 16; ++i) {
93  palFg[i] = palFg[i + 16] = palBg[i] =
94  V9938_COLORS[0][0][0];
95  }
96  }
97 
98  renderSettings.getGamma() .attach(*this);
99  renderSettings.getBrightness() .attach(*this);
100  renderSettings.getContrast() .attach(*this);
101  renderSettings.getColorMatrix().attach(*this);
102 }
103 
104 template <class Pixel>
106 {
107  renderSettings.getColorMatrix().detach(*this);
108  renderSettings.getGamma() .detach(*this);
109  renderSettings.getBrightness() .detach(*this);
110  renderSettings.getContrast() .detach(*this);
111 }
112 
113 template <class Pixel>
115 {
116  return postProcessor.get();
117 }
118 
119 template <class Pixel>
121 {
122  return postProcessor->needRender() &&
123  vdp.getMotherBoard().isActive() &&
124  !vdp.getMotherBoard().isFastForwarding();
125 }
126 
127 template <class Pixel>
129 {
130  // Init renderer state.
131  setDisplayMode(vdp.getDisplayMode());
132  spriteConverter->setTransparency(vdp.getTransparency());
133 
134  resetPalette();
135 }
136 
137 template <class Pixel>
139 {
140  if (!vdp.isMSX1VDP()) {
141  // Reset the palette.
142  for (int i = 0; i < 16; i++) {
143  setPalette(i, vdp.getPalette(i));
144  }
145  }
146 }
147 
148 template<class Pixel>
150 {
151  postProcessor->setSuperimposeVideoFrame(videoSource);
152  precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
153  videoSource, vdp.getBackgroundColor());
154 }
155 
156 template <class Pixel>
158 {
159  workFrame = postProcessor->rotateFrames(std::move(workFrame),
160  vdp.isInterlaced()
161  ? (vdp.getEvenOdd() ? FrameSource::FIELD_ODD : FrameSource::FIELD_EVEN)
163  time);
164 
165  // Calculate line to render at top of screen.
166  // Make sure the display area is centered.
167  // 240 - 212 = 28 lines available for top/bottom border; 14 each.
168  // NTSC: display at [32..244),
169  // PAL: display at [59..271).
170  lineRenderTop = vdp.isPalTiming() ? 59 - 14 : 32 - 14;
171 }
172 
173 template <class Pixel>
175 {
176  // Nothing to do.
177 }
178 
179 template <class Pixel>
181 {
182  if (mode.isBitmapMode()) {
183  bitmapConverter->setDisplayMode(mode);
184  } else {
185  characterConverter->setDisplayMode(mode);
186  }
187  precalcColorIndex0(mode, vdp.getTransparency(),
188  vdp.isSuperimposing(), vdp.getBackgroundColor());
189  spriteConverter->setDisplayMode(mode);
190  spriteConverter->setPalette(mode.getByte() == DisplayMode::GRAPHIC7
191  ? palGraphic7Sprites : palBg);
192 }
193 
194 template <class Pixel>
195 void SDLRasterizer<Pixel>::setPalette(int index, int grb)
196 {
197  // Update SDL colors in palette.
198  Pixel newColor = V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
199  palFg[index ] = newColor;
200  palFg[index + 16] = newColor;
201  palBg[index ] = newColor;
202  bitmapConverter->palette16Changed();
203 
204  precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
205  vdp.isSuperimposing(), vdp.getBackgroundColor());
206 }
207 
208 template <class Pixel>
210 {
211  precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
212  vdp.isSuperimposing(), index);
213 }
214 
215 template <class Pixel>
217 {
218  spriteConverter->setTransparency(enabled);
219  precalcColorIndex0(vdp.getDisplayMode(), enabled,
220  vdp.isSuperimposing(), vdp.getBackgroundColor());
221 }
222 
223 template <class Pixel>
225 {
226  if (vdp.isMSX1VDP()) {
227  // Fixed palette.
228  for (int i = 0; i < 16; i++) {
229  const byte* rgb = Renderer::TMS99X8A_PALETTE[i];
230  double dr = rgb[0] / 255.0;
231  double dg = rgb[1] / 255.0;
232  double db = rgb[2] / 255.0;
233  renderSettings.transformRGB(dr, dg, db);
234  palFg[i] = palFg[i + 16] = palBg[i] =
235  screen.mapKeyedRGB<Pixel>(dr, dg, db);
236  }
237  } else {
238  if (vdp.hasYJK()) {
239  // Precalculate palette for V9958 colors.
240  if (renderSettings.isColorMatrixIdentity()) {
241  // Most users use the "normal" monitor type; making this a
242  // special case speeds up palette precalculation a lot.
243  int intensity[32];
244  for (int i = 0; i < 32; i++) {
245  intensity[i] =
246  int(255 * renderSettings.transformComponent(i / 31.0));
247  }
248  for (int rgb = 0; rgb < (1 << 15); rgb++) {
249  V9958_COLORS[rgb] = screen.mapKeyedRGB<Pixel>(
250  intensity[(rgb >> 10) ],
251  intensity[(rgb >> 5) & 31],
252  intensity[ rgb & 31]);
253  }
254  } else {
255  for (int r5 = 0; r5 < 32; r5++) {
256  for (int g5 = 0; g5 < 32; g5++) {
257  for (int b5 = 0; b5 < 32; b5++) {
258  double dr = r5 / 31.0;
259  double dg = g5 / 31.0;
260  double db = b5 / 31.0;
261  renderSettings.transformRGB(dr, dg, db);
262  V9958_COLORS[(r5<<10) + (g5<<5) + b5] =
263  screen.mapKeyedRGB<Pixel>(dr, dg, db);
264  }
265  }
266  }
267  }
268  // Precalculate palette for V9938 colors.
269  // Based on comparing red and green gradients, using palette and
270  // YJK, in SCREEN11 on a real turbo R.
271  for (int r3 = 0; r3 < 8; r3++) {
272  int r5 = (r3 << 2) | (r3 >> 1);
273  for (int g3 = 0; g3 < 8; g3++) {
274  int g5 = (g3 << 2) | (g3 >> 1);
275  for (int b3 = 0; b3 < 8; b3++) {
276  int b5 = (b3 << 2) | (b3 >> 1);
277  V9938_COLORS[r3][g3][b3] =
278  V9958_COLORS[(r5<<10) + (g5<<5) + b5];
279  }
280  }
281  }
282  } else {
283  // Precalculate palette for V9938 colors.
284  if (renderSettings.isColorMatrixIdentity()) {
285  int intensity[8];
286  for (int i = 0; i < 8; i++) {
287  intensity[i] =
288  int(255 * renderSettings.transformComponent(i / 7.0));
289  }
290  for (int r3 = 0; r3 < 8; r3++) {
291  for (int g3 = 0; g3 < 8; g3++) {
292  for (int b3 = 0; b3 < 8; b3++) {
293  V9938_COLORS[r3][g3][b3] =
294  screen.mapKeyedRGB<Pixel>(
295  intensity[r3], intensity[g3], intensity[b3]
296  );
297  }
298  }
299  }
300  } else {
301  for (int r3 = 0; r3 < 8; r3++) {
302  for (int g3 = 0; g3 < 8; g3++) {
303  for (int b3 = 0; b3 < 8; b3++) {
304  double dr = r3 / 7.0;
305  double dg = g3 / 7.0;
306  double db = b3 / 7.0;
307  renderSettings.transformRGB(dr, dg, db);
308  V9938_COLORS[r3][g3][b3] =
309  screen.mapKeyedRGB<Pixel>(dr, dg, db);
310  }
311  }
312  }
313  }
314  }
315  // Precalculate Graphic 7 bitmap palette.
316  for (int i = 0; i < 256; i++) {
317  PALETTE256[i] = V9938_COLORS
318  [(i & 0x1C) >> 2]
319  [(i & 0xE0) >> 5]
320  [(i & 0x03) == 3 ? 7 : (i & 0x03) * 2];
321  }
322  // Precalculate Graphic 7 sprite palette.
323  for (int i = 0; i < 16; i++) {
324  uint16_t grb = Renderer::GRAPHIC7_SPRITE_PALETTE[i];
325  palGraphic7Sprites[i] =
326  V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
327  }
328  }
329 }
330 
331 template <class Pixel>
332 void SDLRasterizer<Pixel>::precalcColorIndex0(DisplayMode mode,
333  bool transparency, const RawFrame* superimposing, byte bgcolorIndex)
334 {
335  // Graphic7 mode doesn't use transparency.
336  if (mode.getByte() == DisplayMode::GRAPHIC7) {
337  transparency = false;
338  }
339 
340  int tpIndex = transparency ? bgcolorIndex : 0;
341  if (mode.getBase() != DisplayMode::GRAPHIC5) {
342  Pixel c = (superimposing && (bgcolorIndex == 0))
343  ? screen.getKeyColor<Pixel>()
344  : palBg[tpIndex];
345 
346  if (palFg[0] != c) {
347  palFg[0] = c;
348  bitmapConverter->palette16Changed();
349  }
350  } else {
351  // TODO: superimposing
352  if ((palFg[ 0] != palBg[tpIndex >> 2]) ||
353  (palFg[16] != palBg[tpIndex & 3])) {
354  palFg[ 0] = palBg[tpIndex >> 2];
355  palFg[16] = palBg[tpIndex & 3];
356  bitmapConverter->palette16Changed();
357  }
358  }
359 }
360 
361 template <class Pixel>
363  int fromX, int fromY, int limitX, int limitY)
364 {
365  DisplayMode mode = vdp.getDisplayMode();
366  byte modeBase = mode.getBase();
367  int bgColor = vdp.getBackgroundColor();
368  Pixel border0, border1;
369  if (modeBase == DisplayMode::GRAPHIC5) {
370  // border in SCREEN6 has separate color for even and odd pixels.
371  // TODO odd/even swapped?
372  border0 = palBg[(bgColor & 0x0C) >> 2];
373  border1 = palBg[(bgColor & 0x03) >> 0];
374  } else if (modeBase == DisplayMode::GRAPHIC7) {
375  border0 = border1 = PALETTE256[bgColor];
376  } else {
377  if (!bgColor && vdp.isSuperimposing()) {
378  border0 = border1 = screen.getKeyColor<Pixel>();
379  } else {
380  border0 = border1 = palBg[bgColor];
381  }
382  }
383 
384  int startY = std::max(fromY - lineRenderTop, 0);
385  int endY = std::min(limitY - lineRenderTop, 240);
386  if ((fromX == 0) && (limitX == VDP::TICKS_PER_LINE) &&
387  (border0 == border1)) {
388  // complete lines, non striped
389  for (int y = startY; y < endY; y++) {
390  workFrame->setBlank(y, border0);
391  }
392  } else {
393  unsigned lineWidth = mode.getLineWidth();
394  unsigned x = translateX(fromX, (lineWidth == 512));
395  unsigned num = translateX(limitX, (lineWidth == 512)) - x;
396  unsigned width = (lineWidth == 512) ? 640 : 320;
398  for (int y = startY; y < endY; ++y) {
399  memset(workFrame->getLinePtrDirect<Pixel>(y) + x,
400  num, border0, border1);
401  workFrame->setLineWidth(y, width);
402  }
403  }
404 }
405 
406 template <class Pixel>
408  int /*fromX*/, int fromY,
409  int displayX, int displayY,
410  int displayWidth, int displayHeight)
411 {
412  DisplayMode mode = vdp.getDisplayMode();
413  unsigned lineWidth = mode.getLineWidth();
414  if (lineWidth == 256) {
415  int endX = displayX + displayWidth;
416  displayX /= 2;
417  displayWidth = endX / 2 - displayX;
418  }
419 
420  // Clip to screen area.
421  int screenLimitY = std::min(
422  fromY + displayHeight - lineRenderTop,
423  240);
424  int screenY = fromY - lineRenderTop;
425  if (screenY < 0) {
426  displayY -= screenY;
427  fromY = lineRenderTop;
428  screenY = 0;
429  }
430  displayHeight = screenLimitY - screenY;
431  if (displayHeight <= 0) return;
432 
433  int leftBackground =
434  translateX(vdp.getLeftBackground(), lineWidth == 512);
435  // TODO: Find out why this causes 1-pixel jitter:
436  //dest.x = translateX(fromX);
437  int hScroll =
438  mode.isTextMode()
439  ? 0
440  : 8 * (lineWidth / 256) * (vdp.getHorizontalScrollHigh() & 0x1F);
441 
442  // Page border is display X coordinate where to stop drawing current page.
443  // This is either the multi page split point, or the right edge of the
444  // rectangle to draw, whichever comes first.
445  // Note that it is possible for pageBorder to be to the left of displayX,
446  // in that case only the second page should be drawn.
447  int pageBorder = displayX + displayWidth;
448  int scrollPage1, scrollPage2;
449  if (vdp.isMultiPageScrolling()) {
450  scrollPage1 = vdp.getHorizontalScrollHigh() >> 5;
451  scrollPage2 = scrollPage1 ^ 1;
452  } else {
453  scrollPage1 = 0;
454  scrollPage2 = 0;
455  }
456  // Because SDL blits do not wrap, unlike GL textures, the pageBorder is
457  // also used if multi page is disabled.
458  int pageSplit = lineWidth - hScroll;
459  if (pageSplit < pageBorder) {
460  pageBorder = pageSplit;
461  }
462 
463  if (mode.isBitmapMode()) {
464  // Which bits in the name mask determine the page?
465  int pageMaskOdd = (mode.isPlanar() ? 0x000 : 0x200) |
466  vdp.getEvenOddMask();
467  int pageMaskEven = vdp.isMultiPageScrolling()
468  ? (pageMaskOdd & ~0x100)
469  : pageMaskOdd;
470 
471  for (int y = screenY; y < screenLimitY; y++) {
472  const int vramLine[2] = {
473  (vram.nameTable.getMask() >> 7) & (pageMaskEven | displayY),
474  (vram.nameTable.getMask() >> 7) & (pageMaskOdd | displayY)
475  };
476 
477  Pixel buf[512];
478  int lineInBuf = -1; // buffer data not valid
479  Pixel* dst = workFrame->getLinePtrDirect<Pixel>(y)
480  + leftBackground + displayX;
481  int firstPageWidth = pageBorder - displayX;
482  if (firstPageWidth > 0) {
483  if ((displayX + hScroll) == 0) {
484  renderBitmapLine(dst, vramLine[scrollPage1]);
485  } else {
486  lineInBuf = vramLine[scrollPage1];
487  renderBitmapLine(buf, vramLine[scrollPage1]);
488  const Pixel* src = buf + displayX + hScroll;
489  memcpy(dst, src, firstPageWidth * sizeof(Pixel));
490  }
491  } else {
492  firstPageWidth = 0;
493  }
494  if (firstPageWidth < displayWidth) {
495  if (lineInBuf != vramLine[scrollPage2]) {
496  renderBitmapLine(buf, vramLine[scrollPage2]);
497  }
498  unsigned x = displayX < pageBorder
499  ? 0 : displayX + hScroll - lineWidth;
500  memcpy(dst + firstPageWidth,
501  buf + x,
502  (displayWidth - firstPageWidth) * sizeof(Pixel));
503  }
504  workFrame->setLineWidth(y, (lineWidth == 512) ? 640 : 320);
505 
506  displayY = (displayY + 1) & 255;
507  }
508  } else {
509  // horizontal scroll (high) is implemented in CharacterConverter
510  for (int y = screenY; y < screenLimitY; y++) {
511  assert(!vdp.isMSX1VDP() || displayY < 192);
512 
513  Pixel* dst = workFrame->getLinePtrDirect<Pixel>(y)
514  + leftBackground + displayX;
515  if (displayX == 0) {
516  characterConverter->convertLine(dst, displayY);
517  } else {
518  Pixel buf[512];
519  characterConverter->convertLine(buf, displayY);
520  const Pixel* src = buf + displayX;
521  memcpy(dst, src, displayWidth * sizeof(Pixel));
522  }
523 
524  workFrame->setLineWidth(y, (lineWidth == 512) ? 640 : 320);
525  displayY = (displayY + 1) & 255;
526  }
527  }
528 }
529 
530 template <class Pixel>
532  int /*fromX*/, int fromY,
533  int displayX, int displayY,
534  int displayWidth, int displayHeight)
535 {
536  // Clip to screen area.
537  // TODO: Code duplicated from drawDisplay.
538  int screenLimitY = std::min(
539  fromY + displayHeight - lineRenderTop,
540  240);
541  int screenY = fromY - lineRenderTop;
542  if (screenY < 0) {
543  displayY -= screenY;
544  fromY = lineRenderTop;
545  screenY = 0;
546  }
547  displayHeight = screenLimitY - screenY;
548  if (displayHeight <= 0) return;
549 
550  // Render sprites.
551  // TODO: Call different SpriteConverter methods depending on narrow/wide
552  // pixels in this display mode?
553  int spriteMode = vdp.getDisplayMode().getSpriteMode();
554  int displayLimitX = displayX + displayWidth;
555  int limitY = fromY + displayHeight;
556  int screenX = translateX(
557  vdp.getLeftSprites(),
558  vdp.getDisplayMode().getLineWidth() == 512);
559  if (spriteMode == 1) {
560  for (int y = fromY; y < limitY; y++, screenY++) {
561  Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
562  spriteConverter->drawMode1(y, displayX, displayLimitX, pixelPtr);
563  }
564  } else {
565  byte mode = vdp.getDisplayMode().getByte();
566  if (mode == DisplayMode::GRAPHIC5) {
567  for (int y = fromY; y < limitY; y++, screenY++) {
568  Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
569  spriteConverter->template drawMode2<DisplayMode::GRAPHIC5>(
570  y, displayX, displayLimitX, pixelPtr);
571  }
572  } else if (mode == DisplayMode::GRAPHIC6) {
573  for (int y = fromY; y < limitY; y++, screenY++) {
574  Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
575  spriteConverter->template drawMode2<DisplayMode::GRAPHIC6>(
576  y, displayX, displayLimitX, pixelPtr);
577  }
578  } else {
579  for (int y = fromY; y < limitY; y++, screenY++) {
580  Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
581  spriteConverter->template drawMode2<DisplayMode::GRAPHIC4>(
582  y, displayX, displayLimitX, pixelPtr);
583  }
584  }
585  }
586 }
587 
588 template <class Pixel>
590 {
591  return postProcessor->isRecording();
592 }
593 
594 template <class Pixel>
595 void SDLRasterizer<Pixel>::update(const Setting& setting)
596 {
597  if ((&setting == &renderSettings.getGamma()) ||
598  (&setting == &renderSettings.getBrightness()) ||
599  (&setting == &renderSettings.getContrast()) ||
600  (&setting == &renderSettings.getColorMatrix())) {
601  precalcPalette();
602  resetPalette();
603  }
604 }
605 
606 
607 // Force template instantiation.
608 #if HAVE_16BPP
609 template class SDLRasterizer<uint16_t>;
610 #endif
611 #if HAVE_32BPP || COMPONENT_GL
612 template class SDLRasterizer<uint32_t>;
613 #endif
614 
615 } // namespace openmsx
Utility class for converting VRAM contents to host pixels.
bool isPlanar() const
Is VRAM "planar" in the current display mode? Graphic 6 and 7 spread their bytes over two VRAM ICs...
Definition: DisplayMode.hh:158
Represents the output window/screen of openMSX.
Definition: Display.hh:33
Utility class for converting VRAM contents to host pixels.
static const int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition: VDP.hh:77
Interlacing is on and this is an odd frame.
Definition: FrameSource.hh:29
virtual bool isRecording() const
Is video recording active?
bool isBitmapMode() const
Is the current mode a bitmap mode? Graphic4 and higher are bitmap modes.
Definition: DisplayMode.hh:148
unsigned char byte
8 bit unsigned integer
Definition: openmsx.hh:33
Rasterizer using a frame buffer approach: it writes pixels to a single rectangular pixel buffer...
virtual void setSuperimposeVideoFrame(const RawFrame *videoSource)
Represents a VDP display mode.
Definition: DisplayMode.hh:14
virtual bool isActive()
Will the output of this Rasterizer be displayed? There is no point in producing a frame that will not...
virtual void setPalette(int index, int grb)
Change an entry in the palette.
FloatSetting & getContrast() const
Contrast video setting.
void attach(Observer< T > &observer)
Definition: Subject.hh:51
virtual void frameStart(EmuTime::param time)
Indicates the start of a new frame.
FloatSetting & getGamma() const
The amount of gamma correction.
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition: RawFrame.hh:13
unsigned Pixel
bool isTextMode() const
Is the current mode a text mode? Text1 and Text2 are text modes.
Definition: DisplayMode.hh:138
static const uint8_t TMS99X8A_PALETTE[16][3]
NTSC version of the MSX1 palette.
Definition: Renderer.hh:184
bool isMSX1VDP() const
Is this an MSX1 VDP?
Definition: VDP.hh:99
An OutputSurface which is visible to the user, such as a window or a full screen display.
StringSetting & getColorMatrix() const
Color matrix setting.
Interlacing is on and this is an even frame.
Definition: FrameSource.hh:26
virtual void reset()
Resynchronize with VDP: all cached states are flushed.
byte getByte() const
Get the dispay mode as a byte: YAE YJK M5..M1 combined.
Definition: DisplayMode.hh:109
virtual void drawSprites(int fromX, int fromY, int displayX, int displayY, int displayWidth, int displayHeight)
Render a rectangle of sprite pixels on the host screen.
virtual void frameEnd()
Indicates the end of the current frame.
virtual void drawBorder(int fromX, int fromY, int limitX, int limitY)
Render a rectangle of border pixels on the host screen.
Unified implementation of MSX Video Display Processors (VDPs).
Definition: VDP.hh:66
Interlacing is off for this frame.
Definition: FrameSource.hh:23
Abstract base class for post processors.
virtual void setDisplayMode(DisplayMode mode)
Precalc several values that depend on the display mode.
FloatSetting & getBrightness() const
Brightness video setting.
virtual PostProcessor * getPostProcessor() const
See VDP::getPostProcessor().
static const uint16_t GRAPHIC7_SPRITE_PALETTE[16]
Sprite palette in Graphic 7 mode.
Definition: Renderer.hh:190
virtual void setTransparency(bool enabled)
virtual void setBackgroundColor(int index)
Changes the background color.
byte getBase() const
Get the base dispay mode as an integer: M5..M1 combined.
Definition: DisplayMode.hh:123
virtual void drawDisplay(int fromX, int fromY, int displayX, int displayY, int displayWidth, int displayHeight)
Render a rectangle of display pixels on the host screen.
unsigned getLineWidth() const
Get number of pixels on a display line in this mode.
Definition: DisplayMode.hh:184
SDLRasterizer(VDP &vdp, Display &display, VisibleSurface &screen, std::unique_ptr< PostProcessor > postProcessor)
std::unique_ptr< T > make_unique()
Definition: memory.hh:27
Utility class for converting VRAM contents to host pixels.