sdl renderer window texture surface更新关系

方式1:

先创建窗口SDL_CreateWindow,从窗口得到表面SDL_GetWindowSurface,对surface操作,blitscale,blitsurface,loadimage等操作,然后调用SDL_UpdateWindowSurface(window);把对surface的操作反应到窗口

这里面没有render和texture


方式2:

创建窗口,渲染器renderer

创建surface,_sdlsurface_output = SDL_CreateRGBSurface(SDL_SWSURFACE, m_cfg.encwidth, m_cfg.encheight, 32, 0, 0, 0, 0);

根据渲染器和表面创建纹理 = SDL_CreateTextureFromSurface(m_sdlrenderer_pgm, m_sdlsurface_pgm);

对surface操作,blitscale,blitsurface,loadimage等操作

SDL_UpdateTexture(g_ptrMainWnd->m_sdltexture_pgm, &g_ptrMainWnd->m_sdldestrect_pgm, g_ptrMainWnd->m_sdlsurface_pgm->pixels, g_ptrMainWnd->m_sdlsurface_pgm->pitch);
  ret = SDL_RenderCopy(g_ptrMainWnd->m_sdlrenderer_pgm, g_ptrMainWnd->m_sdltexture_pgm, &g_ptrMainWnd->m_sdldestrect_pgm, &g_ptrMainWnd->m_sdldestrect_pgm);
  SDL_RenderPresent(g_ptrMainWnd->m_sdlrenderer_pgm);

方式3:

创建窗口,渲染器renderer,创建yuv420纹理

m_sdltexture_output = SDL_CreateTexture(m_sdlrenderer_output, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_TARGET,
  m_cfg.encwidth, m_cfg.encheight);

  SDL_UpdateYUVTexture(g_ptrMainWnd->m_sdltexture_pgm, &g_ptrMainWnd->m_ptrActList[chnIdx]->m_outputTun.rect,
   data_in[0], linesize_in[0],
   data_in[1], linesize_in[1],
   data_in[2], linesize_in[2]
  );
  
  SDL_RenderCopy(g_ptrMainWnd->m_sdlrenderer_pgm, g_ptrMainWnd->m_sdltexture_pgm, &g_ptrMainWnd->m_ptrActList[chnIdx]->m_outputTun.rect, &g_ptrMainWnd->m_sdldestrect_pgm);


直接用三个分量更新纹理,  SDL_UpdateYUVTexture这个函数里面本身有缩放功能,不需要考虑yuv的图像大小跟window/renderer大小不一致的问题,这个效率最高


texture,renderer是利用d3d,显存操作,速度较快。surface是内存操作,比较慢。如果是直接用yuv更新的texture,未使用到surface,那么surface中并不能代表当前windows的现状。相当于直接操作的显存。所以当你利用sdl_savebmp保存下来是黑屏。只能是利用SDL_RenderReadPixels来读取当前window的现状。但是不知道这个速度能有多快,因为文档中有句话/!\ WARNING: This is a very slow operation, and should not be used frequently.

即便提供了一个SDL_GetWindowSurface操作,你先调用这个得到surface再savebmp.也会是黑屏。原因上同。提供SDL_GetWindowSurface函数的用意并不是让你直接更新完window在取得surface指针。本意是想让你在更新窗口之前或者当时得到surface指针,利用surface在内存绘图,最后利用SDL_UpdateWindowSurface函数,把你绘制的surface更新到window上去,并不是让你反过来用的。


所以,高效的截图方法应该是用opengl,

void Screenshot(int x, int y, int w, int h, const char * filename)
{
    unsigned char * pixels = new unsigned char[w*h*4]; // 4 bytes for RGBA
    glReadPixels(x,y,w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

    SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(pixels, w, h, 8*4, w*4, 0,0,0,0);
    SDL_SaveBMP(surf, filename);

    SDL_FreeSurface(surf);
    delete [] pixels;
}


经过实际检测,SDL_RenderReadPixels的确是十分耗费时间,1920*1080分辨率,我循环执行了1000次,耗时15125ms,

1280*720执行1000次,耗时7983毫秒,564*320分辨率,执行1000次,耗时6583毫秒.

测试机配置i5-2400,8Gb Mem

所以,SDL_RenderReadPixels除非是执行单词的screenshot抓屏操作才可用。否则太耗时,没法用。


以上




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值