SL-16330 Clean up vertical sync handling, add to UI
parent
b6afa7f7dd
commit
768b7a4d33
|
|
@ -403,7 +403,7 @@ LLWindow* LLWindowManager::createWindow(
|
|||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags,
|
||||
BOOL fullscreen,
|
||||
BOOL clearBg,
|
||||
BOOL disable_vsync,
|
||||
BOOL enable_vsync,
|
||||
BOOL use_gl,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples)
|
||||
|
|
@ -415,26 +415,26 @@ LLWindow* LLWindowManager::createWindow(
|
|||
#if LL_MESA_HEADLESS
|
||||
new_window = new LLWindowMesaHeadless(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
||||
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
|
||||
#elif LL_SDL
|
||||
new_window = new LLWindowSDL(callbacks,
|
||||
title, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
#elif LL_WINDOWS
|
||||
new_window = new LLWindowWin32(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
#elif LL_DARWIN
|
||||
new_window = new LLWindowMacOSX(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth, fsaa_samples);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
new_window = new LLWindowHeadless(callbacks,
|
||||
title, name, x, y, width, height, flags,
|
||||
fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth);
|
||||
fullscreen, clearBg, enable_vsync, use_gl, ignore_pixel_depth);
|
||||
}
|
||||
|
||||
if (FALSE == new_window->isValid())
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ public:
|
|||
BOOL setSize(LLCoordScreen size);
|
||||
BOOL setSize(LLCoordWindow size);
|
||||
virtual void setMinSize(U32 min_width, U32 min_height, bool enforce_immediately = true);
|
||||
virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) = 0;
|
||||
virtual BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) = 0;
|
||||
|
||||
//create a new GL context that shares a namespace with this Window's main GL context and make it current on the current thread
|
||||
// returns a pointer to be handed back to destroySharedConext/makeContextCurrent
|
||||
|
|
@ -92,6 +92,7 @@ public:
|
|||
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
|
||||
virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
|
||||
#if LL_WINDOWS
|
||||
virtual void toggleVSync(bool enable_vsync) = 0;
|
||||
virtual BOOL getCursorDelta(LLCoordCommon* delta) = 0;
|
||||
#endif
|
||||
virtual void showCursor() = 0;
|
||||
|
|
@ -295,7 +296,7 @@ public:
|
|||
U32 flags = 0,
|
||||
BOOL fullscreen = FALSE,
|
||||
BOOL clearBg = FALSE,
|
||||
BOOL disable_vsync = TRUE,
|
||||
BOOL enable_vsync = FALSE,
|
||||
BOOL use_gl = TRUE,
|
||||
BOOL ignore_pixel_depth = FALSE,
|
||||
U32 fsaa_samples = 0);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
//
|
||||
LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
|
||||
U32 flags, BOOL fullscreen, BOOL clear_background,
|
||||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
|
||||
BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth)
|
||||
: LLWindow(callbacks, fullscreen, flags)
|
||||
{
|
||||
// Initialize a headless keyboard.
|
||||
|
|
|
|||
|
|
@ -48,13 +48,14 @@ public:
|
|||
/*virtual*/ BOOL setPosition(LLCoordScreen position) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size) {return FALSE;};
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size) {return FALSE;};
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) {return FALSE;};
|
||||
void* createSharedContext() { return nullptr; }
|
||||
void makeContextCurrent(void*) {}
|
||||
void destroySharedContext(void*) {}
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
|
||||
#if LL_WINDOWS
|
||||
/*virtual*/ virtual void toggleVSync(bool enable_vsync) { }
|
||||
/*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; }
|
||||
#endif
|
||||
/*virtual*/ void showCursor() {};
|
||||
|
|
@ -103,7 +104,7 @@ public:
|
|||
S32 x, S32 y,
|
||||
S32 width, S32 height,
|
||||
U32 flags, BOOL fullscreen, BOOL clear_background,
|
||||
BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
|
||||
BOOL enable_vsync, BOOL use_gl, BOOL ignore_pixel_depth);
|
||||
virtual ~LLWindowHeadless();
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
|||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
|
||||
S32 height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL enable_vsync, BOOL use_gl,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples)
|
||||
: LLWindow(NULL, fullscreen, flags)
|
||||
|
|
@ -165,7 +165,7 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
|||
// Stash an object pointer for OSMessageBox()
|
||||
gWindowImplementation = this;
|
||||
// Create the GL context and set it up for windowed or fullscreen, as appropriate.
|
||||
if(createContext(x, y, width, height, 32, fullscreen, disable_vsync))
|
||||
if(createContext(x, y, width, height, 32, fullscreen, enable_vsync))
|
||||
{
|
||||
if(mWindow != NULL)
|
||||
{
|
||||
|
|
@ -610,7 +610,7 @@ void LLWindowMacOSX::getMouseDeltas(float* delta)
|
|||
delta[1] = mCursorLastEventDeltaY;
|
||||
}
|
||||
|
||||
BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync)
|
||||
BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync)
|
||||
{
|
||||
BOOL glNeedsInit = FALSE;
|
||||
|
||||
|
|
@ -625,7 +625,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
|||
{
|
||||
// Our OpenGL view is already defined within SecondLife.xib.
|
||||
// Get the view instead.
|
||||
mGLView = createOpenGLView(mWindow, mFSAASamples, !disable_vsync);
|
||||
mGLView = createOpenGLView(mWindow, mFSAASamples, enable_vsync);
|
||||
mContext = getCGLContextObj(mGLView);
|
||||
|
||||
// Since we just created the context, it needs to be set up.
|
||||
|
|
@ -653,7 +653,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
|||
|
||||
// Disable vertical sync for swap
|
||||
GLint frames_per_swap = 0;
|
||||
if (disable_vsync)
|
||||
if (!enable_vsync)
|
||||
{
|
||||
frames_per_swap = 0;
|
||||
}
|
||||
|
|
@ -689,7 +689,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
|
|||
|
||||
// We only support OS X 10.7's fullscreen app mode which is literally a full screen window that fills a virtual desktop.
|
||||
// This makes this method obsolete.
|
||||
BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp)
|
||||
BOOL LLWindowMacOSX::switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ public:
|
|||
BOOL setPosition(LLCoordScreen position) override;
|
||||
BOOL setSizeImpl(LLCoordScreen size) override;
|
||||
BOOL setSizeImpl(LLCoordWindow size) override;
|
||||
BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL) override;
|
||||
BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL) override;
|
||||
BOOL setCursorPosition(LLCoordWindow position) override;
|
||||
BOOL getCursorPosition(LLCoordWindow *position) override;
|
||||
void showCursor() override;
|
||||
|
|
@ -143,7 +143,7 @@ public:
|
|||
protected:
|
||||
LLWindowMacOSX(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples);
|
||||
~LLWindowMacOSX();
|
||||
|
|
@ -176,7 +176,7 @@ protected:
|
|||
//
|
||||
|
||||
// create or re-create the GL context/window. Called from the constructor and switchContext().
|
||||
BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL disable_vsync);
|
||||
BOOL createContext(int x, int y, int width, int height, int bits, BOOL fullscreen, BOOL enable_vsync);
|
||||
void destroyContext();
|
||||
void setupFailure(const std::string& text, const std::string& caption, U32 type);
|
||||
void adjustCursorDecouple(bool warpingMouse = false);
|
||||
|
|
|
|||
|
|
@ -473,7 +473,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
|
|||
const std::string& title, const std::string& name, S32 x, S32 y, S32 width,
|
||||
S32 height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg,
|
||||
BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL enable_vsync, BOOL use_gl,
|
||||
BOOL ignore_pixel_depth,
|
||||
U32 fsaa_samples)
|
||||
: LLWindow(callbacks, fullscreen, flags)
|
||||
|
|
@ -800,7 +800,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
|
|||
LLCoordScreen windowPos(x,y);
|
||||
LLCoordScreen windowSize(window_rect.right - window_rect.left,
|
||||
window_rect.bottom - window_rect.top);
|
||||
if (!switchContext(mFullscreen, windowSize, disable_vsync, &windowPos))
|
||||
if (!switchContext(mFullscreen, windowSize, enable_vsync, &windowPos))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1126,7 +1126,7 @@ BOOL LLWindowWin32::setSizeImpl(const LLCoordWindow size)
|
|||
}
|
||||
|
||||
// changing fullscreen resolution
|
||||
BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL disable_vsync, const LLCoordScreen* const posp)
|
||||
BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BOOL enable_vsync, const LLCoordScreen* const posp)
|
||||
{
|
||||
//called from main thread
|
||||
GLuint pixel_format;
|
||||
|
|
@ -1802,16 +1802,7 @@ const S32 max_format = (S32)num_formats - 1;
|
|||
}
|
||||
|
||||
// Disable vertical sync for swap
|
||||
if (disable_vsync && wglSwapIntervalEXT)
|
||||
{
|
||||
LL_DEBUGS("Window") << "Disabling vertical sync" << LL_ENDL;
|
||||
wglSwapIntervalEXT(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Window") << "Keeping vertical sync" << LL_ENDL;
|
||||
wglSwapIntervalEXT(1);
|
||||
}
|
||||
toggleVSync(enable_vsync);
|
||||
|
||||
SetWindowLongPtr(mWindowHandle, GWLP_USERDATA, (LONG_PTR)this);
|
||||
|
||||
|
|
@ -1906,6 +1897,20 @@ void LLWindowWin32::destroySharedContext(void* contextPtr)
|
|||
wglDeleteContext((HGLRC)contextPtr);
|
||||
}
|
||||
|
||||
void LLWindowWin32::toggleVSync(bool enable_vsync)
|
||||
{
|
||||
if (!enable_vsync && wglSwapIntervalEXT)
|
||||
{
|
||||
LL_INFOS("Window") << "Disabling vertical sync" << LL_ENDL;
|
||||
wglSwapIntervalEXT(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS("Window") << "Enabling vertical sync" << LL_ENDL;
|
||||
wglSwapIntervalEXT(1);
|
||||
}
|
||||
}
|
||||
|
||||
void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScreen& size )
|
||||
{
|
||||
if( mIsMouseClipping )
|
||||
|
|
|
|||
|
|
@ -93,11 +93,12 @@ public:
|
|||
/*virtual*/ BOOL setPosition(LLCoordScreen position);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordScreen size);
|
||||
/*virtual*/ BOOL setSizeImpl(LLCoordWindow size);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL disable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
/*virtual*/ BOOL switchContext(BOOL fullscreen, const LLCoordScreen &size, BOOL enable_vsync, const LLCoordScreen * const posp = NULL);
|
||||
/*virtual*/ void setTitle(const std::string title);
|
||||
void* createSharedContext() override;
|
||||
void makeContextCurrent(void* context) override;
|
||||
void destroySharedContext(void* context) override;
|
||||
/*virtual*/ void toggleVSync(bool enable_vsync);
|
||||
/*virtual*/ BOOL setCursorPosition(LLCoordWindow position);
|
||||
/*virtual*/ BOOL getCursorPosition(LLCoordWindow *position);
|
||||
/*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta);
|
||||
|
|
@ -164,7 +165,7 @@ public:
|
|||
protected:
|
||||
LLWindowWin32(LLWindowCallbacks* callbacks,
|
||||
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl,
|
||||
BOOL fullscreen, BOOL clearBg, BOOL enable_vsync, BOOL use_gl,
|
||||
BOOL ignore_pixel_depth, U32 fsaa_samples);
|
||||
~LLWindowWin32();
|
||||
|
||||
|
|
|
|||
|
|
@ -3352,16 +3352,16 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DisableVerticalSync</key>
|
||||
<key>RenderVSyncEnable</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Update frames as fast as possible (FALSE = update frames between display scans). Requires restart.</string>
|
||||
<string>Update frames between display scans (FALSE = Update frames as fast as possible).</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
<key>EnableGroupChatPopups</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -241,6 +241,12 @@ static bool handleAnisotropicChanged(const LLSD& newvalue)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool handleVSyncChanged(const LLSD& newvalue)
|
||||
{
|
||||
gViewerWindow->getWindow()->toggleVSync(newvalue.asBoolean());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handleVolumeLODChanged(const LLSD& newvalue)
|
||||
{
|
||||
LLVOVolume::sLODFactor = llclamp((F32) newvalue.asReal(), 0.01f, MAX_LOD_FACTOR);
|
||||
|
|
@ -665,6 +671,7 @@ void settings_setup_listeners()
|
|||
gSavedSettings.getControl("RenderAutoMaskAlphaNonDeferred")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
|
||||
gSavedSettings.getControl("RenderObjectBump")->getSignal()->connect(boost::bind(&handleRenderBumpChanged, _2));
|
||||
gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
|
||||
gSavedSettings.getControl("RenderVSyncEnable")->getSignal()->connect(boost::bind(&handleVSyncChanged, _2));
|
||||
gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
|
||||
gSavedSettings.getControl("RenderDebugGL")->getSignal()->connect(boost::bind(&handleRenderDebugGLChanged, _2));
|
||||
gSavedSettings.getControl("RenderDebugPipeline")->getSignal()->connect(boost::bind(&handleRenderDebugPipelineChanged, _2));
|
||||
|
|
|
|||
|
|
@ -1903,7 +1903,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)
|
|||
p.title, p.name, p.x, p.y, p.width, p.height, 0,
|
||||
p.fullscreen,
|
||||
gHeadlessClient,
|
||||
gSavedSettings.getBOOL("DisableVerticalSync"),
|
||||
gSavedSettings.getBOOL("RenderVSyncEnable"),
|
||||
!gHeadlessClient,
|
||||
p.ignore_pixel_depth,
|
||||
gSavedSettings.getBOOL("RenderDeferred") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled
|
||||
|
|
@ -5569,7 +5569,7 @@ void LLViewerWindow::restartDisplay(BOOL show_progress_bar)
|
|||
}
|
||||
}
|
||||
|
||||
BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar)
|
||||
BOOL LLViewerWindow::changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar)
|
||||
{
|
||||
//BOOL was_maximized = gSavedSettings.getBOOL("WindowMaximized");
|
||||
|
||||
|
|
|
|||
|
|
@ -424,7 +424,7 @@ public:
|
|||
void requestResolutionUpdate();
|
||||
void checkSettings();
|
||||
void restartDisplay(BOOL show_progress_bar);
|
||||
BOOL changeDisplaySettings(LLCoordScreen size, BOOL disable_vsync, BOOL show_progress_bar);
|
||||
BOOL changeDisplaySettings(LLCoordScreen size, BOOL enable_vsync, BOOL show_progress_bar);
|
||||
BOOL getIgnoreDestroyWindow() { return mIgnoreActivate; }
|
||||
F32 getWorldViewAspectRatio() const;
|
||||
const LLVector2& getDisplayScale() const { return mDisplayScale; }
|
||||
|
|
|
|||
|
|
@ -8388,8 +8388,6 @@ LLVector4 pow4fsrgb(LLVector4 v, F32 f)
|
|||
return v;
|
||||
}
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_DEFERRED_LIGHTING("Deferred Lighting");
|
||||
|
||||
void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
|
|
@ -8397,7 +8395,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
|
|||
{
|
||||
return;
|
||||
}
|
||||
LL_RECORD_BLOCK_TIME(FTM_DEFERRED_LIGHTING);
|
||||
|
||||
LLRenderTarget *deferred_target = &mDeferredScreen;
|
||||
LLRenderTarget *deferred_depth_target = &mDeferredDepth;
|
||||
|
|
|
|||
|
|
@ -334,15 +334,15 @@
|
|||
width="256" />
|
||||
|
||||
<check_box
|
||||
control_name="RenderVBOEnable"
|
||||
control_name="RenderVSyncEnable"
|
||||
height="16"
|
||||
initial_value="true"
|
||||
label="Enable OpenGL Vertex Buffer Objects"
|
||||
label="Enable VSync"
|
||||
layout="topleft"
|
||||
left="30"
|
||||
top_delta="16"
|
||||
name="vbo"
|
||||
tool_tip="Enabling this on modern hardware gives a performance gain. However, older hardware often has poor implementations of VBOs and you may get crashes when this is enabled."
|
||||
name="vsync"
|
||||
tool_tip="Synchronizes the frame rate to the refresh rate of the monitor, which results in smooth performance."
|
||||
width="315" />
|
||||
|
||||
<check_box
|
||||
|
|
|
|||
Loading…
Reference in New Issue