2013-04-17 4 views
2

게임 엔진을 만들고 있습니다. Windows에서 공유 된 두 개의 컨텍스트가있는 두 개의 스레드가있었습니다 (wglShareLists 사용). 괜찮 았어. 한 스레드가 리소스를로드하는 동안 다른 스레드가 간단한로드 화면을 렌더링했습니다. Linux에는 WGL이없고 glX 만 있습니다. 나는 그것을 정확하게 사용하는 방법을 모른다. 현재 내 스레드 코드는 다음과 같습니다그래픽 콘텐츠로드 용 스레드

LinuxThread::LinuxThread() : 
    handle_(0), 
    running_(false), 
    task_(0), 
    useGraphicsContext_(0), 
    threadContext_(0), 
    threadDrawable_(0), 
    dsp_(0) 
{ 
} 

LinuxThread::~LinuxThread() { 
    finishTask(); 
    running_ = false; 
    glXDestroyContext(dsp_, threadContext_); 
} 

ULONG LinuxThread::getId() { 
    return static_cast<ULONG>(handle_); 
} 

void LinuxThread::start() { 
    running_ = true; 
    pthread_create(&handle_, 0, &LinuxThread::staticRun, (void*) this); 
} 

bool LinuxThread::isRunning() { 
    return running_; 
} 

void LinuxThread::setGraphicsContext(bool state) { 
    if (state) { 
     Display* dsp = XOpenDisplay(0); 
     threadDrawable_ = glXGetCurrentDrawable(); 
     GLint att[] = { GLX_RGBA, None }; 
     XVisualInfo* vi = glXChooseVisual(dsp, 0, att); 
     GLXContext glc = glXGetCurrentContext(); 
     bool directlyToScreen = true; // False for x-server display. 
     threadContext_ = glXCreateContext(dsp, vi, glc, directlyToScreen); 
    } 
    useGraphicsContext_ = state; 
} 

void LinuxThread::setTask(Task* task) { 
// if (useGraphicsContext_) { 
//  task->run(); 
//  delete task; 
//  return; 
// } 
    finishTask(); 
    task_ = task; 
} 

bool LinuxThread::hasTask() { 
    return task_ != 0; 
} 

void LinuxThread::finishTask() { 
    while (task_ != 0) { 
     usleep(1000); 
    } 
} 

void LinuxThread::stop() { 
    running_ = false; 
} 

void* LinuxThread::staticRun(void* thread) { 
    return (void*) ((LinuxThread*) thread)->run(); 
} 

int LinuxThread::run() { 
    while (running_) { 
     usleep(10000); 
     if (task_ != 0) { 
      if (useGraphicsContext_) { 
       glXMakeCurrent(dsp_, threadDrawable_, threadContext_); 
      } 
      task_->run(); 
      if (useGraphicsContext_) { 
       glFinish(); 
       glXMakeCurrent(dsp_, 0, 0); 
      } 
      delete task_; 
      task_ = 0; 
     } 
    } 
    return 1; 
} 

그것은이 같은 오류 메시지와 함께 충돌 : 내가 잘못 뭐하는 거지

nouveau: kernel rejected pushbuf: No such file or directory 
nouveau: ch6: krec 0 pushes 1 bufs 14 relocs 0 
nouveau: ch6: buf 00000000 00000002 00000006 00000006 00000000 
nouveau: ch6: buf 00000001 00000010 00000002 00000002 00000000 
nouveau: ch6: buf 00000002 0000000f 00000002 00000002 00000002 
nouveau: ch6: buf 00000003 0000000e 00000002 00000000 00000002 
nouveau: ch6: buf 00000004 00000007 00000002 00000002 00000002 
nouveau: ch6: buf 00000005 0000000a 00000002 00000002 00000000 
nouveau: ch6: buf 00000006 0000000b 00000002 00000002 00000000 

?

+0

"Windows에서 OpenGL 컨텍스트가있는 스레드가 하나 있습니다. 한 스레드가 리소스를로드하는 동안 다른 스레드가 간단한로드 화면을 렌더링하는 중이었습니다. *"그럴 필요가 없습니다. " 공유 리소스가있는 두 개의 컨텍스트가 없거나 동일한 컨텍스트가 동시에 두 개의 다른 스레드에 바인딩되지 않도록하는 시스템이 아닌 경우에는 아닙니다. –

+0

내 질문을 편집했습니다. – SMart

답변

1

특정 문제의 소스를 볼 수는 없지만 스레딩 코드는 많은 것을 복잡하게 만듭니다. 내가하고자 신발에서 :

  1. 당신이 누보 드라이버에서 문제를 타격하지하고 있는지 확인하기 위해 실행하기 전에 LIBGL_ALWAYS_SOFTWARE=y을 설정하십시오. (내부 메사 소프트웨어 렌더러를 사용합니다.)
  2. 공유 코드를 단일 스레드로 추출하고 작동하는지 확인한 다음 알려진 작업 코드를 최대한 간단하게 여러 스레드로 옮깁니다.