Skip to content

Commit

Permalink
feat(profiling): add fps meter (#192)
Browse files Browse the repository at this point in the history
Signed-off-by: Vasilyy Balyasnyy <v.balyasnyy@gmail.com>
  • Loading branch information
vbalyasnyy committed Mar 25, 2020
1 parent 7c9a6d1 commit 967b2f9
Show file tree
Hide file tree
Showing 7 changed files with 230 additions and 6 deletions.
3 changes: 2 additions & 1 deletion include/LCUI/gui/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pkginclude_HEADERS = widget_base.h widget_task.h widget_prototype.h \
widget_style.h widget_event.h widget_paint.h widget.h css_library.h \
widget_helper.h css_parser.h css_rule_font_face.h css_fontstyle.h \
builder.h metrics.h widget_layout.h widget_attribute.h widget_id.h \
widget_class.h widget_status.h widget_tree.h widget_hash.h
widget_class.h widget_status.h widget_tree.h widget_hash.h \
widget_fpsmeter.h

pkgincludedir=$(prefix)/include/LCUI/gui
69 changes: 69 additions & 0 deletions include/LCUI/gui/widget_fpsmeter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* widget_fpsmeter.h -- The widget fps meter operation set.
*
* Copyright (c) 2020, Vasilyy Balyasnyy <v.balyasnyy@gmail.com> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of LCUI nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef LCUI_WIDGET_FPSMETER_H
#define LCUI_WIDGET_FPSMETER_H

LCUI_BEGIN_HEADER

#include <LCUI/LCUI.h>
#include <LCUI/gui/widget.h>
#include <LCUI/gui/widget/textview.h>

typedef struct LCUI_FpsMeterRec_ {
LCUI_BOOL is_enabled;

LCUI_Widget widget;

int64_t last_time;
size_t frame_count;

size_t fps;
int render_thread_count;
size_t render_count;
size_t widget_update_count;
} LCUI_FpsMeterRec, *LCUI_FpsMeter;

void LCUI_FpsMeter_FrameCount(void);

void LCUI_FpsMeter_RenderThreadCount(int count);

void LCUI_FpsMeter_RenderCount(size_t count);

void LCUI_FpsMeter_WidgetUpdateCount(size_t count);

void LCUI_FpsMeter_Enable(void);

void LCUI_FpsMeter_Disable(void);

LCUI_END_HEADER

#endif

2 changes: 1 addition & 1 deletion include/LCUI/gui/widget_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ LCUI_API void Widget_AddTask(LCUI_Widget widget, int task_type);
/** 处理部件中当前积累的任务 */
LCUI_API size_t Widget_Update(LCUI_Widget w);

LCUI_API void Widget_UpdateWithProfile(LCUI_Widget w,
LCUI_API size_t Widget_UpdateWithProfile(LCUI_Widget w,
LCUI_WidgetTasksProfile profile);

/** 为子级部件添加任务 */
Expand Down
9 changes: 8 additions & 1 deletion src/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include <LCUI/thread.h>
#include <LCUI/display.h>
#include <LCUI/platform.h>
#include <LCUI/gui/widget_fpsmeter.h>
#ifdef LCUI_DISPLAY_H
#include LCUI_DISPLAY_H
#endif
Expand Down Expand Up @@ -337,6 +338,9 @@ static size_t LCUIDisplay_RenderSurface(SurfaceRecord record)
for (i = 0; i < (int)rects.length; ++i) {
count += LCUIDisplay_RenderSurfaceRect(record,
rect_array[i]);
#ifdef USE_OPENMP
LCUI_FpsMeter_RenderThreadCount(omp_get_num_threads());
#endif
}
} else {
for (i = 0; i < (int)rects.length; ++i) {
Expand Down Expand Up @@ -379,12 +383,14 @@ size_t LCUIDisplay_Render(void)
LinkedListNode *node;

if (!display.active) {
LCUI_FpsMeter_RenderCount(0);
return 0;
}
for (LinkedList_Each(node, &display.surfaces)) {
count += LCUIDisplay_RenderSurface(node->data);
count += LCUIDisplay_UpdateFlashRects(node->data);
}
LCUI_FpsMeter_RenderCount(count);
return count;
}

Expand All @@ -405,6 +411,7 @@ void LCUIDisplay_Present(void)
Surface_Present(surface);
}
}
LCUI_FpsMeter_FrameCount();
}

void LCUIDisplay_InvalidateArea(LCUI_Rect *rect)
Expand Down Expand Up @@ -983,4 +990,4 @@ int LCUI_FreeDisplay(void)
LCUI_DestroyDisplayDriver(display.driver);
}
return 0;
}
}
1 change: 1 addition & 0 deletions src/gui/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ widget_background.c \
widget_border.c \
widget_shadow.c \
widget_diff.c \
widget_fpsmeter.c \
css_parser.c \
css_rule_font_face.c \
css_library.c \
Expand Down
139 changes: 139 additions & 0 deletions src/gui/widget_fpsmeter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*
* widget_fpsmeter.h -- The widget fps meter operation set.
*
* Copyright (c) 2020, Vasilyy Balyasnyy <v.balyasnyy@gmail.com> All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of LCUI nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <LCUI_Build.h>
#include <LCUI/LCUI.h>
#include <LCUI/graph.h>
#include <LCUI/font/fontlibrary.h>
#include <LCUI/gui/css_library.h>
#include <LCUI/gui/css_fontstyle.h>
#include <LCUI/gui/css_parser.h>
#include <LCUI/font/textlayer.h>
#include <LCUI/gui/widget_fpsmeter.h>

#define FPS_METER_TEXT_SIZE_MAX (256)
#define FPS_METER_UPDATE_TIME_MS (1000)

static LCUI_FpsMeterRec self = {FALSE, };


static const char *css = CodeToString(

textview {
color: rgb(255,255,255);
font-size: 16px;
text-align: left;
z-index: INT_MAX;
position: absolute;
padding: 20px, 20px 20px 20px;
background-color: rgb(60, 60, 60);
opacity: 0.5;
}

);

void LCUI_FpsMeter_Update()
{
if (self.is_enabled == FALSE) {
return;
}

char buf[FPS_METER_TEXT_SIZE_MAX];
snprintf(buf, FPS_METER_TEXT_SIZE_MAX,
"FPS: %ld\n"
"Render thread count: %d\n"
"Widget update count: %ld\n"
"Render count: %ld",
self.fps,
self.render_thread_count,
self.widget_update_count,
self.render_count);
TextView_SetText(self.widget, buf);
}

void LCUI_FpsMeter_FrameCount(void)
{
self.frame_count++;
if (LCUI_GetTimeDelta(self.last_time) >= FPS_METER_UPDATE_TIME_MS) {
self.fps = (self.frame_count * 1000 ) / FPS_METER_UPDATE_TIME_MS;
self.frame_count = 0;
self.last_time = LCUI_GetTime();

LCUI_FpsMeter_Update();
}
}

void LCUI_FpsMeter_RenderThreadCount(int count)
{
if (self.render_thread_count != count) {
self.render_thread_count = count;
}
}

void LCUI_FpsMeter_RenderCount(size_t count)
{
if (self.render_count != count) {
self.render_count = count;
}
}

void LCUI_FpsMeter_WidgetUpdateCount(size_t count)
{
if (self.widget_update_count != count) {
self.widget_update_count = count;
}
}

void LCUI_FpsMeter_Enable()
{
self.last_time = LCUI_GetTime();
self.frame_count = 0;
self.fps = 0;
self.render_thread_count = 1;

self.widget = LCUIWidget_New("textview");
LCUI_LoadCSSString(css, __FILE__);
Widget_UpdateStyle(self.widget, TRUE);

self.is_enabled = TRUE;
LCUI_FpsMeter_Update();
Widget_Append(LCUIWidget_GetRoot(), self.widget);
}

void LCUI_FpsMeter_Disable()
{
self.is_enabled = FALSE;
Widget_Destroy(self.widget);
}

13 changes: 10 additions & 3 deletions src/gui/widget_task.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <LCUI_Build.h>
#include <LCUI/LCUI.h>
#include <LCUI/gui/widget.h>
#include <LCUI/gui/widget_fpsmeter.h>
#include <LCUI/gui/metrics.h>
#include "widget_diff.h"
#include "widget_border.h"
Expand Down Expand Up @@ -514,23 +515,28 @@ size_t LCUIWidget_Update(void)
LCUIWidget_ClearTrash();
self.metrics = *metrics;
self.refresh_all = FALSE;
LCUI_FpsMeter_WidgetUpdateCount(count);
return count;
}

void Widget_UpdateWithProfile(LCUI_Widget w, LCUI_WidgetTasksProfile profile)
size_t Widget_UpdateWithProfile(LCUI_Widget w, LCUI_WidgetTasksProfile profile)
{
size_t count;
LCUI_WidgetTaskContext ctx;

ctx = Widget_BeginUpdate(w, NULL);
ctx->profile = profile;
Widget_UpdateWithContext(w, ctx);
count = Widget_UpdateWithContext(w, ctx);
Widget_EndUpdate(ctx);

return count;
}

void LCUIWidget_UpdateWithProfile(LCUI_WidgetTasksProfile profile)
{
LCUI_Widget root;
const LCUI_MetricsRec *metrics;
size_t count = 0;

profile->time = clock();
metrics = LCUI_GetMetrics();
Expand All @@ -544,12 +550,13 @@ void LCUIWidget_UpdateWithProfile(LCUI_WidgetTasksProfile profile)
LCUIWidget_RefreshStyle();
}
root = LCUIWidget_GetRoot();
Widget_UpdateWithProfile(root, profile);
count = Widget_UpdateWithProfile(root, profile);
root->state = LCUI_WSTATE_NORMAL;
profile->time = clock() - profile->time;
profile->destroy_time = clock();
profile->destroy_count = LCUIWidget_ClearTrash();
profile->destroy_time = clock() - profile->destroy_time;
LCUI_FpsMeter_WidgetUpdateCount(count);
}

void LCUIWidget_RefreshStyle(void)
Expand Down

0 comments on commit 967b2f9

Please sign in to comment.