2013-02-03 23 views
0

我試圖實現與谷歌本地客戶端的渲染循環,我知道你不能在除主線程之外的任何線程上進行Pepper API調用,所以我試圖執行以下操作。使用DoGL_() - > DoGL()調用函數使用Pepper API調用函數在主線程上調用函數 - > DoGL_()仍然在單獨的線程上調用DoGL()。谷歌本地客戶端渲染循環

我試圖用胡椒19做到這一點,我真的不知道有關線程來解決這個問題。現在模塊崩潰了。

這裏是我的代碼(不漂亮,我只是試圖讓苦差事碼的方式進行):

DoGL.h

#include "Include.h" 



class Context : public pp::Graphics3DClient 
{ 
    pp::Size size; 
    bool init_; 
    const struct PPB_OpenGLES2 *gles2Interface; 
    public: 
     Context(pp::Instance *instance); 
     ~Context(); 
     virtual void Graphics3DContextLost() { 
     } 
     bool MakeCurrentContext(pp::Instance *instance); 
     void FlushContext(); 
     pp::Graphics3D context; 
     void (*callback) (void*, int32_t); 
     pp::Instance *ppinstance; 
     PPB_Graphics3D* ppb_g3d_interface; 
     GLuint programObject; 
     GLuint LoadShader(const char *shaderSrc, GLenum type); 
     GLuint Init(); 
     void Draw(); 
     void DoGL(); 
     void GLDebug(std::string msg = ""); 
     static void FillIn(void* v, int32_t i) { 
     } 
     pp::Core *ppb_core_interface; 
}; 

static Context *cjcontext; 
void* DoGL_(void* p) { 
    cjcontext->DoGL(); 
} 
void Init_(void *p, int32_t i) { 
    cjcontext->Init(); 
} 
void Draw_(void *p, int32_t i) { 
    cjcontext->Draw(); 
} 
void MakeContext_(void *p, int32_t i) { 
    cjcontext->ppinstance->PostMessage("Called on the main thread!!!!\n"); 
    cjcontext->MakeCurrentContext(cjcontext->ppinstance); 
} 
void FlushContext_(void *p, int32_t i) { 
    cjcontext->FlushContext(); 
} 

DoGL.cpp

#include "DoGL.h" 
Context::Context(pp::Instance *instance) : pp::Graphics3DClient(instance) 
{ 
    pp::Module *module = pp::Module::Get(); 
    gles2Interface = static_cast< const struct PPB_OpenGLES2 * > (module->GetBrowserInterface(PPB_OPENGLES2_INTERFACE)); 
    init_ = false; 
} 
Context::~Context() { 
    glSetCurrentContextPPAPI(0); 
} 
bool Context::MakeCurrentContext(pp::Instance *instance) 
{ 
    //Is somthing broken?// 
    if(instance == NULL) { 
     glSetCurrentContextPPAPI(0); 
     return (false); 
    } 
    if(context.is_null() == true) 
    { 
     //OpenGL attributes.// 
     int32_t attribs[] = 
     { 
      PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8, 
      PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24, 
      PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 8, 
      PP_GRAPHICS3DATTRIB_SAMPLES, 0, 
      PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0, 
      PP_GRAPHICS3DATTRIB_WIDTH, 500, 
      PP_GRAPHICS3DATTRIB_HEIGHT, 500, 
      PP_GRAPHICS3DATTRIB_NONE /*Terminate list.*/ 
     }; 
     context = pp::Graphics3D(instance, pp::Graphics3D(), attribs); 
     if (context.is_null() == true) { 
      glSetCurrentContextPPAPI(0); 
      return (false); 
     } 
     instance->BindGraphics(context); 
    } 
    //Get the context.// 
    glSetCurrentContextPPAPI(context.pp_resource()); 
    glViewport(0, 0, 500, 500); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    return true; 
} 
void Context::FlushContext() 
{ 
    //Make sure that the flush is not pending.// 
    for(unsigned int wait = 0; wait < 1001; ++wait); 
    context.SwapBuffers(pp::CompletionCallback(FillIn, ((void*) this))); 
} 

GLuint Context::LoadShader(const char *shaderSrc, GLenum type) 
{ 
    GLuint shader; 
    GLint compiled; 
    //Create the shader object.// 
    shader = glCreateShader(type); 
    if(shader == 0) { 
     return 0; 
    } 
    //Load the shader source.// 
    glShaderSource(shader, 1, &shaderSrc, NULL); 
    //Compile the shader.// 
    glCompileShader(shader); 
    //Check the compile status.// 
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 
    return shader; 
} 

GLuint Context::Init() 
{ 
    const char* vShaderStr = 
     "#version 100    \n" 
     "attribute vec4 vPosition; \n" 
     "void main()     \n" 
     "{       \n" 
     " gl_Position = vPosition; \n" 
     "}       \n"; 
    const char* fShaderStr = 
     "#version 100        \n" 
     "precision mediump float;     \n" 
     "void main()        \n" 
     "{           \n" 
     " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n" 
     "}           \n"; 
    GLuint vertexShader; 
    GLuint fragmentShader; 
    GLint linked; 
    //Load the vertex/fragment shaders.// 
    vertexShader = LoadShader(vShaderStr, GL_VERTEX_SHADER); 
    fragmentShader = LoadShader(fShaderStr, GL_FRAGMENT_SHADER); 
    //Create the program object.// 
    programObject = glCreateProgram(); 
    if(programObject == 0) { 
     return 0; 
    } 
    glAttachShader(programObject, vertexShader); 
    glAttachShader(programObject, fragmentShader); 
    //Bind vPosition to attribute 0.// 
    glBindAttribLocation(programObject, 0, "vPosition"); 
    //Link the program.// 
    glLinkProgram(programObject); 
    //Check the link status.// 
    glGetProgramiv(programObject, GL_LINK_STATUS, &linked); 
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 
    return programObject; 
} 


void Context::Draw() 
{ 
    ppinstance->PostMessage("Drawing!"); 
    GLfloat scaler = 1.f; 
    GLfloat vVertices[] = 
    { 
     0.0f, (scaler * 0.5f), 0.0f, 
     (scaler * -0.5f), (scaler * -0.5f), 0.0f, 
     (scaler * 0.5f), (scaler * -0.5f), 0.0f 
    }; 
    ++scaler; 
    ppinstance->PostMessage("Scaler"); 
    ppinstance->PostMessage(scaler); 
    //Set the viewport. 
    glViewport(0, 0, 500, 500); 
    //Clear the color buffer.// 
    glClear(GL_COLOR_BUFFER_BIT); 
    //Use the program object.// 
    glUseProgram(programObject); 
    //Load the vertex data.// 
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vVertices); 
    glEnableVertexAttribArray(0); 
    glDrawArrays(GL_TRIANGLES, 0, 3); 
} 

void Context::DoGL() 
{ 
    if(init_ == false) 
    { 
     pp::CompletionCallback cc; 
     //ppinstance->PostMessage("Init is false."); 
     cjcontext->MakeCurrentContext(ppinstance); 
     for(int i = 0; i < 10001; ++i); 
     cc = pp::CompletionCallback(&Init_, 0, 0); 
     ppb_core_interface->CallOnMainThread(0, cc, 0); 
     init_ = true; 
     cjcontext->FlushContext(); 
    } 
    pp::CompletionCallback cc; 
    for(int i = 0; i < 101; ++i); 
    cc = pp::CompletionCallback(&MakeContext_, 0, 0); 
    ppb_core_interface->CallOnMainThread(0, cc, 0); 
    for(int i = 0; i < 101; ++i); 
    cc = pp::CompletionCallback(&Draw_, 0, 0); 
    ppb_core_interface->CallOnMainThread(0, cc, 0); 
    for(int i = 0; i < 101; ++i); 
    cc = pp::CompletionCallback(&FlushContext_, 0, 0); 
    ppb_core_interface->CallOnMainThread(0, cc, 0); 
    void *p; 
    DoGL_(p); 
} 

pthread_t reanderHandle; 
int threadStatus; 

//Standard NaCl chore code.// 
class CubeJumpInstance : public pp::Instance 
{ 
    public: 
     explicit CubeJumpInstance(PP_Instance instance) : pp::Instance(instance) { 
      PostMessage("Instance create.\n"); 
     } 
     virtual ~CubeJumpInstance() { 
      PostMessage("Instance destroyed.\n"); 
     } 
}; 

class CubeJumpModule : public pp::Module 
{ 
    public: 
     CubeJumpModule() : pp::Module() { 
     } 
     virtual ~CubeJumpModule() { 
      glTerminatePPAPI(); 
     } 
     virtual pp::Instance* CreateInstance(PP_Instance instance) 
     { 
      glInitializePPAPI(get_browser_interface()); 
      pp::Instance *instance_ = new CubeJumpInstance(instance); 
      cjcontext = new Context(instance_); 
      cjcontext->ppinstance = instance_; 
      cjcontext->ppb_core_interface = this->core(); 
      threadStatus = pthread_create(&reanderHandle, 0, DoGL_, 0); 
      cjcontext->ppinstance->PostMessage("Instace done.\n"); 
      //pthread_join(reanderHandle, 0); 
      return cjcontext->ppinstance; 
     } 
}; 

namespace pp 
{ 
    pp::Module* CreateModule() { 
     return new CubeJumpModule(); 
    } 
} 

回答

0

這裏有很多問題,我將重點介紹主要概念: 您不需要渲染線程,只需使用交換緩衝區來驅動渲染循環。

的基本概念是:

// do this to kick things off 
CallOnMainThread(Render) 

Render() 
    if (!init) 
     Init(); 

    MakeContext(); 
    Draw(); 
    SwapBuffers(Render); 

就是這樣。 SwapBuffers將安排下一次呼叫在「正確」時間呈現。至於爲什麼你的程序崩潰,它可能是任何數量的東西,我猜你的主要問題是遞歸調用DoGL,直到你的堆棧爆炸。