我正在尝试使用 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();
}
}