Commit d2e33719 authored by Kirinn's avatar Kirinn

Move more stuff into Rendermatic

parent 5db54271
......@@ -35,10 +35,12 @@ begin
// Set up buffers for output.
i := sysvar.windowSize.w * sysvar.windowSize.h * 4;
if mv_OutputBuffy <> NIL then begin freemem(mv_OutputBuffy); mv_OutputBuffy := NIL; end;
getmem(mv_OutputBuffy, i);
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
getmem(stashBuffy, i);
with Rendermatic do begin
if outputBuffy <> NIL then begin freemem(outputBuffy); outputBuffy := NIL; end;
getmem(outputBuffy, i);
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
getmem(stashBuffy, i);
end;
// The viewports may need adjusting. This call imports the new window pixel size into viewport 0, and then cascades the
// change down to child ports. All content in the viewports also gets marked for refreshing.
......@@ -69,7 +71,7 @@ begin
if com = chr(0) + chr(4) + chr($17) then begin
sakuparam.lxyMix := NOT sakuparam.lxyMix;
InitXPal;
AddRefresh(0, 0, sysvar.windowSize.w, sysvar.windowSize.h);
Rendermatic.Reset;
for i := high(BoxHub.textbox) downto 0 do
if BoxHub.textbox[i].isHidden = FALSE then BoxHub.textbox[i].boxNeedsRedraw := TRUE;
end;
......@@ -211,8 +213,10 @@ begin
asman_endthread;
// Release the display buffer.
if mv_OutputBuffy <> NIL then begin freemem(mv_OutputBuffy); mv_OutputBuffy := NIL; end;
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
with Rendermatic do begin
if outputBuffy <> NIL then begin freemem(outputBuffy); outputBuffy := NIL; end;
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
end;
// Free whatever other memory was reserved.
if seengfxp <> NIL then begin freemem(seengfxp); seengfxp := NIL; end;
......@@ -300,10 +304,12 @@ begin
// Set up buffers for output.
i := sysvar.windowSize.w * sysvar.windowSize.h * 4;
if mv_OutputBuffy <> NIL then begin freemem(mv_OutputBuffy); mv_OutputBuffy := NIL; end;
getmem(mv_OutputBuffy, i);
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
getmem(stashBuffy, i);
with Rendermatic do begin
if outputBuffy <> NIL then begin freemem(outputBuffy); outputBuffy := NIL; end;
getmem(outputBuffy, i);
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
getmem(stashBuffy, i);
end;
// One meg should be plenty for console graphics caching.
asman_gfxmemlimit := 1048576;
......
This diff is collapsed.
......@@ -192,7 +192,8 @@ begin
if scratchP <> NIL then begin freemem(scratchP); scratchP := NIL; end;
end;
if (boxState <> BS_NULL) and (isHidden = FALSE) then begin
AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + longint(boxSizeP_r.w), boxLocP_r.y + longint(boxSizeP_r.h));
Rendermatic.AddRefresh(
boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + longint(boxSizeP_r.w), boxLocP_r.y + longint(boxSizeP_r.h));
{$ifdef sakucon}
if sysvar.quit = FALSE then RefreshOverlappingBoxes;
{$endif}
......@@ -274,8 +275,8 @@ procedure TTextBox.Hide(makehidden : boolean);
begin
isHidden := makehidden;
boxNeedsRedraw := NOT makehidden;
if boxState <> BS_NULL then
AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + longint(boxSizeP_r.w), boxLocP_r.y + longint(boxSizeP_r.h));
if boxState <> BS_NULL then Rendermatic.AddRefresh(
boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + longint(boxSizeP_r.w), boxLocP_r.y + longint(boxSizeP_r.h));
end;
procedure TTextBox.StartTextInput;
......
......@@ -190,7 +190,7 @@ var boxnum : dword;
begin
with textbox[boxnum] do begin
if boxState = BS_VANISHING then begin
AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + boxSizeP_r.w, boxLocP_r.y + boxSizeP_r.h);
Rendermatic.AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + boxSizeP_r.w, boxLocP_r.y + boxSizeP_r.h);
{$ifdef sakucon}
RefreshOverlappingBoxes;
{$endif}
......@@ -266,7 +266,7 @@ begin
popRunTime := 0;
boxState := BS_NULL;
// The box has vanished completely; draw over it.
AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + boxSizeP_r.w, boxLocP_r.y + boxSizeP_r.h);
Rendermatic.AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + boxSizeP_r.w, boxLocP_r.y + boxSizeP_r.h);
{$ifdef sakucon}
RefreshOverlappingBoxes;
{$endif}
......@@ -283,7 +283,7 @@ begin
if (boxLoc.xp <> boxLocP_r.x) or (boxSizeP.w <> longint(boxSizeP_r.w))
or (boxLoc.yp <> boxLocP_r.y) or (boxSizeP.h <> longint(boxSizeP_r.h))
then begin
AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + boxSizeP_r.w, boxLocP_r.y + boxSizeP_r.h);
Rendermatic.AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + boxSizeP_r.w, boxLocP_r.y + boxSizeP_r.h);
{$ifdef sakucon}
RefreshOverlappingBoxes;
{$endif}
......@@ -305,7 +305,8 @@ begin
{$ifndef sakucon}
// Graphical textboxes get drawn like any gob, so just add the box's position as a refresh region.
AddRefresh(boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + longint(boxSizeP_r.w), boxLocP_r.y + longint(boxSizeP_r.h));
Rendermatic.AddRefresh(
boxLocP_r.x, boxLocP_r.y, boxLocP_r.x + longint(boxSizeP_r.w), boxLocP_r.y + longint(boxSizeP_r.h));
boxNeedsRedraw := FALSE;
{$else}
// Console textboxes get special treatment. Because of the difficulty in printing textbox content in console
......
This diff is collapsed.
......@@ -574,7 +574,7 @@ begin
// split into separate refresh rectangles. Due to the way refresh areas are merged and split, the only way to be sure the
// transition effect is atomic is to refresh the whole screen every frame.
else with viewport[inViewport] do
AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
Rendermatic.AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
end;
destructor TEffectTransition.Destroy;
......@@ -582,7 +582,7 @@ begin
if data <> NIL then begin freemem(data); data := NIL; end;
EffectHub.transitionActive := high(dword);
if inViewport < dword(length(viewport)) then with viewport[inViewport] do
AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
Rendermatic.AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
inherited;
end;
......@@ -706,7 +706,7 @@ begin
if gobRenderNow then begin
cachedGfxIndex := GetGFX(gobGfxListName, gobSizeP.w, gobSizeP.h);
AddRefresh(gobLoc.xp, gobLoc.yp, gobLoc.xp + longint(gobSizeP.w), gobLoc.yp + longint(gobSizeP.h));
Rendermatic.AddRefresh(gobLoc.xp, gobLoc.yp, gobLoc.xp + longint(gobSizeP.w), gobLoc.yp + longint(gobSizeP.h));
gobRenderNow := FALSE;
gobIsVisible := TRUE;
......@@ -746,7 +746,8 @@ begin
// Show frame and delay.
coleventcount := 0;
gobDrawFrame := gobDrawFrame mod PNGlist[PNGindex].frameCount;
AddRefresh(gobLoc.xp, gobLoc.yp, gobLoc.xp + longint(gobSizeP.w), gobLoc.yp + longint(gobSizeP.h));
Rendermatic.AddRefresh(
gobLoc.xp, gobLoc.yp, gobLoc.xp + longint(gobSizeP.w), gobLoc.yp + longint(gobSizeP.h));
gobIsVisible := TRUE;
l := k and $FFFF; k := k and $3FFF;
......
......@@ -30,7 +30,7 @@ end;
procedure TGob.RefreshGobRect;
begin
AddRefresh(gobLoc.xp, gobLoc.yp, gobLoc.xp + longint(gobSizeP.w), gobLoc.yp + longint(gobSizeP.h));
Rendermatic.AddRefresh(gobLoc.xp, gobLoc.yp, gobLoc.xp + longint(gobSizeP.w), gobLoc.yp + longint(gobSizeP.h));
end;
procedure TGob.SetParent(parentname : UTF8string);
......
......@@ -17,25 +17,22 @@
{ along with SuperSakura. If not, see <https://www.gnu.org/licenses/>. }
{ }
var mv_MainWinH : PSDL_Window; {$note todo: these go in rendermatic}
mv_RendererH : PSDL_Renderer;
mv_MainTexH : PSDL_Texture;
mv_GamepadH : PSDL_GameController;
mv_PKeystate : pointer;
var sdl_GamepadH : PSDL_GameController;
sdl_KeyState : pointer;
procedure LogError(const t : UTF8string);
begin
log('[!] ' + t);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, 'Error', @t[1], mv_MainWinH);
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, 'Error', @t[1], Rendermatic.SDL.mainWindowH);
end;
const SDL_INIT_EVENTS = $00004000;
procedure SetProgramName(const newnamu : UTF8string); inline;
begin
if newnamu <> '' then
SDL_SetWindowTitle(mv_MainWinH, @newnamu[1])
with Rendermatic.SDL do if newnamu <> '' then
SDL_SetWindowTitle(mainWindowH, @newnamu[1])
else
SDL_SetWindowTitle(mv_MainWinH, NIL);
SDL_SetWindowTitle(mainWindowH, NIL);
end;
......@@ -32,48 +32,48 @@ begin
case keyval of
KEYVAL_DOWN:
begin
if (byte((mv_PKeystate + SDL_SCANCODE_DOWN)^) <> 0)
or (mv_GamepadH <> NIL)
and (SDL_GameControllerGetButton(mv_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_DOWN) <> 0)
if (byte((sdl_KeyState + SDL_SCANCODE_DOWN)^) <> 0)
or (sdl_GamepadH <> NIL)
and (SDL_GameControllerGetButton(sdl_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_DOWN) <> 0)
then PollKey := 32767
else begin
PollKey := SDL_GameControllerGetAxis(mv_GamepadH, SDL_CONTROLLER_AXIS_LEFTY);
PollKey := SDL_GameControllerGetAxis(sdl_GamepadH, SDL_CONTROLLER_AXIS_LEFTY);
if PollKey < preference.ctrlDeadZone then PollKey := 0;
end;
end;
KEYVAL_UP:
begin
if (byte((mv_PKeystate + SDL_SCANCODE_UP)^) <> 0)
or (mv_GamepadH <> NIL)
and (SDL_GameControllerGetButton(mv_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_UP) <> 0)
if (byte((sdl_KeyState + SDL_SCANCODE_UP)^) <> 0)
or (sdl_GamepadH <> NIL)
and (SDL_GameControllerGetButton(sdl_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_UP) <> 0)
then PollKey := 32767
else begin
PollKey := -SDL_GameControllerGetAxis(mv_GamepadH, SDL_CONTROLLER_AXIS_LEFTY);
PollKey := -SDL_GameControllerGetAxis(sdl_GamepadH, SDL_CONTROLLER_AXIS_LEFTY);
if PollKey < preference.ctrlDeadZone then PollKey := 0;
end;
end;
KEYVAL_LEFT:
begin
if (byte((mv_PKeystate + SDL_SCANCODE_LEFT)^) <> 0)
or (mv_GamepadH <> NIL)
and (SDL_GameControllerGetButton(mv_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_LEFT) <> 0)
if (byte((sdl_KeyState + SDL_SCANCODE_LEFT)^) <> 0)
or (sdl_GamepadH <> NIL)
and (SDL_GameControllerGetButton(sdl_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_LEFT) <> 0)
then PollKey := 32767
else begin
PollKey := -SDL_GameControllerGetAxis(mv_GamepadH, SDL_CONTROLLER_AXIS_LEFTX);
PollKey := -SDL_GameControllerGetAxis(sdl_GamepadH, SDL_CONTROLLER_AXIS_LEFTX);
if PollKey < preference.ctrlDeadZone then PollKey := 0;
end;
end;
KEYVAL_RIGHT:
begin
if (byte((mv_PKeystate + SDL_SCANCODE_RIGHT)^) <> 0)
or (mv_GamepadH <> NIL)
and (SDL_GameControllerGetButton(mv_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) <> 0)
if (byte((sdl_KeyState + SDL_SCANCODE_RIGHT)^) <> 0)
or (sdl_GamepadH <> NIL)
and (SDL_GameControllerGetButton(sdl_GamepadH, SDL_CONTROLLER_BUTTON_DPAD_RIGHT) <> 0)
then PollKey := 32767
else begin
PollKey := SDL_GameControllerGetAxis(mv_GamepadH, SDL_CONTROLLER_AXIS_LEFTX);
PollKey := SDL_GameControllerGetAxis(sdl_GamepadH, SDL_CONTROLLER_AXIS_LEFTX);
if PollKey < preference.ctrlDeadZone then PollKey := 0;
end;
end;
......
......@@ -102,7 +102,7 @@ begin
SetColor(0);
for y := y1 to y2 - 1 do begin
GotoXY(x1, y);
srcp := mv_OutputBuffy + (y * longint(sysvar.windowSize.w) + x1) shl 2;
srcp := outputBuffy + (y * longint(sysvar.windowSize.w) + x1) shl 2;
for x := x1 to x2 - 1 do begin
_GetColor;
if lastcolor <> l then begin
......@@ -161,7 +161,7 @@ begin
while numfresh <> 0 do begin
dec(numfresh);
// First draw into a full RGBX output buffer. (But at a very low resolution.)
RenderRect(refresh[numfresh], mv_OutputBuffy);
RenderRect(refresh[numfresh], outputBuffy);
// Then convert to ASCII and write to the console.
with refresh[numfresh] do BlitzAscii(left, top, right, bottom);
end;
......
......@@ -19,14 +19,37 @@
// Namespace object for the Rendermatic. It builds output frames from graphic assets and framebuffer effects.
type TRendermatic = object
{$ifndef sakucon}
SDL : record
mainWindowH : PSDL_Window;
rendererH : PSDL_Renderer;
mainTextureH : PSDL_Texture;
end;
{$endif}
// BGRA buffer for the full game window: windowSize.w * windowSize.h * 4
outputBuffy : pointer;
// Another BGRA buffer of the same size. Some effects and transitions need a textboxless view of the game window, which is
// kept here.
stashBuffy : pointer;
refresh : array of TEdgeCoordP;
numFresh : dword;
//RGBtweaktable : array[0..767] of byte; // fullscreen 3-chn adjustment
//RGBtweakactive : byte;
procedure Reset;
procedure ClipRGB(clipdata : pblitstruct);
procedure BuildRGBtweakTable(r1, g1, b1 : longint);
//procedure BuildRGBtweakTable(r1, g1, b1 : longint);
procedure RenderTransition;
procedure RenderRect(const refrect : TEdgeCoordP; const destbuf : pointer);
procedure StashRender(viewnum : dword);
procedure RenderEverything;
procedure AddRefresh(x1p, y1p, x2p, y2p : longint);
{$ifdef sakucon}
procedure RemoveRefresh(x1p, y1p, x2p, y2p : longint);
procedure BlitzAscii(x1, y1, x2, y2 : longint);
{$else}
function CreateRendererAndTexture : boolean;
{$endif}
end;
......
This diff is collapsed.
......@@ -19,6 +19,114 @@
// SuperSakura SDL-specific rendering functions.
function TRendermatic.CreateRendererAndTexture : boolean;
// Prepares SDL components for rendering duties, returns TRUE if successful.
var rendinfo : TSDL_RendererInfo;
i, j : dword;
txformat : dword;
txaccess, txwidth, txheight : longint;
begin
result := FALSE;
with SDL do begin
// Release the old-sized texture and renderer, if any.
if mainTextureH <> NIL then begin
SDL_DestroyTexture(mainTextureH); mainTextureH := NIL;
end;
if rendererH <> NIL then begin
SDL_DestroyRenderer(rendererH); rendererH := NIL;
end;
// Create the renderer!
i := 0;
if preference.useVSync then i := SDL_RENDERER_PRESENTVSYNC;
try
rendererH := SDL_CreateRenderer(mainWindowH, -1, i);
except
on E : Exception do log(E.Message);
end;
if rendererH = NIL then begin
log('Failed to create SDL renderer: ' + SDL_GetError);
log('Trying software fallback...');
try
rendererH := SDL_CreateRenderer(mainWindowH, -1, SDL_RENDERER_SOFTWARE);
except
on E : Exception do log(E.Message);
end;
if rendererH = NIL then begin
LogError('Failed to create SDL renderer: ' + SDL_GetError);
exit;
end;
end;
SDL_GetRendererOutputSize(rendererH, @i, @j);
log(strcat('New renderer output size: %x%', [i, j]));
// Clear the window a few times (double/triple buffering).
for i := 2 downto 0 do begin
SDL_SetRenderDrawColor(rendererH, 0, 0, 0, 255);
SDL_RenderClear(rendererH);
SDL_RenderPresent(rendererH);
end;
i := SDL_GetRendererInfo(rendererH, @rendinfo);
if i <> 0 then
LogError('Error fetching renderer info: ' + SDL_GetError)
else begin
log('Using renderer: ' + rendinfo.name);
log('Desired texture size: ' + sysvar.windowSize.ToString);
log(strcat('Max texture size (effectively, largest possible window): %x%',
[rendinfo.max_texture_width, rendinfo.max_texture_height]));
if rendinfo.flags and SDL_RENDERER_SOFTWARE <> 0 then
log('We''re a software renderer')
else
log('We''re a hardware renderer');
if rendinfo.flags and SDL_RENDERER_ACCELERATED <> 0 then
log('We''re accelerated')
else
log('We''re not accelerated');
if rendinfo.flags and SDL_RENDERER_PRESENTVSYNC <> 0 then
log('We''re vsynched')
else
log('We''re not vsynched');
end;
// Create the texture that is directly used as output.
mainTextureH := SDL_CreateTexture(
rendererH, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, sysvar.windowSize.w, sysvar.windowSize.h);
if mainTextureH = NIL then begin
LogError('Failed to create SDL maintex: ' + SDL_GetError);
exit;
end;
i := SDL_QueryTexture(mainTextureH, @txformat, @txaccess, @txwidth, @txheight);
if i <> 0 then
LogError('Error fetching texture info: ' + SDL_GetError)
else begin
log(strcat('Using texture %x%, format $&', [txwidth, txheight, txformat]));
case txaccess of
SDL_TEXTUREACCESS_STATIC: log('Static texture access, not lockable');
SDL_TEXTUREACCESS_STREAMING: log('Streaming texture access, lockable');
SDL_TEXTUREACCESS_TARGET: log('Texture is a render target');
else log('Unknown texture access');
end;
end;
// Set up buffers for output.
i := sysvar.windowSize.w * sysvar.windowSize.h * 4;
if outputBuffy <> NIL then begin freemem(outputBuffy); outputBuffy := NIL; end;
getmem(outputBuffy, i);
if stashBuffy <> NIL then begin freemem(stashBuffy); stashBuffy := NIL; end;
getmem(stashBuffy, i);
// Make sure we start with a clean, black window.
filldword(outputBuffy^, sysvar.windowSize.w * sysvar.windowSize.h, 0);
SDL_UpdateTexture(mainTextureH, NIL, outputBuffy, sysvar.windowSize.w * 4);
end;
result := TRUE;
end;
{$include sakurendermatic-implementation.pas}
procedure TRendermatic.RenderEverything;
......@@ -31,7 +139,7 @@ begin
dec(numfresh);
// Draw stuff.
RenderRect(refresh[numfresh], mv_OutputBuffy);
RenderRect(refresh[numfresh], outputBuffy);
// Push into the output texture.
with refresh[numfresh] do begin
......@@ -40,13 +148,13 @@ begin
rekt.w := right - left;
rekt.h := bottom - top;
SDL_UpdateTexture(mv_MainTexH, @rekt,
mv_OutputBuffy + top * windowbytewidth + left * 4,
SDL_UpdateTexture(SDL.mainTextureH, @rekt,
outputBuffy + top * windowbytewidth + left * 4,
windowbytewidth);
end;
end;
// Push the texture into the renderer. Apparently we can't rely on the previous frame still being there, so gotta do
// fullscreen updates.
SDL_RenderCopy(mv_RendererH, mv_MainTexH, NIL, NIL);
SDL_RenderCopy(SDL.rendererH, SDL.mainTextureH, NIL, NIL);
end;
......@@ -74,7 +74,7 @@ begin
viewportRatio.h := viewportSizeP.h;
UpdateCoscosTable(sysvar.windowSize.w + sysvar.windowSize.h);
// All previous screen refresh rects can be dropped, as they are now mis-sized.
numfresh := 0;
Rendermatic.numfresh := 0;
end
else begin
if viewportParent >= viewportIndex then begin
......@@ -83,7 +83,7 @@ begin
end;
// Mark the previous viewport pixel position for redrawing.
AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
Rendermatic.AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
// Start from the parent's pixel coords.
with viewport[viewportParent] do begin
......@@ -134,7 +134,7 @@ begin
end;
// Mark the updated viewport pixel position for redrawing.
AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
Rendermatic.AddRefresh(viewportLoc.leftp, viewportLoc.topp, viewportLoc.rightp, viewportLoc.bottomp);
// Refresh all children viewports of this viewport.
i := viewportIndex + 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment