20 template<
typename Pixel>
23 std::unique_ptr<PostProcessor> postProcessor_)
24 : vdp(vdp_), vram(vdp.getVRAM())
26 , workFrame(std::make_unique<
RawFrame>(screen.getPixelFormat(), 1280, 240))
27 , renderSettings(display.getRenderSettings())
30 , postProcessor(std::move(postProcessor_))
31 , bitmapConverter(vdp, palette64, palette64_32768, palette256, palette256_32768, palette32768)
32 , p1Converter(vdp, palette64)
33 , p2Converter(vdp, palette64)
44 template<
typename Pixel>
47 renderSettings.getColorMatrixSetting().detach(*
this);
48 renderSettings.getGammaSetting() .detach(*
this);
49 renderSettings.getBrightnessSetting() .detach(*
this);
50 renderSettings.getContrastSetting() .detach(*
this);
53 template<
typename Pixel>
56 return postProcessor.get();
59 template<
typename Pixel>
62 return postProcessor->needRender() &&
63 vdp.getMotherBoard().isActive() &&
64 !vdp.getMotherBoard().isFastForwarding();
67 template<
typename Pixel>
70 setDisplayMode(vdp.getDisplayMode());
71 setColorMode(vdp.getColorMode());
75 template<
typename Pixel>
87 (horTiming.
display - SCREEN_WIDTH * 8) / 2;
92 (verTiming.
display - SCREEN_HEIGHT) / 2;
95 template<
typename Pixel>
98 workFrame = postProcessor->rotateFrames(std::move(workFrame), time);
105 template<
typename Pixel>
109 bitmapConverter.setColorMode(colorMode, displayMode);
112 template<
typename Pixel>
116 bitmapConverter.setColorMode(colorMode, displayMode);
119 template<
typename Pixel>
121 int fromX,
int fromY,
int limitX,
int limitY)
123 Pixel bgColor = vdp.isOverScan()
125 : palette64[vdp.getBackDropColor() & 63];
127 int startY =
std::max(fromY - lineRenderTop, 0);
128 int endY =
std::min(limitY - lineRenderTop, 240);
129 if (startY >= endY)
return;
133 for (
auto y :
xrange(startY, endY)) {
134 workFrame->setBlank(y, bgColor);
139 static int const screenW = SCREEN_WIDTH * 8;
143 ? screenW :
std::min(screenW, limitX - colZero), displayMode);
144 if (startX >= endX)
return;
146 unsigned lineWidth = vdp.getLineWidth();
148 for (
auto y :
xrange(startY, endY)) {
149 memset(workFrame->getLinePtrDirect<
Pixel>(y) + startX,
150 endX - startX, bgColor);
151 workFrame->setLineWidth(y, lineWidth);
155 template<
typename Pixel>
157 int fromX,
int fromY,
int toX,
int toY,
158 int displayX,
int displayY,
int displayYA,
int displayYB)
160 static int const screenW = SCREEN_WIDTH * 8;
161 static int const screenH = SCREEN_HEIGHT;
166 fromY -= lineRenderTop;
167 toY -= lineRenderTop;
189 if ((toX > fromX) && (toY > fromY)) {
190 bool drawSprites = vdp.spritesEnabled() &&
191 !renderSettings.getDisableSprites();
194 int displayWidth = toX - fromX;
195 int displayHeight = toY - fromY;
197 if (displayMode ==
P1) {
198 drawP1Mode(fromX, fromY, displayX,
199 displayY, displayYA, displayYB,
200 displayWidth, displayHeight,
202 }
else if (displayMode ==
P2) {
203 drawP2Mode(fromX, fromY, displayX,
205 displayWidth, displayHeight,
208 drawBxMode(fromX, fromY, displayX,
210 displayWidth, displayHeight,
216 template<
typename Pixel>
218 int fromX,
int fromY,
int displayX,
219 int displayY,
int displayYA,
int displayYB,
220 int displayWidth,
int displayHeight,
bool drawSprites)
222 while (displayHeight--) {
223 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(fromY) + fromX;
224 p1Converter.convertLine(pixelPtr, displayX, displayWidth,
225 displayY, displayYA, displayYB,
227 workFrame->setLineWidth(fromY, 320);
235 template<
typename Pixel>
237 int fromX,
int fromY,
int displayX,
int displayY,
int displayYA,
238 int displayWidth,
int displayHeight,
bool drawSprites)
240 while (displayHeight--) {
241 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(fromY) + fromX;
242 p2Converter.convertLine(pixelPtr, displayX, displayWidth,
243 displayY, displayYA, drawSprites);
244 workFrame->setLineWidth(fromY, 640);
251 template<
typename Pixel>
253 int fromX,
int fromY,
int displayX,
int displayY,
int displayYA,
254 int displayWidth,
int displayHeight,
bool drawSprites)
256 unsigned scrollX = vdp.getScrollAX();
257 unsigned x = displayX + scrollX;
260 if (vdp.isEvenOddEnabled()) {
261 if (vdp.getEvenOdd()) {
268 unsigned scrollY = vdp.getScrollAY();
269 unsigned rollMask = vdp.getRollMask(0x1FFF);
270 unsigned scrollYBase = scrollY & ~rollMask & 0x1FFF;
271 int cursorY = displayY - vdp.getCursorYOffset();
272 while (displayHeight--) {
278 unsigned y = scrollYBase + ((displayYA + scrollY) & rollMask);
279 Pixel* pixelPtr = workFrame->getLinePtrDirect<
Pixel>(fromY) + fromX;
280 bitmapConverter.convertLine(pixelPtr,
x, y, displayWidth,
281 cursorY, drawSprites);
282 workFrame->setLineWidth(fromY, vdp.getLineWidth());
284 displayYA += lineStep;
290 template<
typename Pixel>
294 if (renderSettings.isColorMatrixIdentity()) {
298 for (
auto [i, r] :
enumerate(intensity)) {
299 r = int(255 * renderSettings.transformComponent(i / 31.0f));
301 for (
auto [grb, col] :
enumerate(palette32768)) {
303 intensity[(grb >> 5) & 31],
304 intensity[(grb >> 10) & 31],
305 intensity[(grb >> 0) & 31]));
309 for (
auto r :
xrange(32)) {
310 for (
auto b :
xrange(32)) {
311 palette32768[(
g << 10) + (r << 5) + b] =
312 screen.mapRGB(renderSettings.transformRGB(
320 int mapRG[8] = { 0, 4, 9, 13, 18, 22, 27, 31 };
321 int mapB [4] = { 0, 11, 21, 31 };
323 for (
auto r :
xrange(8)) {
324 for (
auto b :
xrange(4)) {
325 auto idx256 = (
g << 5) | (r << 2) | b;
326 auto idx32768 = (mapRG[
g] << 10) | (mapRG[r] << 5) | mapB[b];
327 palette256_32768[idx256] = idx32768;
328 palette256[idx256] = palette32768[idx32768];
336 template<
typename Pixel>
338 byte r,
byte g,
byte b,
bool ys)
340 auto idx32768 = ((
g & 31) << 10) | ((r & 31) << 5) | ((b & 31) << 0);
341 palette64_32768[index & 63] = idx32768;
342 palette64[index & 63] = ys ? screen.getKeyColor<
Pixel>()
343 : palette32768[idx32768];
346 template<
typename Pixel>
350 for (
auto i :
xrange(64)) {
351 auto [r,
g, b, ys] = vdp.getPalette(i);
352 setPalette(i, r,
g, b, ys);
354 palette256[0] = vdp.isSuperimposing() ? screen.getKeyColor<
Pixel>()
359 template<
typename Pixel>
365 template<
typename Pixel>
368 return postProcessor->isRecording();
371 template<
typename Pixel>
375 &renderSettings.getBrightnessSetting(),
376 &renderSettings.getContrastSetting(),
377 &renderSettings.getColorMatrixSetting())) {
386 #if HAVE_32BPP || COMPONENT_GL
Represents the output window/screen of openMSX.
@ 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.
A frame buffer where pixels can be written to.
Abstract base class for post processors.
A video frame as output by the VDP scanline conversion unit, before any postprocessing filters are ap...
StringSetting & getColorMatrixSetting()
Color matrix setting.
FloatSetting & getGammaSetting()
The amount of gamma correction.
FloatSetting & getBrightnessSetting()
Brightness video setting.
FloatSetting & getContrastSetting()
Contrast video setting.
void attach(Observer< T > &observer)
static constexpr int UC_TICKS_PER_LINE
The number of clockticks per line is independent of the crystal used or the display mode (NTSC/PAL)
void drawP1Mode(int fromX, int fromY, int displayX, int displayY, int displayYA, int displayYB, int displayWidth, int displayHeight, bool drawSprites)
void frameStart() override
Indicates the start of a new frame.
void setPalette(int index, byte r, byte g, byte b, bool ys) override
Set RGB values for a palette entry.
void reset() override
Resynchronize with VDP - flush caches etc.
void setSuperimpose(bool enabled) override
Is superimpose enabled?
bool isActive() override
Will the output of this Rasterizer be displayed? There is no point in producing a frame that will not...
bool isRecording() const override
Is video recording active?
void drawBxMode(int fromX, int fromY, int displayX, int displayY, int displayYA, int displayWidth, int displayHeight, bool drawSprites)
void drawBorder(int fromX, int fromY, int limitX, int limitY) override
Render a rectangle of border pixels on the host screen.
void drawDisplay(int fromX, int fromY, int toX, int toY, int displayX, int displayY, int displayYA, int displayYB) override
Render a rectangle of display pixels on the host screen.
void drawP2Mode(int fromX, int fromY, int displayX, int displayY, int displayYA, int displayWidth, int displayHeight, bool drawSprites)
PostProcessor * getPostProcessor() const override
See V9990::getPostProcessor().
void setDisplayMode(V9990DisplayMode displayMode) override
The display mode determines the screens geometry and how V9990 pixels are mapped to pixels on screen.
void update(const Setting &setting) noexcept override
void preCalcPalettes()
Fill the palettes.
~V9990SDLRasterizer() override
void frameEnd(EmuTime::param time) override
Indicates the end of the current frame.
void setColorMode(V9990ColorMode colorMode) override
The color mode determines how the V9990 VRAM data gets converted to pixel colors.
V9990SDLRasterizer(V9990 &vdp, Display &display, OutputSurface &screen, std::unique_ptr< PostProcessor > postProcessor)
Implementation of the Yamaha V9990 VDP as used in the GFX9000 cartridge by Sunrise.
static int UCtoX(int ticks, V9990DisplayMode mode)
Convert UC ticks to V9990 pixel position on a line.
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
This file implemented 3 utility functions:
constexpr KeyMatrixPosition x
Keyboard bindings.
A period, either horizontal or vertical, starts with a synchronisation pulse followed by a blank peri...
constexpr auto xrange(T e)