mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-24 05:25:12 +00:00
Merge branch 'dx9'
thanks to the DirectX 9 testing team: - crappyfilename.exe - EpicTyphlosion - Mr. Hassium - wbcbz7 - Yuzu4K
This commit is contained in:
commit
a0efe1ec2c
31 changed files with 1010 additions and 54 deletions
|
@ -972,17 +972,17 @@ if (WITH_RENDER_DX11)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
#if (WITH_RENDER_DX9)
|
||||
# if (WIN32)
|
||||
# list(APPEND GUI_SOURCES src/gui/render/renderDX9.cpp)
|
||||
# list(APPEND GUI_SOURCES extern/imgui_patched/backends/imgui_impl_dx9.cpp)
|
||||
# list(APPEND DEPENDENCIES_DEFINES HAVE_RENDER_DX9)
|
||||
# list(APPEND DEPENDENCIES_LIBRARIES d3d9)
|
||||
# message(STATUS "UI render backend: DirectX 9")
|
||||
# else()
|
||||
# message(FATAL_ERROR "DirectX 9 render backend only for Windows!")
|
||||
# endif()
|
||||
#endif()
|
||||
if (WITH_RENDER_DX9)
|
||||
if (WIN32)
|
||||
list(APPEND GUI_SOURCES src/gui/render/renderDX9.cpp)
|
||||
list(APPEND GUI_SOURCES extern/imgui_patched/backends/imgui_impl_dx9.cpp)
|
||||
list(APPEND DEPENDENCIES_DEFINES HAVE_RENDER_DX9)
|
||||
list(APPEND DEPENDENCIES_LIBRARIES d3d9)
|
||||
message(STATUS "UI render backend: DirectX 9")
|
||||
else()
|
||||
message(FATAL_ERROR "DirectX 9 render backend only for Windows!")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WITH_RENDER_METAL)
|
||||
if (APPLE)
|
||||
|
|
39
extern/imgui_patched/backends/imgui_impl_dx9.cpp
vendored
39
extern/imgui_patched/backends/imgui_impl_dx9.cpp
vendored
|
@ -170,11 +170,12 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||
{
|
||||
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
|
||||
bd->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(ImDrawIdx), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, sizeof(ImDrawIdx) == 2 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
if (bd->pd3dDevice->CreateIndexBuffer(bd->IndexBufferSize * sizeof(unsigned short), D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &bd->pIB, nullptr) < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 state
|
||||
/*
|
||||
IDirect3DStateBlock9* d3d9_state_block = nullptr;
|
||||
if (bd->pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
||||
return;
|
||||
|
@ -182,26 +183,28 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||
{
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
||||
/*
|
||||
D3DMATRIX last_world, last_view, last_projection;
|
||||
bd->pd3dDevice->GetTransform(D3DTS_WORLD, &last_world);
|
||||
bd->pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
|
||||
bd->pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
*/
|
||||
|
||||
// Allocate buffers
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
unsigned short* idx_dst;
|
||||
if (bd->pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
//d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
if (bd->pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(unsigned short)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
bd->pVB->Unlock();
|
||||
d3d9_state_block->Release();
|
||||
//d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -224,7 +227,14 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||
vtx_dst++;
|
||||
vtx_src++;
|
||||
}
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
if (sizeof(ImDrawIdx) == sizeof(unsigned short)) {
|
||||
memcpy(idx_dst, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx));
|
||||
} else {
|
||||
// slower, but works on VIA
|
||||
for (int i=0; i<cmd_list->IdxBuffer.Size; i++) {
|
||||
idx_dst[i]=cmd_list->IdxBuffer.Data[i];
|
||||
}
|
||||
}
|
||||
idx_dst += cmd_list->IdxBuffer.Size;
|
||||
}
|
||||
bd->pVB->Unlock();
|
||||
|
@ -282,13 +292,18 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
|||
bd->pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 0, 0, 0);
|
||||
|
||||
// Restore the DX9 transform
|
||||
// don't. I like this transform.
|
||||
/*
|
||||
bd->pd3dDevice->SetTransform(D3DTS_WORLD, &last_world);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_VIEW, &last_view);
|
||||
bd->pd3dDevice->SetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
*/
|
||||
|
||||
// Restore the DX9 state
|
||||
/*
|
||||
d3d9_state_block->Apply();
|
||||
d3d9_state_block->Release();
|
||||
*/
|
||||
}
|
||||
|
||||
bool ImGui_ImplDX9_Init(IDirect3DDevice9* device)
|
||||
|
@ -391,13 +406,15 @@ void ImGui_ImplDX9_InvalidateDeviceObjects()
|
|||
ImGui_ImplDX9_InvalidateDeviceObjectsForPlatformWindows();
|
||||
}
|
||||
|
||||
void ImGui_ImplDX9_NewFrame()
|
||||
bool ImGui_ImplDX9_NewFrame()
|
||||
{
|
||||
ImGui_ImplDX9_Data* bd = ImGui_ImplDX9_GetBackendData();
|
||||
IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplDX9_Init()?");
|
||||
|
||||
if (!bd->FontTexture)
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
return ImGui_ImplDX9_CreateDeviceObjects();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
|
@ -506,9 +523,7 @@ static void ImGui_ImplDX9_RenderWindow(ImGuiViewport* viewport, void*)
|
|||
static void ImGui_ImplDX9_SwapBuffers(ImGuiViewport* viewport, void*)
|
||||
{
|
||||
ImGui_ImplDX9_ViewportData* vd = (ImGui_ImplDX9_ViewportData*)viewport->RendererUserData;
|
||||
HRESULT hr = vd->SwapChain->Present(nullptr, nullptr, vd->d3dpp.hDeviceWindow, nullptr, 0);
|
||||
// Let main application handle D3DERR_DEVICELOST by resetting the device.
|
||||
IM_ASSERT(hr == D3D_OK || hr == D3DERR_DEVICELOST);
|
||||
vd->SwapChain->Present(nullptr, nullptr, vd->d3dpp.hDeviceWindow, nullptr, 0);
|
||||
}
|
||||
|
||||
static void ImGui_ImplDX9_InitPlatformInterface()
|
||||
|
|
|
@ -19,7 +19,7 @@ struct IDirect3DDevice9;
|
|||
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_Init(IDirect3DDevice9* device);
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_NewFrame();
|
||||
IMGUI_IMPL_API bool ImGui_ImplDX9_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
|
|
|
@ -15,7 +15,7 @@ fi
|
|||
cd win32build
|
||||
|
||||
# TODO: potential Arch-ism?
|
||||
i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2 -march=i586" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type -march=i586" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=OFF -DWITH_RENDER_DX11=ON -DUSE_BACKWARD=ON -DSDL_SSE2=OFF -DSDL_SSE3=OFF -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DENABLE_AVX=OFF -DENABLE_AVX2=OFF .. || exit 1
|
||||
i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2 -march=i586" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type -march=i586" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=OFF -DWITH_RENDER_DX11=ON -DUSE_BACKWARD=ON -DSDL_SSE=OFF -DSDL_SSE2=OFF -DSDL_SSE3=OFF -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DENABLE_AVX=OFF -DENABLE_AVX2=OFF .. || exit 1
|
||||
make -j8 || exit 1
|
||||
|
||||
cd ..
|
||||
|
|
|
@ -15,7 +15,7 @@ fi
|
|||
cd xpbuild
|
||||
|
||||
# TODO: potential Arch-ism?
|
||||
i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=ON -DWITH_RENDER_DX11=OFF -DSDL_SSE2=OFF -DSDL_SSE3=OFF -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DENABLE_AVX=OFF -DENABLE_AVX2=OFF -DUSE_BACKWARD=ON .. || exit 1
|
||||
i686-w64-mingw32-cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Wno-cast-function-type" -DBUILD_SHARED_LIBS=OFF -DSUPPORT_XP=ON -DWITH_RENDER_DX11=OFF -DSDL_SSE=OFF -DSDL_SSE2=OFF -DSDL_SSE3=OFF -DENABLE_SSE=OFF -DENABLE_SSE2=OFF -DENABLE_AVX=OFF -DENABLE_AVX2=OFF -DUSE_BACKWARD=ON -DCONSOLE_SUBSYSTEM=OFF .. || exit 1
|
||||
make -j8 || exit 1
|
||||
|
||||
cd ..
|
||||
|
|
|
@ -52,10 +52,10 @@ class DivWorkPool;
|
|||
#define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock();
|
||||
#define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false;
|
||||
|
||||
//#define DIV_UNSTABLE
|
||||
#define DIV_UNSTABLE
|
||||
|
||||
#define DIV_VERSION "0.6.3"
|
||||
#define DIV_ENGINE_VERSION 201
|
||||
#define DIV_VERSION "DX9 Test X"
|
||||
#define DIV_ENGINE_VERSION 211
|
||||
// for imports
|
||||
#define DIV_VERSION_MOD 0xff01
|
||||
#define DIV_VERSION_FC 0xff02
|
||||
|
|
|
@ -212,7 +212,7 @@ void FurnaceGUI::drawChanOsc() {
|
|||
|
||||
if (chanOscUseGrad) {
|
||||
if (chanOscGradTex==NULL) {
|
||||
chanOscGradTex=rend->createTexture(true,chanOscGrad.width,chanOscGrad.height);
|
||||
chanOscGradTex=rend->createTexture(true,chanOscGrad.width,chanOscGrad.height,true,bestTexFormat);
|
||||
|
||||
if (chanOscGradTex==NULL) {
|
||||
logE("error while creating gradient texture!");
|
||||
|
|
|
@ -614,7 +614,7 @@ void FurnaceGUI::drawDebug() {
|
|||
ImGui::Text("Create and Destroy 128 Textures");
|
||||
if (ImGui::Button("No Write")) {
|
||||
for (int i=0; i<128; i++) {
|
||||
FurnaceGUITexture* t=rend->createTexture(false,2048,2048);
|
||||
FurnaceGUITexture* t=rend->createTexture(false,2048,2048,true,bestTexFormat);
|
||||
if (t==NULL) {
|
||||
showError(fmt::sprintf("Failure! %d",i));
|
||||
break;
|
||||
|
@ -628,7 +628,7 @@ void FurnaceGUI::drawDebug() {
|
|||
data[i]=rand();
|
||||
}
|
||||
for (int i=0; i<128; i++) {
|
||||
FurnaceGUITexture* t=rend->createTexture(false,2048,2048);
|
||||
FurnaceGUITexture* t=rend->createTexture(false,2048,2048,true,bestTexFormat);
|
||||
if (t==NULL) {
|
||||
showError(fmt::sprintf("Failure! %d",i));
|
||||
break;
|
||||
|
@ -642,7 +642,7 @@ void FurnaceGUI::drawDebug() {
|
|||
unsigned char* data=NULL;
|
||||
int pitch=0;
|
||||
for (int i=0; i<128; i++) {
|
||||
FurnaceGUITexture* t=rend->createTexture(false,2048,2048);
|
||||
FurnaceGUITexture* t=rend->createTexture(false,2048,2048,true,bestTexFormat);
|
||||
if (t==NULL) {
|
||||
showError(fmt::sprintf("Failure! %d",i));
|
||||
break;
|
||||
|
|
|
@ -7091,6 +7091,18 @@ bool FurnaceGUI::init() {
|
|||
}
|
||||
logV("render backend started");
|
||||
|
||||
// set best texture format
|
||||
unsigned int availTexFormats=rend->getTextureFormats();
|
||||
if (availTexFormats&GUI_TEXFORMAT_ABGR32) {
|
||||
bestTexFormat=GUI_TEXFORMAT_ABGR32;
|
||||
} else if (availTexFormats&GUI_TEXFORMAT_ARGB32) {
|
||||
bestTexFormat=GUI_TEXFORMAT_ARGB32;
|
||||
} else if (availTexFormats&GUI_TEXFORMAT_RGBA32) {
|
||||
bestTexFormat=GUI_TEXFORMAT_RGBA32;
|
||||
} else if (availTexFormats&GUI_TEXFORMAT_BGRA32) {
|
||||
bestTexFormat=GUI_TEXFORMAT_BGRA32;
|
||||
}
|
||||
|
||||
// try acquiring the canvas size
|
||||
if (!rend->getOutputSize(canvasW,canvasH)) {
|
||||
logW("could not get renderer output size!");
|
||||
|
|
|
@ -1443,6 +1443,14 @@ struct FurnaceGUIWaveSizeEntry {
|
|||
sys(NULL) {}
|
||||
};
|
||||
|
||||
enum FurnaceGUITextureFormat: unsigned int {
|
||||
GUI_TEXFORMAT_UNKNOWN=0,
|
||||
GUI_TEXFORMAT_ABGR32=1,
|
||||
GUI_TEXFORMAT_ARGB32=2,
|
||||
GUI_TEXFORMAT_BGRA32=4,
|
||||
GUI_TEXFORMAT_RGBA32=8,
|
||||
};
|
||||
|
||||
class FurnaceGUITexture {
|
||||
};
|
||||
|
||||
|
@ -1482,10 +1490,12 @@ class FurnaceGUIRender {
|
|||
virtual ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
virtual float getTextureU(FurnaceGUITexture* which);
|
||||
virtual float getTextureV(FurnaceGUITexture* which);
|
||||
virtual FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
virtual bool isTextureValid(FurnaceGUITexture* which);
|
||||
virtual bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
virtual bool unlockTexture(FurnaceGUITexture* which);
|
||||
virtual bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
virtual FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
virtual FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
virtual bool destroyTexture(FurnaceGUITexture* which);
|
||||
virtual void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
virtual void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -1504,6 +1514,7 @@ class FurnaceGUIRender {
|
|||
virtual int getWindowFlags();
|
||||
virtual int getMaxTextureWidth();
|
||||
virtual int getMaxTextureHeight();
|
||||
virtual unsigned int getTextureFormats();
|
||||
virtual const char* getBackendName();
|
||||
virtual const char* getVendorName();
|
||||
virtual const char* getDeviceName();
|
||||
|
@ -1543,6 +1554,7 @@ class FurnaceGUI {
|
|||
|
||||
FurnaceGUIRenderBackend renderBackend;
|
||||
FurnaceGUIRender* rend;
|
||||
FurnaceGUITextureFormat bestTexFormat;
|
||||
|
||||
SDL_Window* sdlWin;
|
||||
SDL_Haptic* vibrator;
|
||||
|
|
|
@ -53,8 +53,20 @@ FurnaceGUITexture* FurnaceGUI::getTexture(FurnaceGUIImages image, FurnaceGUIBlen
|
|||
if (img->data==NULL) return NULL;
|
||||
if (img->width<=0 || img->height<=0) return NULL;
|
||||
|
||||
bool createTex=false;
|
||||
|
||||
if (img->tex==NULL) {
|
||||
img->tex=rend->createTexture(false,img->width,img->height);
|
||||
createTex=true;
|
||||
} else {
|
||||
if (!rend->isTextureValid(img->tex)) {
|
||||
rend->destroyTexture(img->tex);
|
||||
img->tex=NULL;
|
||||
createTex=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (createTex) {
|
||||
img->tex=rend->createTexture(false,img->width,img->height,true,bestTexFormat);
|
||||
if (img->tex==NULL) {
|
||||
logE("error while creating image %d texture! %s",(int)image,SDL_GetError());
|
||||
return NULL;
|
||||
|
@ -101,6 +113,44 @@ FurnaceGUIImage* FurnaceGUI::getImage(FurnaceGUIImages image) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (ret->ch==4) {
|
||||
size_t total=ret->width*ret->height*ret->ch;
|
||||
switch (bestTexFormat) {
|
||||
case GUI_TEXFORMAT_ARGB32:
|
||||
for (size_t i=0; i<total; i+=4) {
|
||||
ret->data[i]^=ret->data[i|2];
|
||||
ret->data[i|2]^=ret->data[i];
|
||||
ret->data[i]^=ret->data[i|2];
|
||||
}
|
||||
break;
|
||||
case GUI_TEXFORMAT_BGRA32:
|
||||
for (size_t i=0; i<total; i+=4) {
|
||||
ret->data[i]^=ret->data[i|3];
|
||||
ret->data[i|3]^=ret->data[i];
|
||||
ret->data[i]^=ret->data[i|3];
|
||||
ret->data[i|1]^=ret->data[i|2];
|
||||
ret->data[i|2]^=ret->data[i|1];
|
||||
ret->data[i|1]^=ret->data[i|2];
|
||||
ret->data[i|1]^=ret->data[i|3];
|
||||
ret->data[i|3]^=ret->data[i|1];
|
||||
ret->data[i|1]^=ret->data[i|3];
|
||||
}
|
||||
break;
|
||||
case GUI_TEXFORMAT_RGBA32:
|
||||
for (size_t i=0; i<total; i+=4) {
|
||||
ret->data[i]^=ret->data[i|3];
|
||||
ret->data[i|3]^=ret->data[i];
|
||||
ret->data[i]^=ret->data[i|3];
|
||||
ret->data[i|1]^=ret->data[i|2];
|
||||
ret->data[i|2]^=ret->data[i|1];
|
||||
ret->data[i|1]^=ret->data[i|2];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
images[image]=ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ void FurnaceGUI::drawImage(ImDrawList* dl, FurnaceGUIImages image, const ImVec2&
|
|||
FurnaceGUIImage* imgI=getImage(image);
|
||||
FurnaceGUITexture* img=getTexture(image);
|
||||
|
||||
if (img==NULL) return;
|
||||
|
||||
float squareSize=MAX(introMax.x-introMin.x,introMax.y-introMin.y);
|
||||
float uDiff=uvMax.x-uvMin.x;
|
||||
float vDiff=uvMax.y-uvMin.y;
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#ifdef HAVE_RENDER_DX11
|
||||
#include "render/renderDX11.h"
|
||||
#endif
|
||||
#ifdef HAVE_RENDER_DX9
|
||||
#include "render/renderDX9.h"
|
||||
#endif
|
||||
#ifdef HAVE_RENDER_METAL
|
||||
#include "render/renderMetal.h"
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,14 @@ float FurnaceGUIRender::getTextureV(FurnaceGUITexture* which) {
|
|||
return 1.0;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRender::getTextureFormat(FurnaceGUITexture* which) {
|
||||
return GUI_TEXFORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRender::isTextureValid(FurnaceGUITexture* which) {
|
||||
return (which!=NULL);
|
||||
}
|
||||
|
||||
bool FurnaceGUIRender::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
return false;
|
||||
}
|
||||
|
@ -43,7 +51,7 @@ bool FurnaceGUIRender::updateTexture(FurnaceGUITexture* which, void* data, int p
|
|||
return false;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRender::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRender::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -109,6 +117,10 @@ int FurnaceGUIRender::getMaxTextureHeight() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRender::getTextureFormats() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRender::getBackendName() {
|
||||
return "Dummy";
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ class FurnaceDXTexture: public FurnaceGUITexture {
|
|||
ID3D11Texture2D* tex;
|
||||
ID3D11ShaderResourceView* view;
|
||||
int width, height;
|
||||
FurnaceGUITextureFormat format;
|
||||
unsigned char* lockedData;
|
||||
bool dynamic;
|
||||
FurnaceDXTexture():
|
||||
|
@ -82,6 +83,7 @@ class FurnaceDXTexture: public FurnaceGUITexture {
|
|||
view(NULL),
|
||||
width(0),
|
||||
height(0),
|
||||
format(GUI_TEXFORMAT_UNKNOWN),
|
||||
lockedData(NULL),
|
||||
dynamic(false) {}
|
||||
};
|
||||
|
@ -147,6 +149,11 @@ ImTextureID FurnaceGUIRenderDX11::getTextureID(FurnaceGUITexture* which) {
|
|||
return (ImTextureID)t->view;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderDX11::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceDXTexture* t=(FurnaceDXTexture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX11::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceDXTexture* t=(FurnaceDXTexture*)which;
|
||||
if (t->lockedData!=NULL) return false;
|
||||
|
@ -200,7 +207,7 @@ bool FurnaceGUIRenderDX11::updateTexture(FurnaceGUITexture* which, void* data, i
|
|||
return true;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
|
||||
ID3D11Texture2D* tex=NULL;
|
||||
|
@ -214,7 +221,17 @@ FurnaceGUITexture* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width,
|
|||
texDesc.Height=height;
|
||||
texDesc.MipLevels=1;
|
||||
texDesc.ArraySize=1;
|
||||
texDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM; // ???
|
||||
switch (format) {
|
||||
case GUI_TEXFORMAT_ABGR32:
|
||||
texDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case GUI_TEXFORMAT_ARGB32:
|
||||
texDesc.Format=DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
texDesc.SampleDesc.Count=1;
|
||||
texDesc.SampleDesc.Quality=0;
|
||||
texDesc.Usage=dynamic?D3D11_USAGE_DYNAMIC:D3D11_USAGE_DEFAULT;
|
||||
|
@ -246,6 +263,7 @@ FurnaceGUITexture* FurnaceGUIRenderDX11::createTexture(bool dynamic, int width,
|
|||
ret->tex=tex;
|
||||
ret->view=view;
|
||||
ret->dynamic=dynamic;
|
||||
ret->format=format;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -377,6 +395,10 @@ int FurnaceGUIRenderDX11::getMaxTextureHeight() {
|
|||
return maxHeight;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderDX11::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ABGR32|GUI_TEXFORMAT_ARGB32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderDX11::getBackendName() {
|
||||
return "DirectX 11";
|
||||
}
|
||||
|
|
|
@ -64,10 +64,11 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender {
|
|||
|
||||
public:
|
||||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -84,6 +85,7 @@ class FurnaceGUIRenderDX11: public FurnaceGUIRender {
|
|||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
|
|
592
src/gui/render/renderDX9.cpp
Normal file
592
src/gui/render/renderDX9.cpp
Normal file
|
@ -0,0 +1,592 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2024 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.
|
||||
*/
|
||||
|
||||
#define INCLUDE_D3D9
|
||||
#include "renderDX9.h"
|
||||
#include <SDL_syswm.h>
|
||||
#include "backends/imgui_impl_dx9.h"
|
||||
#include "../../ta-log.h"
|
||||
#include "../../utfutils.h"
|
||||
#include "../engine/bsr.h"
|
||||
|
||||
class FurnaceDX9Texture: public FurnaceGUITexture {
|
||||
public:
|
||||
IDirect3DTexture9* tex;
|
||||
IDirect3DTexture9* texPre;
|
||||
int width, height, widthReal, heightReal;
|
||||
FurnaceGUITextureFormat format;
|
||||
unsigned char* lockedData;
|
||||
bool dynamic;
|
||||
FurnaceDX9Texture():
|
||||
tex(NULL),
|
||||
texPre(NULL),
|
||||
width(0),
|
||||
height(0),
|
||||
widthReal(0),
|
||||
heightReal(0),
|
||||
format(GUI_TEXFORMAT_UNKNOWN),
|
||||
lockedData(NULL),
|
||||
dynamic(false) {}
|
||||
};
|
||||
|
||||
struct FurnaceGUIRenderDX9Private {
|
||||
D3DPRESENT_PARAMETERS present;
|
||||
std::vector<FurnaceDX9Texture*> texPool;
|
||||
};
|
||||
|
||||
struct WipeVertex {
|
||||
float x, y, z;
|
||||
unsigned int color;
|
||||
|
||||
WipeVertex(float _x, float _y, float _z, unsigned int c):
|
||||
x(_x),
|
||||
y(_y),
|
||||
z(_z),
|
||||
color(c) {}
|
||||
WipeVertex():
|
||||
x(0),
|
||||
y(0),
|
||||
z(0),
|
||||
color(0) {}
|
||||
};
|
||||
|
||||
|
||||
ImTextureID FurnaceGUIRenderDX9::getTextureID(FurnaceGUITexture* which) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
return (ImTextureID)t->tex;
|
||||
}
|
||||
|
||||
float FurnaceGUIRenderDX9::getTextureU(FurnaceGUITexture* which) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
if (which==NULL) return 0.0;
|
||||
if (t->widthReal<1) return 0.0f;
|
||||
return (float)t->width/(float)t->widthReal;
|
||||
}
|
||||
|
||||
float FurnaceGUIRenderDX9::getTextureV(FurnaceGUITexture* which) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
if (which==NULL) return 0.0;
|
||||
if (t->heightReal<1) return 0.0f;
|
||||
return (float)t->height/(float)t->heightReal;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderDX9::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::isTextureValid(FurnaceGUITexture* which) {
|
||||
if (which==NULL) return false;
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
return (t->tex!=NULL);
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
D3DLOCKED_RECT lockedRect;
|
||||
|
||||
HRESULT result=t->tex->LockRect(0,&lockedRect,NULL,D3DLOCK_DISCARD);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not lock texture!");
|
||||
return false;
|
||||
}
|
||||
|
||||
*data=lockedRect.pBits;
|
||||
*pitch=lockedRect.Pitch;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::unlockTexture(FurnaceGUITexture* which) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
HRESULT result=t->tex->UnlockRect(0);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not unlock texture!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::updateTexture(FurnaceGUITexture* which, void* data, int pitch) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
IDirect3DTexture9* crap=NULL;
|
||||
|
||||
if (t->texPre==NULL) {
|
||||
// update by locking
|
||||
if (!t->dynamic) {
|
||||
logW("updating static texture but texPre does not exist!");
|
||||
return false;
|
||||
}
|
||||
crap=t->tex;
|
||||
} else {
|
||||
// update by calling UpdateTexture
|
||||
crap=t->texPre;
|
||||
}
|
||||
|
||||
D3DLOCKED_RECT lockedRect;
|
||||
HRESULT result=crap->LockRect(0,&lockedRect,NULL,D3DLOCK_DISCARD);
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not update texture (lock)! %.8x",result);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lockedRect.Pitch==pitch) {
|
||||
memcpy(lockedRect.pBits,data,pitch*t->height);
|
||||
} else {
|
||||
unsigned char* ucData=(unsigned char*)data;
|
||||
unsigned char* d=(unsigned char*)lockedRect.pBits;
|
||||
int srcPos=0;
|
||||
int destPos=0;
|
||||
for (int i=0; i<t->height; i++) {
|
||||
memcpy(&d[destPos],&ucData[srcPos],pitch);
|
||||
srcPos+=pitch;
|
||||
destPos+=lockedRect.Pitch;
|
||||
}
|
||||
}
|
||||
|
||||
crap->UnlockRect(0);
|
||||
|
||||
if (t->texPre!=NULL) {
|
||||
result=t->tex->AddDirtyRect(NULL);
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not taint texture! %.8x",result);
|
||||
}
|
||||
result=device->UpdateTexture(t->texPre,t->tex);
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not update texture! %.8x",result);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderDX9::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
IDirect3DTexture9* tex=NULL;
|
||||
IDirect3DTexture9* texPre=NULL;
|
||||
int widthReal=width;
|
||||
int heightReal=height;
|
||||
|
||||
if (format!=GUI_TEXFORMAT_ARGB32) {
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((widthReal&(widthReal-1))!=0) {
|
||||
widthReal=1<<bsr(width);
|
||||
}
|
||||
if ((heightReal&(heightReal-1))!=0) {
|
||||
heightReal=1<<bsr(height);
|
||||
}
|
||||
if (squareTex) {
|
||||
if (widthReal>heightReal) {
|
||||
heightReal=widthReal;
|
||||
} else {
|
||||
widthReal=heightReal;
|
||||
}
|
||||
}
|
||||
logV("width: %d (requested)... %d (actual)",width,widthReal);
|
||||
logV("height: %d (requested)... %d (actual)",height,heightReal);
|
||||
|
||||
if (!supportsDynamicTex) dynamic=false;
|
||||
|
||||
HRESULT result=device->CreateTexture(widthReal,heightReal,1,dynamic?D3DUSAGE_DYNAMIC:0,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not create texture! %.8x",result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!dynamic) {
|
||||
HRESULT result=device->CreateTexture(widthReal,heightReal,1,0,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&texPre,NULL);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not create pre-texture! %.8x",result);
|
||||
tex->Release();
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
FurnaceDX9Texture* ret=new FurnaceDX9Texture;
|
||||
ret->width=width;
|
||||
ret->height=height;
|
||||
ret->widthReal=widthReal;
|
||||
ret->heightReal=heightReal;
|
||||
ret->tex=tex;
|
||||
ret->texPre=texPre;
|
||||
ret->dynamic=dynamic;
|
||||
ret->format=format;
|
||||
|
||||
priv->texPool.push_back(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::destroyTexture(FurnaceGUITexture* which) {
|
||||
FurnaceDX9Texture* t=(FurnaceDX9Texture*)which;
|
||||
if (t->texPre!=NULL) t->texPre->Release();
|
||||
if (t->tex!=NULL) t->tex->Release();
|
||||
delete t;
|
||||
|
||||
for (size_t i=0; i<priv->texPool.size(); i++) {
|
||||
if (priv->texPool[i]==t) {
|
||||
priv->texPool.erase(priv->texPool.begin()+i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode) {
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::setBlendMode(FurnaceGUIBlendMode mode) {
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::resized(const SDL_Event& ev) {
|
||||
mustResize=true;
|
||||
outW=ev.window.data1;
|
||||
outH=ev.window.data2;
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::clear(ImVec4 color) {
|
||||
device->Clear(0,NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,ImGui::ColorConvertFloat4ToU32(color),0,0);
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::present() {
|
||||
if (inScene) {
|
||||
device->EndScene();
|
||||
inScene=false;
|
||||
}
|
||||
|
||||
if (device->Present(NULL,NULL,NULL,NULL)==D3DERR_DEVICEREMOVED) {
|
||||
logI("device is gone");
|
||||
dead=true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mustResize) {
|
||||
logI("DX9: resizing buffers");
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
|
||||
if (wipeBuf) {
|
||||
wipeBuf->Release();
|
||||
wipeBuf=NULL;
|
||||
}
|
||||
|
||||
for (FurnaceDX9Texture* i: priv->texPool) {
|
||||
if (i->tex) {
|
||||
i->tex->Release();
|
||||
i->tex=NULL;
|
||||
}
|
||||
if (i->texPre) {
|
||||
i->texPre->Release();
|
||||
i->texPre=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
priv->present.BackBufferWidth=outW;
|
||||
priv->present.BackBufferHeight=outH;
|
||||
priv->present.BackBufferCount=1;
|
||||
HRESULT result=device->Reset(&priv->present);
|
||||
priv->present.BackBufferWidth=outW;
|
||||
priv->present.BackBufferHeight=outH;
|
||||
priv->present.BackBufferCount=1;
|
||||
if (result==D3DERR_INVALIDCALL) {
|
||||
logE("OH NO");
|
||||
dead=true;
|
||||
mustResize=false;
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
|
||||
result=device->CreateVertexBuffer(sizeof(WipeVertex)*4,0,D3DFVF_XYZ|D3DFVF_DIFFUSE,D3DPOOL_DEFAULT,&wipeBuf,NULL);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logE("could not create wipe buffer! %.8x",result);
|
||||
}
|
||||
|
||||
mustResize=false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::newFrame() {
|
||||
return ImGui_ImplDX9_NewFrame();
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::canVSync() {
|
||||
return supportsVSync;
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::createFontsTexture() {
|
||||
ImGui_ImplDX9_CreateDeviceObjects();
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::destroyFontsTexture() {
|
||||
ImGui_ImplDX9_InvalidateDeviceObjects();
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::renderGUI() {
|
||||
if (!inScene) {
|
||||
HRESULT result=device->BeginScene();
|
||||
if (result!=D3D_OK) {
|
||||
logW("couldn't render GUI! %.8x",result);
|
||||
return;
|
||||
}
|
||||
inScene=true;
|
||||
}
|
||||
|
||||
ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::wipe(float alpha) {
|
||||
if (wipeBuf==NULL) return;
|
||||
|
||||
logV("WIPE...");
|
||||
|
||||
if (!inScene) {
|
||||
HRESULT result=device->BeginScene();
|
||||
if (result!=D3D_OK) {
|
||||
logW("couldn't render GUI! %.8x",result);
|
||||
return;
|
||||
}
|
||||
inScene=true;
|
||||
}
|
||||
|
||||
D3DVIEWPORT9 view;
|
||||
view.X=0;
|
||||
view.Y=0;
|
||||
view.Width=outW;
|
||||
view.Height=outH;
|
||||
view.MinZ=0.0f;
|
||||
view.MaxZ=1.0f;
|
||||
HRESULT result=device->SetViewport(&view);
|
||||
if (result!=D3D_OK) {
|
||||
logW("could not set viewport! %.8x",result);
|
||||
}
|
||||
|
||||
unsigned char alphaU=alpha*255.0f;
|
||||
unsigned int color=alphaU<<24;
|
||||
|
||||
void* lockedData;
|
||||
WipeVertex vertex[4];
|
||||
vertex[0]=WipeVertex(0,0,0,color);
|
||||
vertex[1]=WipeVertex(outW,0,0,color);
|
||||
vertex[2]=WipeVertex(outW,outH,0,color);
|
||||
vertex[3]=WipeVertex(0,outH,0,color);
|
||||
|
||||
result=wipeBuf->Lock(0,0,&lockedData,D3DLOCK_DISCARD);
|
||||
if (result==D3D_OK) {
|
||||
memcpy(lockedData,vertex,sizeof(WipeVertex)*4);
|
||||
wipeBuf->Unlock();
|
||||
|
||||
result=device->SetRenderState(D3DRS_SCISSORTESTENABLE,FALSE);
|
||||
if (result!=D3D_OK) {
|
||||
logE("SHIT! scissor, %.8x",result);
|
||||
}
|
||||
result=device->SetTexture(0,NULL);
|
||||
if (result!=D3D_OK) {
|
||||
logE("SHIT! set texture, %.8x",result);
|
||||
}
|
||||
result=device->SetStreamSource(0,wipeBuf,0,sizeof(WipeVertex));
|
||||
if (result!=D3D_OK) {
|
||||
logE("SHIT! set stream source, %.8x",result);
|
||||
}
|
||||
result=device->SetTexture(0,NULL);
|
||||
if (result!=D3D_OK) {
|
||||
logE("SHIT! set texture, %.8x",result);
|
||||
}
|
||||
result=device->SetFVF(D3DFVF_XYZ|D3DFVF_DIFFUSE);
|
||||
if (result!=D3D_OK) {
|
||||
logE("SHIT! set FVF, %.8x",result);
|
||||
}
|
||||
result=device->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2);
|
||||
if (result!=D3D_OK) {
|
||||
logE("SHIT! draw primitive, %.8x",result);
|
||||
}
|
||||
} else {
|
||||
logE("SHIT! lock, %.8x",result);
|
||||
}
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::getOutputSize(int& w, int& h) {
|
||||
w=outW;
|
||||
h=outH;
|
||||
return true;
|
||||
}
|
||||
|
||||
int FurnaceGUIRenderDX9::getWindowFlags() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FurnaceGUIRenderDX9::getMaxTextureWidth() {
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
int FurnaceGUIRenderDX9::getMaxTextureHeight() {
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderDX9::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ARGB32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderDX9::getBackendName() {
|
||||
return "DirectX 9";
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderDX9::getVendorName() {
|
||||
return vendorName.c_str();
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderDX9::getDeviceName() {
|
||||
return deviceName.c_str();
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderDX9::getAPIVersion() {
|
||||
return apiVersion.c_str();
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::setSwapInterval(int swapInt) {
|
||||
swapInterval=swapInt;
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::preInit(const DivConfig& conf) {
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::init(SDL_Window* win, int swapInt) {
|
||||
D3DADAPTER_IDENTIFIER9 adapterInfo;
|
||||
SDL_SysWMinfo sysWindow;
|
||||
|
||||
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;
|
||||
|
||||
iface=Direct3DCreate9(D3D_SDK_VERSION);
|
||||
if (iface==NULL) {
|
||||
logE("could not create Direct3D 9!");
|
||||
return false;
|
||||
}
|
||||
|
||||
priv=new FurnaceGUIRenderDX9Private;
|
||||
|
||||
SDL_GetWindowSize(win,&outW,&outH);
|
||||
|
||||
memset(&priv->present,0,sizeof(D3DPRESENT_PARAMETERS));
|
||||
priv->present.Windowed=TRUE;
|
||||
priv->present.SwapEffect=D3DSWAPEFFECT_DISCARD;
|
||||
priv->present.BackBufferWidth=outW;
|
||||
priv->present.BackBufferHeight=outH;
|
||||
priv->present.BackBufferCount=1;
|
||||
priv->present.BackBufferFormat=D3DFMT_UNKNOWN;
|
||||
//priv->present.EnableAutoDepthStencil=TRUE;
|
||||
//priv->present.AutoDepthStencilFormat=D3DFMT_D16;
|
||||
if (swapInt>0) {
|
||||
priv->present.PresentationInterval=D3DPRESENT_INTERVAL_ONE;
|
||||
} else {
|
||||
priv->present.PresentationInterval=D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
}
|
||||
priv->present.hDeviceWindow=window;
|
||||
|
||||
HRESULT result=iface->GetAdapterIdentifier(D3DADAPTER_DEFAULT,0,&adapterInfo);
|
||||
|
||||
if (result==D3D_OK) {
|
||||
vendorName=fmt::sprintf("0x%.4X",adapterInfo.VendorId);
|
||||
deviceName=fmt::sprintf("%s (%s)",adapterInfo.Description,adapterInfo.DeviceName);
|
||||
apiVersion=fmt::sprintf("%.8X %.8X %s",adapterInfo.DriverVersion.HighPart,adapterInfo.DriverVersion.LowPart,adapterInfo.Driver);
|
||||
} else {
|
||||
logW("could not get adapter info! %.8x",result);
|
||||
}
|
||||
|
||||
result=iface->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,window,D3DCREATE_HARDWARE_VERTEXPROCESSING,&priv->present,&device);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logW("no hardware vertex processing!");
|
||||
result=iface->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,window,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&priv->present,&device);
|
||||
if (result!=D3D_OK) {
|
||||
logE("could not create device! %.8x",result);
|
||||
iface->Release();
|
||||
iface=NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
D3DCAPS9 caps;
|
||||
|
||||
result=device->GetDeviceCaps(&caps);
|
||||
|
||||
if (result==D3D_OK) {
|
||||
supportsDynamicTex=(caps.Caps2&D3DCAPS2_DYNAMICTEXTURES);
|
||||
squareTex=(caps.TextureCaps&D3DPTEXTURECAPS_SQUAREONLY);
|
||||
supportsVSync=(caps.PresentationIntervals&D3DPRESENT_INTERVAL_ONE);
|
||||
maxWidth=caps.MaxTextureWidth;
|
||||
maxHeight=caps.MaxTextureHeight;
|
||||
|
||||
if (!supportsDynamicTex) {
|
||||
logI("no support for dynamic textures");
|
||||
}
|
||||
if (squareTex) {
|
||||
logI("square textures only");
|
||||
}
|
||||
}
|
||||
|
||||
result=device->CreateVertexBuffer(sizeof(WipeVertex)*4,0,D3DFVF_XYZ|D3DFVF_DIFFUSE,D3DPOOL_DEFAULT,&wipeBuf,NULL);
|
||||
|
||||
if (result!=D3D_OK) {
|
||||
logE("could not create wipe buffer! %.8x",result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::initGUI(SDL_Window* win) {
|
||||
ImGui_ImplSDL2_InitForD3D(win);
|
||||
ImGui_ImplDX9_Init(device);
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::quit() {
|
||||
if (wipeBuf) {
|
||||
wipeBuf->Release();
|
||||
wipeBuf=NULL;
|
||||
}
|
||||
if (device) {
|
||||
device->Release();
|
||||
device=NULL;
|
||||
}
|
||||
if (iface) {
|
||||
iface->Release();
|
||||
iface=NULL;
|
||||
}
|
||||
priv->texPool.clear();
|
||||
dead=false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FurnaceGUIRenderDX9::quitGUI() {
|
||||
ImGui_ImplDX9_Shutdown();
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderDX9::isDead() {
|
||||
return dead;
|
||||
}
|
101
src/gui/render/renderDX9.h
Normal file
101
src/gui/render/renderDX9.h
Normal file
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2024 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.
|
||||
*/
|
||||
|
||||
#include "../gui.h"
|
||||
#ifdef INCLUDE_D3D9
|
||||
#include <d3d9.h>
|
||||
struct FurnaceGUIRenderDX9Private;
|
||||
#else
|
||||
typedef void IDirect3D9;
|
||||
typedef void IDirect3DVertexBuffer9;
|
||||
typedef void FurnaceGUIRenderDX9Private;
|
||||
#endif
|
||||
|
||||
class FurnaceGUIRenderDX9: public FurnaceGUIRender {
|
||||
IDirect3D9* iface;
|
||||
IDirect3DDevice9* device;
|
||||
FurnaceGUIRenderDX9Private* priv;
|
||||
IDirect3DVertexBuffer9* wipeBuf;
|
||||
|
||||
int outW, outH, swapInterval;
|
||||
|
||||
bool dead, haveScene, supportsDynamicTex, supportsVSync, mustResize, squareTex, inScene;
|
||||
|
||||
// SHADERS //
|
||||
|
||||
int maxWidth, maxHeight;
|
||||
String vendorName, deviceName, apiVersion;
|
||||
|
||||
public:
|
||||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
float getTextureU(FurnaceGUITexture* which);
|
||||
float getTextureV(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool isTextureValid(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
void resized(const SDL_Event& ev);
|
||||
void clear(ImVec4 color);
|
||||
bool newFrame();
|
||||
bool canVSync();
|
||||
void createFontsTexture();
|
||||
void destroyFontsTexture();
|
||||
void renderGUI();
|
||||
void wipe(float alpha);
|
||||
void present();
|
||||
bool getOutputSize(int& w, int& h);
|
||||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
const char* getAPIVersion();
|
||||
void setSwapInterval(int swapInterval);
|
||||
void preInit(const DivConfig& conf);
|
||||
bool init(SDL_Window* win, int swapInterval);
|
||||
void initGUI(SDL_Window* win);
|
||||
void quitGUI();
|
||||
bool quit();
|
||||
bool isDead();
|
||||
FurnaceGUIRenderDX9():
|
||||
iface(NULL),
|
||||
device(NULL),
|
||||
priv(NULL),
|
||||
wipeBuf(NULL),
|
||||
outW(0),
|
||||
outH(0),
|
||||
swapInterval(1),
|
||||
dead(false),
|
||||
haveScene(false),
|
||||
supportsDynamicTex(false),
|
||||
supportsVSync(false),
|
||||
mustResize(false),
|
||||
squareTex(false),
|
||||
inScene(false),
|
||||
maxWidth(8192),
|
||||
maxHeight(8192) {
|
||||
}
|
||||
};
|
|
@ -65,11 +65,13 @@ class FurnaceGLTexture: public FurnaceGUITexture {
|
|||
public:
|
||||
GLuint id;
|
||||
int width, height;
|
||||
FurnaceGUITextureFormat format;
|
||||
unsigned char* lockedData;
|
||||
FurnaceGLTexture():
|
||||
id(0),
|
||||
width(0),
|
||||
height(0),
|
||||
format(GUI_TEXFORMAT_UNKNOWN),
|
||||
lockedData(NULL) {}
|
||||
};
|
||||
|
||||
|
@ -281,6 +283,11 @@ ImTextureID FurnaceGUIRenderGL::getTextureID(FurnaceGUITexture* which) {
|
|||
return (ImTextureID)ret;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderGL::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceGLTexture* t=(FurnaceGLTexture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderGL::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceGLTexture* t=(FurnaceGLTexture*)which;
|
||||
if (t->lockedData!=NULL) return false;
|
||||
|
@ -315,7 +322,11 @@ bool FurnaceGUIRenderGL::updateTexture(FurnaceGUITexture* which, void* data, int
|
|||
return true;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderGL::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRenderGL::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
if (format!=GUI_TEXFORMAT_ABGR32) {
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
FurnaceGLTexture* t=new FurnaceGLTexture;
|
||||
C(glGenTextures(1,&t->id));
|
||||
C(glBindTexture(GL_TEXTURE_2D,t->id));
|
||||
|
@ -330,6 +341,7 @@ FurnaceGUITexture* FurnaceGUIRenderGL::createTexture(bool dynamic, int width, in
|
|||
C(furActiveTexture(GL_TEXTURE0));
|
||||
t->width=width;
|
||||
t->height=height;
|
||||
t->format=format;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -554,6 +566,10 @@ int FurnaceGUIRenderGL::getMaxTextureHeight() {
|
|||
return maxHeight;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderGL::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ABGR32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderGL::getBackendName() {
|
||||
return backendName.c_str();
|
||||
}
|
||||
|
|
|
@ -56,10 +56,11 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender {
|
|||
|
||||
public:
|
||||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -77,6 +78,7 @@ class FurnaceGUIRenderGL: public FurnaceGUIRender {
|
|||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
|
|
|
@ -29,6 +29,7 @@ class FurnaceGL1Texture: public FurnaceGUITexture {
|
|||
public:
|
||||
GLuint id;
|
||||
int width, height, widthReal, heightReal;
|
||||
FurnaceGUITextureFormat format;
|
||||
unsigned char* lockedData;
|
||||
FurnaceGL1Texture():
|
||||
id(0),
|
||||
|
@ -36,6 +37,7 @@ class FurnaceGL1Texture: public FurnaceGUITexture {
|
|||
height(0),
|
||||
widthReal(0),
|
||||
heightReal(0),
|
||||
format(GUI_TEXFORMAT_UNKNOWN),
|
||||
lockedData(NULL) {}
|
||||
};
|
||||
|
||||
|
@ -46,14 +48,21 @@ ImTextureID FurnaceGUIRenderGL1::getTextureID(FurnaceGUITexture* which) {
|
|||
|
||||
float FurnaceGUIRenderGL1::getTextureU(FurnaceGUITexture* which) {
|
||||
FurnaceGL1Texture* t=(FurnaceGL1Texture*)which;
|
||||
if (t->widthReal<1) return 0.0f;
|
||||
return (float)t->width/(float)t->widthReal;
|
||||
}
|
||||
|
||||
float FurnaceGUIRenderGL1::getTextureV(FurnaceGUITexture* which) {
|
||||
FurnaceGL1Texture* t=(FurnaceGL1Texture*)which;
|
||||
if (t->heightReal<1) return 0.0f;
|
||||
return (float)t->height/(float)t->heightReal;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderGL1::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceGL1Texture* t=(FurnaceGL1Texture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderGL1::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceGL1Texture* t=(FurnaceGL1Texture*)which;
|
||||
if (t->lockedData!=NULL) return false;
|
||||
|
@ -90,7 +99,11 @@ bool FurnaceGUIRenderGL1::updateTexture(FurnaceGUITexture* which, void* data, in
|
|||
return true;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderGL1::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRenderGL1::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
if (format!=GUI_TEXFORMAT_ABGR32) {
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
FurnaceGL1Texture* t=new FurnaceGL1Texture;
|
||||
C(glGenTextures(1,&t->id));
|
||||
C(glBindTexture(GL_TEXTURE_2D,t->id));
|
||||
|
@ -119,6 +132,7 @@ FurnaceGUITexture* FurnaceGUIRenderGL1::createTexture(bool dynamic, int width, i
|
|||
t->height=height;
|
||||
t->widthReal=widthReal;
|
||||
t->heightReal=heightReal;
|
||||
t->format=format;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -219,6 +233,10 @@ int FurnaceGUIRenderGL1::getMaxTextureHeight() {
|
|||
return maxHeight;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderGL1::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ABGR32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderGL1::getBackendName() {
|
||||
return "OpenGL 1.1";
|
||||
}
|
||||
|
|
|
@ -32,10 +32,11 @@ class FurnaceGUIRenderGL1: public FurnaceGUIRender {
|
|||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
float getTextureU(FurnaceGUITexture* which);
|
||||
float getTextureV(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -51,6 +52,7 @@ class FurnaceGUIRenderGL1: public FurnaceGUIRender {
|
|||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
|
|
|
@ -28,10 +28,11 @@ class FurnaceGUIRenderMetal: public FurnaceGUIRender {
|
|||
String vendorName, deviceName, apiVersion;
|
||||
public:
|
||||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -47,6 +48,7 @@ class FurnaceGUIRenderMetal: public FurnaceGUIRender {
|
|||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
|
|
|
@ -44,11 +44,13 @@ class FurnaceMetalTexture: public FurnaceGUITexture {
|
|||
public:
|
||||
id<MTLTexture> tex;
|
||||
int width, height;
|
||||
FurnaceGUITextureFormat format;
|
||||
unsigned char* lockedData;
|
||||
FurnaceMetalTexture():
|
||||
tex(NULL),
|
||||
width(0),
|
||||
height(0),
|
||||
format(GUI_TEXFORMAT_UNKNOWN),
|
||||
lockedData(NULL) {}
|
||||
};
|
||||
|
||||
|
@ -57,6 +59,11 @@ ImTextureID FurnaceGUIRenderMetal::getTextureID(FurnaceGUITexture* which) {
|
|||
return t->tex;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderMetal::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceMetalTexture* t=(FurnaceMetalTexture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderMetal::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceMetalTexture* t=(FurnaceMetalTexture*)which;
|
||||
if (t->lockedData!=NULL) return false;
|
||||
|
@ -84,7 +91,11 @@ bool FurnaceGUIRenderMetal::updateTexture(FurnaceGUITexture* which, void* data,
|
|||
return true;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderMetal::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRenderMetal::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
if (format!=GUI_TEXFORMAT_ABGR32) {
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
MTLTextureDescriptor* texDesc=[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatRGBA8Unorm width:(NSUInteger)width height:(NSUInteger)height mipmapped:NO];
|
||||
texDesc.usage=MTLTextureUsageShaderRead;
|
||||
texDesc.storageMode=MTLStorageModeManaged;
|
||||
|
@ -193,6 +204,10 @@ int FurnaceGUIRenderMetal::getMaxTextureHeight() {
|
|||
return bigTextures?16384:8192;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderMetal::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ABGR32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderMetal::getBackendName() {
|
||||
return "Metal";
|
||||
}
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
class FurnaceSDLTexture: public FurnaceGUITexture {
|
||||
public:
|
||||
SDL_Texture* tex;
|
||||
FurnaceGUITextureFormat format;
|
||||
FurnaceSDLTexture():
|
||||
tex(NULL) {}
|
||||
tex(NULL),
|
||||
format(GUI_TEXFORMAT_UNKNOWN) {}
|
||||
};
|
||||
|
||||
ImTextureID FurnaceGUIRenderSDL::getTextureID(FurnaceGUITexture* which) {
|
||||
|
@ -33,6 +35,11 @@ ImTextureID FurnaceGUIRenderSDL::getTextureID(FurnaceGUITexture* which) {
|
|||
return t->tex;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderSDL::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceSDLTexture* t=(FurnaceSDLTexture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderSDL::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceSDLTexture* t=(FurnaceSDLTexture*)which;
|
||||
return SDL_LockTexture(t->tex,NULL,data,pitch)==0;
|
||||
|
@ -49,7 +56,11 @@ bool FurnaceGUIRenderSDL::updateTexture(FurnaceGUITexture* which, void* data, in
|
|||
return SDL_UpdateTexture(t->tex,NULL,data,pitch)==0;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderSDL::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRenderSDL::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
if (format!=GUI_TEXFORMAT_ABGR32) {
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,interpolate?"1":"0");
|
||||
SDL_Texture* t=SDL_CreateTexture(sdlRend,SDL_PIXELFORMAT_ABGR8888,dynamic?SDL_TEXTUREACCESS_STREAMING:SDL_TEXTUREACCESS_STATIC,width,height);
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY,"1");
|
||||
|
@ -57,6 +68,7 @@ FurnaceGUITexture* FurnaceGUIRenderSDL::createTexture(bool dynamic, int width, i
|
|||
if (t==NULL) return NULL;
|
||||
FurnaceSDLTexture* ret=new FurnaceSDLTexture;
|
||||
ret->tex=t;
|
||||
ret->format=format;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -156,6 +168,10 @@ int FurnaceGUIRenderSDL::getMaxTextureHeight() {
|
|||
return renderInfo.max_texture_height;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderSDL::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ABGR32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderSDL::getBackendName() {
|
||||
return "SDL Renderer";
|
||||
}
|
||||
|
|
|
@ -26,10 +26,11 @@ class FurnaceGUIRenderSDL: public FurnaceGUIRender {
|
|||
bool swapIntervalSet;
|
||||
public:
|
||||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -45,6 +46,7 @@ class FurnaceGUIRenderSDL: public FurnaceGUIRender {
|
|||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
class FurnaceSoftwareTexture: public FurnaceGUITexture {
|
||||
public:
|
||||
SWTexture* tex;
|
||||
FurnaceGUITextureFormat format;
|
||||
FurnaceSoftwareTexture():
|
||||
tex(NULL) {}
|
||||
tex(NULL),
|
||||
format(GUI_TEXFORMAT_UNKNOWN) {}
|
||||
};
|
||||
|
||||
ImTextureID FurnaceGUIRenderSoftware::getTextureID(FurnaceGUITexture* which) {
|
||||
|
@ -33,6 +35,11 @@ ImTextureID FurnaceGUIRenderSoftware::getTextureID(FurnaceGUITexture* which) {
|
|||
return t->tex;
|
||||
}
|
||||
|
||||
FurnaceGUITextureFormat FurnaceGUIRenderSoftware::getTextureFormat(FurnaceGUITexture* which) {
|
||||
FurnaceSoftwareTexture* t=(FurnaceSoftwareTexture*)which;
|
||||
return t->format;
|
||||
}
|
||||
|
||||
bool FurnaceGUIRenderSoftware::lockTexture(FurnaceGUITexture* which, void** data, int* pitch) {
|
||||
FurnaceSoftwareTexture* t=(FurnaceSoftwareTexture*)which;
|
||||
if (!t->tex->managed) return false;
|
||||
|
@ -52,9 +59,14 @@ bool FurnaceGUIRenderSoftware::updateTexture(FurnaceGUITexture* which, void* dat
|
|||
return true;
|
||||
}
|
||||
|
||||
FurnaceGUITexture* FurnaceGUIRenderSoftware::createTexture(bool dynamic, int width, int height, bool interpolate) {
|
||||
FurnaceGUITexture* FurnaceGUIRenderSoftware::createTexture(bool dynamic, int width, int height, bool interpolate, FurnaceGUITextureFormat format) {
|
||||
if (format!=GUI_TEXFORMAT_ARGB32) {
|
||||
logE("unsupported texture format!");
|
||||
return NULL;
|
||||
}
|
||||
FurnaceSoftwareTexture* ret=new FurnaceSoftwareTexture;
|
||||
ret->tex=new SWTexture(width,height);
|
||||
ret->format=format;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -141,6 +153,10 @@ int FurnaceGUIRenderSoftware::getMaxTextureHeight() {
|
|||
return 16384;
|
||||
}
|
||||
|
||||
unsigned int FurnaceGUIRenderSoftware::getTextureFormats() {
|
||||
return GUI_TEXFORMAT_ARGB32;
|
||||
}
|
||||
|
||||
const char* FurnaceGUIRenderSoftware::getBackendName() {
|
||||
return "Software";
|
||||
}
|
||||
|
|
|
@ -23,10 +23,11 @@ class FurnaceGUIRenderSoftware: public FurnaceGUIRender {
|
|||
SDL_Window* sdlWin;
|
||||
public:
|
||||
ImTextureID getTextureID(FurnaceGUITexture* which);
|
||||
FurnaceGUITextureFormat getTextureFormat(FurnaceGUITexture* which);
|
||||
bool lockTexture(FurnaceGUITexture* which, void** data, int* pitch);
|
||||
bool unlockTexture(FurnaceGUITexture* which);
|
||||
bool updateTexture(FurnaceGUITexture* which, void* data, int pitch);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true);
|
||||
FurnaceGUITexture* createTexture(bool dynamic, int width, int height, bool interpolate=true, FurnaceGUITextureFormat format=GUI_TEXFORMAT_ABGR32);
|
||||
bool destroyTexture(FurnaceGUITexture* which);
|
||||
void setTextureBlendMode(FurnaceGUITexture* which, FurnaceGUIBlendMode mode);
|
||||
void setBlendMode(FurnaceGUIBlendMode mode);
|
||||
|
@ -42,6 +43,7 @@ class FurnaceGUIRenderSoftware: public FurnaceGUIRender {
|
|||
int getWindowFlags();
|
||||
int getMaxTextureWidth();
|
||||
int getMaxTextureHeight();
|
||||
unsigned int getTextureFormats();
|
||||
const char* getBackendName();
|
||||
const char* getVendorName();
|
||||
const char* getDeviceName();
|
||||
|
|
|
@ -31,6 +31,15 @@
|
|||
#include "sampleUtil.h"
|
||||
#include "util.h"
|
||||
|
||||
#define SWAP_COLOR_ARGB(x) \
|
||||
x=(x&0xff00ff00)|((x&0xff)<<16)|((x&0xff0000)>>16);
|
||||
|
||||
#define SWAP_COLOR_BGRA(x) \
|
||||
x=((x&0xff0000000)>>24)|((x&0xffffff)<<8);
|
||||
|
||||
#define SWAP_COLOR_RGBA(x) \
|
||||
x=((x&0xff)<<24)|((x&0xff00)<<8)|((x&0xff0000)>>8)|((x&0xff000000)>>24);
|
||||
|
||||
const double timeDivisors[10]={
|
||||
1000.0, 500.0, 200.0, 100.0, 50.0, 20.0, 10.0, 5.0, 2.0, 1.0
|
||||
};
|
||||
|
@ -1469,14 +1478,14 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
}
|
||||
}
|
||||
|
||||
if (sampleTex==NULL || sampleTexW!=avail.x || sampleTexH!=avail.y) {
|
||||
if (sampleTex==NULL || sampleTexW!=avail.x || sampleTexH!=avail.y || !rend->isTextureValid(sampleTex)) {
|
||||
if (sampleTex!=NULL) {
|
||||
rend->destroyTexture(sampleTex);
|
||||
sampleTex=NULL;
|
||||
}
|
||||
if (avail.x>=1 && avail.y>=1) {
|
||||
logD("recreating sample texture.");
|
||||
sampleTex=rend->createTexture(true,avail.x,avail.y);
|
||||
sampleTex=rend->createTexture(true,avail.x,avail.y,true,bestTexFormat);
|
||||
sampleTexW=avail.x;
|
||||
sampleTexH=avail.y;
|
||||
if (sampleTex==NULL) {
|
||||
|
@ -1501,6 +1510,30 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
ImU32 bgColorLoop=ImGui::GetColorU32(uiColors[GUI_COLOR_SAMPLE_LOOP]);
|
||||
ImU32 lineColor=ImGui::GetColorU32(uiColors[GUI_COLOR_SAMPLE_FG]);
|
||||
ImU32 centerLineColor=ImGui::GetColorU32(uiColors[GUI_COLOR_SAMPLE_CENTER]);
|
||||
|
||||
switch (rend->getTextureFormat(sampleTex)) {
|
||||
case GUI_TEXFORMAT_ARGB32:
|
||||
SWAP_COLOR_ARGB(bgColor);
|
||||
SWAP_COLOR_ARGB(bgColorLoop);
|
||||
SWAP_COLOR_ARGB(lineColor);
|
||||
SWAP_COLOR_ARGB(centerLineColor);
|
||||
break;
|
||||
case GUI_TEXFORMAT_BGRA32:
|
||||
SWAP_COLOR_BGRA(bgColor);
|
||||
SWAP_COLOR_BGRA(bgColorLoop);
|
||||
SWAP_COLOR_BGRA(lineColor);
|
||||
SWAP_COLOR_BGRA(centerLineColor);
|
||||
break;
|
||||
case GUI_TEXFORMAT_RGBA32:
|
||||
SWAP_COLOR_RGBA(bgColor);
|
||||
SWAP_COLOR_RGBA(bgColorLoop);
|
||||
SWAP_COLOR_RGBA(lineColor);
|
||||
SWAP_COLOR_RGBA(centerLineColor);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int ij=0;
|
||||
for (int i=0; i<availY; i++) {
|
||||
for (int j=0; j<availX; j++) {
|
||||
|
|
|
@ -388,6 +388,12 @@ void FurnaceGUI::drawSettings() {
|
|||
settingsChanged=true;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_RENDER_DX9
|
||||
if (ImGui::Selectable("DirectX 9",curRenderBackend=="DirectX 9")) {
|
||||
settings.renderBackend="DirectX 9";
|
||||
settingsChanged=true;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_RENDER_METAL
|
||||
if (ImGui::Selectable("Metal",curRenderBackend=="Metal")) {
|
||||
settings.renderBackend="Metal";
|
||||
|
|
|
@ -791,7 +791,10 @@ void FurnaceGUI::drawTutorial() {
|
|||
cv->hiScore=cvHiScore;
|
||||
}
|
||||
if (cvTex==NULL) {
|
||||
cvTex=rend->createTexture(true,320,224,false);
|
||||
cvTex=rend->createTexture(true,320,224,false,bestTexFormat);
|
||||
} else if (!rend->isTextureValid(cvTex)) {
|
||||
rend->destroyTexture(cvTex);
|
||||
cvTex=rend->createTexture(true,320,224,false,bestTexFormat);
|
||||
}
|
||||
|
||||
if (cv->pleaseInitSongs) {
|
||||
|
|
Loading…
Reference in a new issue