Board index » cppbuilder » OpenGl Texture sharing between main application and thread?

OpenGl Texture sharing between main application and thread?

Hi,

I developed a OpenGL component.
The display function is called from a thread, but I found out that
a texture created by the main application (such as when I push a button)
could not be rendered. The thread must create it from its callback functions
to render.
Is there any one who knows sharing textures between multiple processes etc.
There is lots of FAQ for sharing textures between different window contexts
but I only have one context, main application and a thread.

Thanks

Cagatay

 

Re:OpenGl Texture sharing between main application and thread?


An OpenGL render context can be current in only 1 thread at a time.
Therefore, you cannot make OpenGL calls in your GUI thread while your render
context is current in your render thread.

The solution to the problem is to "protect" the render context with a
critical section or a mutex as demonstrated in the following code snippets:

file://---------------------------------------------------------------------
------
// the render thread
DWORD WINAPI TOGLVRenderThread( void *param )
{
    TThreadedOpenGLView *w = (TThreadedOpenGLView *)param;
    return w->InternalRenderLoop();

Quote
}

file://---------------------------------------------------------------------
------
__fastcall TThreadedOpenGLView::TThreadedOpenGLView(TComponent* Owner)
    : TWinControl(Owner)
{
    // ... lot's of initialization stuff removed for clarity
    InitializeCriticalSection( &m_RCMutex );
Quote
}

file://---------------------------------------------------------------------
------
DWORD TThreadedOpenGLView::InternalRenderLoop()
{
    DoInitRenderLoop();

    while ( m_KeepLooping )
    {
        DoRenderLoop();
    }

    return 0;

Quote
}

file://---------------------------------------------------------------------
------
// set this panel up for OpenGL rendering
void __fastcall TThreadedOpenGLView::CreateWnd(void)
{
    TWinControl::CreateWnd();

        // disable floating point exceptions
        // Create a device context for OpenGL rendering.
        // set pixel format descriptor
        // This function creates the OpenGL rendering context
        m_hRC = wglCreateContext( m_hDC );
        if ( m_hRC == NULL )
        {
            throw Exception( "OpenGL Error - Could not make rendering
context" );
        }

        // create a thread for the render loop
        m_RenderThread = CreateThread( NULL, 0, TOGLVRenderThread, (void
*)this,
                                   0, &m_RenderThreadID );
        if ( m_RenderThread == NULL )
        {
            throw Exception("Failed to create render thread");
        }

        m_Initialized = true;

Quote
}

file://---------------------------------------------------------------------
------
void __fastcall TThreadedOpenGLView::DoInitRenderLoop(void)
{
    if ( m_Initialized )
    {
        LockRC();

// call any OpenGL initialization functions here

        FreeRC();
    }

Quote
}

file://---------------------------------------------------------------------
------
void __fastcall TThreadedOpenGLView::DoRenderLoop(void)
{
    if ( m_Initialized && LockRC() )
    {
//     call any OpenGL rendering functions here
        FreeRC();
    }

Quote
}

file://---------------------------------------------------------------------
------
// this function waits for an object to release the RC critical section,
makes the OpenGL
// rendering context current, and then returns a true
bool __fastcall TThreadedOpenGLView::LockRC()
{
    EnterCriticalSection( &m_RCMutex );

    // try to make the RC current in this thread
    if ( wglMakeCurrent( m_hDC, m_hRC ) )
    {
        return true;
    }
    // release the critical sectionand return an error code if the RC could
not be
    // made current
    else
    {
        LeaveCriticalSection( &m_RCMutex );
        return false;
    }

Quote
}

file://---------------------------------------------------------------------
------
void __fastcall TThreadedOpenGLView::FreeRC()
{
    wglMakeCurrent( m_hDC, NULL );
    LeaveCriticalSection( &m_RCMutex );

Quote
}

file://---------------------------------------------------------------------
------
void __fastcall TThreadedOpenGLView::WMDestroy( TMessage &msg )
{
      // kill the render loop thread
      m_KeepLooping = false;

      WaitForSingleObject( m_RenderThread, 5000 );

      DeleteCriticalSection( &m_RCMutex );

      // clean up OpenGL stuff
      wglMakeCurrent( NULL, NULL );
      wglDeleteContext( m_hRC );
      ReleaseDC( Handle, m_hDC );
    }

Quote
}

Now, if you want to call OpenGL functions from a GUI thread:

file://---------------------------------------------------------------------
------
void __fastcall TThreadedOpenGLView::SomeGUIFunction( )
{
    LockRC();
    // call OpenGL functions here
   FreeRC();

Quote
}

--
Regards,
Scott
http://members.cox.net/scottheiman/
(a valid e-mail address can be found on my home page)

Re:OpenGl Texture sharing between main application and thread?


With that method will the texture created by the GUI function be used by the
thead also?
I mean texture will be created from GUI, but the thead will use it for
displaying.

Thank you very much,

Cagatay

Quote
Scott Heiman <addr...@home.page> wrote in message news:3c80d07c$1_1@dnews...
> An OpenGL render context can be current in only 1 thread at a time.
> Therefore, you cannot make OpenGL calls in your GUI thread while your
render
> context is current in your render thread.

> The solution to the problem is to "protect" the render context with a
> critical section or a mutex as demonstrated in the following code
snippets:

file://---------------------------------------------------------------------
Quote
> ------
> // the render thread
> DWORD WINAPI TOGLVRenderThread( void *param )
> {
>     TThreadedOpenGLView *w = (TThreadedOpenGLView *)param;
>     return w->InternalRenderLoop();
> }

file://---------------------------------------------------------------------
Quote
> ------
> __fastcall TThreadedOpenGLView::TThreadedOpenGLView(TComponent* Owner)
>     : TWinControl(Owner)
> {
>     // ... lot's of initialization stuff removed for clarity
>     InitializeCriticalSection( &m_RCMutex );
> }

file://---------------------------------------------------------------------
Quote
> ------
> DWORD TThreadedOpenGLView::InternalRenderLoop()
> {
>     DoInitRenderLoop();

>     while ( m_KeepLooping )
>     {
>         DoRenderLoop();
>     }

>     return 0;
> }

file://---------------------------------------------------------------------
Quote
> ------
> // set this panel up for OpenGL rendering
> void __fastcall TThreadedOpenGLView::CreateWnd(void)
> {
>     TWinControl::CreateWnd();

>         // disable floating point exceptions
>         // Create a device context for OpenGL rendering.
>         // set pixel format descriptor
>         // This function creates the OpenGL rendering context
>         m_hRC = wglCreateContext( m_hDC );
>         if ( m_hRC == NULL )
>         {
>             throw Exception( "OpenGL Error - Could not make rendering
> context" );
>         }

>         // create a thread for the render loop
>         m_RenderThread = CreateThread( NULL, 0, TOGLVRenderThread, (void
> *)this,
>                                    0, &m_RenderThreadID );
>         if ( m_RenderThread == NULL )
>         {
>             throw Exception("Failed to create render thread");
>         }

>         m_Initialized = true;
> }

file://---------------------------------------------------------------------
Quote
> ------
> void __fastcall TThreadedOpenGLView::DoInitRenderLoop(void)
> {
>     if ( m_Initialized )
>     {
>         LockRC();

> // call any OpenGL initialization functions here

>         FreeRC();
>     }
> }

file://---------------------------------------------------------------------
Quote
> ------
> void __fastcall TThreadedOpenGLView::DoRenderLoop(void)
> {
>     if ( m_Initialized && LockRC() )
>     {
> //     call any OpenGL rendering functions here
>         FreeRC();
>     }
> }

file://---------------------------------------------------------------------

- Show quoted text -

Quote
> ------
> // this function waits for an object to release the RC critical section,
> makes the OpenGL
> // rendering context current, and then returns a true
> bool __fastcall TThreadedOpenGLView::LockRC()
> {
>     EnterCriticalSection( &m_RCMutex );

>     // try to make the RC current in this thread
>     if ( wglMakeCurrent( m_hDC, m_hRC ) )
>     {
>         return true;
>     }
>     // release the critical sectionand return an error code if the RC
could
> not be
>     // made current
>     else
>     {
>         LeaveCriticalSection( &m_RCMutex );
>         return false;
>     }
> }

file://---------------------------------------------------------------------
Quote
> ------
> void __fastcall TThreadedOpenGLView::FreeRC()
> {
>     wglMakeCurrent( m_hDC, NULL );
>     LeaveCriticalSection( &m_RCMutex );
> }

file://---------------------------------------------------------------------

- Show quoted text -

Quote
> ------
> void __fastcall TThreadedOpenGLView::WMDestroy( TMessage &msg )
> {
>       // kill the render loop thread
>       m_KeepLooping = false;

>       WaitForSingleObject( m_RenderThread, 5000 );

>       DeleteCriticalSection( &m_RCMutex );

>       // clean up OpenGL stuff
>       wglMakeCurrent( NULL, NULL );
>       wglDeleteContext( m_hRC );
>       ReleaseDC( Handle, m_hDC );
>     }
> }

> Now, if you want to call OpenGL functions from a GUI thread:

file://---------------------------------------------------------------------

- Show quoted text -

Quote
> ------
> void __fastcall TThreadedOpenGLView::SomeGUIFunction( )
> {
>     LockRC();
>     // call OpenGL functions here
>    FreeRC();
> }

> --
> Regards,
> Scott
> http://members.cox.net/scottheiman/
> (a valid e-mail address can be found on my home page)

Re:OpenGl Texture sharing between main application and thread?


That depends upon your implementation.

Typically, I will open an image file in the GUI thread, parse the pixel data
and put it into the format that OpenGL supports, and use gluScaleImage to
resize the image if necessary.

I use the folowing code snippet in the render loop to display the texture:

   // MakeTexture is set to true in the GUI thread that opens an image file
    if ( MakeTexture )
    {
        MakeTexture = false;
        if ( HasTexture )
            glDeleteTextures( 1, &texname );
        HasTexture = true;
        glGenTextures( 1, &texname );
        glBindTexture( GL_TEXTURE_2D, texname );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
// following calls "smear" small bitmaps
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_LINEAR );
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR );
        glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height,
                      0, GL_RGBA, GL_UNSIGNED_BYTE, bits );
    }

    if ( HasTexture )
    {
        glBindTexture( GL_TEXTURE_2D, texname );
        for ( int i = 0; i < 70; i++ )
        {
            glBegin( GL_QUAD_strip );
                for ( int j = 0; j < 71; j++ )
                {
                    glTexCoord2fv( uv[i][j] );
                    glVertex3fv( xyz[i][j] );
                    glTexCoord2fv( uv[i+1][j] );
                    glVertex3fv( xyz[i+1][j] );
                }
            glEnd();
        }
    }
    else
    {
        for ( int i = 0; i < 70; i++ )
        {
            glBegin( GL_QUAD_strip );
                for ( int j = 0; j < 71; j++ )
                {
                    glVertex3fv( xyz[i][j] );
                    glVertex3fv( xyz[i+1][j] );
                }
            glEnd();
        }
    }

--
Regards,
Scott
http://members.cox.net/scottheiman/
(a valid e-mail address can be found on my home page)

Other Threads