方式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等操作
ret = SDL_RenderCopy(g_ptrMainWnd->m_sdlrenderer_pgm, g_ptrMainWnd->m_sdltexture_pgm, &g_ptrMainWnd->m_sdldestrect_pgm, &g_ptrMainWnd->m_sdldestrect_pgm);
创建窗口,渲染器renderer,创建yuv420纹理
m_sdltexture_output = SDL_CreateTexture(m_sdlrenderer_output, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_TARGET,
m_cfg.encwidth, m_cfg.encheight);
data_in[0], linesize_in[0],
data_in[1], linesize_in[1],
data_in[2], linesize_in[2]
);
直接用三个分量更新纹理, 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抓屏操作才可用。否则太耗时,没法用。
以上