summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d7e26c5)
raw | patch | inline | side by side (parent: d7e26c5)
author | fgsfds <pvt.fgsfds@gmail.com> | |
Sun, 9 Feb 2020 21:07:58 +0000 (00:07 +0300) | ||
committer | fgsfds <pvt.fgsfds@gmail.com> | |
Sun, 9 Feb 2020 21:07:58 +0000 (00:07 +0300) |
index 6e8966eaf5628467df56d3dc145d29f22f05193b..18f75c44ea3263119bd6bfbb429a614c05060e09 100644 (file)
procedure e_InitGL();
procedure e_SetViewPort(X, Y, Width, Height: Word);
procedure e_ResizeWindow(Width, Height: Integer);
+procedure e_ResizeFramebuffer(Width, Height: Integer);
+procedure e_BlitFramebuffer(WinWidth, WinHeight: Integer);
procedure e_Draw(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean;
Blending: Boolean; Mirror: TMirrorType = TMirrorType.None);
e_NoGraphics: Boolean = False;
e_FastScreenshots: Boolean = true; // it's REALLY SLOW with `false`
g_dbg_scale: Single = 1.0;
+ r_pixel_scale: Single = 1.0;
implementation
e_TextureFonts: array of TTextureFont = nil;
e_CharFonts: array of TCharFont;
//e_SavedTextures: array of TSavedTexture;
+ e_FBO: GLuint = 0;
+ e_RBO: GLuint = 0;
+ e_Frame: GLuint = 0;
+ e_FrameW: Integer = -1;
+ e_FrameH: Integer = -1;
//function e_getTextGLId (ID: DWORD): GLuint; begin result := e_Textures[ID].tx.id; end;
if Height <> nil then Height^ := e_Textures[ID].tx.Height;
end;
+procedure e_ResizeFramebuffer(Width, Height: Integer);
+begin
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindRenderbuffer(GL_RENDERBUFFER, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if e_Frame > 0 then
+ begin
+ glDeleteTextures(1, @e_Frame);
+ e_Frame := 0;
+ end;
+
+ if e_RBO > 0 then
+ begin
+ glDeleteRenderbuffers(1, @e_RBO);
+ e_RBO := 0;
+ end;
+
+ if e_FBO > 0 then
+ begin
+ glDeleteFramebuffers(1, @e_FBO);
+ e_FBO := 0;
+ end;
+
+ e_FrameW := Width;
+ e_FrameH := Height;
+
+ glGenFramebuffers(1, @e_FBO);
+
+ glGenTextures(1, @e_Frame);
+ glBindTexture(GL_TEXTURE_2D, e_Frame);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, nil);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glGenRenderbuffers(1, @e_RBO);
+ glBindRenderbuffer(GL_RENDERBUFFER, e_RBO);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, Width, Height);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, e_FBO);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e_Frame, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, e_RBO);
+end;
+
procedure e_ResizeWindow(Width, Height: Integer);
begin
if Height = 0 then
glTexCoord2f(u, v); glVertex2i(x1, y0);
end;
+procedure e_BlitFramebuffer(WinWidth, WinHeight: Integer);
+begin
+ if (e_FBO = 0) or (e_Frame = 0) then exit;
+ glDisable(GL_BLEND);
+ glEnable(GL_TEXTURE_2D);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glBindTexture(GL_TEXTURE_2D, e_Frame);
+ glColor4ub(255, 255, 255, 255);
+ e_SetViewPort(0, 0, WinWidth, WinHeight);
+ glBegin(GL_QUADS);
+ drawTxQuad(0, 0, WinWidth, WinHeight, e_FrameW, e_FrameH, 1, 1, TMirrorType.None);
+ glEnd();
+ glBindFramebuffer(GL_FRAMEBUFFER, e_FBO);
+ e_SetViewPort(0, 0, e_FrameW, e_FrameH);
+end;
+
procedure e_Draw(ID: DWORD; X, Y: Integer; Alpha: Byte; AlphaChannel: Boolean;
Blending: Boolean; Mirror: TMirrorType = TMirrorType.None);
begin
diff --git a/src/game/g_game.pas b/src/game/g_game.pas
index 854a15a978ea9dbb3faecef572e6973abaa77ebb..8d784c2a2be634127f934150244bae03af5e5cb2 100644 (file)
--- a/src/game/g_game.pas
+++ b/src/game/g_game.pas
gMapToDelete: String;
gTempDelete: Boolean = False;
gLastMap: Boolean = False;
- gWinSizeX, gWinSizeY: Integer;
+ gScreenWidth: Word;
+ gScreenHeight: Word;
gResolutionChange: Boolean = False;
gRC_Width, gRC_Height: Integer;
gRC_FullScreen, gRC_Maximized: Boolean;
SortGameStat(CustomStat.PlayerStat);
- if (gSaveStats or gScreenshotStats) and (Length(gPlayers) > 1) then
+ if (gSaveStats or gScreenshotStats) and (Length(CustomStat.PlayerStat) > 1) then
begin
t := Now;
if g_Game_IsNet then StatFilename := NetServerName else StatFilename := 'local';
end;
// HACK: take stats screenshot immediately after the first frame of the stats showing
- if gScreenshotStats and not StatShotDone then
+ if gScreenshotStats and (not StatShotDone) and (Length(CustomStat.PlayerStat) > 1) then
begin
g_TakeScreenShot('stats/' + StatFilename);
StatShotDone := True;
end
else
begin
- glScissor(0, 0, gWinSizeX, gWinSizeY);
+ glScissor(0, 0, gScreenWidth, gScreenHeight);
end;
// no need to clear stencil buffer, light blitting will do it for us... but only for normal scale
if (g_dbg_scale <> 1.0) then glClear(GL_STENCIL_BUFFER_BIT);
if cmd = 'd_window' then
begin
g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
- g_Console_Add(Format('gWinSizeX = %d, gWinSizeY = %d', [gWinSizeX, gWinSizeY]));
+ g_Console_Add(Format('gScreenWidth = %d, gScreenHeight = %d', [gScreenWidth, gScreenHeight]));
end
else if cmd = 'd_sounds' then
begin
conRegVar('dbg_ignore_level_bounds', @g_dbg_ignore_bounds, 'ignore level bounds', '', false);
conRegVar('r_scale', @g_dbg_scale, 0.01, 100.0, 'render scale', '', false);
+ conRegVar('r_resolution_scale', @r_pixel_scale, 0.01, 100.0, 'upscale factor', '', false);
conRegVar('light_enabled', @gwin_k8_enable_light_experiments, 'enable/disable dynamic lighting', 'lighting');
conRegVar('light_player_halo', @g_playerLight, 'enable/disable player halo', 'player light halo');
diff --git a/src/game/g_holmes.pas b/src/game/g_holmes.pas
index a2a55ad87bb0664ec651338a1b396a0994b7b77d..c173bd00312e9686a7e4cb9df0165251e0de4ce4 100644 (file)
--- a/src/game/g_holmes.pas
+++ b/src/game/g_holmes.pas
procedure clearEdgeBmp ();
begin
- SetLength(edgeBmp, (gWinSizeX+4)*(gWinSizeY+4));
+ SetLength(edgeBmp, (gScreenWidth+4)*(gScreenHeight+4));
FillChar(edgeBmp[0], Length(edgeBmp)*sizeof(edgeBmp[0]), 0);
end;
begin
sx := pan.X-(vpx-1);
len := pan.Width;
- if (len > gWinSizeX+4) then len := gWinSizeX+4;
+ if (len > gScreenWidth+4) then len := gScreenWidth+4;
if (sx < 0) then begin len += sx; sx := 0; end;
- if (sx+len > gWinSizeX+4) then len := gWinSizeX+4-sx;
+ if (sx+len > gScreenWidth+4) then len := gScreenWidth+4-sx;
if (len < 1) then exit;
assert(sx >= 0);
- assert(sx+len <= gWinSizeX+4);
+ assert(sx+len <= gScreenWidth+4);
y0 := pan.Y-(vpy-1);
y1 := y0+pan.Height;
if (y0 < 0) then y0 := 0;
- if (y1 > gWinSizeY+4) then y1 := gWinSizeY+4;
+ if (y1 > gScreenHeight+4) then y1 := gScreenHeight+4;
while (y0 < y1) do
begin
- FillChar(edgeBmp[y0*(gWinSizeX+4)+sx], len*sizeof(edgeBmp[0]), 1);
+ FillChar(edgeBmp[y0*(gScreenWidth+4)+sx], len*sizeof(edgeBmp[0]), 1);
Inc(y0);
end;
end
glColor4f(r/255.0, g/255.0, b/255.0, 1.0);
for y := 1 to vph do
begin
- a := @edgeBmp[y*(gWinSizeX+4)+1];
+ a := @edgeBmp[y*(gScreenWidth+4)+1];
startLine(y);
for x := 1 to vpw do
begin
if (a[0] <> 0) then
begin
- if (a[-1] = 0) or (a[1] = 0) or (a[-(gWinSizeX+4)] = 0) or (a[gWinSizeX+4] = 0) or
- (a[-(gWinSizeX+4)-1] = 0) or (a[-(gWinSizeX+4)+1] = 0) or
- (a[gWinSizeX+4-1] = 0) or (a[gWinSizeX+4+1] = 0) then
+ if (a[-1] = 0) or (a[1] = 0) or (a[-(gScreenWidth+4)] = 0) or (a[gScreenWidth+4] = 0) or
+ (a[-(gScreenWidth+4)-1] = 0) or (a[-(gScreenWidth+4)+1] = 0) or
+ (a[gScreenWidth+4-1] = 0) or (a[gScreenWidth+4+1] = 0) then
begin
putPixel(x);
end;
glColor4f(r/255.0, g/255.0, b/255.0, 1.0);
for y := 1 to vph do
begin
- a := @edgeBmp[y*(gWinSizeX+4)+1];
+ a := @edgeBmp[y*(gScreenWidth+4)+1];
startLine(y);
for x := 1 to vpw do
begin
gxSetContext(hlmContext);
try
- //glScissor(0, gWinSizeY-gPlayerScreenSize.Y-1, vpw, vph);
+ //glScissor(0, gScreenHeight-gPlayerScreenSize.Y-1, vpw, vph);
//hlmContext.clip := TGxRect.Create(0, gScreenHeight-gPlayerScreenSize.Y-1, gPlayerScreenSize.X, gPlayerScreenSize.Y);
{
begin
for dx := -1 to 1 do
begin
- if (dx <> 0) or (dy <> 0) then hlmContext.drawText(4+dx, gWinSizeY-10+dy, s);
+ if (dx <> 0) or (dy <> 0) then hlmContext.drawText(4+dx, gScreenHeight-10+dy, s);
end;
end;
hlmContext.color := TGxRGBA.Create(255, 255, 0);
- hlmContext.drawText(4, gWinSizeY-10, s);
+ hlmContext.drawText(4, gScreenHeight-10, s);
gxSetContext(nil);
end;
end;
diff --git a/src/game/g_menu.pas b/src/game/g_menu.pas
index 3513439d44e4b2574f2e33b1b64c9351324a74e6..fe650785d11a8b34baa3b623089b0788e1b37349 100644 (file)
--- a/src/game/g_menu.pas
+++ b/src/game/g_menu.pas
PromptIP: string;
PromptPort: Word;
TempScale: Integer = -1;
+ TempResScale: Integer = -1;
implementation
menu := TGUIMenu(g_GUI_GetWindow('OptionsVideoResMenu').GetControl('mOptionsVideoResMenu'));
TGUILabel(menu.GetControl('lbCurrentRes')).Text :=
- IntToStr(gScreenWidth) +
- ' x ' + IntToStr(gScreenHeight) +
+ IntToStr(gWinSizeX) +
+ ' x ' + IntToStr(gWinSizeY) +
', ' + IntToStr(gBPP) + ' bpp';
with TGUIListBox(menu.GetControl('lsResolution')) do
ItemIndex := 0
else
ItemIndex := 1;
+
+ TempResScale := Round(r_pixel_scale - 1);
+ TGUIScroll(menu.GetControl('scResFactor')).Value := TempResScale;
end;
procedure ProcApplyVideoOptions();
menu: TGUIMenu;
Fullscreen: Boolean;
SWidth, SHeight: Integer;
+ ScaleChanged: Boolean;
str: String;
begin
menu := TGUIMenu(g_GUI_GetWindow('OptionsVideoResMenu').GetControl('mOptionsVideoResMenu'));
str := TGUIListBox(menu.GetControl('lsResolution')).SelectedItem;
- SScanf(str, '%dx%d', [@SWidth, @SHeight]);
+ if str <> '' then
+ SScanf(str, '%dx%d', [@SWidth, @SHeight])
+ else
+ begin
+ SWidth := gWinSizeX;
+ SHeight := gWinSizeY;
+ end;
Fullscreen := TGUISwitch(menu.GetControl('swFullScreen')).ItemIndex = 0;
- if (SWidth <> gScreenWidth) or
- (SHeight <> gScreenHeight) or
- (Fullscreen <> gFullscreen) then
+ ScaleChanged := False;
+ if TGUIScroll(menu.GetControl('scResFactor')).Value <> TempResScale then
+ begin
+ TempResScale := TGUIScroll(menu.GetControl('scResFactor')).Value;
+ r_pixel_scale := TempResScale + 1;
+ ScaleChanged := True;
+ end;
+
+ if (SWidth <> gWinSizeX) or
+ (SHeight <> gWinSizeY) or
+ (Fullscreen <> gFullscreen) or
+ ScaleChanged then
begin
gResolutionChange := True;
gRC_Width := SWidth;
AddItem(_lc[I_MENU_YES]);
AddItem(_lc[I_MENU_NO]);
end;
+ with AddScroll(_lc[I_MENU_GAME_SCALE_FACTOR]) do
+ begin
+ Name := 'scResFactor';
+ Max := 10;
+ end;
AddSpace();
AddButton(@ProcApplyVideoOptions, _lc[I_MENU_RESOLUTION_APPLY]);
UpdateIndex();
diff --git a/src/game/g_options.pas b/src/game/g_options.pas
index 02889313813d3d9cbbba34e7db62f47efa24e6ac..706ca33a1a357d740a82b0282c9557e590a8f929 100644 (file)
--- a/src/game/g_options.pas
+++ b/src/game/g_options.pas
const DF_Default_Megawad_Start = 'megawads/DOOM2D.WAD:\MAP01';
var
- gScreenWidth: Word;
- gScreenHeight: Word;
gBPP: Integer;
gFreq: Byte;
gFullscreen: Boolean;
+ gWinSizeX, gWinSizeY: Integer;
gWinMaximized: Boolean;
gVSync: Boolean;
glLegacyNPOT: Boolean;
+ glRenderToFBO: Boolean = True;
gTextureFilter: Boolean;
gNoSound: Boolean;
gSoundLevel: Integer;
(* Display 0 = Primary display *)
gScreenWidth := 640;
gScreenHeight := 480;
+ gWinSizeX := 640;
+ gWinSizeY := 480;
//gBPP := SDL_BITSPERPIXEL(dispaly.format);
gBPP := 32;
{$IFDEF ANDROID}
if SDL_GetDesktopDisplayMode(0, @display) = 0 then
begin
{$IFDEF ANDROID}
- gScreenWidth := display.w;
- gScreenHeight := display.h;
+ gWinSizeX := display.w;
+ gWinSizeY := display.h;
{$ELSE}
(* Window must be smaller than display *)
closest.w := display.w;
SDL_GetClosestDisplayMode(0, @target, @closest);
Dec(percentage);
end;
- gScreenWidth := closest.w;
- gScreenHeight := closest.h;
+ gWinSizeX := closest.w;
+ gWinSizeY := closest.h;
//gBPP := SDL_BITSPERPIXEL(closest.format); (* Resolution list didn't work for some reason *)
{$ENDIF}
end
gVSync := True;
gTextureFilter := True;
glLegacyNPOT := False;
- gRC_Width := gScreenWidth;
- gRC_Height := gScreenHeight;
+ gRC_Width := gWinSizeX;
+ gRC_Height := gWinSizeY;
gRC_FullScreen := gFullScreen;
gRC_Maximized := gWinMaximized;
- e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gScreenWidth) + ' h = ' + IntToStr(gScreenHeight));
+ e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gWinSizeX) + ' h = ' + IntToStr(gWinSizeY));
g_Console_ResetBinds;
end;
{$ELSE}
procedure g_Options_SetDefaultVideo;
begin
- gScreenWidth := 640;
- gScreenHeight := 480;
+ gWinSizeX := 640;
+ gWinSizeY := 480;
gBPP := 32;
gFullScreen := False;
gWinMaximized := False;
gVSync := True;
gTextureFilter := True;
glLegacyNPOT := False;
- gRC_Width := gScreenWidth;
- gRC_Height := gScreenHeight;
+ gScreenWidth := gWinSizeX;
+ gScreenHeight := gWinSizeY;
+ gRC_Width := gWinSizeX;
+ gRC_Height := gWinSizeY;
gRC_FullScreen := gFullScreen;
gRC_Maximized := gWinMaximized;
- e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gScreenWidth) + ' h = ' + IntToStr(gScreenHeight));
+ e_LogWriteLn('g_Options_SetDefaultVideo: w = ' + IntToStr(gWinSizeX) + ' h = ' + IntToStr(gWinSizeY));
g_Console_ResetBinds;
end;
{$ENDIF}
conRegVar('r_vsync', @gVSync, '', '');
conRegVar('r_texfilter', @gTextureFilter, '', '');
conRegVar('r_npot', @glNPOTOverride, '', '');
+ conRegVar('r_fbo', @glRenderToFBO, '', '');
(* Sound *)
conRegVar('s_nosound', @gNoSound, '', '');
diff --git a/src/game/g_window.pas b/src/game/g_window.pas
index afc23e2b1b22a6e22f4adcd9e89cfa154495e10b..7774c0a34c0c03b2bda5fd5418ece817dc492963 100644 (file)
--- a/src/game/g_window.pas
+++ b/src/game/g_window.pas
mdfo.Free();
Halt(0);
end;
+
+ if (arg = '--pixel-scale') or (arg = '-pixel-scale') then
+ begin
+ if (idx <= ParamCount) then
+ begin
+ if not conParseFloat(r_pixel_scale, ParamStr(idx)) then r_pixel_scale := 1.0;
+ Inc(idx);
+ end;
+ end;
end;
{$IFNDEF USE_SYSSTUB}
glLegacyNPOT := not (GLExtensionSupported('GL_ARB_texture_non_power_of_two') or GLExtensionSupported('GL_OES_texture_npot'));
{$ELSE}
glLegacyNPOT := False;
+ glRenderToFBO := False;
{$ENDIF}
if glNPOTOverride and glLegacyNPOT then
begin
index 00770890eb99be483c7e1f2b6cfe3e7cad38efaf..e5f62750ea6b0ca2c993025d4f7ab23125eb1d35 100644 (file)
begin
gWinSizeX := w;
gWinSizeY := h;
- gScreenWidth := w;
- gScreenHeight := h;
gRC_Width := w;
gRC_Height := h;
+ if glRenderToFBO then
+ begin
+ // store real window size in gWinSize, downscale resolution now
+ w := round(w / r_pixel_scale);
+ h := round(h / r_pixel_scale);
+ e_ResizeFramebuffer(w, h);
+ end;
+ gScreenWidth := w;
+ gScreenHeight := h;
{$IFDEF ENABLE_HOLMES}
fuiScrWdt := w;
fuiScrHgt := h;
begin
{$IFDEF NOGL_INIT}
nogl_Init;
+ glRenderToFBO := False; // TODO: check for GL_OES_framebuffer_object
+ {$ELSE}
+ if glRenderToFBO then
+ if not Load_GL_ARB_framebuffer_object() then
+ if not Load_GL_EXT_framebuffer_object() then
+ begin
+ e_LogWriteln('SDL: no framebuffer support detected');
+ glRenderToFBO := False
+ end;
{$ENDIF}
SDL_WM_SetCaption(GetTitle(), nil);
gFullScreen := fullscreen;
procedure sys_Repaint;
begin
+ if glRenderToFBO then
+ e_BlitFramebuffer(gWinSizeX, gWinSizeY);
SDL_GL_SwapBuffers
end;
index 694042c37dea2db0f756e690b4d14a00f63f16e7..89cebaf02b5e84d292118595e878a4a17e680f52 100644 (file)
begin
gWinSizeX := w;
gWinSizeY := h;
- gScreenWidth := w;
- gScreenHeight := h;
gRC_Width := w;
gRC_Height := h;
+ if glRenderToFBO then
+ begin
+ // store real window size in gWinSize, downscale resolution now
+ w := round(w / r_pixel_scale);
+ h := round(h / r_pixel_scale);
+ e_ResizeFramebuffer(w, h);
+ end;
+ gScreenWidth := w;
+ gScreenHeight := h;
{$IFDEF ENABLE_HOLMES}
fuiScrWdt := w;
fuiScrHgt := h;
begin
{$IFDEF NOGL_INIT}
nogl_Init;
+ glRenderToFBO := False; // TODO: check for GL_OES_framebuffer_object
+ {$ELSE}
+ if glRenderToFBO then
+ if not Load_GL_ARB_framebuffer_object() then
+ if not Load_GL_EXT_framebuffer_object() then
+ begin
+ e_LogWriteln('SDL: no framebuffer support detected');
+ glRenderToFBO := False
+ end;
{$ENDIF}
if (fullscreen = false) and (maximized = false) and (wc = false) then
begin
procedure sys_Repaint;
begin
+ if glRenderToFBO then
+ e_BlitFramebuffer(gWinSizeX, gWinSizeY);
SDL_GL_SwapWindow(window)
end;
index 23cfbc1fc3ca8920b518d9e0af0494ae7de90ab7..3f999ed551d03babf7c615b457c774f810d1b605 100644 (file)
dpi := 96;
{$ENDIF}
- sz := Trunc(g_touch_size * dpi); sw := gScreenWidth; sh := gScreenHeight;
+ sz := Trunc(g_touch_size * dpi); sw := gWinSizeX; sh := gWinSizeY;
x := 0; y := Round(sh * g_touch_offset / 100);
w := sz; h := sz;
Exit;
finger := ev.fingerId + 2;
- x := Trunc(ev.x * gScreenWidth);
- y := Trunc(ev.y * gScreenHeight);
+ x := Trunc(ev.x * gWinSizeX);
+ y := Trunc(ev.y * gWinSizeY);
for i := VK_FIRSTKEY to VK_LASTKEY do
begin