123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- #include "SDLRasterizer.hh"
- #include "VDP.hh"
- #include "VDPVRAM.hh"
- #include "RawFrame.hh"
- #include "Display.hh"
- #include "Renderer.hh"
- #include "RenderSettings.hh"
- #include "PostProcessor.hh"
- #include "MemoryOps.hh"
- #include "OutputSurface.hh"
- #include "one_of.hh"
- #include "build-info.hh"
- #include "components.hh"
- #include <algorithm>
- #include <cassert>
- #include <cstdint>
- #include <memory>
- using namespace gl;
- namespace openmsx {
- /** VDP ticks between start of line and start of left border.
- */
- constexpr int TICKS_LEFT_BORDER = 100 + 102;
- /** The middle of the visible (display + borders) part of a line,
- * expressed in VDP ticks since the start of the line.
- * TODO: Move this to a central location?
- */
- constexpr int TICKS_VISIBLE_MIDDLE =
- TICKS_LEFT_BORDER + (VDP::TICKS_PER_LINE - TICKS_LEFT_BORDER - 27) / 2;
- /** Translate from absolute VDP coordinates to screen coordinates:
- * Note: In reality, there are only 569.5 visible pixels on a line.
- * Because it looks better, the borders are extended to 640.
- * @param absoluteX Absolute VDP coordinate.
- * @param narrow Is this a narrow (512 pixels wide) display mode?
- */
- static inline int translateX(int absoluteX, bool narrow)
- {
- int maxX = narrow ? 640 : 320;
- if (absoluteX == VDP::TICKS_PER_LINE) return maxX;
- // Note: The ROUND_MASK forces the ticks to a pixel (2-tick) boundary.
- // If this is not done, rounding errors will occur.
- const int ROUND_MASK = narrow ? ~1 : ~3;
- int screenX =
- ((absoluteX - (TICKS_VISIBLE_MIDDLE & ROUND_MASK))
- >> (narrow ? 1 : 2))
- + maxX / 2;
- return std::max(screenX, 0);
- }
- template <class Pixel>
- inline void SDLRasterizer<Pixel>::renderBitmapLine(Pixel* buf, unsigned vramLine)
- {
- if (vdp.getDisplayMode().isPlanar()) {
- const byte* vramPtr0;
- const byte* vramPtr1;
- vram.bitmapCacheWindow.getReadAreaPlanar(
- vramLine * 256, 256, vramPtr0, vramPtr1);
- bitmapConverter.convertLinePlanar(buf, vramPtr0, vramPtr1);
- } else {
- const byte* vramPtr =
- vram.bitmapCacheWindow.getReadArea(vramLine * 128, 128);
- bitmapConverter.convertLine(buf, vramPtr);
- }
- }
- template <class Pixel>
- SDLRasterizer<Pixel>::SDLRasterizer(
- VDP& vdp_, Display& display, OutputSurface& screen_,
- std::unique_ptr<PostProcessor> postProcessor_)
- : vdp(vdp_), vram(vdp.getVRAM())
- , screen(screen_)
- , postProcessor(std::move(postProcessor_))
- , workFrame(std::make_unique<RawFrame>(screen.getPixelFormat(), 640, 240))
- , renderSettings(display.getRenderSettings())
- , characterConverter(vdp, palFg, palBg)
- , bitmapConverter(palFg, PALETTE256, V9958_COLORS)
- , spriteConverter(vdp.getSpriteChecker())
- {
- // Init the palette.
- precalcPalette();
- // Initialize palette (avoid UMR)
- if (!vdp.isMSX1VDP()) {
- for (int i = 0; i < 16; ++i) {
- palFg[i] = palFg[i + 16] = palBg[i] =
- V9938_COLORS[0][0][0];
- }
- }
- renderSettings.getGammaSetting() .attach(*this);
- renderSettings.getBrightnessSetting() .attach(*this);
- renderSettings.getContrastSetting() .attach(*this);
- renderSettings.getColorMatrixSetting().attach(*this);
- }
- template <class Pixel>
- SDLRasterizer<Pixel>::~SDLRasterizer()
- {
- renderSettings.getColorMatrixSetting().detach(*this);
- renderSettings.getGammaSetting() .detach(*this);
- renderSettings.getBrightnessSetting() .detach(*this);
- renderSettings.getContrastSetting() .detach(*this);
- }
- template <class Pixel>
- PostProcessor* SDLRasterizer<Pixel>::getPostProcessor() const
- {
- return postProcessor.get();
- }
- template <class Pixel>
- bool SDLRasterizer<Pixel>::isActive()
- {
- return postProcessor->needRender() &&
- vdp.getMotherBoard().isActive() &&
- !vdp.getMotherBoard().isFastForwarding();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::reset()
- {
- // Init renderer state.
- setDisplayMode(vdp.getDisplayMode());
- spriteConverter.setTransparency(vdp.getTransparency());
- resetPalette();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::resetPalette()
- {
- if (!vdp.isMSX1VDP()) {
- // Reset the palette.
- for (int i = 0; i < 16; i++) {
- setPalette(i, vdp.getPalette(i));
- }
- }
- }
- template<class Pixel>
- void SDLRasterizer<Pixel>::setSuperimposeVideoFrame(const RawFrame* videoSource)
- {
- postProcessor->setSuperimposeVideoFrame(videoSource);
- precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
- videoSource, vdp.getBackgroundColor());
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::frameStart(EmuTime::param time)
- {
- workFrame = postProcessor->rotateFrames(std::move(workFrame), time);
- workFrame->init(
- vdp.isInterlaced() ? (vdp.getEvenOdd() ? FrameSource::FIELD_ODD
- : FrameSource::FIELD_EVEN)
- : FrameSource::FIELD_NONINTERLACED);
- // Calculate line to render at top of screen.
- // Make sure the display area is centered.
- // 240 - 212 = 28 lines available for top/bottom border; 14 each.
- // NTSC: display at [32..244),
- // PAL: display at [59..271).
- lineRenderTop = vdp.isPalTiming() ? 59 - 14 : 32 - 14;
- // We haven't drawn any left/right borders yet this frame, thus so far
- // all is still consistent (same settings for all left/right borders).
- mixedLeftRightBorders = false;
- auto& borderInfo = workFrame->getBorderInfo();
- Pixel color0, color1;
- getBorderColors(color0, color1);
- canSkipLeftRightBorders =
- (borderInfo.mode == vdp.getDisplayMode().getByte()) &&
- (borderInfo.color0 == color0) &&
- (borderInfo.color1 == color1) &&
- (borderInfo.adjust == vdp.getHorizontalAdjust()) &&
- (borderInfo.scroll == vdp.getHorizontalScrollLow()) &&
- (borderInfo.masked == vdp.isBorderMasked());
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::frameEnd()
- {
- auto& borderInfo = workFrame->getBorderInfo();
- if (mixedLeftRightBorders) {
- // This frame contains left/right borders drawn with different
- // settings. So don't use it as a starting point for future
- // border drawing optimizations.
- borderInfo.mode = 0xff; // invalid mode, other fields don't matter
- } else {
- // All left/right borders in this frame are uniform (drawn with
- // the same settings). If in a later frame the border-related
- // settings are still the same, we can skip drawing borders.
- Pixel color0, color1;
- getBorderColors(color0, color1);
- borderInfo.mode = vdp.getDisplayMode().getByte();
- borderInfo.color0 = color0;
- borderInfo.color1 = color1;
- borderInfo.adjust = vdp.getHorizontalAdjust();
- borderInfo.scroll = vdp.getHorizontalScrollLow();
- borderInfo.masked = vdp.isBorderMasked();
- }
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::borderSettingChanged()
- {
- // Can no longer use the skip-border drawing optimization this frame.
- canSkipLeftRightBorders = false;
- // Cannot use this frame as a starting point for future skip-border
- // optimizations.
- mixedLeftRightBorders = true;
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setDisplayMode(DisplayMode mode)
- {
- if (mode.isBitmapMode()) {
- bitmapConverter.setDisplayMode(mode);
- } else {
- characterConverter.setDisplayMode(mode);
- }
- precalcColorIndex0(mode, vdp.getTransparency(),
- vdp.isSuperimposing(), vdp.getBackgroundColor());
- spriteConverter.setDisplayMode(mode);
- spriteConverter.setPalette(mode.getByte() == DisplayMode::GRAPHIC7
- ? palGraphic7Sprites : palBg);
- borderSettingChanged();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setPalette(int index, int grb)
- {
- // Update SDL colors in palette.
- Pixel newColor = V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
- palFg[index ] = newColor;
- palFg[index + 16] = newColor;
- palBg[index ] = newColor;
- bitmapConverter.palette16Changed();
- precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
- vdp.isSuperimposing(), vdp.getBackgroundColor());
- borderSettingChanged();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setBackgroundColor(int index)
- {
- if (vdp.getDisplayMode().getByte() != DisplayMode::GRAPHIC7) {
- precalcColorIndex0(vdp.getDisplayMode(), vdp.getTransparency(),
- vdp.isSuperimposing(), index);
- }
- borderSettingChanged();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setHorizontalAdjust(int /*adjust*/)
- {
- borderSettingChanged();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setHorizontalScrollLow(byte /*scroll*/)
- {
- borderSettingChanged();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setBorderMask(bool /*masked*/)
- {
- borderSettingChanged();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::setTransparency(bool enabled)
- {
- spriteConverter.setTransparency(enabled);
- precalcColorIndex0(vdp.getDisplayMode(), enabled,
- vdp.isSuperimposing(), vdp.getBackgroundColor());
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::precalcPalette()
- {
- if (vdp.isMSX1VDP()) {
- // Fixed palette.
- const auto palette = vdp.getMSX1Palette();
- for (int i = 0; i < 16; ++i) {
- const auto rgb = palette[i];
- palFg[i] = palFg[i + 16] = palBg[i] =
- screen.mapKeyedRGB<Pixel>(
- renderSettings.transformRGB(
- vec3(rgb[0], rgb[1], rgb[2]) / 255.0f));
- }
- } else {
- if (vdp.hasYJK()) {
- // Precalculate palette for V9958 colors.
- if (renderSettings.isColorMatrixIdentity()) {
- // Most users use the "normal" monitor type; making this a
- // special case speeds up palette precalculation a lot.
- int intensity[32];
- for (int i = 0; i < 32; ++i) {
- intensity[i] =
- int(255 * renderSettings.transformComponent(i / 31.0));
- }
- for (int rgb = 0; rgb < (1 << 15); ++rgb) {
- V9958_COLORS[rgb] = screen.mapKeyedRGB255<Pixel>(ivec3(
- intensity[(rgb >> 10) & 31],
- intensity[(rgb >> 5) & 31],
- intensity[(rgb >> 0) & 31]));
- }
- } else {
- for (int r = 0; r < 32; ++r) {
- for (int g = 0; g < 32; ++g) {
- for (int b = 0; b < 32; ++b) {
- V9958_COLORS[(r << 10) + (g << 5) + b] =
- screen.mapKeyedRGB<Pixel>(
- renderSettings.transformRGB(
- vec3(r, g, b) / 31.0f));
- }
- }
- }
- }
- // Precalculate palette for V9938 colors.
- // Based on comparing red and green gradients, using palette and
- // YJK, in SCREEN11 on a real turbo R.
- for (int r3 = 0; r3 < 8; ++r3) {
- int r5 = (r3 << 2) | (r3 >> 1);
- for (int g3 = 0; g3 < 8; ++g3) {
- int g5 = (g3 << 2) | (g3 >> 1);
- for (int b3 = 0; b3 < 8; ++b3) {
- int b5 = (b3 << 2) | (b3 >> 1);
- V9938_COLORS[r3][g3][b3] =
- V9958_COLORS[(r5 << 10) + (g5 << 5) + b5];
- }
- }
- }
- } else {
- // Precalculate palette for V9938 colors.
- if (renderSettings.isColorMatrixIdentity()) {
- int intensity[8];
- for (int i = 0; i < 8; ++i) {
- intensity[i] =
- int(255 * renderSettings.transformComponent(i / 7.0f));
- }
- for (int r = 0; r < 8; ++r) {
- for (int g = 0; g < 8; ++g) {
- for (int b = 0; b < 8; ++b) {
- V9938_COLORS[r][g][b] =
- screen.mapKeyedRGB255<Pixel>(ivec3(
- intensity[r],
- intensity[g],
- intensity[b]));
- }
- }
- }
- } else {
- for (int r = 0; r < 8; ++r) {
- for (int g = 0; g < 8; ++g) {
- for (int b = 0; b < 8; ++b) {
- V9938_COLORS[r][g][b] =
- screen.mapKeyedRGB<Pixel>(
- renderSettings.transformRGB(
- vec3(r, g, b) / 7.0f));;
- }
- }
- }
- }
- }
- // Precalculate Graphic 7 bitmap palette.
- for (int i = 0; i < 256; ++i) {
- PALETTE256[i] = V9938_COLORS
- [(i & 0x1C) >> 2]
- [(i & 0xE0) >> 5]
- [(i & 0x03) == 3 ? 7 : (i & 0x03) * 2];
- }
- // Precalculate Graphic 7 sprite palette.
- for (int i = 0; i < 16; ++i) {
- uint16_t grb = Renderer::GRAPHIC7_SPRITE_PALETTE[i];
- palGraphic7Sprites[i] =
- V9938_COLORS[(grb >> 4) & 7][grb >> 8][grb & 7];
- }
- }
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::precalcColorIndex0(DisplayMode mode,
- bool transparency, const RawFrame* superimposing, byte bgcolorIndex)
- {
- // Graphic7 mode doesn't use transparency.
- if (mode.getByte() == DisplayMode::GRAPHIC7) {
- transparency = false;
- }
- int tpIndex = transparency ? bgcolorIndex : 0;
- if (mode.getBase() != DisplayMode::GRAPHIC5) {
- Pixel c = (superimposing && (bgcolorIndex == 0))
- ? screen.getKeyColor<Pixel>()
- : palBg[tpIndex];
- if (palFg[0] != c) {
- palFg[0] = c;
- bitmapConverter.palette16Changed();
- }
- } else {
- // TODO: superimposing
- if ((palFg[ 0] != palBg[tpIndex >> 2]) ||
- (palFg[16] != palBg[tpIndex & 3])) {
- palFg[ 0] = palBg[tpIndex >> 2];
- palFg[16] = palBg[tpIndex & 3];
- bitmapConverter.palette16Changed();
- }
- }
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::getBorderColors(Pixel& border0, Pixel& border1)
- {
- DisplayMode mode = vdp.getDisplayMode();
- int bgColor = vdp.getBackgroundColor();
- if (mode.getBase() == DisplayMode::GRAPHIC5) {
- // border in SCREEN6 has separate color for even and odd pixels.
- // TODO odd/even swapped?
- border0 = palBg[(bgColor & 0x0C) >> 2];
- border1 = palBg[(bgColor & 0x03) >> 0];
- } else if (mode.getByte() == DisplayMode::GRAPHIC7) {
- border0 = border1 = PALETTE256[bgColor];
- } else {
- if (!bgColor && vdp.isSuperimposing()) {
- border0 = border1 = screen.getKeyColor<Pixel>();
- } else {
- border0 = border1 = palBg[bgColor];
- }
- }
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::drawBorder(
- int fromX, int fromY, int limitX, int limitY)
- {
- Pixel border0, border1;
- getBorderColors(border0, border1);
- int startY = std::max(fromY - lineRenderTop, 0);
- int endY = std::min(limitY - lineRenderTop, 240);
- if ((fromX == 0) && (limitX == VDP::TICKS_PER_LINE) &&
- (border0 == border1)) {
- // complete lines, non striped
- for (int y = startY; y < endY; y++) {
- workFrame->setBlank(y, border0);
- // setBlank() implies this line is not suitable
- // for left/right border optimization in a later
- // frame.
- }
- } else {
- unsigned lineWidth = vdp.getDisplayMode().getLineWidth();
- unsigned x = translateX(fromX, (lineWidth == 512));
- unsigned num = translateX(limitX, (lineWidth == 512)) - x;
- unsigned width = (lineWidth == 512) ? 640 : 320;
- MemoryOps::MemSet2<Pixel> memset;
- for (int y = startY; y < endY; ++y) {
- // workFrame->linewidth != 1 means the line has
- // left/right borders.
- if (canSkipLeftRightBorders &&
- (workFrame->getLineWidthDirect(y) != 1)) continue;
- memset(workFrame->getLinePtrDirect<Pixel>(y) + x,
- num, border0, border1);
- if (limitX == VDP::TICKS_PER_LINE) {
- // Only set line width at the end (right
- // border) of the line. This ensures we can
- // keep testing the width of the previous
- // version of this line for all (partial)
- // updates of this line.
- workFrame->setLineWidth(y, width);
- }
- }
- }
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::drawDisplay(
- int /*fromX*/, int fromY,
- int displayX, int displayY,
- int displayWidth, int displayHeight)
- {
- // Note: we don't call workFrame->setLineWidth() because that's done in
- // drawBorder() (for the right border). And the value we set there is
- // anyway the same as the one we would set here.
- DisplayMode mode = vdp.getDisplayMode();
- int lineWidth = mode.getLineWidth();
- if (lineWidth == 256) {
- int endX = displayX + displayWidth;
- displayX /= 2;
- displayWidth = endX / 2 - displayX;
- }
- // Clip to screen area.
- int screenLimitY = std::min(
- fromY + displayHeight - lineRenderTop,
- 240);
- int screenY = fromY - lineRenderTop;
- if (screenY < 0) {
- displayY -= screenY;
- fromY = lineRenderTop;
- screenY = 0;
- }
- displayHeight = screenLimitY - screenY;
- if (displayHeight <= 0) return;
- int leftBackground =
- translateX(vdp.getLeftBackground(), lineWidth == 512);
- // TODO: Find out why this causes 1-pixel jitter:
- //dest.x = translateX(fromX);
- int hScroll =
- mode.isTextMode()
- ? 0
- : 8 * (lineWidth / 256) * (vdp.getHorizontalScrollHigh() & 0x1F);
- // Page border is display X coordinate where to stop drawing current page.
- // This is either the multi page split point, or the right edge of the
- // rectangle to draw, whichever comes first.
- // Note that it is possible for pageBorder to be to the left of displayX,
- // in that case only the second page should be drawn.
- int pageBorder = displayX + displayWidth;
- int scrollPage1, scrollPage2;
- if (vdp.isMultiPageScrolling()) {
- scrollPage1 = vdp.getHorizontalScrollHigh() >> 5;
- scrollPage2 = scrollPage1 ^ 1;
- } else {
- scrollPage1 = 0;
- scrollPage2 = 0;
- }
- // Because SDL blits do not wrap, unlike GL textures, the pageBorder is
- // also used if multi page is disabled.
- int pageSplit = lineWidth - hScroll;
- if (pageSplit < pageBorder) {
- pageBorder = pageSplit;
- }
- if (mode.isBitmapMode()) {
- for (int y = screenY; y < screenLimitY; y++) {
- // Which bits in the name mask determine the page?
- // TODO optimize this?
- // Calculating pageMaskOdd/Even is a non-trivial amount
- // of work. We used to do this per frame (more or less)
- // but now do it per line. Per-line is actually only
- // needed when vdp.isFastBlinkEnabled() is true.
- // Idea: can be cheaply calculated incrementally.
- int pageMaskOdd = (mode.isPlanar() ? 0x000 : 0x200) |
- vdp.getEvenOddMask(y);
- int pageMaskEven = vdp.isMultiPageScrolling()
- ? (pageMaskOdd & ~0x100)
- : pageMaskOdd;
- const int vramLine[2] = {
- (vram.nameTable.getMask() >> 7) & (pageMaskEven | displayY),
- (vram.nameTable.getMask() >> 7) & (pageMaskOdd | displayY)
- };
- Pixel buf[512];
- int lineInBuf = -1; // buffer data not valid
- Pixel* dst = workFrame->getLinePtrDirect<Pixel>(y)
- + leftBackground + displayX;
- int firstPageWidth = pageBorder - displayX;
- if (firstPageWidth > 0) {
- if (((displayX + hScroll) == 0) &&
- (firstPageWidth == lineWidth)) {
- // fast-path, directly render to destination
- renderBitmapLine(dst, vramLine[scrollPage1]);
- } else {
- lineInBuf = vramLine[scrollPage1];
- renderBitmapLine(buf, vramLine[scrollPage1]);
- const Pixel* src = buf + displayX + hScroll;
- memcpy(dst, src, firstPageWidth * sizeof(Pixel));
- }
- } else {
- firstPageWidth = 0;
- }
- if (firstPageWidth < displayWidth) {
- if (lineInBuf != vramLine[scrollPage2]) {
- renderBitmapLine(buf, vramLine[scrollPage2]);
- }
- unsigned x = displayX < pageBorder
- ? 0 : displayX + hScroll - lineWidth;
- memcpy(dst + firstPageWidth,
- buf + x,
- (displayWidth - firstPageWidth) * sizeof(Pixel));
- }
- displayY = (displayY + 1) & 255;
- }
- } else {
- // horizontal scroll (high) is implemented in CharacterConverter
- for (int y = screenY; y < screenLimitY; y++) {
- assert(!vdp.isMSX1VDP() || displayY < 192);
- Pixel* dst = workFrame->getLinePtrDirect<Pixel>(y)
- + leftBackground + displayX;
- if ((displayX == 0) && (displayWidth == lineWidth)){
- characterConverter.convertLine(dst, displayY);
- } else {
- Pixel buf[512];
- characterConverter.convertLine(buf, displayY);
- const Pixel* src = buf + displayX;
- memcpy(dst, src, displayWidth * sizeof(Pixel));
- }
- displayY = (displayY + 1) & 255;
- }
- }
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::drawSprites(
- int /*fromX*/, int fromY,
- int displayX, int displayY,
- int displayWidth, int displayHeight)
- {
- // Clip to screen area.
- // TODO: Code duplicated from drawDisplay.
- int screenLimitY = std::min(
- fromY + displayHeight - lineRenderTop,
- 240);
- int screenY = fromY - lineRenderTop;
- if (screenY < 0) {
- displayY -= screenY;
- fromY = lineRenderTop;
- screenY = 0;
- }
- displayHeight = screenLimitY - screenY;
- if (displayHeight <= 0) return;
- // Render sprites.
- // TODO: Call different SpriteConverter methods depending on narrow/wide
- // pixels in this display mode?
- int spriteMode = vdp.getDisplayMode().getSpriteMode(vdp.isMSX1VDP());
- int displayLimitX = displayX + displayWidth;
- int limitY = fromY + displayHeight;
- int screenX = translateX(
- vdp.getLeftSprites(),
- vdp.getDisplayMode().getLineWidth() == 512);
- if (spriteMode == 1) {
- for (int y = fromY; y < limitY; y++, screenY++) {
- Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
- spriteConverter.drawMode1(y, displayX, displayLimitX, pixelPtr);
- }
- } else {
- byte mode = vdp.getDisplayMode().getByte();
- if (mode == DisplayMode::GRAPHIC5) {
- for (int y = fromY; y < limitY; y++, screenY++) {
- Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
- spriteConverter.template drawMode2<DisplayMode::GRAPHIC5>(
- y, displayX, displayLimitX, pixelPtr);
- }
- } else if (mode == DisplayMode::GRAPHIC6) {
- for (int y = fromY; y < limitY; y++, screenY++) {
- Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
- spriteConverter.template drawMode2<DisplayMode::GRAPHIC6>(
- y, displayX, displayLimitX, pixelPtr);
- }
- } else {
- for (int y = fromY; y < limitY; y++, screenY++) {
- Pixel* pixelPtr = workFrame->getLinePtrDirect<Pixel>(screenY) + screenX;
- spriteConverter.template drawMode2<DisplayMode::GRAPHIC4>(
- y, displayX, displayLimitX, pixelPtr);
- }
- }
- }
- }
- template <class Pixel>
- bool SDLRasterizer<Pixel>::isRecording() const
- {
- return postProcessor->isRecording();
- }
- template <class Pixel>
- void SDLRasterizer<Pixel>::update(const Setting& setting)
- {
- if (&setting == one_of(&renderSettings.getGammaSetting(),
- &renderSettings.getBrightnessSetting(),
- &renderSettings.getContrastSetting(),
- &renderSettings.getColorMatrixSetting())) {
- precalcPalette();
- resetPalette();
- }
- }
- // Force template instantiation.
- #if HAVE_16BPP
- template class SDLRasterizer<uint16_t>;
- #endif
- #if HAVE_32BPP || COMPONENT_GL
- template class SDLRasterizer<uint32_t>;
- #endif
- } // namespace openmsx
|