Leviathan  0.8.0.0
Leviathan game engine
Leviathan::Graphics Class Reference

#include <Graphics.h>

Classes

struct  Private
 

Public Member Functions

DLLEXPORT Graphics ()
 
DLLEXPORT ~Graphics ()
 
DLLEXPORT bool Init (AppDef *appdef)
 
DLLEXPORT void Release ()
 
DLLEXPORT bool Frame ()
 
DLLEXPORT void UpdateShownOverlays (bs::RenderTarget &target, const std::vector< bs::SPtr< bs::Texture >> &overlays)
 
DLLEXPORT bool IsVerticalUVFlipped () const
 
DLLEXPORT bs::HShader LoadShaderByName (const std::string &name)
 Finds and loads a shader with the name. More...
 
DLLEXPORT bs::HTexture LoadTextureByName (const std::string &name)
 Works the same as LoadShaderByName. More...
 
DLLEXPORT bs::HMesh LoadMeshByName (const std::string &name)
 Works the same as LoadShaderByName. More...
 
DLLEXPORT bs::HAnimationClip LoadAnimationClipByName (const std::string &name)
 Works the same as LoadShaderByName. More...
 

Protected Member Functions

bs::SPtr< bs::RenderWindow > RegisterCreatedWindow (Window &window)
 Called when Window objects are created to register them with bsf and with the case of the first window this initializes the rest of bsf. More...
 
bool UnRegisterWindow (Window &window)
 Called just before a window is destroyed. This needs to stop rendering to it. More...
 

Detailed Description

Definition at line 12 of file Graphics.h.

Constructor & Destructor Documentation

◆ Graphics()

DLLEXPORT Graphics::Graphics ( )

Definition at line 159 of file Graphics.cpp.

159 {}

◆ ~Graphics()

Graphics::~Graphics ( )

Definition at line 161 of file Graphics.cpp.

162 {
163  LEVIATHAN_ASSERT(!Initialized, "Graphics not released before destructor");
164 }
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:98

Member Function Documentation

◆ Frame()

DLLEXPORT bool Graphics::Frame ( )

Definition at line 523 of file Graphics.cpp.

524 {
525  // Logic for this frame is already ready, just tell bsf to render once
526  Pimpl->OurApp->runMainLoopFrame();
527 
528  // At this point the frame render operation is happening on the BSF core thread, but it is
529  // safe to use non-core thread objects normally, only in special cases do we need to wait
530  // for a frame to end
531  return true;
532 }

◆ Init()

bool Graphics::Init ( AppDef appdef)

Definition at line 166 of file Graphics.cpp.

167 {
168  // StartUp SDL //
169  if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) != 0) {
170 
171  LOG_ERROR("Graphics: Init: SDL init failed, error: " + std::string(SDL_GetError()));
172  return false;
173  }
174 
175  SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
176 
177  int displays = SDL_GetNumVideoDisplays();
178 
179  LOG_INFO("SDL: display count: " + Convert::ToString(displays));
180 
181  // Get display positions
182  std::vector<SDL_Rect> displayBounds;
183 
184  for(int i = 0; i < displays; i++) {
185 
186  displayBounds.push_back(SDL_Rect());
187 
188  SDL_GetDisplayBounds(i, &displayBounds.back());
189 
190  const char* nameptr = SDL_GetDisplayName(i);
191 
192  const auto name = nameptr ? std::string(nameptr) : std::string("unnamed");
193 
194  // Video modes //
195  int videomodecount = SDL_GetNumDisplayModes(i);
196 
197  std::vector<std::string> videomodes;
198 
199  for(int a = 0; a < videomodecount; a++) {
200 
201 
202  SDL_DisplayMode mode = {SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0};
203 
204  if(SDL_GetDisplayMode(i, a, &mode) == 0) {
205 
206  videomodes.push_back(Convert::ToString(SDL_BITSPERPIXEL(mode.format)) +
207  " bpp " + Convert::ToString(mode.w) + "x" +
208  Convert::ToString(mode.h) + " at " +
209  Convert::ToString(mode.refresh_rate) + "Hz");
210  }
211  }
212 
213 
214  LOG_INFO("Display(" + Convert::ToString(i) + ", " + name + "): top left: (" +
215  Convert::ToString(displayBounds.back().x) + ", " +
216  Convert::ToString(displayBounds.back().y) +
217  ") size: " + Convert::ToString(displayBounds.back().w) + "x" +
218  Convert::ToString(displayBounds.back().h));
219 
220  // LOG_INFO("Supported modes(" + Convert::ToString(videomodes.size()) + "): ");
221  // for(const auto& mode : videomodes){
222 
223  // LOG_WRITE(" " + mode);
224  // }
225  }
226 
227 
228  if(!InitializeBSF(appdef)) {
229 
230  Logger::Get()->Error("Graphics: Init: failed to create bs::framework renderer");
231  return false;
232  }
233 
234 #ifdef __linux
235  // Set X11 error handler to not crash on non-fatal errors
236  XSetErrorHandler(LeviathanX11ErrorHandler);
237 #endif
238 
239  Initialized = true;
240  return true;
241 }
#define LOG_INFO(x)
Definition: Define.h:88
#define LOG_ERROR(x)
Definition: Define.h:90
static std::string ToString(const T &val)
Definition: Convert.h:72
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177

◆ IsVerticalUVFlipped()

DLLEXPORT bool Graphics::IsVerticalUVFlipped ( ) const

Definition at line 555 of file Graphics.cpp.

556 {
557  const auto capabilities = bs::ct::RenderAPI::instance().getCapabilities(0);
558 
559  return capabilities.conventions.ndcYAxis != bs::Conventions::Axis::Down;
560 }

◆ LoadAnimationClipByName()

DLLEXPORT bs::HAnimationClip Graphics::LoadAnimationClipByName ( const std::string &  name)

Works the same as LoadShaderByName.

Definition at line 613 of file Graphics.cpp.

614 {
616  // Leviathan::StringOperations::RemoveExtension(name, true),
618  // Leviathan::StringOperations::GetExtension(name)
619  "asset");
620 
621  if(file.empty()) {
622  LOG_ERROR(
623  "Graphics: LoadAnimationClipByName: could not find resource with name: " + name);
624  return nullptr;
625  }
626 
627  return Pimpl->LoadResource<bs::AnimationClip>(
628  std::filesystem::absolute(file).string().c_str());
629 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:90
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ LoadMeshByName()

DLLEXPORT bs::HMesh Graphics::LoadMeshByName ( const std::string &  name)

Works the same as LoadShaderByName.

Definition at line 597 of file Graphics.cpp.

598 {
600  // Leviathan::StringOperations::RemoveExtension(name, true),
602  // Leviathan::StringOperations::GetExtension(name)
603  "asset");
604 
605  if(file.empty()) {
606  LOG_ERROR("Graphics: LoadMeshByName: could not find resource with name: " + name);
607  return nullptr;
608  }
609 
610  return Pimpl->LoadResource<bs::Mesh>(std::filesystem::absolute(file).string().c_str());
611 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:90
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ LoadShaderByName()

DLLEXPORT bs::HShader Graphics::LoadShaderByName ( const std::string &  name)

Finds and loads a shader with the name.

If a full path or a valid relative path is specified a full search is not done. Unless a variant of the name with ".asset" is found, which is preferred to skip expensive importing.

Definition at line 563 of file Graphics.cpp.

564 {
565  // TODO: .asset detection
566 
568  // Leviathan::StringOperations::RemoveExtension(name, true),
570  // Leviathan::StringOperations::GetExtension(name)
571  "asset");
572 
573  if(file.empty()) {
574  LOG_ERROR("Graphics: LoadShaderByName: could not find resource with name: " + name);
575  return nullptr;
576  }
577 
578  return Pimpl->LoadResource<bs::Shader>(std::filesystem::absolute(file).string().c_str());
579 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:90
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ LoadTextureByName()

DLLEXPORT bs::HTexture Graphics::LoadTextureByName ( const std::string &  name)

Works the same as LoadShaderByName.

Definition at line 581 of file Graphics.cpp.

582 {
584  // Leviathan::StringOperations::RemoveExtension(name, true),
586  // Leviathan::StringOperations::GetExtension(name)
587  "asset");
588 
589  if(file.empty()) {
590  LOG_ERROR("Graphics: LoadTextureByName: could not find resource with name: " + name);
591  return nullptr;
592  }
593 
594  return Pimpl->LoadResource<bs::Texture>(std::filesystem::absolute(file).string().c_str());
595 }
static const StringTypeN RemovePath(const StringTypeN &filepath)
#define LOG_ERROR(x)
Definition: Define.h:90
static DLLEXPORT FileSystem * Get()
Definition: FileSystem.cpp:74
DLLEXPORT std::string SearchForFile(FILEGROUP which, const std::string &name, const std::string &extensions, bool searchall=true)
Searches for a file.
Definition: FileSystem.cpp:666

◆ RegisterCreatedWindow()

bs::SPtr< bs::RenderWindow > Graphics::RegisterCreatedWindow ( Window window)
protected

Called when Window objects are created to register them with bsf and with the case of the first window this initializes the rest of bsf.

Definition at line 378 of file Graphics.cpp.

379 {
380  if(FirstWindowCreated) {
381  // Register secondary window
382 
383  bs::RENDER_WINDOW_DESC windowDesc;
384 
385  windowDesc.depthBuffer = true;
386 
387  int multiSample;
388 
389  ObjectFileProcessor::LoadValueFromNamedVars<int>(
390  Engine::Get()->GetDefinition()->GetValues(), "WindowMultiSampleCount", multiSample,
391  1);
392 
393  windowDesc.multisampleCount = multiSample;
394  // windowDesc.multisampleHint = "";
395  // Not sure what all settings need to be copied
396  windowDesc.fullscreen = /* window.IsFullScreen() */ false;
397  windowDesc.vsync = false;
398 
399  int32_t width, height;
400  window.GetSize(width, height);
401  windowDesc.videoMode = bs::VideoMode(
402  width, height, Pimpl->Description.primaryWindowDesc.videoMode.refreshRate, 0);
403 
404 #ifdef _WIN32
405  windowDesc.platformSpecific["externalWindowHandle"] =
406  std::to_string((uint64_t)window.GetNativeHandle());
407 #else
408  windowDesc.platformSpecific["externalWindowHandle"] =
409  std::to_string(window.GetNativeHandle());
410 
411  windowDesc.platformSpecific["externalDisplay"] =
412  std::to_string(window.GetWindowXDisplay());
413 #endif
414 
415  auto window = bs::RenderWindow::create(windowDesc);
416 
417  if(!window)
418  LOG_FATAL("Failed to create additional BSF window");
419 
420  return window;
421 
422  } else {
423  // Finish initializing graphics
424  FirstWindowCreated = true;
425  LOG_INFO("Graphics: doing bs::framework initialization after creating first window");
426 
427  // Setup first window properties
428  auto& windowDesc = Pimpl->Description.primaryWindowDesc;
429  windowDesc.depthBuffer = true;
430 
431  int multiSample;
432 
433  ObjectFileProcessor::LoadValueFromNamedVars<int>(
434  Engine::Get()->GetDefinition()->GetValues(), "WindowMultiSampleCount", multiSample,
435  1);
436 
437  windowDesc.multisampleCount = multiSample;
438  // windowDesc.multisampleHint = "";
439  // Not sure what all settings need to be copied
440  windowDesc.fullscreen = /* window.IsFullScreen() */ false;
441  windowDesc.vsync = false;
442 
443  // Fill video mode info from SDL
444  SDL_DisplayMode dm;
445  if(SDL_GetDesktopDisplayMode(0, &dm) != 0) {
446  LOG_ERROR("Graphics: RegisterCreatedWindow: failed to get desktop display mode:" +
447  std::string(SDL_GetError()));
448  return nullptr;
449  }
450 
451  int32_t width, height;
452  window.GetSize(width, height);
453  windowDesc.videoMode = bs::VideoMode(width, height, dm.refresh_rate, 0);
454 
455 #ifdef _WIN32
456  windowDesc.platformSpecific["externalWindowHandle"] =
457  std::to_string((uint64_t)window.GetNativeHandle());
458 #else
459  windowDesc.platformSpecific["externalWindowHandle"] =
460  std::to_string(window.GetNativeHandle());
461 
462  windowDesc.platformSpecific["externalDisplay"] =
463  std::to_string(window.GetWindowXDisplay());
464 #endif
465 
466  bs::Application::startUp<LeviathanBSFApplication>(Pimpl->Description);
467 
468  Pimpl->OurApp =
469  static_cast<LeviathanBSFApplication*>(bs::CoreApplication::instancePtr());
470 
471  bs::SPtr<bs::RenderWindow> bsWindow =
472  bs::CoreApplication::instance().getPrimaryWindow();
473 
474  LEVIATHAN_ASSERT(bsWindow, "window creation failed");
475 
476  // Notify engine to register threads to work with Ogre //
477  // Engine::GetEngine()->_NotifyThreadsRegisterOgre();
478 
479  auto shader =
480  bs::gImporter().import<bs::Shader>("Data/Shaders/CoreShaders/ScreenSpaceGUI.bsl");
481 
482  auto material = bs::Material::create(shader);
483 
484  Pimpl->OurApp->GUIRenderer =
485  bs::RendererExtension::create<GUIOverlayRenderer>(GUIOverlayInitializationData{
486  GeometryHelpers::CreateScreenSpaceQuad(-1, -1, 2, 2)->getCore(),
487  material->getCore()});
488 
489  Pimpl->OurApp->beginMainLoop();
490  return bsWindow;
491  }
492 }
static DLLEXPORT bs::HMesh CreateScreenSpaceQuad(float x, float y, float width, float height, bool autoflipUV=true)
Creates a screen space plane with UV coordinates.
DLLEXPORT unsigned long GetNativeHandle() const
Definition: Window.cpp:917
DLLEXPORT void GetSize(int32_t &width, int32_t &height) const
Definition: Window.cpp:896
#define LOG_INFO(x)
Definition: Define.h:88
#define LOG_ERROR(x)
Definition: Define.h:90
#define LOG_FATAL(x)
Definition: Define.h:92
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:98
static DLLEXPORT Engine * Get()
Definition: Engine.cpp:85

◆ Release()

DLLEXPORT void Graphics::Release ( )

Definition at line 243 of file Graphics.cpp.

244 {
245  if(Initialized) {
246 
247  ShutdownBSF();
248 
249  SDL_Quit();
250  }
251 
252  Initialized = false;
253  FirstWindowCreated = false;
254  Pimpl.reset();
255 }

◆ UnRegisterWindow()

bool Graphics::UnRegisterWindow ( Window window)
protected

Called just before a window is destroyed. This needs to stop rendering to it.

Returns
True if the window was primary and should only be hidden instead of destroyed

Definition at line 494 of file Graphics.cpp.

495 {
496  if(Pimpl) {
497  Pimpl->OurApp->waitUntilFrameFinished();
498  }
499 
500  if(window.GetBSFWindow() == bs::CoreApplication::instance().getPrimaryWindow()) {
501  LOG_INFO("Graphics: primary window is closing, hiding it instead until shutdown");
502  return true;
503  }
504 
505  // TODO: additional window unregister
506  return false;
507 }
#define LOG_INFO(x)
Definition: Define.h:88
DLLEXPORT const auto & GetBSFWindow() const
Definition: Window.h:166

◆ UpdateShownOverlays()

DLLEXPORT void Graphics::UpdateShownOverlays ( bs::RenderTarget &  target,
const std::vector< bs::SPtr< bs::Texture >> &  overlays 
)

Definition at line 534 of file Graphics.cpp.

536 {
537  const auto targetRenderTarget = reinterpret_cast<uint64_t>(target.getCore().get());
538 
539  std::vector<bs::SPtr<bs::ct::Texture>> coreVersion;
540  coreVersion.reserve(overlays.size());
541 
542  std::transform(overlays.begin(), overlays.end(), std::back_inserter(coreVersion),
543  [](const bs::SPtr<bs::Texture>& item) { return item->getCore(); });
544 
545  std::weak_ptr<GUIOverlayRenderer> rendererExtension = Pimpl->OurApp->GUIRenderer;
546 
547  bs::gCoreThread().queueCommand(
548  [rendererExtension, targetRenderTarget, coreVersion = std::move(coreVersion)]() {
549  const auto locked = rendererExtension.lock();
550  if(locked)
551  locked->UpdateShownOverlays(targetRenderTarget, coreVersion);
552  });
553 }

The documentation for this class was generated from the following files: