2017-06-14 40 views
1

因此,我們試圖在一個進程內建立一個搶佔式的實時系統,將每個任務作爲一個單獨的線程執行。爲了構建GUI,SDL是選擇的庫,我們將GUI初始化與渲染分開,以便後者可以是不同的任務。儘管SDL有自己的線程,但我們使用了pthreads。發現的信息是矛盾的,因爲一些消息來源指出渲染不能在不同的過程中執行,而另一些消息則另外聲明。但是,在Debian中使用虛擬機時,渲染已正確執行,但在Raspberry Pi中通過改變主線程和渲染線程之間的上下文來執行,SDL_GetError()不會返回錯誤,但不會呈現導致黑色窗口的任何內容一個遊標。說明主線程中的渲染在Pi和虛擬機中按照預期工作是很重要的。樹莓派上的多線程SDL2渲染2

爲了解決這個問題,在Pi和SDL配置中使用了幾種替代方案。關於皮本身,使用sudo raspi-config,完全和假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; 

我們e使用Raspbian Jessie Lite作爲操作系統。這裏可能是什麼問題?

+1

對於GUI庫來說,所有操作都必須在同一個線程中執行是非常典型的,我真的不認爲SDL在這裏是一個例外...... –

+0

大多數消息來源指出GUI庫不是線程安全的,但我覺得奇怪是它按照Debian的預期工作,而不是Raspbian,這讓我相信這是可行的。 –

+1

你可以隨時有東西沒有線程安全「工作」在意外 –

回答

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狀態。

+0

解決它,謝謝你,主線程它是。但是,如何解釋不同操作系統中的不同行爲? –

+0

@JoaoPereira:可能是由於SDL_Renderer後端的不同。 Win32具有DirectX,OpenGL和軟件後端,我認爲它默認爲DirectX。 – genpfault