mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 10:05:44 -04:00
Fix error recreating D3D9 context crash. A big thank you to SpicyCombo for running a debug version of the game for an extended period of time to allow me to track down the cause.
The circumstances that cause this to happen are quite rare, which is why I had great difficulty getting it to occur myself. Approximate steps to cause this error are: 1) Do something that causes the Direct3D9 context to be lost for a long period of time, like running a fullscreen Direct3D9 game 2) Get the texture pack changed in ClassiCube while it's still running in the background (e.g. someone summons you to another map) 3) Now come back to this game 4) Gfx_RecreateContext gets called, triggering each subscriber to the ContextRecreated event 5) One of the first subscribers is the TexturePack component, which reload the texture pack (because of step 2). Sometimes this causes default.png to be changed, which will then cause the Gui to call OnContextRecreated on all the current screens/menus 6) One of the last subscribers is the Gui component, which causes the Gui to call OnContextRecreated on all of the current screens/menus The problem is that step 5) and 6) means OnContextRecreated is called twice in a row without an OnContextLost, causing some D3D9 resources allocated in step 5) to get leaked, and hence crashing the game later with D3DERR_INVALIDCALL. So the solution is to change Screen_CreateVb to always try deleting the existing vb first before replacing, so that way it doesn't leak
This commit is contained in:
parent
fb9757252b
commit
df5e41ebf9
@ -420,8 +420,9 @@ void Screen_ContextLost(void* screen) {
|
||||
}
|
||||
}
|
||||
|
||||
void Screen_CreateVb(void* screen) {
|
||||
void Screen_UpdateVb(void* screen) {
|
||||
struct Screen* s = (struct Screen*)screen;
|
||||
Gfx_DeleteDynamicVb(&s->vb);
|
||||
s->vb = Gfx_CreateDynamicVb(VERTEX_FORMAT_TEXTURED, s->maxVertices);
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ void Screen_Layout(void* screen);
|
||||
/* Calls Widget_Free on each widget in the screen. */
|
||||
/* Also deletes the screen's vb. */
|
||||
void Screen_ContextLost(void* screen);
|
||||
void Screen_CreateVb(void* screen);
|
||||
void Screen_UpdateVb(void* screen);
|
||||
struct VertexTextured* Screen_LockVb(void* screen);
|
||||
void Screen_BuildMesh(void* screen);
|
||||
int Screen_DoPointerDown(void* screen, int id, int x, int y);
|
||||
|
30
src/Menus.c
30
src/Menus.c
@ -383,7 +383,7 @@ static void ListScreen_ContextLost(void* screen) {
|
||||
|
||||
static void ListScreen_ContextRecreated(void* screen) {
|
||||
struct ListScreen* s = (struct ListScreen*)screen;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Gui_MakeTitleFont(&s->font);
|
||||
ListScreen_RedrawEntries(s);
|
||||
|
||||
@ -458,7 +458,7 @@ static void PauseScreen_ContextRecreated(void* screen) {
|
||||
struct PauseScreen* s = (struct PauseScreen*)screen;
|
||||
struct FontDesc titleFont;
|
||||
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
Menu_SetButtons(s->btns, &titleFont, s->descs, s->descsCount);
|
||||
|
||||
@ -604,7 +604,7 @@ static void OptionsGroupScreen_ContextLost(void* screen) {
|
||||
static void OptionsGroupScreen_ContextRecreated(void* screen) {
|
||||
struct OptionsGroupScreen* s = (struct OptionsGroupScreen*)screen;
|
||||
struct FontDesc titleFont;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
Gui_MakeBodyFont(&s->textFont);
|
||||
@ -852,7 +852,7 @@ static void EditHotkeyScreen_ContextRecreated(void* screen) {
|
||||
|
||||
Gui_MakeTitleFont(&s->titleFont);
|
||||
Gui_MakeBodyFont(&s->textFont);
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
EditHotkeyScreen_UpdateBaseKey(s);
|
||||
EditHotkeyScreen_UpdateModifiers(s);
|
||||
@ -1061,7 +1061,7 @@ static void GenLevelScreen_ContextRecreated(void* screen) {
|
||||
struct FontDesc titleFont;
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
Gui_MakeBodyFont(&s->textFont);
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
TextInputWidget_SetFont(&s->inputs[0], &s->textFont);
|
||||
TextInputWidget_SetFont(&s->inputs[1], &s->textFont);
|
||||
@ -1165,7 +1165,7 @@ static void ClassicGenScreen_Huge(void* a, void* b) { ClassicGenScreen_Gen(512
|
||||
static void ClassicGenScreen_ContextRecreated(void* screen) {
|
||||
struct ClassicGenScreen* s = (struct ClassicGenScreen*)screen;
|
||||
struct FontDesc titleFont;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
ButtonWidget_SetConst(&s->btns[0], "Small", &titleFont);
|
||||
@ -1415,7 +1415,7 @@ static void SaveLevelScreen_ContextRecreated(void* screen) {
|
||||
Gui_MakeTitleFont(&s->titleFont);
|
||||
Gui_MakeBodyFont(&s->textFont);
|
||||
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
SaveLevelScreen_UpdateSave(s);
|
||||
SaveLevelScreen_UpdateAlt(s);
|
||||
|
||||
@ -1769,7 +1769,7 @@ static void KeyBindsScreen_ContextRecreated(void* screen) {
|
||||
struct FontDesc textFont;
|
||||
int i;
|
||||
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Gui_MakeTitleFont(&s->titleFont);
|
||||
Gui_MakeBodyFont(&textFont);
|
||||
for (i = 0; i < s->bindsCount; i++) { KeyBindsScreen_Update(s, i); }
|
||||
@ -2094,7 +2094,7 @@ static void MenuInputOverlay_ContextRecreated(void* screen) {
|
||||
struct FontDesc font;
|
||||
Gui_MakeTitleFont(&font);
|
||||
Gui_MakeBodyFont(&s->textFont);
|
||||
Screen_CreateVb(s);
|
||||
Screen_UpdateVb(s);
|
||||
|
||||
TextInputWidget_SetFont(&s->input, &s->textFont);
|
||||
ButtonWidget_SetConst(&s->ok, "OK", &font);
|
||||
@ -3177,7 +3177,7 @@ static void TexIdsOverlay_ContextRecreated(void* screen) {
|
||||
struct TexIdsOverlay* s = (struct TexIdsOverlay*)screen;
|
||||
struct FontDesc textFont, titleFont;
|
||||
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Drawer2D_MakeFont(&textFont, 8, FONT_FLAGS_PADDING);
|
||||
Font_SetPadding(&textFont, 1);
|
||||
TextAtlas_Make(&s->idAtlas, &chars, &textFont, &prefix);
|
||||
@ -3364,7 +3364,7 @@ static void UrlWarningOverlay_AppendUrl(void* screen, void* b) {
|
||||
static void UrlWarningOverlay_ContextRecreated(void* screen) {
|
||||
struct UrlWarningOverlay* s = (struct UrlWarningOverlay*)screen;
|
||||
struct FontDesc titleFont, textFont;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
Gui_MakeBodyFont(&textFont);
|
||||
@ -3519,7 +3519,7 @@ static void TexPackOverlay_ContextLost(void* screen) {
|
||||
static void TexPackOverlay_ContextRecreated(void* screen) {
|
||||
struct TexPackOverlay* s = (struct TexPackOverlay*)screen;
|
||||
struct FontDesc titleFont;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
Gui_MakeBodyFont(&s->textFont);
|
||||
@ -3685,7 +3685,7 @@ static void TouchOnscreenScreen_ContextLost(void* screen) {
|
||||
static void TouchOnscreenScreen_ContextRecreated(void* screen) {
|
||||
struct TouchOnscreenScreen* s = (struct TouchOnscreenScreen*)screen;
|
||||
Gui_MakeTitleFont(&s->font);
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Menu_SetButtons(s->btns, &s->font, s->btnDescs, ONSCREEN_PAGE_BTNS);
|
||||
ButtonWidget_SetConst(&s->back, "Done", &s->font);
|
||||
ButtonWidget_SetConst(&s->left, "<", &s->font);
|
||||
@ -3826,7 +3826,7 @@ static void TouchCtrlsScreen_ContextLost(void* screen) {
|
||||
static void TouchCtrlsScreen_ContextRecreated(void* screen) {
|
||||
struct TouchCtrlsScreen* s = (struct TouchCtrlsScreen*)screen;
|
||||
Gui_MakeTitleFont(&s->font);
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Menu_SetButtons(s->btns, &s->font, touchCtrls_btns, TOUCHCTRLS_BTNS);
|
||||
ButtonWidget_SetConst(&s->back, "Done", &s->font);
|
||||
|
||||
@ -3914,7 +3914,7 @@ static void TouchMoreScreen_ContextRecreated(void* screen) {
|
||||
struct TouchMoreScreen* s = (struct TouchMoreScreen*)screen;
|
||||
struct FontDesc titleFont;
|
||||
Gui_MakeTitleFont(&titleFont);
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
Menu_SetButtons(s->btns, &titleFont, touchMore_btns, TOUCHMORE_BTNS);
|
||||
ButtonWidget_SetConst(&s->back, "Back to game", &titleFont);
|
||||
|
@ -1535,9 +1535,7 @@ static void LoadingScreen_Layout(void* screen) {
|
||||
oldRows = s->rows;
|
||||
LoadingScreen_CalcMaxVertices(s);
|
||||
if (oldRows == s->rows) return;
|
||||
|
||||
Gfx_DeleteDynamicVb(&s->vb);
|
||||
Screen_CreateVb(s);
|
||||
Screen_UpdateVb(s);
|
||||
}
|
||||
|
||||
static void LoadingScreen_ContextLost(void* screen) {
|
||||
@ -1551,7 +1549,7 @@ static void LoadingScreen_ContextRecreated(void* screen) {
|
||||
Gui_MakeBodyFont(&s->font);
|
||||
LoadingScreen_SetTitle(s);
|
||||
LoadingScreen_SetMessage(s);
|
||||
Screen_CreateVb(s);
|
||||
Screen_UpdateVb(s);
|
||||
}
|
||||
|
||||
static void LoadingScreen_BuildMesh(void* screen) {
|
||||
@ -1805,7 +1803,7 @@ static void DisconnectScreen_ContextLost(void* screen) {
|
||||
|
||||
static void DisconnectScreen_ContextRecreated(void* screen) {
|
||||
struct DisconnectScreen* s = (struct DisconnectScreen*)screen;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
|
||||
Gui_MakeTitleFont(&s->titleFont);
|
||||
Gui_MakeBodyFont(&s->messageFont);
|
||||
@ -2039,7 +2037,7 @@ static void TouchScreen_ContextRecreated(void* screen) {
|
||||
struct TouchScreen* s = (struct TouchScreen*)screen;
|
||||
const struct TouchButtonDesc* desc;
|
||||
int i;
|
||||
Screen_CreateVb(screen);
|
||||
Screen_UpdateVb(screen);
|
||||
Gui_MakeTitleFont(&s->font);
|
||||
|
||||
for (i = 0; i < s->numOnscreen; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user