MFC SDL2 stuck when the window size is changed

This article is reprinted, the original link: http://www.cnblogs.com/lihaiping/p/4324315.html

Today, I used the SDL2.0 library for video display in the project, and there were many problems in it, which are recorded here and used as a reference in the future.

 

After using SDL_CreateWindowFrom and SDL_DestroyWindow multiple times with the same window handle, it is found that the program is running normally, but the video is not displayed.

Pass Hwnd to SDL_CreateWindowFrom for the first time to create a display window to SDL, and then call SDL_DestroyWindow when not in use to destroy the display window just created, release the display related resources, and then use SDL_CreateWindowFrom again, the same A handle is passed to SDL_CreateWindowFrom, it returns success, and all subsequent operations are performed normally, but the video is always not displayed on the window.

For the reasons, I searched for a long time, and then slowly speculated and suspected some problems from the SDL source code. The SDL source code is as follows:

Copy code

 1 void
 2 SDL_DestroyWindow(SDL_Window * window)
 3 {
 4     SDL_VideoDisplay *display;
 5 
 6     CHECK_WINDOW_MAGIC(window, );
 7 
 8     /* Restore video mode, etc. */
 9 SDL_HideWindow(window);/*Pay attention to this place*/
10 
11     /* Make sure this window no longer has focus */
12     if (SDL_GetKeyboardFocus() == window) {
13         SDL_SetKeyboardFocus(NULL);
14     }
15     if (SDL_GetMouseFocus() == window) {
16         SDL_SetMouseFocus(NULL);
17     }
18 
19     /* make no context current if this is the current context window. */
20     if (window->flags & SDL_WINDOW_OPENGL) {
21         if (_this->current_glwin == window) {
22             SDL_GL_MakeCurrent(window, NULL);
23         }
24     }
25 
26     if (window->surface) {
27         window->surface->flags &= ~SDL_DONTFREE;
28         SDL_FreeSurface(window->surface);
29     }
30     if (_this->DestroyWindowFramebuffer) {
31         _this->DestroyWindowFramebuffer(_this, window);
32     }
33     if (_this->DestroyWindow) {
34         _this->DestroyWindow(_this, window);
35     }
36     if (window->flags & SDL_WINDOW_OPENGL) {
37         SDL_GL_UnloadLibrary();
38     }
39 
40     display = SDL_GetDisplayForWindow(window);
41     if (display->fullscreen_window == window) {
42         display->fullscreen_window = NULL;
43     }
44 
45     /* Now invalidate magic */
46     window->magic = NULL;
47 
48     /* Free memory associated with the window */
49     SDL_free(window->title);
50     SDL_FreeSurface(window->icon);
51     SDL_free(window->gamma);
52     while (window->data) {
53         SDL_WindowUserData *data = window->data;
54 
55         window->data = data->next;
56         SDL_free(data->name);
57         SDL_free(data);
58     }
59 
60     /* Unlink the window from the list */
61     if (window->next) {
62         window->next->prev = window->prev;
63     }
64     if (window->prev) {
65         window->prev->next = window->next;
66     } else {
67         _this->windows = window->next;
68     }
69 
70     SDL_free(window);
71 }

Copy code

From the above code, I began to wonder if SDL hid the window after calling SDL_DestroyWindow, which caused the problem that the video cannot be displayed all the time when the video is displayed on it.

So I added the following statement to my test code. After calling SDL_DestroyWindow, I said:

vDisplay.ShowWindow(SW_SHOWNORMAL);//If you want to show the window, show it out,
where vDisplay corresponds to the displayed window control object.

 After adding this line of code to the tested project code, the problem of the project is perfectly solved.

=============================================================

Question 2:

When I create some related resources of the display window in the MFC UI message corresponding function, a separate thread created in the background is used to refresh and update the display data, and then release and destroy the SDL window related resources in the UI close message response.

The problem is coming. When I use full screen, the background update data thread keeps reporting errors:

Copy code

 1     if(o_pSdlHelper->SDL_RenderClear(pDispContext->pStruOut->pRender)<0)
 2     {
 3         char outstr[200]={0};
 4         const char *pbuf=o_pSdlHelper->SDL_GetError();
 5 _snprintf(outstr,sizeof(outstr),"%s \n",pbuf);//The error message here is: Reset(): INVALIDCALL
 6         OutputDebugStringA(outstr);
 7         memset(outstr,0,sizeof(outstr));
 8 
 9         return PCI_MC_UNKNOWN_ERR;
10     }

Copy code

This makes me strange. When I was in full screen before, there was no error. Why is there an error now? And the display window screen has not been refreshed! !

So I thought about the difference with the previous code. The only difference is that I call resources such as window creation and rendering, texture creation, etc., which are placed in the same thread as the data update. No way, I don’t know. The reason is to change back to the original code and transfer the created code from the UI message response to the same thread as the background refresh data. The strange result is that such a full-screen operation can run?

Damn it, why is this?

//For this reason, we still need to verify the relevant information and SDL source code to know. Temporarily resolved, but I don't know the reason.

=========================================

Recently, there are always unexplainable errors in using sdl. Later, I know from the sdl source code:

https://bugzilla.libsdl.org/show_bug.cgi?id=1995

 

 

/

When sdl is doing video display, when the window size is constantly adjusted, the sdl crash will occur. Later tracking found that the crash is in the windowsizechange message of sdl, the function render->updateview.

However, this crash seems to only crash on some machines. The specific reason is still unknown, but my current solution is to comment out the message response processing function of sdl:

Copy code

 1 #ifdef GWLP_WNDPROC
 2 data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
 3 if (data->wndproc == WIN_WindowProc) {
 4 data->wndproc = NULL;
 5 } else {//modefy by lhp-20150720
 6 //SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
 7 }
 8 #else
 9 data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
10 if (data->wndproc == WIN_WindowProc) {
11 data->wndproc = NULL;
12} else {//modefy by lhp-20150720-note this sdl message takeover function
13 //SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
14 }
15 #endif

Copy code

From: http://www.cnblogs.com/lihaiping/p/4324315.html 

Guess you like

Origin blog.csdn.net/gouguofei/article/details/81331271