今天测试人员反应,之前做的视频绘图显示,会在她机器上,会出现崩溃现象,最后我在她机器上对代码进行跟踪,发现在某种情况,确实会崩溃。

最主要的原因是,视频显示窗口变成非活动窗口的时候,sdl内部会循环消息处理,当处理WM_WINDOWPOSCHANGED消息的时候,就会出现崩溃,崩溃的代码在,D3D_UpdateViewport函数内部的IDirect3DDevice9_SetViewport函数。

当初我为了解决这个问题,觉得是sdl内部接管了窗口的消息处理函数引起的,因为实际上我们这里也没用到sdl的事件处理消息函数,所以我最初是打算把消息接管函数给屏蔽掉,就饿可以解决这个问题,当时也免得消息函数里面出现其他异常情况。

 #ifdef GWLP_WNDPROC
data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
if (data->wndproc == WIN_WindowProc) {
data->wndproc = NULL;
} else {
//SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);//以为屏蔽掉这里的消息处理函数,就可以解决问题了。
}
#else
data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
if (data->wndproc == WIN_WindowProc) {
data->wndproc = NULL;
} else {
//SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
}
#endif

结果是,崩溃的问题看似解决了,在她那台机器和其他机器上也不会出现崩溃,但有一个其他的问题引入了,就是sdl内部不能响应事件处理函数,这样当我们从视频显示画面变为全屏的时候,出现了一个问题,全屏的时候,画面质量很差,线条和边界画面出现明显的锯齿现象。所以最后此方法没行通,只能再找解决办法:

分析sdl内部消息的源码:

 ///////////////SDL消息分析//////////////////////////
WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)//这个函数是SDL接管windows窗口消息的函数
{
...
case WM_WINDOWPOSCHANGED://会触发这个消息
{
RECT rect;
int x, y;
int w, h; if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
break;
}
ClientToScreen(hwnd, (LPPOINT) & rect);
ClientToScreen(hwnd, (LPPOINT) & rect + ); WIN_UpdateClipCursor(data->window); x = rect.left;
y = rect.top;
//这里先发送窗口移动消息,移动x,y的坐标位置
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y); w = rect.right - rect.left;
h = rect.bottom - rect.top;
//然后这里发送尺寸修改消息,修改显示窗口的w,h
//屏蔽掉这个消息之后,全屏会出现锯齿,视频渲染效果很差
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,h);//发送这个事件
}
break;
...
} ////////////////////////////////////////////////////
int SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1,int data2)
{
case SDL_WINDOWEVENT_MOVED: //处理
if (SDL_WINDOWPOS_ISUNDEFINED(data1) ||
SDL_WINDOWPOS_ISUNDEFINED(data2)) {
return ;
}
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
window->windowed.x = data1;
window->windowed.y = data2;
}
if (data1 == window->x && data2 == window->y) {
return ;
}
window->x = data1;
window->y = data2;
break;
case SDL_WINDOWEVENT_RESIZED://处理
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
window->windowed.w = data1;
window->windowed.h = data2;
}
if (data1 == window->w && data2 == window->h) {
return ;
}
window->w = data1;
window->h = data2;
SDL_OnWindowResized(window);//进入这个事件处理会崩溃-lhp
{//注意这个函数里面也是发送一个窗口大小改变的消息
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SIZE_CHANGED, window->w, window->h);//发送改变消息-LHP
}
break;
/////////////////Break出来以后////////////////////////
if (SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE) {
SDL_Event event;
event.type = SDL_WINDOWEVENT;
event.window.event = windowevent;
event.window.data1 = data1;
event.window.data2 = data2;
event.window.windowID = window->id; /* Fixes queue overflow with resize events that aren't processed */
if (windowevent == SDL_WINDOWEVENT_RESIZED) {//2)然后触发这个消息事件
SDL_FilterEvents(RemovePendingResizedEvents, &event);
}
if (windowevent == SDL_WINDOWEVENT_SIZE_CHANGED) {//3)最后触发这个消息事件
SDL_FilterEvents(RemovePendingSizeChangedEvents, &event);
}
if (windowevent == SDL_WINDOWEVENT_MOVED) {//1)首先触发这个消息事件
SDL_FilterEvents(RemovePendingMoveEvents, &event);
} posted = (SDL_PushEvent(&event) > );
}
} //////////////////////////////////////
//上面的分析是消息的触发,下面看看消息捕捉以后消息的处理分析
//SDL的渲染事件watch函数用于捕捉事件
static int SDL_RendererEventWatch(void *userdata, SDL_Event *event)
{
SDL_Renderer *renderer = (SDL_Renderer *)userdata;
if (event->type == SDL_WINDOWEVENT) {
SDL_Window *window = SDL_GetWindowFromID(event->window.windowID);
if (window == renderer->window) {
if (renderer->WindowEvent) {
renderer->WindowEvent(renderer, &event->window);
//这个函数的内部实现源码如下:
static void D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED) {
data->updateSize = SDL_TRUE;
}
}
} if (event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
if (renderer->logical_w) {
UpdateLogicalSize(renderer);
} else {
/* Window was resized, reset viewport */
int w, h; if (renderer->GetOutputSize) {
renderer->GetOutputSize(renderer, &w, &h);
} else {
SDL_GetWindowSize(renderer->window, &w, &h);
} if (renderer->target) {
renderer->viewport_backup.x = ;
renderer->viewport_backup.y = ;
renderer->viewport_backup.w = w;
renderer->viewport_backup.h = h;
} else {
renderer->viewport.x = ;
renderer->viewport.y = ;
renderer->viewport.w = w;
renderer->viewport.h = h;
//这个函数会导致崩溃,在部分机器上,设置视区区域
//最后我把这个地方的这个函数给注释掉了。
//modefy by lhp -20150805
//renderer->UpdateViewport(renderer);//崩溃的地方-LHP
}
}
}
}
} }
//updateViewport
static int D3D_UpdateViewport(SDL_Renderer * renderer)
{
D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; viewport.X = renderer->viewport.x;
viewport.Y = renderer->viewport.y;
viewport.Width = renderer->viewport.w;
viewport.Height = renderer->viewport.h;
viewport.MinZ = 0.0f;
viewport.MaxZ = 1.0f;
//这里是跟踪的时候,调用崩溃的函数,在部分机器上,当窗口视区改变大小的时候,这个函数会崩溃
IDirect3DDevice9_SetViewport(data->device, &viewport); }

当时想从D3D_UpdateViewport函数入手,但发现我改的几个版本出来的效果,依然会崩溃,例如加clear,getviewport函数看会失败不,等等操作函数,都无用,没办法,只有在消息函数里面处理,把更新显示视区的函数给屏蔽掉。(这个地方做修改也是影响最小的屏蔽,因为这个地方是针对SDL_WINDOWEVENT_SIZE_CHANGED这个事件。)

转载请注明出处:http://www.cnblogs.com/lihaiping/p/4704836.html

(原)关于sdl在部分机器上做视频显示,改变显示窗口大小会崩溃的更多相关文章

  1. [原]在AMD机器上使用android studio

    amd机器上使用android studio进行调试.因为amd的cpu不支持IntelVT,所以可能会有如下错误提示   我们有几个选择: 1. 使用真机调试 2. 配合genymotion 3. ...

  2. 关于LogStash运行在AIX 64位机器上的问题与临时解决方案

    需求;logstash运行在SUSE,LINUX,PPC LINUX,AIX机器上,并监控文件发送日志到KAFKA中去, 问题:在AIX机器上,file插件总是报异常,无法完成数据的读取 NotImp ...

  3. 配置hooks使svn提交后自动同步客户端代码(客户端与服务端在同一台机器上)

    1.配置svn的hooks 2.实例演示 1.配置svn的hooks 1.1)配置情况 承接上篇svn搭建的文章,今次继续使用上篇文章的配置 上篇文章的地址:linux下搭建svn代码库 svn仓库所 ...

  4. 大数据架构-使用HBase和Solr将存储与索引放在不同的机器上

    大数据架构-使用HBase和Solr将存储与索引放在不同的机器上 摘要:HBase可以通过协处理器Coprocessor的方式向Solr发出请求,Solr对于接收到的数据可以做相关的同步:增.删.改索 ...

  5. 用pf透明地将流量从一台机器转到另一台机器上的缘起及实现方式对比

    下面是也是我在12580工作时发生的事情,重新记录并发出来.这种特殊需求很考 验PF的功底.在新旧系统并存,做重构的时候有时很需要这种救急的作法.一.缘起miscweb1(172.16.88.228) ...

  6. Shell获取Aix/linux/unix机器上db2和os的信息并上传到指定服务器

    (之前写过一篇类似的文章,当时传输文件用的是ftp,因为项目觉得ftp不够安全所以这次换成了scp,同时对脚本的一些地方也做了一些调整) 其实做这个东西还是因为项目的需求,需要获取某些机器(目前主要是 ...

  7. mapreduce (五) MapReduce实现倒排索引 修改版 combiner是把同一个机器上的多个map的结果先聚合一次

    (总感觉上一篇的实现有问题)http://www.cnblogs.com/i80386/p/3444726.html combiner是把同一个机器上的多个map的结果先聚合一次现重新实现一个: 思路 ...

  8. mapreduce (二) MapReduce实现倒排索引(一) combiner是把同一个机器上的多个map的结果先聚合一次

    1 思路:0.txt MapReduce is simple1.txt MapReduce is powerfull is simple2.txt Hello MapReduce bye MapRed ...

  9. Detours简介 (拦截x86机器上的任意的win32 API函数)

    Detours 当然是用detours,微软明显高腾讯一筹,同上,至今没失败过.写这种HOOK一定要再写个测试程序,不要直接HOOK你的目的程序,例如QQ,因为这样不方面更灵活的测试.说明一下:Det ...

随机推荐

  1. (转)C++11里的智能指针

    1. std::auto_ptr有些违背c++编程思想. 已经被"不建议使用了".2. 下文转自:http://blog.csdn.net/lanergaming/article/ ...

  2. 双系统linux+win之血的教训

    绝对不要用win的软件来直接调整linux分区!!!!! 除非你不想要这个linux分区里的数据了...

  3. Node和Electron开发入门(四):操作PC端文件系统

    一.调用PC端默认方式打开本地文件 在main.js里 // 打开系统本地文件或者网页链接 const {shell} = require('electron'); // Open a local f ...

  4. git file mode change

    近期在做ffmpeg版本合并时发现,TortoiseGit的Check for Modifications的修改对话框中有未修改的问题,直接导出diff,会有类似下面的输出: compat/plan9 ...

  5. NSLOOKUP命令的使用方法

    查询IP地址 nslookup最简单的用法是查询域名对应的IP地址,包括A记录.MX记录.NS记录CNAME记录. 查询A记录:nslookup 域名 查询MX记录:nslookup -q=mx 域名 ...

  6. 【Linux】利用Xvfb关闭chrome的图形化输出

    利用Xvfb关闭chrome的图形化输出 #!/bin/bash . /home/fzuir/.profile # JAVA export JAVA_HOME=/usr/local/jdk1.7.0_ ...

  7. Zabbix监控数据库连通性所遇问题

    Zabbix配合db2bp监控DB2数据库能否远程连接问题分析: 所遇问题,有时监控一直获取不到数据,原因是connect to连接超时了,zabbix默认监控脚本获取数据时间是3s,但最多支持30s ...

  8. 3. CNN卷积网络-反向更新

    1. CNN卷积网络-初识 2. CNN卷积网络-前向传播算法 3. CNN卷积网络-反向更新 1. 前言 如果读者详细的了解了DNN神经网络的反向更新,那对我们今天的学习会有很大的帮助.我们的CNN ...

  9. phpize的作用(资料整理)

    phpize的作用可以这样理解:侦测环境(phpize工具是在php安装目录下,基于这点phpize对应了当时的php环境,所以是要根据该php的配置情况生成对应的configure文件),建立一个c ...

  10. <[成长股基本面]【怎样选择成长股】>读书笔记

    书在这里 投资想赚大钱,必须有耐性 这家公司的产品或服务有没有充分的市场潜力,至少几年内营业额能否大幅成长? 为了进一步提高总体销售水平,发现新的产品增长点,管理层是不是决心继续开发新产品或新工艺? ...