(原)SDL調試心得


今天在項目中用到SDL2.0的庫做視頻顯示用,在其中出現不少問題,這里一一記錄下來,並作為以后的參考。

 

同一個窗口句柄在多次使用SDL_CreateWindowFrom和SDL_DestroyWindow以后,發現程序運行正常,但視頻顯示不出來的問題。

第一次將Hwnd傳遞給SDL_CreateWindowFrom,創建一個顯示窗口給SDL,隨后在不使用的時候,調用SDL_DestroyWindow,將剛剛創建的顯示窗口銷毀,釋放顯示相關資源之后,然后在再次使用SDL_CreateWindowFrom的時候,將同一個句柄傳遞給SDL_CreateWindowFrom,返回成功,后續的操作也全部正常進行,但視頻在窗口上始終顯示不出來。

對於其中的原因,我找了好久,后面從SDL的源碼中才慢慢推測並懷疑一些問題,SDL源碼如下:

 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);/*注意這個地方哦*/
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 }

從上面的代碼,我開始懷疑是不是在調用SDL_DestroyWindow以后,SDL將窗口給隱藏了,導致在上面顯示視頻的時候,始終顯示不出來的問題。

於是我在自己的測試代碼中加入如下語句,在調用SDL_DestroyWindow以后,我一句:

vDisplay.ShowWindow(SW_SHOWNORMAL);//想顯示窗口給顯示出來,show出來
其中vDisplay對應於顯示的窗口控件對象。

 在測試的項目代碼中加入這行代碼以后,就完美的解決了項目的問題。

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

問題2:

當我在MFC的UI消息相應函數中創建顯示窗口的一些相關資源,在后台創建的單獨線程,用於刷新和更新顯示數據,然后在UI的關閉消息響應中釋放和銷毀SDL窗口相關資源。

問題來了,當我使用全屏的時候,出現了后台更新數據線程一直報錯:

 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);//這里出錯信息為:Reset(): INVALIDCALL  6         OutputDebugStringA(outstr);
 7         memset(outstr,0,sizeof(outstr));
 8 
 9         return PCI_MC_UNKNOWN_ERR;
10     }

這就讓我奇怪了,之前我全屏的時候,沒有錯誤啊,現在為什么有錯?而且顯示窗口畫面也沒有顯示刷新了!!

於是我想了下和之前的代碼有什么不同,唯一的不同在於,我調用創建窗口和創建渲染,紋理等等這些操作等資源放在了和更新數據的同一個線程中,沒辦法,不知道原因,只有改回原來的代碼,將創建的代碼從UI消息響應中調入和后台刷新數據同一個線程中。結果奇怪的是,居然這樣全屏操作能運行?

見鬼了,這是啥原因?

//這個原因,還有待查證相關資料和SDL源碼才能知道。暫時解決了,但不知道原因何在。

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

最近使用sdl老是出現莫名其妙的錯誤,后面從sdl源碼中知道:

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

 

 

/////////////////////////////////////////////////////////////////////////////////////////

sdl做視頻顯示的時候,在不斷調整窗口大小的時候,會出現sdl崩潰,后面跟蹤發現崩潰在sdl的windowsizechange消息,render->updateview這個函數上.

不過這個崩潰,貌似也只是會在部分機器上崩潰,具體原因還不得而知,但目前我的解決方法是sdl的消息響應處理函數給注釋掉了:

 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-注釋這個sdl消息接管函數
13 //SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
14 }
15 #endif

出自:http://www.cnblogs.com/lihaiping/p/4324315.html 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM