0

Google Native Client でレンダー ループを実装しようとしています。メイン スレッド以外のスレッドでは Pepper API 呼び出しを行うことができないことを認識しているため、以下を実装しようとしています。Module() -> DoGL_() で新しいスレッドを作成します -> DoGL() はメイン スレッドで Pepper API 呼び出しを使用して関数を呼び出します -> DoGL_() は別のスレッドで DoGL() を呼び出します。

私は Pepper 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();
    }
}
4

1 に答える 1

0

ここには多くの問題がありますが、主な概念に焦点を当てます: レンダー スレッドは必要なく、スワップ バッファーを使用してレンダー ループを駆動できます。

基本的なコンセプトは次のとおりです。

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

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

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

それでおしまい。SwapBuffers「適切な」時間にレンダリングする次の呼び出しをスケジュールします。

DoGLプログラムがクラッシュする理由については、さまざまな可能性があります。主な問題は、スタックが爆発するまで再帰的に呼び出すことだと思います。

于 2013-02-13T21:07:43.350 に答える