2023-06-12 17:47:54 -04:00
|
|
|
/**
|
|
|
|
* Furnace Tracker - multi-system chiptune tracker
|
|
|
|
* Copyright (C) 2021-2023 tildearrow and contributors
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2023-06-12 20:17:46 -04:00
|
|
|
#define INCLUDE_D3D11
|
2023-06-12 17:47:54 -04:00
|
|
|
#include "renderDX11.h"
|
2023-06-12 20:17:46 -04:00
|
|
|
#include <SDL_syswm.h>
|
|
|
|
#include "backends/imgui_impl_dx11.h"
|
|
|
|
#include "../../ta-log.h"
|
|
|
|
|
|
|
|
const D3D_FEATURE_LEVEL possibleFeatureLevels[2]={
|
|
|
|
D3D_FEATURE_LEVEL_11_0,
|
|
|
|
D3D_FEATURE_LEVEL_10_0
|
|
|
|
};
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::destroyRenderTarget() {
|
|
|
|
if (renderTarget!=NULL) {
|
|
|
|
renderTarget->Release();
|
|
|
|
renderTarget=NULL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::createRenderTarget() {
|
|
|
|
ID3D11Texture2D* screen=NULL;
|
|
|
|
HRESULT result;
|
|
|
|
|
|
|
|
destroyRenderTarget();
|
|
|
|
|
|
|
|
if (swapchain==NULL || device==NULL) {
|
|
|
|
logW("createRenderTarget: swapchain or device are NULL!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:43:26 -04:00
|
|
|
DXGI_SWAP_CHAIN_DESC chainDesc;
|
|
|
|
memset(&chainDesc,0,sizeof(chainDesc));
|
|
|
|
if (swapchain->GetDesc(&chainDesc)!=S_OK) {
|
|
|
|
logW("createRenderTarget: could not get swapchain desc!");
|
|
|
|
} else {
|
|
|
|
outW=chainDesc.BufferDesc.Width;
|
|
|
|
outH=chainDesc.BufferDesc.Height;
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:17:46 -04:00
|
|
|
result=swapchain->GetBuffer(0,IID_PPV_ARGS(&screen));
|
|
|
|
if (result!=S_OK) {
|
|
|
|
logW("createRenderTarget: could not get buffer! %.8x",result);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (screen==NULL) {
|
|
|
|
logW("createRenderTarget: screen is null!");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
result=device->CreateRenderTargetView(screen,NULL,&renderTarget);
|
|
|
|
if (result!=S_OK) {
|
|
|
|
logW("createRenderTarget: could not create render target view! %.8x",result);
|
|
|
|
screen->Release();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (renderTarget==NULL) {
|
|
|
|
logW("createRenderTarget: what the hell the render target is null?");
|
|
|
|
screen->Release();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2023-06-12 17:47:54 -04:00
|
|
|
|
|
|
|
ImTextureID FurnaceGUIRenderDX11::getTextureID(void* which) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::lockTexture(void* which, void** data, int* pitch) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::unlockTexture(void* which) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::updateTexture(void* which, void* data, int pitch) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width, int height) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::destroyTexture(void* which) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::setTextureBlendMode(void* which, FurnaceGUIBlendMode mode) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::setBlendMode(FurnaceGUIBlendMode mode) {
|
|
|
|
}
|
|
|
|
|
2023-06-12 20:43:26 -04:00
|
|
|
void FurnaceGUIRenderDX11::resized(const SDL_Event& ev) {
|
|
|
|
destroyRenderTarget();
|
|
|
|
swapchain->ResizeBuffers(0,0,0,DXGI_FORMAT_UNKNOWN,0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
createRenderTarget();
|
|
|
|
}
|
|
|
|
|
2023-06-12 17:47:54 -04:00
|
|
|
void FurnaceGUIRenderDX11::clear(ImVec4 color) {
|
2023-06-12 20:17:46 -04:00
|
|
|
float floatColor[4]={
|
|
|
|
color.x*color.w,
|
|
|
|
color.y*color.w,
|
|
|
|
color.z*color.w,
|
|
|
|
color.w,
|
|
|
|
};
|
|
|
|
|
|
|
|
context->OMSetRenderTargets(1,&renderTarget,NULL);
|
|
|
|
context->ClearRenderTargetView(renderTarget,floatColor);
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::newFrame() {
|
2023-06-12 20:17:46 -04:00
|
|
|
ImGui_ImplDX11_NewFrame();
|
2023-06-12 17:47:54 -04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::createFontsTexture() {
|
2023-06-12 20:17:46 -04:00
|
|
|
ImGui_ImplDX11_CreateDeviceObjects();
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::destroyFontsTexture() {
|
2023-06-12 20:17:46 -04:00
|
|
|
ImGui_ImplDX11_InvalidateDeviceObjects();
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::renderGUI() {
|
2023-06-12 20:17:46 -04:00
|
|
|
ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::wipe(float alpha) {
|
2023-06-12 20:17:46 -04:00
|
|
|
// TODO
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::present() {
|
2023-06-12 20:17:46 -04:00
|
|
|
swapchain->Present(1,0);
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::getOutputSize(int& w, int& h) {
|
2023-06-12 20:43:26 -04:00
|
|
|
w=outW;
|
|
|
|
h=outH;
|
|
|
|
return true;
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
int FurnaceGUIRenderDX11::getWindowFlags() {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::preInit() {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::init(SDL_Window* win) {
|
2023-06-12 20:17:46 -04:00
|
|
|
SDL_SysWMinfo sysWindow;
|
|
|
|
D3D_FEATURE_LEVEL featureLevel;
|
|
|
|
|
|
|
|
SDL_VERSION(&sysWindow.version);
|
|
|
|
if (SDL_GetWindowWMInfo(win,&sysWindow)==SDL_FALSE) {
|
|
|
|
logE("could not get window WM info! %s",SDL_GetError());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
HWND window=(HWND)sysWindow.info.win.window;
|
|
|
|
|
|
|
|
DXGI_SWAP_CHAIN_DESC chainDesc;
|
|
|
|
memset(&chainDesc,0,sizeof(chainDesc));
|
|
|
|
chainDesc.BufferDesc.Width=0;
|
|
|
|
chainDesc.BufferDesc.Height=0;
|
|
|
|
chainDesc.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
chainDesc.BufferDesc.RefreshRate.Numerator=60;
|
|
|
|
chainDesc.BufferDesc.RefreshRate.Denominator=1;
|
|
|
|
chainDesc.SampleDesc.Count=1;
|
|
|
|
chainDesc.SampleDesc.Quality=0;
|
|
|
|
chainDesc.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
chainDesc.BufferCount=2;
|
|
|
|
chainDesc.OutputWindow=window;
|
|
|
|
chainDesc.Windowed=TRUE; // TODO: what if we're in full screen mode?
|
|
|
|
chainDesc.SwapEffect=DXGI_SWAP_EFFECT_DISCARD;
|
|
|
|
chainDesc.Flags=DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
|
|
|
|
|
|
|
HRESULT result=D3D11CreateDeviceAndSwapChain(NULL,D3D_DRIVER_TYPE_HARDWARE,NULL,0,possibleFeatureLevels,2,D3D11_SDK_VERSION,&chainDesc,&swapchain,&device,&featureLevel,&context);
|
|
|
|
if (result!=S_OK) {
|
|
|
|
logE("could not create device and/or swap chain! %.8x",result);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
createRenderTarget();
|
|
|
|
return true;
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::initGUI(SDL_Window* win) {
|
2023-06-12 20:17:46 -04:00
|
|
|
IMGUI_CHECKVERSION();
|
|
|
|
ImGui::CreateContext();
|
|
|
|
|
|
|
|
ImGui_ImplSDL2_InitForD3D(win);
|
|
|
|
ImGui_ImplDX11_Init(device,context);
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FurnaceGUIRenderDX11::quit() {
|
2023-06-12 20:17:46 -04:00
|
|
|
destroyRenderTarget();
|
|
|
|
|
|
|
|
if (swapchain!=NULL) {
|
|
|
|
swapchain->Release();
|
|
|
|
swapchain=NULL;
|
|
|
|
}
|
|
|
|
if (context!=NULL) {
|
|
|
|
context->Release();
|
|
|
|
context=NULL;
|
|
|
|
}
|
|
|
|
if (device!=NULL) {
|
|
|
|
device->Release();
|
|
|
|
device=NULL;
|
|
|
|
}
|
|
|
|
return true;
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void FurnaceGUIRenderDX11::quitGUI() {
|
2023-06-12 20:17:46 -04:00
|
|
|
ImGui_ImplDX11_Shutdown();
|
2023-06-12 17:47:54 -04:00
|
|
|
}
|