在Raspberry Pi 2上使用多线程进行SDL2渲染

时间:2017-06-14 13:47:24

标签: c multithreading opengl sdl-2

因此,我们试图在一个进程中构建一个带有抢占的实时系统,将每个任务作为一个单独的线程执行。为了构建GUI,SDL是选择的库,我们将GUI初始化与渲染分离,以便后者可以是一个不同的任务。尽管SDL本身有线程,但我们使用了pthreads。发现的信息是矛盾的,因为一些消息来源声称渲染不能在不同的过程中执行而其他人则说明不同。但是,使用带有Debian的虚拟机,渲染是正确执行的,但是在Raspberry Pi中这样做,通过改变主线程和渲染线程之间的上下文,SDL_GetError()不会返回错误,但不会渲染任何导致带光标的黑色窗口。重要的是要声明主线程内的呈现在Pi和虚拟机中都按预期工作。

为了解决这个问题,在Pi和SDL配置中使用了几种替代方案。关于Pi本身,使用sudo raspi-config,使用Full和Fake KMS来启用OpenGL不会出现不同的错误:

完整KMS - Could not initialize OpenGL / GLES library*

假KMS - * failed to add service - already in use?(键盘停止工作)。

禁用OpenGL (原点) - 没有错误,黑色窗口未渲染。

以下,代码按线程显示:

主线程:

SDL_Window* GUI_init(int w, int h) {
  if (SDL_Init(SDL_INIT_VIDEO) != 0) {
    fprintf(stderr, "Cannot initialise SDL: %s\n", SDL_GetError());
    exit(1);
  }

  window = SDL_CreateWindow(
    "Tron", 
    SDL_WINDOWPOS_CENTERED, 
    SDL_WINDOWPOS_CENTERED, 
    w, h,
    SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL
  );
  if (window == NULL) {
    fprintf(stderr, "Unable to create window: %s\n", SDL_GetError());
    exit(1);
  }

  globalRenderer = SDL_CreateRenderer(
    window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC
  );
  if (globalRenderer == NULL) {
    fprintf(stderr, "Unable to create renderer: %s\n", SDL_GetError());
    exit(1);
  }

  if (SDL_SetRenderDrawBlendMode(globalRenderer, SDL_BLENDMODE_BLEND) != 0) {
    fprintf(stderr, "SDL_BlendMode failed: %s\n", SDL_GetError());
    exit(1);
  };

  ctx = SDL_GL_CreateContext(window);
  if(ctx == NULL) {
    fprintf(stderr, "Unable to create context: %s\n", SDL_GetError());
    exit(1);
  }

  int ctx1 = SDL_GL_MakeCurrent(window,NULL);
  if(ctx1!=0) {
    fprintf(stderr, "Unable to make currents context: %s\n", SDL_GetError());
    exit(1);
  }

  //return globalRenderer;
  return window;
}

渲染线程:

void* GUI_update(void* params) {
  SDL_GL_MakeCurrent(window,ctx);

  GUI_setRenderDrawColor(globalRenderer);

  SDL_RenderClear(globalRenderer);

  GUI_fillBoardBorders(globalRenderer);
  GUI_fillBoard(globalRenderer);

  SDL_RenderPresent(globalRenderer);
}

使用3个全局变量:

SDL_Window *window = NULL;
SDL_GLContext ctx = NULL;
SDL_Renderer* globalRenderer = NULL;

我们使用Raspbian Jessie Lite作为操作系统。这可能是什么问题?

1 个答案:

答案 0 :(得分:1)

SDL_Renderer top-level documentation

  

此API不适用于多个线程,有关详细信息,请参阅SDL bug #1995

更多authoritatively

/**
 *  \file SDL_render.h
 *
 *  Header file for SDL 2D rendering functions.
 *
 *  This API supports the following features:
 *      * single pixel points
 *      * single pixel lines
 *      * filled rectangles
 *      * texture images
 *
 *  The primitives may be drawn in opaque, blended, or additive modes.
 *
 *  The texture images may be drawn in opaque, blended, or additive modes.
 *  They can have an additional color tint or alpha modulation applied to
 *  them, and may also be stretched with linear interpolation.
 *
 *  This API is designed to accelerate simple 2D operations. You may
 *  want more functionality such as polygons and particle effects and
 *  in that case you should use SDL's OpenGL/Direct3D support or one
 *  of the many good 3D engines.
 *
 *  These functions must be called from the main thread.
 *  See this bug for details: http://bugzilla.libsdl.org/show_bug.cgi?id=1995
 */

另外,不要试图使用OpenGL&一个SDL_RENDERER_ACCELERATED SDL_Renderer同时。 SDL_Renderer没有提供任何方法来保存/恢复它可能正在使用的OpenGL状态。