zoukankan      html  css  js  c++  java
  • (原)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 
    ",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 

  • 相关阅读:
    HDOJ -- 4632 区间DP
    leetcode230- Kth Smallest Element in a BST- medium
    leetcode240- Search a 2D Matrix II- medium
    leetcode369- Plus One Linked List- medium
    leetcode276- Paint Fence- easy
    leetcode54- Spiral Matrix- medium
    leetcode264- Ugly Number II- medium
    leetcode263- Ugly Number- easy
    leetcode616- Add Bold Tag in String- medium
    leetcode289- Game of Life- medium
  • 原文地址:https://www.cnblogs.com/lihaiping/p/4324315.html
Copyright © 2011-2022 走看看