mirror of
https://github.com/k4zmu2a/SpaceCadetPinball.git
synced 2024-12-18 10:37:53 +01:00
Improved frame time diagnostic tool.
Split overdraw palette from frame time tool.
This commit is contained in:
parent
16b527e3cf
commit
f3e4211226
6 changed files with 150 additions and 99 deletions
|
@ -111,6 +111,44 @@ void gdrv_bitmap8::ScaleIndexed(float scaleX, float scaleY)
|
|||
BmpBufPtr1 = new ColorRgba[Stride * Height];
|
||||
}
|
||||
|
||||
void gdrv_bitmap8::CreateTexture(const char* scaleHint, int access)
|
||||
{
|
||||
if (Texture != nullptr)
|
||||
{
|
||||
SDL_DestroyTexture(Texture);
|
||||
}
|
||||
|
||||
UsingSdlHint hint{ SDL_HINT_RENDER_SCALE_QUALITY, scaleHint };
|
||||
Texture = SDL_CreateTexture
|
||||
(
|
||||
winmain::Renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
access,
|
||||
Width, Height
|
||||
);
|
||||
SDL_SetTextureBlendMode(Texture, SDL_BLENDMODE_NONE);
|
||||
}
|
||||
|
||||
void gdrv_bitmap8::BlitToTexture()
|
||||
{
|
||||
assertm(Texture, "Updating null texture");
|
||||
int pitch = 0;
|
||||
ColorRgba* lockedPixels;
|
||||
auto result = SDL_LockTexture
|
||||
(
|
||||
Texture,
|
||||
nullptr,
|
||||
reinterpret_cast<void**>(&lockedPixels),
|
||||
&pitch
|
||||
);
|
||||
assertm(result == 0, "Updating non-streaming texture");
|
||||
assertm(static_cast<unsigned>(pitch) == Width * sizeof(ColorRgba), "Padding on vScreen texture");
|
||||
|
||||
std::memcpy(lockedPixels, BmpBufPtr1, Width * Height * sizeof(ColorRgba));
|
||||
|
||||
SDL_UnlockTexture(Texture);
|
||||
}
|
||||
|
||||
int gdrv::display_palette(ColorRgba* plt)
|
||||
{
|
||||
const uint32_t sysPaletteColors[]
|
||||
|
@ -168,12 +206,16 @@ int gdrv::display_palette(ColorRgba* plt)
|
|||
|
||||
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar)
|
||||
{
|
||||
auto color = current_palette[fillChar];
|
||||
fill_bitmap(bmp, width, height, xOff, yOff, current_palette[fillChar]);
|
||||
}
|
||||
|
||||
void gdrv::fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, ColorRgba fillColor)
|
||||
{
|
||||
auto bmpPtr = &bmp->BmpBufPtr1[bmp->Width * yOff + xOff];
|
||||
for (; height > 0; --height)
|
||||
{
|
||||
for (int x = width; x > 0; --x)
|
||||
*bmpPtr++ = color;
|
||||
*bmpPtr++ = fillColor;
|
||||
bmpPtr += bmp->Stride - width;
|
||||
}
|
||||
}
|
||||
|
@ -213,6 +255,19 @@ void gdrv::copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int heigh
|
|||
}
|
||||
}
|
||||
|
||||
void gdrv::ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart)
|
||||
{
|
||||
auto srcPtr = bmp->BmpBufPtr1;
|
||||
auto startOffset = xStart >= 0 ? 0 : -xStart;
|
||||
auto endOffset = xStart >= 0 ? xStart : 0;
|
||||
auto length = bmp->Width - std::abs(xStart);
|
||||
for (int y = bmp->Height; y > 0; --y)
|
||||
{
|
||||
std::memmove(srcPtr + endOffset, srcPtr + startOffset, length * sizeof(ColorRgba));
|
||||
srcPtr += bmp->Stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gdrv::grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6)
|
||||
{
|
||||
|
@ -242,13 +297,6 @@ void gdrv::CreatePreview(gdrv_bitmap8& bmp)
|
|||
if (bmp.Texture)
|
||||
return;
|
||||
|
||||
auto texture = SDL_CreateTexture
|
||||
(
|
||||
winmain::Renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STATIC,
|
||||
bmp.Width, bmp.Height
|
||||
);
|
||||
SDL_UpdateTexture(texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
|
||||
bmp.Texture = texture;
|
||||
bmp.CreateTexture("nearest", SDL_TEXTUREACCESS_STATIC);
|
||||
SDL_UpdateTexture(bmp.Texture, nullptr, bmp.BmpBufPtr1, bmp.Width * 4);
|
||||
}
|
||||
|
|
|
@ -19,14 +19,20 @@ struct Rgba
|
|||
|
||||
union ColorRgba
|
||||
{
|
||||
static constexpr ColorRgba Black() { return ColorRgba{ Rgba{0, 0, 0, 255} }; }
|
||||
static constexpr ColorRgba White() { return ColorRgba{ Rgba{255, 255, 255, 255} }; }
|
||||
static constexpr ColorRgba Red() { return ColorRgba{ Rgba{0, 0, 255, 255} }; }
|
||||
static constexpr ColorRgba Green() { return ColorRgba{ Rgba{0, 255,0, 255} }; }
|
||||
static constexpr ColorRgba Blue() { return ColorRgba{ Rgba{255, 0, 0, 255} }; }
|
||||
|
||||
ColorRgba() = default;
|
||||
|
||||
explicit ColorRgba(uint32_t color)
|
||||
explicit constexpr ColorRgba(uint32_t color)
|
||||
: Color(color)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ColorRgba(Rgba rgba)
|
||||
explicit constexpr ColorRgba(Rgba rgba)
|
||||
: rgba(rgba)
|
||||
{
|
||||
}
|
||||
|
@ -43,6 +49,8 @@ struct gdrv_bitmap8
|
|||
gdrv_bitmap8(const struct dat8BitBmpHeader& header);
|
||||
~gdrv_bitmap8();
|
||||
void ScaleIndexed(float scaleX, float scaleY);
|
||||
void CreateTexture(const char* scaleHint, int access);
|
||||
void BlitToTexture();
|
||||
ColorRgba* BmpBufPtr1;
|
||||
char* IndexedBmpPtr;
|
||||
int Width;
|
||||
|
@ -62,10 +70,12 @@ class gdrv
|
|||
public:
|
||||
static int display_palette(ColorRgba* plt);
|
||||
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, uint8_t fillChar);
|
||||
static void fill_bitmap(gdrv_bitmap8* bmp, int width, int height, int xOff, int yOff, ColorRgba fillColor);
|
||||
static void copy_bitmap(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp,
|
||||
int srcXOff, int srcYOff);
|
||||
static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff,
|
||||
gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff);
|
||||
static void ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart);
|
||||
static void grtext_draw_ttext_in_box(LPCSTR text, int xOff, int yOff, int width, int height, int a6);
|
||||
static void ApplyPalette(gdrv_bitmap8& bmp);
|
||||
static void CreatePreview(gdrv_bitmap8& bmp);
|
||||
|
|
|
@ -16,7 +16,6 @@ float render::zscaler, render::zmin, render::zmax;
|
|||
rectangle_type render::vscreen_rect;
|
||||
gdrv_bitmap8 *render::vscreen, *render::background_bitmap, *render::ball_bitmap[20];
|
||||
zmap_header_type* render::zscreen;
|
||||
SDL_Texture* render::vScreenTex = nullptr;
|
||||
SDL_Rect render::DestinationRect{};
|
||||
|
||||
void render::init(gdrv_bitmap8* bmp, float zMin, float zScaler, int width, int height)
|
||||
|
@ -58,26 +57,11 @@ void render::uninit()
|
|||
ball_list.clear();
|
||||
dirty_list.clear();
|
||||
sprite_list.clear();
|
||||
SDL_DestroyTexture(vScreenTex);
|
||||
vScreenTex = nullptr;
|
||||
}
|
||||
|
||||
void render::recreate_screen_texture()
|
||||
{
|
||||
if (vScreenTex != nullptr)
|
||||
{
|
||||
SDL_DestroyTexture(vScreenTex);
|
||||
}
|
||||
|
||||
UsingSdlHint hint{ SDL_HINT_RENDER_SCALE_QUALITY, options::Options.LinearFiltering ? "linear" : "nearest" };
|
||||
vScreenTex = SDL_CreateTexture
|
||||
(
|
||||
winmain::Renderer,
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
vscreen_rect.Width, vscreen_rect.Height
|
||||
);
|
||||
SDL_SetTextureBlendMode(vScreenTex, SDL_BLENDMODE_NONE);
|
||||
vscreen->CreateTexture(options::Options.LinearFiltering ? "linear" : "nearest", SDL_TEXTUREACCESS_STREAMING);
|
||||
}
|
||||
|
||||
void render::update()
|
||||
|
@ -535,31 +519,13 @@ void render::SpriteViewer(bool* show)
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void render::BlitVScreen()
|
||||
{
|
||||
int pitch = 0;
|
||||
ColorRgba* lockedPixels;
|
||||
SDL_LockTexture
|
||||
(
|
||||
vScreenTex,
|
||||
nullptr,
|
||||
reinterpret_cast<void**>(&lockedPixels),
|
||||
&pitch
|
||||
);
|
||||
assertm(static_cast<unsigned>(pitch) == vscreen->Width * sizeof(ColorRgba), "Padding on vScreen texture");
|
||||
|
||||
std::memcpy(lockedPixels, vscreen->BmpBufPtr1, vscreen->Width * vscreen->Height * sizeof(ColorRgba));
|
||||
|
||||
SDL_UnlockTexture(vScreenTex);
|
||||
}
|
||||
|
||||
void render::PresentVScreen()
|
||||
{
|
||||
BlitVScreen();
|
||||
vscreen->BlitToTexture();
|
||||
|
||||
if (offset_x == 0 && offset_y == 0)
|
||||
{
|
||||
SDL_RenderCopy(winmain::Renderer, vScreenTex, nullptr, &DestinationRect);
|
||||
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, nullptr, &DestinationRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -591,8 +557,8 @@ void render::PresentVScreen()
|
|||
DestinationRect.w - dstSeparationX, static_cast<float>(DestinationRect.h)
|
||||
};
|
||||
|
||||
SDL_RenderCopyF(winmain::Renderer, vScreenTex, &srcBoardRect, &dstBoardRect);
|
||||
SDL_RenderCopyF(winmain::Renderer, vScreenTex, &srcSidebarRect, &dstSidebarRect);
|
||||
SDL_RenderCopyF(winmain::Renderer, vscreen->Texture, &srcBoardRect, &dstBoardRect);
|
||||
SDL_RenderCopyF(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
|
||||
#else
|
||||
// SDL_RenderCopy cannot express sub pixel offset.
|
||||
// Vscreen shift is required for that.
|
||||
|
@ -615,8 +581,8 @@ void render::PresentVScreen()
|
|||
DestinationRect.w - dstSeparationX, DestinationRect.h
|
||||
};
|
||||
|
||||
SDL_RenderCopy(winmain::Renderer, vScreenTex, &srcBoardRect, &dstBoardRect);
|
||||
SDL_RenderCopy(winmain::Renderer, vScreenTex, &srcSidebarRect, &dstSidebarRect);
|
||||
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcBoardRect, &dstBoardRect);
|
||||
SDL_RenderCopy(winmain::Renderer, vscreen->Texture, &srcSidebarRect, &dstSidebarRect);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,10 +60,8 @@ private:
|
|||
static rectangle_type vscreen_rect;
|
||||
static gdrv_bitmap8 *ball_bitmap[20];
|
||||
static zmap_header_type* zscreen;
|
||||
static SDL_Texture* vScreenTex;
|
||||
|
||||
static void repaint(struct render_sprite_type_struct* sprite);
|
||||
static void paint_balls();
|
||||
static void unpaint_balls();
|
||||
static void BlitVScreen();
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ int winmain::return_value = 0;
|
|||
bool winmain::bQuit = false;
|
||||
bool winmain::activated = false;
|
||||
int winmain::DispFrameRate = 0;
|
||||
int winmain::DispGRhistory = 0;
|
||||
bool winmain::DispGRhistory = false;
|
||||
bool winmain::single_step = false;
|
||||
bool winmain::has_focus = true;
|
||||
int winmain::last_mouse_x;
|
||||
|
@ -185,7 +185,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
else
|
||||
pb::replay_level(0);
|
||||
|
||||
unsigned dtHistoryCounter = 300u, updateCounter = 0, frameCounter = 0;
|
||||
unsigned updateCounter = 0, frameCounter = 0;
|
||||
|
||||
auto frameStart = Clock::now();
|
||||
double UpdateToFrameCounter = 0;
|
||||
|
@ -209,36 +209,6 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
}
|
||||
}
|
||||
|
||||
if (DispGRhistory)
|
||||
{
|
||||
if (!gfr_display)
|
||||
{
|
||||
auto plt = static_cast<ColorRgba*>(malloc(1024u));
|
||||
auto pltPtr = &plt[10]; // first 10 entries are system colors hardcoded in display_palette()
|
||||
for (int i1 = 0, i2 = 0; i1 < 256 - 10; ++i1, i2 += 8)
|
||||
{
|
||||
unsigned char blue = i2, redGreen = i2;
|
||||
if (i2 > 255)
|
||||
{
|
||||
blue = 255;
|
||||
redGreen = i1;
|
||||
}
|
||||
|
||||
*pltPtr++ = ColorRgba{Rgba{redGreen, redGreen, blue, 0}};
|
||||
}
|
||||
gdrv::display_palette(plt);
|
||||
free(plt);
|
||||
gfr_display = new gdrv_bitmap8(400, 15, false);
|
||||
}
|
||||
|
||||
if (!dtHistoryCounter)
|
||||
{
|
||||
dtHistoryCounter = 300;
|
||||
gdrv::copy_bitmap(render::vscreen, 300, 10, 0, 30, gfr_display, 0, 0);
|
||||
gdrv::fill_bitmap(gfr_display, 300, 10, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!ProcessWindowMessages() || bQuit)
|
||||
break;
|
||||
|
||||
|
@ -262,18 +232,30 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
if (!single_step && !no_time_loss)
|
||||
{
|
||||
auto dt = static_cast<float>(frameDuration.count());
|
||||
auto dtWhole = static_cast<int>(std::round(dt));
|
||||
pb::frame(dt);
|
||||
if (gfr_display)
|
||||
if (DispGRhistory)
|
||||
{
|
||||
auto deltaTPal = dtWhole + 10;
|
||||
auto fillChar = static_cast<uint8_t>(deltaTPal);
|
||||
if (deltaTPal > 236)
|
||||
auto width = 300;
|
||||
auto height = 64;
|
||||
if (!gfr_display)
|
||||
{
|
||||
fillChar = 1;
|
||||
gfr_display = new gdrv_bitmap8(width, height, false);
|
||||
gfr_display->CreateTexture("nearest", SDL_TEXTUREACCESS_STREAMING);
|
||||
}
|
||||
gdrv::fill_bitmap(gfr_display, 1, 10, 300 - dtHistoryCounter, 0, fillChar);
|
||||
--dtHistoryCounter;
|
||||
|
||||
gdrv::ScrollBitmapHorizontal(gfr_display, -1);
|
||||
|
||||
auto target = static_cast<float>(TargetFrameTime.count());
|
||||
auto scale = height / target / 2;
|
||||
gdrv::fill_bitmap(gfr_display, 1, height, width - 1, 0, ColorRgba::Black()); // Background
|
||||
|
||||
auto targetVal = dt < target ? dt : target;
|
||||
auto targetHeight = std::min(static_cast<int>(std::round(targetVal * scale)), width);
|
||||
gdrv::fill_bitmap(gfr_display, 1, targetHeight, width - 1, height - targetHeight, ColorRgba::White()); // Target
|
||||
|
||||
auto diffVal = dt < target ? target - dt : dt - target;
|
||||
auto diffHeight = std::min(static_cast<int>(std::round(diffVal * scale)), width);
|
||||
gdrv::fill_bitmap(gfr_display, 1, diffHeight, width - 1, height - targetHeight - diffHeight, ColorRgba::Red()); // Target diff
|
||||
}
|
||||
updateCounter++;
|
||||
}
|
||||
|
@ -327,6 +309,7 @@ int winmain::WinMain(LPCSTR lpCmdLine)
|
|||
}
|
||||
|
||||
delete gfr_display;
|
||||
gfr_display = nullptr;
|
||||
options::uninit();
|
||||
midi::music_shutdown();
|
||||
pb::uninit();
|
||||
|
@ -561,6 +544,10 @@ void winmain::RenderUi()
|
|||
pause();
|
||||
ShowSpriteViewer ^= true;
|
||||
}
|
||||
if (pb::cheat_mode && ImGui::MenuItem("Frame Times", nullptr, DispGRhistory))
|
||||
{
|
||||
DispGRhistory ^= true;
|
||||
}
|
||||
if (ImGui::BeginMenu("Cheats"))
|
||||
{
|
||||
if (ImGui::MenuItem("hidden test", nullptr, pb::cheat_mode))
|
||||
|
@ -599,6 +586,8 @@ void winmain::RenderUi()
|
|||
if (ShowSpriteViewer)
|
||||
render::SpriteViewer(&ShowSpriteViewer);
|
||||
options::RenderControlDialog();
|
||||
if (DispGRhistory)
|
||||
RenderFrameTimeDialog();
|
||||
}
|
||||
|
||||
int winmain::event_handler(const SDL_Event* event)
|
||||
|
@ -687,7 +676,26 @@ int winmain::event_handler(const SDL_Event* event)
|
|||
switch (event->key.keysym.sym)
|
||||
{
|
||||
case SDLK_g:
|
||||
DispGRhistory = 1;
|
||||
DispGRhistory ^= true;
|
||||
break;
|
||||
case SDLK_o:
|
||||
{
|
||||
auto plt = new ColorRgba[4 * 256];
|
||||
auto pltPtr = &plt[10]; // first 10 entries are system colors hardcoded in display_palette()
|
||||
for (int i1 = 0, i2 = 0; i1 < 256 - 10; ++i1, i2 += 8)
|
||||
{
|
||||
unsigned char blue = i2, redGreen = i2;
|
||||
if (i2 > 255)
|
||||
{
|
||||
blue = 255;
|
||||
redGreen = i1;
|
||||
}
|
||||
|
||||
*pltPtr++ = ColorRgba{ Rgba{redGreen, redGreen, blue, 0} };
|
||||
}
|
||||
gdrv::display_palette(plt);
|
||||
delete[] plt;
|
||||
}
|
||||
break;
|
||||
case SDLK_y:
|
||||
SDL_SetWindowTitle(MainWindow, "Pinball");
|
||||
|
@ -925,3 +933,23 @@ void winmain::UpdateFrameRate()
|
|||
UpdateToFrameRatio = static_cast<double>(ups) / fps;
|
||||
TargetFrameTime = DurationMs(1000.0 / ups);
|
||||
}
|
||||
|
||||
void winmain::RenderFrameTimeDialog()
|
||||
{
|
||||
if (!gfr_display)
|
||||
return;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2{ 300, 70 });
|
||||
if (ImGui::Begin("Frame Times", &DispGRhistory, ImGuiWindowFlags_NoScrollbar))
|
||||
{
|
||||
auto target = static_cast<float>(TargetFrameTime.count());
|
||||
auto scale = 1 / (64 / 2 / target);
|
||||
|
||||
ImGui::Text("Target frame time:%03.04fms, 1px:%03.04fms", target, scale);
|
||||
gfr_display->BlitToTexture();
|
||||
auto region = ImGui::GetContentRegionAvail();
|
||||
ImGui::Image(gfr_display->Texture, region);
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
|
|
|
@ -63,9 +63,9 @@ public:
|
|||
static bool RestartRequested() { return restart; }
|
||||
static void UpdateFrameRate();
|
||||
private:
|
||||
static int return_value, DispFrameRate, DispGRhistory;
|
||||
static int return_value, DispFrameRate;
|
||||
static int mouse_down, last_mouse_x, last_mouse_y;
|
||||
static bool no_time_loss, activated, bQuit, has_focus;
|
||||
static bool no_time_loss, activated, bQuit, has_focus, DispGRhistory;
|
||||
static gdrv_bitmap8* gfr_display;
|
||||
static std::string FpsDetails;
|
||||
static bool restart;
|
||||
|
@ -77,4 +77,5 @@ private:
|
|||
static struct optionsStruct& Options;
|
||||
|
||||
static void RenderUi();
|
||||
static void RenderFrameTimeDialog();
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue