2013-04-17 3 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

«* В окнах у меня был один поток с контекстом OpenGL. Он работал нормально. В то время как один поток загружал ресурсы, другой отображал простой экран загрузки. *« Этого не должно было «отлично работать». Если только у вас не было двух контекстов с общими ресурсами или какой-либо системой, которая гарантирует, что один и тот же контекст не связан одновременно с двумя разными потоками. –

+0

Я отредактировал мой вопрос. – SMart

ответ

1

Я не вижу конкретного источника проблем, но код многопоточности усложняет ситуацию. В вашей обуви, я бы:

  1. Попробуйте установить LIBGL_ALWAYS_SOFTWARE=y перед запуском, чтобы убедиться, что вы не ударять проблемы в драйвере нуво. (Это будет использовать внутренний рендеринг программного обеспечения Mesa Software.)
  2. Извлеките свой код совместного доступа в один поток, убедитесь, что он работает, а затем переместите известный рабочий код обратно в несколько потоков как можно проще.