mirror of https://github.com/stella-emu/stella.git
Implement triple buffering in TIA.
This commit is contained in:
parent
f7a9a12c23
commit
a5ce457b72
|
@ -168,6 +168,8 @@ void TiaOutputWidget::drawWidget(bool hilite)
|
|||
uInt32 scanx, scany, scanoffset;
|
||||
bool visible = instance().console().tia().electronBeamPos(scanx, scany);
|
||||
scanoffset = width * scany + scanx;
|
||||
uInt8* tiaOutputBuffer = instance().console().tia().outputBuffer();
|
||||
TIASurface& tiaSurface(instance().frameBuffer().tiaSurface());
|
||||
|
||||
for(uInt32 y = 0, i = 0; y < height; ++y)
|
||||
{
|
||||
|
@ -175,7 +177,7 @@ void TiaOutputWidget::drawWidget(bool hilite)
|
|||
for(uInt32 x = 0; x < width; ++x, ++i)
|
||||
{
|
||||
uInt8 shift = i >= scanoffset ? 1 : 0;
|
||||
uInt32 pixel = instance().frameBuffer().tiaSurface().pixel(i, shift);
|
||||
uInt32 pixel = tiaSurface.mapIndexedPixel(tiaOutputBuffer[i], shift);
|
||||
*line_ptr++ = pixel;
|
||||
*line_ptr++ = pixel;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ class DispatchResult
|
|||
|
||||
void setOk(uInt32 cycles);
|
||||
|
||||
void setDebugger(uInt32 cycles, const string& message = "", int address = -1, bool wasReadTrap = -1);
|
||||
void setDebugger(uInt32 cycles, const string& message = "", int address = -1, bool wasReadTrap = false);
|
||||
|
||||
void setFatal(uInt32 cycles);
|
||||
|
||||
|
|
|
@ -678,8 +678,8 @@ void OSystem::mainLoop()
|
|||
timesliceSeconds = dispatchEmulation(myConsole ? myConsole->emulationTiming().cyclesPerSecond() : 1);
|
||||
|
||||
if (myConsole && myConsole->tia().newFramePending()) {
|
||||
myConsole->tia().renderToFrameBuffer();
|
||||
myFrameBuffer->updateInEmulationMode();
|
||||
myConsole->tia().clearNewFramePending();
|
||||
}
|
||||
} else {
|
||||
timesliceSeconds = 1. / 30.;
|
||||
|
|
|
@ -138,11 +138,12 @@ const FBSurface& TIASurface::baseSurface(GUI::Rect& rect) const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 TIASurface::pixel(uInt32 idx, uInt8 shift)
|
||||
uInt32 TIASurface::mapIndexedPixel(uInt8 indexedColor, uInt8 shift)
|
||||
{
|
||||
return myPalette[*(myTIA->frameBuffer() + idx) | shift];
|
||||
return myPalette[indexedColor | shift];
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
|
||||
{
|
||||
|
|
|
@ -73,10 +73,9 @@ class TIASurface
|
|||
const FBSurface& baseSurface(GUI::Rect& rect) const;
|
||||
|
||||
/**
|
||||
Get the TIA pixel associated with the given TIA buffer index,
|
||||
shifting by the given offset (for greyscale values).
|
||||
*/
|
||||
uInt32 pixel(uInt32 idx, uInt8 shift = 0);
|
||||
Use the palette to map a single indexed pixel color. This is used by the TIA output widget.
|
||||
*/
|
||||
uInt32 mapIndexedPixel(uInt8 indexedColor, uInt8 shift = 0);
|
||||
|
||||
/**
|
||||
Get the NTSCFilter object associated with the framebuffer
|
||||
|
|
|
@ -196,6 +196,7 @@ void TIA::reset()
|
|||
void TIA::frameReset()
|
||||
{
|
||||
memset(myBackBuffer, 0, 160 * TIAConstants::frameBufferHeight);
|
||||
memset(myFrontBuffer, 0, 160 * TIAConstants::frameBufferHeight);
|
||||
memset(myFramebuffer, 0, 160 * TIAConstants::frameBufferHeight);
|
||||
enableColorLoss(mySettings.getBool("dev.settings") ? "dev.colorloss" : "plr.colorloss");
|
||||
}
|
||||
|
@ -784,6 +785,7 @@ bool TIA::saveDisplay(Serializer& out) const
|
|||
{
|
||||
out.putByteArray(myFramebuffer, 160* TIAConstants::frameBufferHeight);
|
||||
out.putByteArray(myBackBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
out.putByteArray(myFrontBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
out.putBool(myNewFramePending);
|
||||
}
|
||||
catch(...)
|
||||
|
@ -803,6 +805,7 @@ bool TIA::loadDisplay(Serializer& in)
|
|||
// Reset frame buffer pointer and data
|
||||
in.getByteArray(myFramebuffer, 160*TIAConstants::frameBufferHeight);
|
||||
in.getByteArray(myBackBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
in.getByteArray(myFrontBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
myNewFramePending = in.getBool();
|
||||
}
|
||||
catch(...)
|
||||
|
@ -817,13 +820,19 @@ bool TIA::loadDisplay(Serializer& in)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::update(DispatchResult& result, uInt32 maxCycles)
|
||||
{
|
||||
uInt64 timestampOld = myTimestamp;
|
||||
|
||||
mySystem->m6502().execute(maxCycles, result);
|
||||
|
||||
updateEmulation();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::renderToFrameBuffer()
|
||||
{
|
||||
if (!myNewFramePending) return;
|
||||
|
||||
memcpy(myFramebuffer, myFrontBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIA::update(uInt32 maxCycles)
|
||||
{
|
||||
|
@ -1171,7 +1180,7 @@ void TIA::onFrameComplete()
|
|||
if (missingScanlines > 0)
|
||||
memset(myBackBuffer + 160 * myFrameManager->getY(), 0, missingScanlines * 160);
|
||||
|
||||
memcpy(&myFramebuffer, &myBackBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
memcpy(myFrontBuffer, myBackBuffer, 160 * TIAConstants::frameBufferHeight);
|
||||
myNewFramePending = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -210,9 +210,15 @@ class TIA : public Device
|
|||
bool newFramePending() { return myNewFramePending; }
|
||||
|
||||
/**
|
||||
Clear the flag
|
||||
*/
|
||||
void clearNewFramePending() { myNewFramePending = false; }
|
||||
Render the pending frame to the framebuffer and clear the flag.
|
||||
*/
|
||||
void renderToFrameBuffer();
|
||||
|
||||
/**
|
||||
Return the buffer that holds the currently drawing TIA frame
|
||||
(the TIA output widget needs this).
|
||||
*/
|
||||
uInt8* outputBuffer() { return myBackBuffer; }
|
||||
|
||||
/**
|
||||
Returns a pointer to the internal frame buffer.
|
||||
|
@ -673,6 +679,7 @@ class TIA : public Device
|
|||
// The frame is rendered to the backbuffer and only copied to the framebuffer
|
||||
// upon completion
|
||||
uInt8 myBackBuffer[160 * TIAConstants::frameBufferHeight];
|
||||
uInt8 myFrontBuffer[160 * TIAConstants::frameBufferHeight];
|
||||
|
||||
// Did we emit a frame?
|
||||
bool myNewFramePending;
|
||||
|
|
Loading…
Reference in New Issue