(原)关于sdl在部分机器上做视频显示,改变显示窗口大小会崩溃
今天测试人员反应,之前做的视频绘图显示,会在她机器上,会出现崩溃现象,最后我在她机器上对代码进行跟踪,发现在某种情况,确实会崩溃。
最主要的原因是,视频显示窗口变成非活动窗口的时候,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在部分机器上做视频显示,改变显示窗口大小会崩溃的更多相关文章
- [原]在AMD机器上使用android studio
		
amd机器上使用android studio进行调试.因为amd的cpu不支持IntelVT,所以可能会有如下错误提示 我们有几个选择: 1. 使用真机调试 2. 配合genymotion 3. ...
 - 关于LogStash运行在AIX 64位机器上的问题与临时解决方案
		
需求;logstash运行在SUSE,LINUX,PPC LINUX,AIX机器上,并监控文件发送日志到KAFKA中去, 问题:在AIX机器上,file插件总是报异常,无法完成数据的读取 NotImp ...
 - 配置hooks使svn提交后自动同步客户端代码(客户端与服务端在同一台机器上)
		
1.配置svn的hooks 2.实例演示 1.配置svn的hooks 1.1)配置情况 承接上篇svn搭建的文章,今次继续使用上篇文章的配置 上篇文章的地址:linux下搭建svn代码库 svn仓库所 ...
 - 大数据架构-使用HBase和Solr将存储与索引放在不同的机器上
		
大数据架构-使用HBase和Solr将存储与索引放在不同的机器上 摘要:HBase可以通过协处理器Coprocessor的方式向Solr发出请求,Solr对于接收到的数据可以做相关的同步:增.删.改索 ...
 - 用pf透明地将流量从一台机器转到另一台机器上的缘起及实现方式对比
		
下面是也是我在12580工作时发生的事情,重新记录并发出来.这种特殊需求很考 验PF的功底.在新旧系统并存,做重构的时候有时很需要这种救急的作法.一.缘起miscweb1(172.16.88.228) ...
 - Shell获取Aix/linux/unix机器上db2和os的信息并上传到指定服务器
		
(之前写过一篇类似的文章,当时传输文件用的是ftp,因为项目觉得ftp不够安全所以这次换成了scp,同时对脚本的一些地方也做了一些调整) 其实做这个东西还是因为项目的需求,需要获取某些机器(目前主要是 ...
 - mapreduce (五) MapReduce实现倒排索引 修改版 combiner是把同一个机器上的多个map的结果先聚合一次
		
(总感觉上一篇的实现有问题)http://www.cnblogs.com/i80386/p/3444726.html combiner是把同一个机器上的多个map的结果先聚合一次现重新实现一个: 思路 ...
 - mapreduce (二) MapReduce实现倒排索引(一) combiner是把同一个机器上的多个map的结果先聚合一次
		
1 思路:0.txt MapReduce is simple1.txt MapReduce is powerfull is simple2.txt Hello MapReduce bye MapRed ...
 - Detours简介 (拦截x86机器上的任意的win32 API函数)
		
Detours 当然是用detours,微软明显高腾讯一筹,同上,至今没失败过.写这种HOOK一定要再写个测试程序,不要直接HOOK你的目的程序,例如QQ,因为这样不方面更灵活的测试.说明一下:Det ...
 
随机推荐
- (转)用stunnel给普通http通信加密
			
转自:https://www.digitalocean.com/community/tutorials/how-to-set-up-an-ssl-tunnel-using-stunnel-on-ubu ...
 - Leetcode:Flatten Binary Tree to Linked List  解题报告
			
Flatten Binary Tree to Linked List Given a binary tree, flatten it to a linked list in-place. For ex ...
 - git 常用命令以及解决问题方法
			
1. 创建分支: git branch test 2.切换分支: git checkout test 或切换为主分支 git checkout master 3.查看当前分支 git branch - ...
 - 【Turing Award】Robin Milner And Butler W. Lampson
			
1991 罗宾·米尔纳(Robin Milner) Robin Milner(13 January 1934 – 20 March 2010) Introduction : Milner was bo ...
 - idea 在tomcat中部署的时候 莫名其妙的错误
			
针对web项目需要 打成 war exploded 包,这样就不会每次重新构建打包,也不会出现莫名其妙的错误
 - jetty  6.1 笔记
			
download: http://dist.codehaus.org/jetty/jetty-6.1.22/ jetty 6.2 代码启动 必要jar包 lib --->> lib---& ...
 - BaseRecyclerViewAdapterHelper使用
			
Reference: https://www.jianshu.com/p/1e20f301272e 一.框架引入 先在项目的 build.gradle(Project:XXXX) 的 reposito ...
 - 【计算机网络基础】TCP/IP、HTTP、Socket的概念
			
TCP/IP协议是一个协议簇.里面包括很多协议的.UDP也是其中的一个.之所以命名为TCP/IP协议,因为TCP,IP协议是两个很重要的协议,就用他两命名了.(资料来源: http://www.cnb ...
 - WPF重写Button样式
			
首先指定OverridesDefaultStyle属性为True: 然后添加样式: 重写ControlTemplate: <Window.Resources> <Style x:Ke ...
 - html绝对路径与相对路径
			
文件,图片和html文档同一个目录的直接写文件名即可(相对路径). 工作中一般使用相对路径,项目放到服务器上部署不能保证绝对路径不出错.