Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Xlib support to gfxrecon-replay #437

Merged
merged 4 commits into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion USAGE_desktop.md
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ Optional arguments:
--opcd Omit pipeline cache data from calls to
vkCreatePipelineCache (same as --omit-pipeline-cache-data).
--wsi <platform> Force replay to use the specified wsi platform.
Available platforms are: auto,win32,xcb,wayland
Available platforms are: auto,win32,xlib,xcb,wayland
--sync Synchronize after each queue submission with vkQueueWaitIdle.
-m <mode> Enable memory translation for replay on GPUs with memory
types that are not compatible with the capture GPU's
Expand Down
4 changes: 4 additions & 0 deletions framework/application/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ target_sources(gfxrecon_application
$<$<BOOL:${XCB_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xcb_window.h>
$<$<BOOL:${XCB_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xcb_application.cpp>
$<$<BOOL:${XCB_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xcb_window.cpp>
$<$<BOOL:${X11_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xlib_application.h>
$<$<BOOL:${X11_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xlib_window.h>
$<$<BOOL:${X11_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xlib_application.cpp>
$<$<BOOL:${X11_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/xlib_window.cpp>
$<$<BOOL:${WAYLAND_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/wayland_application.h>
$<$<BOOL:${WAYLAND_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/wayland_window.h>
$<$<BOOL:${WAYLAND_FOUND}>:${CMAKE_CURRENT_LIST_DIR}/wayland_application.cpp>
Expand Down
152 changes: 152 additions & 0 deletions framework/application/xlib_application.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
** Copyright (c) 2020 LunarG, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include "application/xlib_application.h"

#include "application/xlib_window.h"
#include "util/logging.h"

#include <cstdlib>

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(application)

XlibApplication::XlibApplication(const std::string& name) : Application(name) {}

XlibApplication::~XlibApplication()
{
if (display_ != nullptr)
{
const auto xlib = xlib_loader_.GetFunctionTable();
xlib.CloseDisplay(display_);
}
}

static int ErrorHandler(Display* display, XErrorEvent* error_event)
{
GFXRECON_LOG_ERROR("Xlib error: %d", error_event->error_code);
return 0;
}

// A reference-counting interface to to XOpenDisplay/XCloseDisplay which shares
// a single display connection among multiple windows, and closes it when the
// last window is destroyed. This is a workaround for an issue with the NVIDIA
// driver which registers a callback for XCloseDisplay that needs to happen
// before the ICD is unloaded at vkDestroyInstance time.
// https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/1894
Display* XlibApplication::OpenDisplay()
{
if (display_ == nullptr)
{
auto xlib = xlib_loader_.GetFunctionTable();
display_ = xlib.OpenDisplay(nullptr);
}
++display_open_count_;
return display_;
}

void XlibApplication::CloseDisplay(Display* display)
{
assert(display == display_);

if ((--display_open_count_ == 0) && (display_ != nullptr))
{
auto xlib = xlib_loader_.GetFunctionTable();
xlib.CloseDisplay(display_);
display_ = nullptr;
}
}

bool XlibApplication::Initialize(decode::FileProcessor* file_processor)
{
if (!xlib_loader_.Initialize())
{
return false;
}

const auto xlib = xlib_loader_.GetFunctionTable();
xlib.SetErrorHandler(ErrorHandler);

display_ = xlib.OpenDisplay(nullptr);
if (!display_)
{
return false;
}

SetFileProcessor(file_processor);

return true;
}

bool XlibApplication::RegisterXlibWindow(XlibWindow* window)
{
return Application::RegisterWindow(window);
}

bool XlibApplication::UnregisterXlibWindow(XlibWindow* window)
{
return Application::UnregisterWindow(window);
}

void XlibApplication::ProcessEvents(bool wait_for_input)
{
const auto xlib = xlib_loader_.GetFunctionTable();
while (IsRunning() && (wait_for_input || (xlib.Pending(display_) > 0)))
{
wait_for_input = false;

XEvent event;
xlib.NextEvent(display_, &event);

switch (event.type)
{
case KeyRelease:
switch (event.xkey.keycode)
{
case 0x9: // Escape
StopRunning();
break;
case 0x21: // p
case 0x41: // Space
SetPaused(!GetPaused());
break;
default:
break;
}
break;

case KeyPress:
switch (event.xkey.keycode)
{
// Using XCB_KEY_PRESS for repeat when key is held down.
case 0x72: // Right arrow
case 0x39: // n
if (GetPaused())
{
PlaySingleFrame();
}
break;
default:
break;
}

break;
}
}
}

GFXRECON_END_NAMESPACE(application)
GFXRECON_END_NAMESPACE(gfxrecon)
59 changes: 59 additions & 0 deletions framework/application/xlib_application.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
** Copyright (c) 2020 LunarG, Inc.
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef GFXRECON_APPLICATION_XLIB_APPLICATION_H
#define GFXRECON_APPLICATION_XLIB_APPLICATION_H

#include "application/application.h"
#include "util/defines.h"
#include "util/xlib_loader.h"

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(application)

class XlibWindow;

class XlibApplication : public Application
{
public:
XlibApplication(const std::string& name);

virtual ~XlibApplication() override;

const util::XlibLoader::FunctionTable& GetXlibFunctionTable() const { return xlib_loader_.GetFunctionTable(); }

Display* OpenDisplay();

void CloseDisplay(Display* display);

virtual bool Initialize(decode::FileProcessor* file_processor) override;

bool RegisterXlibWindow(XlibWindow* window);

bool UnregisterXlibWindow(XlibWindow* window);

virtual void ProcessEvents(bool wait_for_input) override;

private:
Display* display_;
size_t display_open_count_;
util::XlibLoader xlib_loader_;
};

GFXRECON_END_NAMESPACE(application)
GFXRECON_END_NAMESPACE(gfxrecon)

#endif // GFXRECON_APPLICATION_XLIB_APPLICATION_H
Loading