diff --git a/CMakeLists.txt b/CMakeLists.txt index edd581b6f..9a53310bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/extern/imgui_patched/backends/imgui_impl_dx9.cpp b/extern/imgui_patched/backends/imgui_impl_dx9.cpp index 7ee02b5b9..27fc73793 100644 --- a/extern/imgui_patched/backends/imgui_impl_dx9.cpp +++ b/extern/imgui_patched/backends/imgui_impl_dx9.cpp @@ -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; iIdxBuffer.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() diff --git a/extern/imgui_patched/backends/imgui_impl_dx9.h b/extern/imgui_patched/backends/imgui_impl_dx9.h index ffcd46826..716de6488 100644 --- a/extern/imgui_patched/backends/imgui_impl_dx9.h +++ b/extern/imgui_patched/backends/imgui_impl_dx9.h @@ -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. diff --git a/scripts/release-win32.sh b/scripts/release-win32.sh index 388ceb5aa..0126d213e 100755 --- a/scripts/release-win32.sh +++ b/scripts/release-win32.sh @@ -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 .. diff --git a/scripts/release-winxp.sh b/scripts/release-winxp.sh index 134fc9f17..bbe751c65 100755 --- a/scripts/release-winxp.sh +++ b/scripts/release-winxp.sh @@ -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 .. diff --git a/src/engine/engine.h b/src/engine/engine.h index ace57ec76..b0d6071dd 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -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 "dev211" +#define DIV_ENGINE_VERSION 211 // for imports #define DIV_VERSION_MOD 0xff01 #define DIV_VERSION_FC 0xff02 diff --git a/src/gui/chanOsc.cpp b/src/gui/chanOsc.cpp index bb7e345be..111c59b65 100644 --- a/src/gui/chanOsc.cpp +++ b/src/gui/chanOsc.cpp @@ -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!"); diff --git a/src/gui/debugWindow.cpp b/src/gui/debugWindow.cpp index fdaf3b066..53b8aa9ae 100644 --- a/src/gui/debugWindow.cpp +++ b/src/gui/debugWindow.cpp @@ -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; diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 76cc6b758..0ab61c4a9 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -7101,6 +7101,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!"); diff --git a/src/gui/gui.h b/src/gui/gui.h index 7159fefdf..15e664fa6 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -43,7 +43,7 @@ #define unimportant(x) if (x) {handleUnimportant} #define MARK_MODIFIED modified=true; -#define WAKE_UP drawHalt=16; +#define WAKE_UP drawHalt=5; #define RESET_WAVE_MACRO_ZOOM \ for (DivInstrument* _wi: e->song.ins) { \ @@ -1444,6 +1444,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 { }; @@ -1483,10 +1491,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); @@ -1505,6 +1515,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(); @@ -1544,6 +1555,7 @@ class FurnaceGUI { FurnaceGUIRenderBackend renderBackend; FurnaceGUIRender* rend; + FurnaceGUITextureFormat bestTexFormat; SDL_Window* sdlWin; SDL_Haptic* vibrator; diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index fccc5b86c..dd3955ad7 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -1006,7 +1006,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={ D(GUI_COLOR_INSTR_GBA_DMA,"",ImVec4(0.6f,0.4f,1.0f,1.0f)), D(GUI_COLOR_INSTR_GBA_MINMOD,"",ImVec4(0.5f,0.45f,0.7f,1.0f)), D(GUI_COLOR_INSTR_BIFURCATOR,"",ImVec4(0.8925f,0.8925f,0.8925f,1.0f)), - D(GUI_COLOR_INSTR_C64,"",ImVec4(0.6f,0.75f,1.0f,1.0f)), + D(GUI_COLOR_INSTR_SID2,"",ImVec4(0.6f,0.75f,1.0f,1.0f)), D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)), D(GUI_COLOR_CHANNEL_BG,"",ImVec4(0.4f,0.6f,0.8f,1.0f)), diff --git a/src/gui/image.cpp b/src/gui/image.cpp index a31c1dd9f..e526b43ed 100644 --- a/src/gui/image.cpp +++ b/src/gui/image.cpp @@ -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; idata[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; idata[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; idata[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; } diff --git a/src/gui/intro.cpp b/src/gui/intro.cpp index cbb4ff042..f191d4b34 100644 --- a/src/gui/intro.cpp +++ b/src/gui/intro.cpp @@ -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; diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 81dcc2dc2..8db99c025 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -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 diff --git a/src/gui/render/abstract.cpp b/src/gui/render/abstract.cpp index 48710cb2f..90fc67a01 100644 --- a/src/gui/render/abstract.cpp +++ b/src/gui/render/abstract.cpp @@ -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"; } diff --git a/src/gui/render/renderDX11.cpp b/src/gui/render/renderDX11.cpp index 75ff58fc9..a05220124 100644 --- a/src/gui/render/renderDX11.cpp +++ b/src/gui/render/renderDX11.cpp @@ -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"; } diff --git a/src/gui/render/renderDX11.h b/src/gui/render/renderDX11.h index 1fd015122..3243999f1 100644 --- a/src/gui/render/renderDX11.h +++ b/src/gui/render/renderDX11.h @@ -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(); diff --git a/src/gui/render/renderDX9.cpp b/src/gui/render/renderDX9.cpp new file mode 100644 index 000000000..353208114 --- /dev/null +++ b/src/gui/render/renderDX9.cpp @@ -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 +#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 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; iheight; 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<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; itexPool.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; +} diff --git a/src/gui/render/renderDX9.h b/src/gui/render/renderDX9.h new file mode 100644 index 000000000..3d46326e8 --- /dev/null +++ b/src/gui/render/renderDX9.h @@ -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 +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) { + } +}; diff --git a/src/gui/render/renderGL.cpp b/src/gui/render/renderGL.cpp index dffd16d20..161b36b2e 100644 --- a/src/gui/render/renderGL.cpp +++ b/src/gui/render/renderGL.cpp @@ -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(); } diff --git a/src/gui/render/renderGL.h b/src/gui/render/renderGL.h index 4664bec34..0cf861596 100644 --- a/src/gui/render/renderGL.h +++ b/src/gui/render/renderGL.h @@ -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(); diff --git a/src/gui/render/renderGL1.cpp b/src/gui/render/renderGL1.cpp index 9fb4485b5..0ebf8b391 100644 --- a/src/gui/render/renderGL1.cpp +++ b/src/gui/render/renderGL1.cpp @@ -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"; } diff --git a/src/gui/render/renderGL1.h b/src/gui/render/renderGL1.h index f6081be6a..9b3b6d2d3 100644 --- a/src/gui/render/renderGL1.h +++ b/src/gui/render/renderGL1.h @@ -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(); diff --git a/src/gui/render/renderMetal.h b/src/gui/render/renderMetal.h index 8aaa88d89..a0a249416 100644 --- a/src/gui/render/renderMetal.h +++ b/src/gui/render/renderMetal.h @@ -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(); diff --git a/src/gui/render/renderMetal.mm b/src/gui/render/renderMetal.mm index 8649b66a0..ae27b3b89 100644 --- a/src/gui/render/renderMetal.mm +++ b/src/gui/render/renderMetal.mm @@ -44,11 +44,13 @@ class FurnaceMetalTexture: public FurnaceGUITexture { public: id 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"; } diff --git a/src/gui/render/renderSDL.cpp b/src/gui/render/renderSDL.cpp index a5f95ead9..cb0a6a402 100644 --- a/src/gui/render/renderSDL.cpp +++ b/src/gui/render/renderSDL.cpp @@ -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"; } diff --git a/src/gui/render/renderSDL.h b/src/gui/render/renderSDL.h index 46a47559a..fa394dcac 100644 --- a/src/gui/render/renderSDL.h +++ b/src/gui/render/renderSDL.h @@ -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(); diff --git a/src/gui/render/renderSoftware.cpp b/src/gui/render/renderSoftware.cpp index 8ca812661..d18c11aa2 100644 --- a/src/gui/render/renderSoftware.cpp +++ b/src/gui/render/renderSoftware.cpp @@ -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"; } diff --git a/src/gui/render/renderSoftware.h b/src/gui/render/renderSoftware.h index 05315dab8..eef580aff 100644 --- a/src/gui/render/renderSoftware.h +++ b/src/gui/render/renderSoftware.h @@ -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(); diff --git a/src/gui/sampleEdit.cpp b/src/gui/sampleEdit.cpp index b5bf8f736..4a85cdd06 100644 --- a/src/gui/sampleEdit.cpp +++ b/src/gui/sampleEdit.cpp @@ -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; ihiScore=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) {