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 "Display.hh"
6#include "Renderer.hh"
7#include "RenderSettings.hh"
8#include "PostProcessor.hh"
9#include "MemoryOps.hh"
10#include "OutputSurface.hh"
11#include "enumerate.hh"
12#include "one_of.hh"
13#include "xrange.hh"
14#include <algorithm>
15#include <array>
16#include <cassert>
17#include <cstdint>
18#include <memory>
19
20using namespace gl;
21
22namespace openmsx {
23
25
28static constexpr int TICKS_LEFT_BORDER = 100 + 102;
29
34static constexpr int TICKS_VISIBLE_MIDDLE =
35 TICKS_LEFT_BORDER + (VDP::TICKS_PER_LINE - TICKS_LEFT_BORDER - 27) / 2;
36
43static constexpr int translateX(int absoluteX, bool narrow)
44{
45 int maxX = narrow ? 640 : 320;
46 if (absoluteX == VDP::TICKS_PER_LINE) return maxX;
47
48 // Note: The ROUND_MASK forces the ticks to a pixel (2-tick) boundary.
49 // If this is not done, rounding errors will occur.
50 const int ROUND_MASK = narrow ? ~1 : ~3;
51 int screenX =
52 ((absoluteX - (TICKS_VISIBLE_MIDDLE & ROUND_MASK))
53 >> (narrow ? 1 : 2))
54 + maxX / 2;
55 return std::max(screenX, 0);
56}
57
58inline void SDLRasterizer::renderBitmapLine(std::span<Pixel> buf, unsigned vramLine)
59{
60 if (vdp.getDisplayMode().isPlanar()) {
61 auto [vramPtr0, vramPtr1] =
62 vram.bitmapCacheWindow.getReadAreaPlanar<256>(vramLine * 256);
63 bitmapConverter.convertLinePlanar(buf, vramPtr0, vramPtr1);
64 } else {
65 auto vramPtr =
66 vram.bitmapCacheWindow.getReadArea<128>(vramLine * 128);
67 bitmapConverter.convertLine(buf, vramPtr);
68 }
69}
70
72 VDP& vdp_, Display& display, OutputSurface& screen_,
73 std::unique_ptr<PostProcessor> postProcessor_)
74 : vdp(vdp_), vram(vdp.getVRAM())
75 , screen(screen_)
76 , postProcessor(std::move(postProcessor_))
77 , workFrame(std::make_unique<RawFrame>(640, 240))
78 , renderSettings(display.getRenderSettings())
79 , characterConverter(vdp, subspan<16>(palFg), palBg)
80 , bitmapConverter(palFg, PALETTE256, V9958_COLORS)
81 , spriteConverter(vdp.getSpriteChecker(), palBg)
82{
83 // Init the palette.
84 precalcPalette();
85
86 // Initialize palette (avoid UMR)
87 if (!vdp.isMSX1VDP()) {
88 for (auto i : xrange(16)) {
89 palFg[i] = palFg[i + 16] = palBg[i] =
90 V9938_COLORS[0][0][0];
91 }
92 }
93
94 renderSettings.getGammaSetting() .attach(*this);
95 renderSettings.getBrightnessSetting() .attach(*this);
96 renderSettings.getContrastSetting() .attach(*this);
97 renderSettings.getColorMatrixSetting().attach(*this);
98}
99
101{
102 renderSettings.getColorMatrixSetting().detach(*this);
103 renderSettings.getGammaSetting() .detach(*this);
104 renderSettings.getBrightnessSetting() .detach(*this);
105 renderSettings.getContrastSetting() .detach(*this);
106}
107
109{
110 return postProcessor.get();
111}
112
114{
115 return postProcessor->needRender() &&
116 vdp.getMotherBoard().isActive() &&
118}
119
121{
122 // Init renderer state.
124 spriteConverter.setTransparency(vdp.getTransparency());
125
126 resetPalette();
127}
128
129void SDLRasterizer::resetPalette()
130{
131 if (!vdp.isMSX1VDP()) {
132 // Reset the palette.
133 for (auto i : xrange(16)) {
134 setPalette(i, vdp.getPalette(i));
135 }
136 }
137}
138
140{
141 postProcessor->setSuperimposeVideoFrame(videoSource);
142 precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
143 videoSource, vdp.getBackgroundColor());
144}
145
146void SDLRasterizer::frameStart(EmuTime::param time)
147{
148 workFrame = postProcessor->rotateFrames(std::move(workFrame), time);
149 workFrame->init(
153
154 // Calculate line to render at top of screen.
155 // Make sure the display area is centered.
156 // 240 - 212 = 28 lines available for top/bottom border; 14 each.
157 // NTSC: display at [32..244),
158 // PAL: display at [59..271).
159 lineRenderTop = vdp.isPalTiming() ? 59 - 14 : 32 - 14;
160}
161
163{
164}
165
167{
168 if (mode.isBitmapMode()) {
169 bitmapConverter.setDisplayMode(mode);
170 } else {
171 characterConverter.setDisplayMode(mode);
172 }
173 precalcColorIndex0(mode, vdp.getTransparency(),
175 spriteConverter.setDisplayMode(mode);
176 spriteConverter.setPalette(mode.getByte() == DisplayMode::GRAPHIC7
177 ? palGraphic7Sprites : palBg);
178
179}
180
181void SDLRasterizer::setPalette(unsigned index, int grb)
182{
183 // Update SDL colors in palette.
184 Pixel newColor = V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
185 palFg[index ] = newColor;
186 palFg[index + 16] = newColor;
187 palBg[index ] = newColor;
188 bitmapConverter.palette16Changed();
189
190 precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
192}
193
195{
197 precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
198 vdp.isSuperimposing(), index);
199 }
200}
201
203{
204}
205
207{
208}
209
210void SDLRasterizer::setBorderMask(bool /*masked*/)
211{
212}
213
215{
216 spriteConverter.setTransparency(enabled);
217 precalcColorIndex0(vdp.getDisplayMode(), enabled,
219}
220
221void SDLRasterizer::precalcPalette()
222{
223 if (vdp.isMSX1VDP()) {
224 // Fixed palette.
225 const auto palette = vdp.getMSX1Palette();
226 for (auto i : xrange(16)) {
227 const auto rgb = palette[i];
228 palFg[i] = palFg[i + 16] = palBg[i] =
229 screen.mapRGB(
230 renderSettings.transformRGB(
231 vec3(rgb[0], rgb[1], rgb[2]) * (1.0f / 255.0f)));
232 }
233 } else {
234 if (vdp.hasYJK()) {
235 // Precalculate palette for V9958 colors.
236 if (renderSettings.isColorMatrixIdentity()) {
237 // Most users use the "normal" monitor type; making this a
238 // special case speeds up palette precalculation a lot.
239 std::array<int, 32> intensity;
240 for (auto [i, r] : enumerate(intensity)) {
241 r = narrow_cast<int>(255.0f * renderSettings.transformComponent(narrow<float>(i) * (1.0f / 31.0f)));
242 }
243 for (auto [rgb, col] : enumerate(V9958_COLORS)) {
244 col = screen.mapRGB255(ivec3(
245 intensity[(rgb >> 10) & 31],
246 intensity[(rgb >> 5) & 31],
247 intensity[(rgb >> 0) & 31]));
248 }
249 } else {
250 for (auto r : xrange(32)) {
251 for (auto g : xrange(32)) {
252 for (auto b : xrange(32)) {
253 vec3 rgb{narrow<float>(r),
254 narrow<float>(g),
255 narrow<float>(b)};
256 V9958_COLORS[(r << 10) + (g << 5) + b] =
257 screen.mapRGB(
258 renderSettings.transformRGB(rgb * (1.0f / 31.0f)));
259 }
260 }
261 }
262 }
263 // Precalculate palette for V9938 colors.
264 // Based on comparing red and green gradients, using palette and
265 // YJK, in SCREEN11 on a real turbo R.
266 for (auto r3 : xrange(8)) {
267 int r5 = (r3 << 2) | (r3 >> 1);
268 for (auto g3 : xrange(8)) {
269 int g5 = (g3 << 2) | (g3 >> 1);
270 for (auto b3 : xrange(8)) {
271 int b5 = (b3 << 2) | (b3 >> 1);
272 V9938_COLORS[r3][g3][b3] =
273 V9958_COLORS[(r5 << 10) + (g5 << 5) + b5];
274 }
275 }
276 }
277 } else {
278 // Precalculate palette for V9938 colors.
279 if (renderSettings.isColorMatrixIdentity()) {
280 std::array<int, 8> intensity;
281 for (auto [i, r] : enumerate(intensity)) {
282 r = narrow_cast<int>(255.0f * renderSettings.transformComponent(narrow<float>(i) * (1.0f / 7.0f)));
283 }
284 for (auto r : xrange(8)) {
285 for (auto g : xrange(8)) {
286 for (auto b : xrange(8)) {
287 V9938_COLORS[r][g][b] =
288 screen.mapRGB255(ivec3(
289 intensity[r],
290 intensity[g],
291 intensity[b]));
292 }
293 }
294 }
295 } else {
296 for (auto r : xrange(8)) {
297 for (auto g : xrange(8)) {
298 for (auto b : xrange(8)) {
299 vec3 rgb{narrow<float>(r),
300 narrow<float>(g),
301 narrow<float>(b)};
302 V9938_COLORS[r][g][b] =
303 screen.mapRGB(
304 renderSettings.transformRGB(rgb * (1.0f / 7.0f)));
305 }
306 }
307 }
308 }
309 }
310 // Precalculate Graphic 7 bitmap palette.
311 for (auto i : xrange(256)) {
312 PALETTE256[i] = V9938_COLORS
313 [(i & 0x1C) >> 2]
314 [(i & 0xE0) >> 5]
315 [(i & 0x03) == 3 ? 7 : (i & 0x03) * 2];
316 }
317 // Precalculate Graphic 7 sprite palette.
318 for (auto i : xrange(16)) {
319 uint16_t grb = Renderer::GRAPHIC7_SPRITE_PALETTE[i];
320 palGraphic7Sprites[i] =
321 V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
322 }
323 }
324}
325
326void SDLRasterizer::precalcColorIndex0(DisplayMode mode,
327 bool transparency, const RawFrame* superimposing, byte bgColorIndex)
328{
329 // Graphic7 mode doesn't use transparency.
330 if (mode.getByte() == DisplayMode::GRAPHIC7) {
331 transparency = false;
332 }
333
334 int tpIndex = transparency ? bgColorIndex : 0;
335 if (mode.getBase() != DisplayMode::GRAPHIC5) {
336 Pixel c = (superimposing && (bgColorIndex == 0))
337 ? screen.getKeyColor()
338 : palBg[tpIndex];
339
340 if (palFg[0] != c) {
341 palFg[0] = c;
342 bitmapConverter.palette16Changed();
343 }
344 } else {
345 // TODO: superimposing
346 if ((palFg[ 0] != palBg[tpIndex >> 2]) ||
347 (palFg[16] != palBg[tpIndex & 3])) {
348 palFg[ 0] = palBg[tpIndex >> 2];
349 palFg[16] = palBg[tpIndex & 3];
350 bitmapConverter.palette16Changed();
351 }
352 }
353}
354
355std::pair<Pixel, Pixel> SDLRasterizer::getBorderColors()
356{
357 DisplayMode mode = vdp.getDisplayMode();
358 int bgColor = vdp.getBackgroundColor();
359 if (mode.getBase() == DisplayMode::GRAPHIC5) {
360 // border in SCREEN6 has separate color for even and odd pixels.
361 // TODO odd/even swapped?
362 return {palBg[(bgColor & 0x0C) >> 2],
363 palBg[(bgColor & 0x03) >> 0]};
364 }
365 Pixel col = [&] { // other modes only have a single border color
366 if (mode.getByte() == DisplayMode::GRAPHIC7) {
367 return PALETTE256[bgColor];
368 } else {
369 if (!bgColor && vdp.isSuperimposing()) {
370 return screen.getKeyColor();
371 } else {
372 return palBg[bgColor];
373 }
374 }
375 }();
376 return {col, col};
377}
378
380 int fromX, int fromY, int limitX, int limitY)
381{
382 auto [border0, border1] = getBorderColors();
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 (auto y : xrange(startY, endY)) {
390 workFrame->setBlank(y, border0);
391 // setBlank() implies this line is not suitable
392 // for left/right border optimization in a later
393 // frame.
394 }
395 } else {
396 unsigned lineWidth = vdp.getDisplayMode().getLineWidth();
397 unsigned x = translateX(fromX, (lineWidth == 512));
398 unsigned num = translateX(limitX, (lineWidth == 512)) - x;
399 unsigned width = (lineWidth == 512) ? 640 : 320;
401 for (auto y : xrange(startY, endY)) {
402 memset(workFrame->getLineDirect(y).subspan(x, num),
403 border0, border1);
404 if (limitX == VDP::TICKS_PER_LINE) {
405 // Only set line width at the end (right
406 // border) of the line. This ensures we can
407 // keep testing the width of the previous
408 // version of this line for all (partial)
409 // updates of this line.
410 workFrame->setLineWidth(y, width);
411 }
412 }
413 }
414}
415
417 int /*fromX*/, int fromY,
418 int displayX, int displayY,
419 int displayWidth, int displayHeight)
420{
421 // Note: we don't call workFrame->setLineWidth() because that's done in
422 // drawBorder() (for the right border). And the value we set there is
423 // anyway the same as the one we would set here.
424 DisplayMode mode = vdp.getDisplayMode();
425 unsigned lineWidth = mode.getLineWidth();
426 if (lineWidth == 256) {
427 int endX = displayX + displayWidth;
428 displayX /= 2;
429 displayWidth = endX / 2 - displayX;
430 }
431
432 // Clip to screen area.
433 int screenLimitY = std::min(
434 fromY + displayHeight - lineRenderTop,
435 240);
436 int screenY = fromY - lineRenderTop;
437 if (screenY < 0) {
438 displayY -= screenY;
439 //fromY = lineRenderTop;
440 screenY = 0;
441 }
442 displayHeight = screenLimitY - screenY;
443 if (displayHeight <= 0) return;
444
445 int leftBackground =
446 translateX(vdp.getLeftBackground(), lineWidth == 512);
447 // TODO: Find out why this causes 1-pixel jitter:
448 //dest.x = translateX(fromX);
449 unsigned hScroll =
450 mode.isTextMode()
451 ? 0
452 : 8 * (lineWidth / 256) * (vdp.getHorizontalScrollHigh() & 0x1F);
453
454 // Page border is display X coordinate where to stop drawing current page.
455 // This is either the multi page split point, or the right edge of the
456 // rectangle to draw, whichever comes first.
457 // Note that it is possible for pageBorder to be to the left of displayX,
458 // in that case only the second page should be drawn.
459 int pageBorder = displayX + displayWidth;
460 auto [scrollPage1, scrollPage2] = [&]() -> std::pair<int, int> {
461 if (vdp.isMultiPageScrolling()) {
462 int p1 = vdp.getHorizontalScrollHigh() >> 5;
463 int p2 = p1 ^ 1;
464 return {p1, p2};
465 } else {
466 return {0, 0};
467 }
468 }();
469 // Because SDL blits do not wrap, unlike GL textures, the pageBorder is
470 // also used if multi page is disabled.
471 if (int pageSplit = narrow<int>(lineWidth - hScroll);
472 pageSplit < pageBorder) {
473 pageBorder = pageSplit;
474 }
475
476 if (mode.isBitmapMode()) {
477 for (auto y : xrange(screenY, screenLimitY)) {
478 // Which bits in the name mask determine the page?
479 // TODO optimize this?
480 // Calculating pageMaskOdd/Even is a non-trivial amount
481 // of work. We used to do this per frame (more or less)
482 // but now do it per line. Per-line is actually only
483 // needed when vdp.isFastBlinkEnabled() is true.
484 // Idea: can be cheaply calculated incrementally.
485 unsigned pageMaskOdd = (mode.isPlanar() ? 0x000 : 0x200) |
486 vdp.getEvenOddMask(y);
487 unsigned pageMaskEven = vdp.isMultiPageScrolling()
488 ? (pageMaskOdd & ~0x100)
489 : pageMaskOdd;
490 const std::array<unsigned, 2> vramLine = {
491 (vram.nameTable.getMask() >> 7) & (pageMaskEven | displayY),
492 (vram.nameTable.getMask() >> 7) & (pageMaskOdd | displayY)
493 };
494
495 std::array<Pixel, 512> buf;
496 auto lineInBuf = unsigned(-1); // buffer data not valid
497 auto dst = workFrame->getLineDirect(y).subspan(leftBackground + displayX);
498 int firstPageWidth = pageBorder - displayX;
499 if (firstPageWidth > 0) {
500 if (((displayX + hScroll) == 0) &&
501 (firstPageWidth == narrow<int>(lineWidth))) {
502 // fast-path, directly render to destination
503 renderBitmapLine(dst, vramLine[scrollPage1]);
504 } else {
505 lineInBuf = vramLine[scrollPage1];
506 renderBitmapLine(buf, vramLine[scrollPage1]);
507 auto src = subspan(buf, displayX + hScroll, firstPageWidth);
508 ranges::copy(src, dst);
509 }
510 } else {
511 firstPageWidth = 0;
512 }
513 if (firstPageWidth < displayWidth) {
514 if (lineInBuf != vramLine[scrollPage2]) {
515 renderBitmapLine(buf, vramLine[scrollPage2]);
516 }
517 unsigned x = displayX < pageBorder
518 ? 0 : displayX + hScroll - lineWidth;
519 ranges::copy(subspan(buf, x, displayWidth - firstPageWidth),
520 subspan(dst, firstPageWidth));
521 }
522
523 displayY = (displayY + 1) & 255;
524 }
525 } else {
526 // horizontal scroll (high) is implemented in CharacterConverter
527 for (auto y : xrange(screenY, screenLimitY)) {
528 assert(!vdp.isMSX1VDP() || displayY < 192);
529
530 auto dst = workFrame->getLineDirect(y).subspan(leftBackground + displayX);
531 if ((displayX == 0) && (displayWidth == narrow<int>(lineWidth))){
532 characterConverter.convertLine(dst, displayY);
533 } else {
534 std::array<Pixel, 512> buf;
535 characterConverter.convertLine(buf, displayY);
536 auto src = subspan(buf, displayX, displayWidth);
537 ranges::copy(src, dst);
538 }
539
540 displayY = (displayY + 1) & 255;
541 }
542 }
543}
544
546 int /*fromX*/, int fromY,
547 int displayX, int /*displayY*/,
548 int displayWidth, int displayHeight)
549{
550 // Clip to screen area.
551 // TODO: Code duplicated from drawDisplay.
552 int screenLimitY = std::min(
553 fromY + displayHeight - lineRenderTop,
554 240);
555 int screenY = fromY - lineRenderTop;
556 if (screenY < 0) {
557 fromY = lineRenderTop;
558 screenY = 0;
559 }
560 displayHeight = screenLimitY - screenY;
561 if (displayHeight <= 0) return;
562
563 // Render sprites.
564 // TODO: Call different SpriteConverter methods depending on narrow/wide
565 // pixels in this display mode?
566 int spriteMode = vdp.getDisplayMode().getSpriteMode(vdp.isMSX1VDP());
567 int displayLimitX = displayX + displayWidth;
568 int limitY = fromY + displayHeight;
569 int screenX = translateX(
570 vdp.getLeftSprites(),
571 vdp.getDisplayMode().getLineWidth() == 512);
572 if (spriteMode == 1) {
573 for (int y = fromY; y < limitY; y++, screenY++) {
574 auto dst = workFrame->getLineDirect(screenY).subspan(screenX);
575 spriteConverter.drawMode1(y, displayX, displayLimitX, dst);
576 }
577 } else {
578 byte mode = vdp.getDisplayMode().getByte();
579 if (mode == DisplayMode::GRAPHIC5) {
580 for (int y = fromY; y < limitY; y++, screenY++) {
581 auto dst = workFrame->getLineDirect(screenY).subspan(screenX);
582 spriteConverter.template drawMode2<DisplayMode::GRAPHIC5>(
583 y, displayX, displayLimitX, dst);
584 }
585 } else if (mode == DisplayMode::GRAPHIC6) {
586 for (int y = fromY; y < limitY; y++, screenY++) {
587 auto dst = workFrame->getLineDirect(screenY).subspan(screenX);
588 spriteConverter.template drawMode2<DisplayMode::GRAPHIC6>(
589 y, displayX, displayLimitX, dst);
590 }
591 } else {
592 for (int y = fromY; y < limitY; y++, screenY++) {
593 auto dst = workFrame->getLineDirect(screenY).subspan(screenX);
594 spriteConverter.template drawMode2<DisplayMode::GRAPHIC4>(
595 y, displayX, displayLimitX, dst);
596 }
597 }
598 }
599}
600
602{
603 return postProcessor->isRecording();
604}
605
606void SDLRasterizer::update(const Setting& setting) noexcept
607{
608 if (&setting == one_of(&renderSettings.getGammaSetting(),
609 &renderSettings.getBrightnessSetting(),
610 &renderSettings.getContrastSetting(),
611 &renderSettings.getColorMatrixSetting())) {
612 precalcPalette();
613 resetPalette();
614 }
615}
616
617} // namespace openmsx
BaseSetting * setting
int g
void convertLinePlanar(std::span< Pixel > buf, std::span< const byte, 128 > vramPtr0, std::span< const byte, 128 > vramPtr1)
Convert a line of V9938 VRAM to 256 or 512 host pixels.
void convertLine(std::span< Pixel > buf, std::span< const byte, 128 > vramPtr)
Convert a line of V9938 VRAM to 256 or 512 host pixels.
void palette16Changed()
Inform this class about changes in the palette16 array.
void setDisplayMode(DisplayMode mode_)
Select the display mode to use for scanline conversion.
void setDisplayMode(DisplayMode mode)
Select the display mode to use for scanline conversion.
void convertLine(std::span< Pixel > buf, int line) const
Convert a line of V9938 VRAM to 256 or 512 host pixels.
Represents a VDP display mode.
constexpr bool isPlanar() const
Is VRAM "planar" in the current display mode? Graphic 6 and 7 spread their bytes over two VRAM ICs,...
constexpr unsigned getLineWidth() const
Get number of pixels on a display line in this mode.
constexpr bool isBitmapMode() const
Is the current mode a bitmap mode? Graphic4 and higher are bitmap modes.
constexpr bool isTextMode() const
Is the current mode a text mode? Text1 and Text2 are text modes.
constexpr byte getByte() const
Get the display mode as a byte: YAE YJK M5..M1 combined.
constexpr int getSpriteMode(bool isMSX1) const
Get the sprite mode of this display mode.
Represents the output window/screen of openMSX.
Definition Display.hh:32
@ FIELD_NONINTERLACED
Interlacing is off for this frame.
@ FIELD_EVEN
Interlacing is on and this is an even frame.
@ FIELD_ODD
Interlacing is on and this is an odd frame.
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition MSXDevice.cc:70
A frame buffer where pixels can be written to.
uint32_t mapRGB255(gl::ivec3 rgb) const
Same as mapRGB, but RGB components are in range [0..255].
Pixel getKeyColor() const
Returns the color key for this output surface.
uint32_t mapRGB(gl::vec3 rgb) const
Returns the pixel value for the given RGB color.
A post processor builds the frame that is displayed from the MSX frame, while applying effects such a...
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
Definition RawFrame.hh:16
float transformComponent(float c) const
Apply brightness, contrast and gamma transformation on the input color component.
gl::vec3 transformRGB(gl::vec3 rgb) const
Apply brightness, contrast and gamma transformation on the input color.
bool isColorMatrixIdentity() const
Returns true iff the current color matrix is the identity matrix.
FloatSetting & getContrastSetting()
Contrast video setting.
FloatSetting & getBrightnessSetting()
Brightness video setting.
FloatSetting & getGammaSetting()
The amount of gamma correction.
StringSetting & getColorMatrixSetting()
Color matrix setting.
static constexpr std::array< uint16_t, 16 > GRAPHIC7_SPRITE_PALETTE
Sprite palette in Graphic 7 mode.
Definition Renderer.hh:186
PostProcessor * getPostProcessor() const override
See VDP::getPostProcessor().
bool isActive() override
Will the output of this Rasterizer be displayed? There is no point in producing a frame that will not...
void setBackgroundColor(byte index) override
Changes the background color.
void drawDisplay(int fromX, int fromY, int displayX, int displayY, int displayWidth, int displayHeight) override
Render a rectangle of display pixels on the host screen.
void setPalette(unsigned index, int grb) override
Change an entry in the palette.
void frameEnd() override
Indicates the end of the current frame.
void setBorderMask(bool masked) override
void frameStart(EmuTime::param time) override
Indicates the start of a new frame.
void setHorizontalAdjust(int adjust) override
SDLRasterizer(VDP &vdp, Display &display, OutputSurface &screen, std::unique_ptr< PostProcessor > postProcessor)
void setDisplayMode(DisplayMode mode) override
Precalc several values that depend on the display mode.
void drawBorder(int fromX, int fromY, int limitX, int limitY) override
Render a rectangle of border pixels on the host screen.
void drawSprites(int fromX, int fromY, int displayX, int displayY, int displayWidth, int displayHeight) override
Render a rectangle of sprite pixels on the host screen.
void reset() override
Resynchronize with VDP: all cached states are flushed.
bool isRecording() const override
Is video recording active?
void setTransparency(bool enabled) override
void setSuperimposeVideoFrame(const RawFrame *videoSource) override
void setHorizontalScrollLow(byte scroll) override
void drawMode1(int absLine, int minX, int maxX, std::span< Pixel > pixelPtr) const
Draw sprites in sprite mode 1.
void setTransparency(bool enabled)
Update the transparency setting.
void setDisplayMode(DisplayMode newMode)
Notify SpriteConverter of a display mode change.
void setPalette(std::span< const Pixel, 16 > newPalette)
Set palette to use for converting sprites.
void detach(Observer< T > &observer)
Definition Subject.hh:60
void attach(Observer< T > &observer)
Definition Subject.hh:54
VRAMWindow bitmapCacheWindow
Definition VDPVRAM.hh:693
VRAMWindow nameTable
Definition VDPVRAM.hh:689
Unified implementation of MSX Video Display Processors (VDPs).
Definition VDP.hh:66
bool getEvenOdd() const
Is the even or odd field being displayed?
Definition VDP.hh:438
unsigned getEvenOddMask() const
Expresses the state of even/odd page interchange in a mask on the line number.
Definition VDP.hh:453
int getLeftBackground() const
Gets the number of VDP clock ticks between start of line and the time when the background pixel with ...
Definition VDP.hh:625
std::array< std::array< uint8_t, 3 >, 16 > getMSX1Palette() const
Get the (fixed) palette for this MSX1 VDP.
Definition VDP.cc:1541
const RawFrame * isSuperimposing() const
Are we currently superimposing? In case of superimpose, returns a pointer to the to-be-superimposed f...
Definition VDP.hh:169
static constexpr int TICKS_PER_LINE
Number of VDP clock ticks per line.
Definition VDP.hh:75
uint16_t getPalette(unsigned index) const
Gets a palette entry.
Definition VDP.hh:278
byte getHorizontalScrollHigh() const
Gets the current horizontal scroll higher bits.
Definition VDP.hh:348
DisplayMode getDisplayMode() const
Get the display mode the VDP is in.
Definition VDP.hh:155
bool isMSX1VDP() const
Is this an MSX1 VDP?
Definition VDP.hh:107
byte getBackgroundColor() const
Gets the current background color.
Definition VDP.hh:218
bool hasYJK() const
Does this VDP support YJK display?
Definition VDP.hh:142
bool isMultiPageScrolling() const
Is multi page scrolling enabled? It is considered enabled if both the multi page scrolling flag is en...
Definition VDP.hh:367
bool isPalTiming() const
Is PAL timing active? This setting is fixed at start of frame.
Definition VDP.hh:390
bool isInterlaced() const
Get interlace status.
Definition VDP.hh:401
bool getTransparency() const
Gets the current transparency setting.
Definition VDP.hh:188
int getLeftSprites() const
Gets the number of VDP clock ticks between start of line and the start of the sprite plane.
Definition VDP.hh:597
unsigned getMask() const
Gets the mask for this window.
Definition VDPVRAM.hh:147
std::pair< std::span< const byte, size/2 >, std::span< const byte, size/2 > > getReadAreaPlanar(unsigned index) const
Similar to getReadArea(), but now with planar addressing mode.
Definition VDPVRAM.hh:245
std::span< const byte, size > getReadArea(unsigned index) const
Gets a span of a contiguous part of the VRAM.
Definition VDPVRAM.hh:228
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition enumerate.hh:28
Definition gl_mat.hh:23
vecN< 3, int > ivec3
Definition gl_vec.hh:182
This file implemented 3 utility functions:
Definition Autofire.cc:11
CharacterConverter::Pixel Pixel
auto copy(InputRange &&range, OutputIter out)
Definition ranges.hh:250
STL namespace.
constexpr To narrow(From from) noexcept
Definition narrow.hh:37
constexpr auto subspan(Range &&range, size_t offset, size_t count=std::dynamic_extent)
Definition ranges.hh:471
constexpr auto xrange(T e)
Definition xrange.hh:132