LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2096|回复: 15

简单的SDL程序,速度却非常慢

[复制链接]
发表于 2006-3-1 20:39:57 | 显示全部楼层 |阅读模式
像下面这种简单的程序,有明显的延迟,并且CPU占用100%,试输出timepass,30左右。如果用微软的Direct Draw在Windows下实现类似功能的程序,timepass一般在5以下。请问我的程序有什么问题吗?还是我的系统(如显卡驱动SDL驱动等)有问题?

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include "SDL/SDL.h"
  5. #include "SDL/SDL_image.h"

  6. #define TICK_INTERVAL    15

  7. int main(int argc, char *argv[]){
  8.         SDL_Surface *screen;
  9.         SDL_Surface *image;
  10.         SDL_Event event;
  11.         SDL_Rect r = {0,0,0,0};
  12.         int x=0,y=0;
  13.         char *file_name = "logofish.png";
  14.         int timepass=0, timeold=0;
  15.        
  16.         if(SDL_Init(SDL_INIT_VIDEO) < 0){
  17.                 printf("Could not initializing SDL: %s.\n",SDL_GetError());
  18.                 exit(-1);
  19.         }
  20.         atexit(SDL_Quit);
  21.         screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE|SDL_DOUBLEBUF);
  22.         if(screen == NULL){
  23.         fprintf(stderr, "Couldn't set 800x600x32 video mode: %s\n", SDL_GetError());
  24.         exit(1);
  25.         }
  26.        
  27.         image = IMG_Load(file_name);
  28.         if (image == NULL) {
  29.                 fprintf(stderr, "Couldn't load %s: %s\n", file_name, SDL_GetError());
  30.                 return 1;
  31.         }
  32.         while(1){
  33.                 while(SDL_PollEvent(&event)){
  34.                         switch(event.type){
  35.                                 case SDL_MOUSEMOTION:
  36.                                         x = event.motion.x; y = event.motion.y;
  37.                                         break;
  38.                                 case SDL_KEYDOWN:
  39.                                         switch(event.key.keysym.sym){
  40.                                                 case SDLK_UP:
  41.                                                         y -= 4;
  42.                                                         break;
  43.                                                 case SDLK_DOWN:
  44.                                                         y += 4;
  45.                                                         break;
  46.                                                 case SDLK_LEFT:
  47.                                                         x -= 4;
  48.                                                         break;
  49.                                                 case SDLK_RIGHT:
  50.                                                         x += 4;
  51.                                                         break;
  52.                                         }
  53.                                         break;
  54.                                 case SDL_QUIT:
  55.                                         exit(0);
  56.                                         break;
  57.                         }
  58.                         if(x < -image->w + 2) x = -image->w + 2;
  59.                         if(y < -image->h + 2) y = -image->h + 2;
  60.                         if(x > screen->w + image->w - 2) x = screen->w + image->w - 2;
  61.                         if(y > screen->h + image->h - 2) y = screen->h + image->h - 2;
  62.                         r.x = x;
  63.                         r.y = y;

  64.                         timeold = SDL_GetTicks();
  65.                        
  66.         //                SDL_FillRect(screen, NULL, 0);
  67.                         if(SDL_BlitSurface(image, NULL, screen, &r) < 0)
  68.                                 fprintf(stderr, "BlitSurface error: %s\n", SDL_GetError());
  69.                         SDL_Flip(screen);
  70.                         timepass = SDL_GetTicks() - timeold;
  71.         //                printf("%d  ", timepass);
  72.                         if(timepass < TICK_INTERVAL)
  73.                                 SDL_Delay(TICK_INTERVAL - timepass);
  74.                 }
  75.         }
  76.        
  77.         return 1;
  78. }
复制代码
发表于 2006-3-1 20:59:30 | 显示全部楼层
呵, 想试试都不行
回复 支持 反对

使用道具 举报

发表于 2006-3-1 20:59:30 | 显示全部楼层
呵, 想试试都不行
回复 支持 反对

使用道具 举报

发表于 2006-3-2 09:29:58 | 显示全部楼层
SDL_PollEvent()这个方法很耗CPU的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-3-2 12:12:39 | 显示全部楼层
Post by realtang
SDL_PollEvent()这个方法很耗CPU的。

应该不是这问题。因为我把SDL_Flip(screen);注释后,timepass只有3.问题应该在SDL_Flip(screen);

是不是没有用到硬件Flip?
回复 支持 反对

使用道具 举报

发表于 2006-3-2 12:22:22 | 显示全部楼层
顺便问一下:
有没有取消息队列, 如果没有消息, 就锁住直到有消息的函数?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-3-2 12:52:34 | 显示全部楼层
SDL_WaitEvent()
回复 支持 反对

使用道具 举报

发表于 2006-3-2 16:26:11 | 显示全部楼层
可能因为你的驱动不支持异步硬件Flip,所以SDL_Flip()这个方法是同步的,会耗用CPU等待垂直同步。最好不用。
fbdev提供了FBIO_WAITFORVSYNC的ioctl,等待垂直同步的时候会把当前进程挂起。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-3-2 21:28:30 | 显示全部楼层
Post by realtang
可能因为你的驱动不支持异步硬件Flip,所以SDL_Flip()这个方法是同步的,会耗用CPU等待垂直同步。最好不用。

可能是显卡驱动的问题吧。我没有安装ATI的官方驱动,而是使用系统自带的ATI驱动。如果不用这个Flip方法,有其它的方法吗?SDL_UpdateRect也是一样慢。
回复 支持 反对

使用道具 举报

发表于 2006-3-3 09:09:49 | 显示全部楼层
可恨的就是这个SDL_Flip()没有参数。建议你使用DirectFB的API,它和SDL很像的,而且可以在做Flip指定进行Idle等待,而不是像SDL这样的忙等待。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表