bool StGLStereoFrameBuffer::initLazy(StGLContext&  theCtx,
                                     const GLsizei theSizeX,
                                     const GLsizei theSizeY,
                                     const bool    theNeedDepthBuffer,
                                     const bool    theToCompress) {
    if(isValid()
    && (theSizeX <= getSizeX() && getSizeX() < theCtx.getMaxTextureSize())
    && (theSizeY <= getSizeY() && getSizeY() < theCtx.getMaxTextureSize())) {
        if(!theToCompress
        || (((getSizeX() - theSizeX) < 256)
        &&  ((getSizeY() - theSizeY) < 256))) {
            setVPDimensions(theCtx, theSizeX, theSizeY);
            return true;
        }
    }
    release(theCtx);

    GLsizei aSizeX = stMax(32, (GLsizei )getAligned(theSizeX, 256));
    GLsizei aSizeY = stMax(32, (GLsizei )getAligned(theSizeY, 256));
    if(!theCtx.arbNPTW) {
        StGLFrameBuffer::convertToPowerOfTwo(theCtx, aSizeX, aSizeY);
    }

    if(!init(theCtx, aSizeX, aSizeY, theNeedDepthBuffer)) {
        return false;
    }

    theCtx.stglFillBitsFBO(myGLFBufferIds[StGLStereoTexture::LEFT_TEXTURE], aSizeX, aSizeY);
    ST_DEBUG_LOG("FBO resized to " + aSizeX + " x " + aSizeY + " (for " + theSizeX + " x " + theSizeY + ")");

    setVPDimensions(theCtx, theSizeX, theSizeY);
    return true;
}
Esempio n. 2
0
bool StGLFontEntry::createTexture(StGLContext& theCtx) {
    const GLint aMaxSize = theCtx.getMaxTextureSize();

    GLint aGlyphsNb = 0;
    if(myFont->hasCJK()
    || myFont->hasKorean()) {
        // italic does not make sense for Chinese
        // limit overall number of glyphs in the single texture to 4k
        // (single font file might contain about 20k-50k glyphs)
        aGlyphsNb = stMin(4000, 2 * myFont->getGlyphsNumber() - GLint(myLastTileId) + 1);
    } else {
        // western might contain reg/bold/italic/bolditalic styles
        // limit overall number of glyphs in the single texture to 1k
        // (single font file might contain about 6k glyphs for different languages)
        aGlyphsNb = stMin(1000, 4 * myFont->getGlyphsNumber() - GLint(myLastTileId) + 1);
    }

    const GLsizei aTextureSizeX = getPowerOfTwo(aGlyphsNb * myTileSizeX, aMaxSize);
    const size_t  aTilesPerRow  = aTextureSizeX / myTileSizeX;
    GLsizei aTextureSizeY = stMin(getEvenNumber(GLint((aGlyphsNb / aTilesPerRow) + 1) * myTileSizeY), aMaxSize);
    if(!theCtx.arbNPTW) {
        aTextureSizeY = getPowerOfTwo(aTextureSizeY, aMaxSize);
    }

    stMemZero(&myLastTilePx, sizeof(myLastTilePx));
    myLastTilePx.bottom() = myTileSizeY;

    myTextures.add(new StGLTexture(theCtx.arbTexRG ? GL_R8 : GL_ALPHA));
    myFbos.add(new StGLFrameBuffer());
    StHandle<StGLTexture>&     aTexture = myTextures[myTextures.size() - 1];
    StHandle<StGLFrameBuffer>& aFbo     = myFbos    [myTextures.size() - 1];
    if(!aTexture->initTrash(theCtx, aTextureSizeX, aTextureSizeY)) {
        return false;
    }
    aTexture->bind(theCtx);
    theCtx.core11fwd->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    theCtx.core11fwd->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    aTexture->unbind(theCtx);

    // destruction of temporary FBO produces broken texture on Catalyst drivers for unknown reason
    //StGLFrameBuffer::clearTexture(theCtx, aTexture);
#if !defined(GL_ES_VERSION_2_0)
    if(theCtx.arbTexClear) {
        theCtx.core11fwd->glPixelStorei(GL_UNPACK_LSB_FIRST,  GL_FALSE);
        theCtx.core11fwd->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
        theCtx.core11fwd->glPixelStorei(GL_UNPACK_ALIGNMENT,  1);
        const stUByte_t THE_BLACK = 0;
        theCtx.extAll->glClearTexImage(aTexture->getTextureId(), 0, theCtx.arbTexRG ? GL_RED : GL_ALPHA, GL_UNSIGNED_BYTE, &THE_BLACK);
    } else if(aFbo->init(theCtx, aTexture, false)) {
        aFbo->clearTexture(theCtx);
    } else {
        ST_ERROR_LOG("Fail to bind " + (theCtx.arbTexRG ? "GL_R8" : "GL_ALPHA8") + " texture to FBO!");
    }
#else
    (void )aFbo;
#endif

    return true;
}
Esempio n. 3
0
void StGLProjCamera::resize(StGLContext&  theCtx,
                            const GLsizei theSizeX,
                            const GLsizei theSizeY) {
    const GLsizei aSizeY = (theSizeY > 0) ? theSizeY : 1;
    myAspect = GLfloat(theSizeX) / GLfloat(aSizeY);

    theCtx.stglResizeViewport(theSizeX, aSizeY); // reset the current viewport
    updateFrustum();
}
Esempio n. 4
0
// this function called ONLY from plugin thread
bool StGLTextureQueue::stglUpdateStTextures(StGLContext& theCtx) {
    int aSwapState = swapFBOnReady(theCtx);
    if(aSwapState == SWAPONREADY_WAITLIM) {
        return false;
    }

    if(!myMutexPop.tryLock()) {
        return aSwapState == SWAPONREADY_SWAPPED;
    }

    // do we already in update cycle?
    if(!myIsInUpdTexture) {
        // check event from video thread
        if(!isEmpty()) {
            myIsInUpdTexture = true;
        }
    } else if(isEmpty()) {
        // if we in texture update sequence - check queue not emptied!
        myIsInUpdTexture = false;
    }

    // still nothing to update? so return
    if(!myIsInUpdTexture) {
        myMutexPop.unlock();
        return aSwapState == SWAPONREADY_SWAPPED;
    }

    if(!theCtx.isBound()
    || myDataFront->fillTexture(theCtx, myQTexture)) {
        myIsReadyToSwap = true;
        myMutexSize.lock();
            myCurrPts   = myDataFront->getPTS();
            myDataSnap  = myDataFront; myNewShotEvent.set();
            if(myToCompress) {
                myDataFront->reset();
            }
            myDataFront = myDataFront->getNext();
            ST_DEBUG_ASSERT(myQueueSize != 0); // critical error!
            --myQueueSize;
        myMutexSize.unlock();
        myIsInUpdTexture = false;
    }
    myMutexPop.unlock();

    // try early swap
    const bool isAlreadySwapped = (aSwapState == SWAPONREADY_SWAPPED);
    aSwapState = swapFBOnReady(theCtx);
    return (aSwapState == SWAPONREADY_SWAPPED || isAlreadySwapped);
}
Esempio n. 5
0
bool StGLProgram::link(StGLContext& theCtx) {
    if(!isValid()) {
        return false;
    }
    theCtx.core20fwd->glLinkProgram(myProgramId);

    // if linkage failed - automatically remove the program!
    if(!isLinked(theCtx)) {
        theCtx.pushError(StString("Linking of the program '") + myTitle + "' failed!\n" + getLinkageInfo(theCtx));
        release(theCtx);
        return false;
    }
#ifdef __ST_DEBUG_SHADERS__
    const StString anInfo = getLinkageInfo(theCtx);
    ST_DEBUG_LOG("Program '" + myTitle + "' has been linked"
              + (!anInfo.isEmpty() ? (StString(". Log:\n") + anInfo) : (StString())));
#endif
    return true;
}
Esempio n. 6
0
void StGLFrameTextures::increaseSize(StGLContext&      theCtx,
                                     StGLFrameTexture& theTexture,
                                     const GLsizei     theTextureSizeX,
                                     const GLsizei     theTextureSizeY) {
    // test existing size / new size
    /// TODO (Kirill Gavrilov#8) we can automatically reduce texture size here
    if((theTexture.getSizeX() < theTextureSizeX) ||
       (theTexture.getSizeY() < theTextureSizeY) ||
       !theTexture.isValid()) {
        ST_DEBUG_LOG("Requested texture size (" + theTextureSizeX + 'x' + theTextureSizeY
                   + ") larger than current texture size(" + theTexture.getSizeX() + 'x' + theTexture.getSizeY() + ')');
        const GLsizei anOriginalSizeX = theTexture.getSizeX();
        const GLsizei anOriginalSizeY = theTexture.getSizeY();

        const GLint aMaxTexDim = theCtx.getMaxTextureSize();
        GLsizei aNewSizeX = stMin(theTextureSizeX, GLsizei(aMaxTexDim));
        GLsizei aNewSizeY = stMin(theTextureSizeY, GLsizei(aMaxTexDim));
        if(!theCtx.arbNPTW) {
            aNewSizeX = getPowerOfTwo(theTextureSizeX, GLsizei(aMaxTexDim));
            aNewSizeY = getPowerOfTwo(theTextureSizeY, GLsizei(aMaxTexDim));
        }
        if((aNewSizeY != anOriginalSizeY)
        || (aNewSizeX != anOriginalSizeX)) {
            if(!theTexture.initTrash(theCtx, aNewSizeX, aNewSizeY)) {
                theTexture.initTrash(theCtx,
                                     (anOriginalSizeX > 0) ? anOriginalSizeX : 512,
                                     (anOriginalSizeY > 0) ? anOriginalSizeY : 512);
                ST_DEBUG_LOG("FAILED to Increase the texture size to (" + aNewSizeX + 'x' +  aNewSizeY + ")!");
            } else {
                ST_DEBUG_LOG("Increase the texture size to (" + aNewSizeX + 'x' +  aNewSizeY + ") success!");
            }
        } else {
            ST_DEBUG_LOG("Not possible to Increase the texture size!");
        }
    }
}
Esempio n. 7
0
StWinHandles::StWinHandles()
#ifdef _WIN32
: ThreadWnd(0),
  EventMsgThread(true),
  hWindow(NULL),
  hWindowGl(NULL),
  hWinTmp(NULL),
  myMKeyStop(GlobalAddAtom(MAKEINTATOM(VK_MEDIA_STOP))),
  myMKeyPlay(GlobalAddAtom(MAKEINTATOM(VK_MEDIA_PLAY_PAUSE))),
  myMKeyPrev(GlobalAddAtom(MAKEINTATOM(VK_MEDIA_PREV_TRACK))),
  myMKeyNext(GlobalAddAtom(MAKEINTATOM(VK_MEDIA_NEXT_TRACK))),
  ThreadGL(0),
  hDC(NULL) {
    //
#elif defined(__linux__)
: hWindow(0),
  hWindowGl(0),
  stXDisplay(),
  iconImage(0),
  iconShape(0),
  xDNDRequestType(None),
  xDNDSrcWindow(0),
  xDNDVersion(0),
  xrandrEventBase(0),
  isRecXRandrEvents(false) {
    //
#endif
}

StWinHandles::~StWinHandles() {
    close();
}

void StWinHandles::glSwap() {
#ifdef _WIN32
    if(hDC != NULL) {
        SwapBuffers(hDC);
    }
#elif defined(__linux__)
    if(!stXDisplay.isNull()
    && hRC->makeCurrent(hWindowGl)) { // if GL rendering context is bound to another drawable - we got BadMatch error
        glXSwapBuffers(stXDisplay->hDisplay, hWindowGl);
    }
#endif
}

bool StWinHandles::glMakeCurrent() {
#ifdef _WIN32
    if(hDC != NULL && !hRC.isNull()) {
        return hRC->isCurrent(hDC)
            || hRC->makeCurrent(hDC);
    }
#elif defined(__linux__)
    if(!stXDisplay.isNull() && !hRC.isNull()) {
        return hRC->makeCurrent(hWindowGl);
    }
#endif
    return false;
}

/**
 * Auxiliary macros.
 */
#define ST_GL_ERROR_CHECK(theTrueCondition, theErrCode, theErrDesc) \
    if(!(theTrueCondition)) { \
        stError(theErrDesc); \
        return theErrCode; \
    }

int StWinHandles::glCreateContext(StWinHandles*    theSlave,
                                  const StRectI_t& theRect,
                                  const int        theDepthSize,
                                  const bool       theIsQuadStereo,
                                  const bool       theDebugCtx) {
#ifdef _WIN32
    ThreadGL = StThread::getCurrentThreadId();
    ST_DEBUG_LOG("WinAPI, glCreateContext, ThreadGL= " + ThreadGL + ", ThreadWnd= " + ThreadWnd);
    hDC = GetDC(hWindowGl);
    ST_GL_ERROR_CHECK(hDC != NULL, STWIN_ERROR_WIN32_GLDC,
                      "WinAPI, Can't create Master GL Device Context");
    if(theSlave != NULL) {
        theSlave->ThreadGL = ThreadGL;
        theSlave->hDC      = GetDC(theSlave->hWindowGl);
        ST_GL_ERROR_CHECK(theSlave->hDC != NULL, STWIN_ERROR_WIN32_GLDC,
                          "WinAPI, Can't create Slave GL Device Context");
    }

    PIXELFORMATDESCRIPTOR aPixFrmtDesc = THE_PIXELFRMT_DOUBLE;
    aPixFrmtDesc.cDepthBits = (BYTE )theDepthSize;
    if(theIsQuadStereo) {
        aPixFrmtDesc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL
                             | PFD_DOUBLEBUFFER | PFD_STEREO;
    }
    int aPixFrmtId = ChoosePixelFormat(hDC, &aPixFrmtDesc);
    ST_GL_ERROR_CHECK(aPixFrmtId != 0, STWIN_ERROR_WIN32_PIXELFORMATF,
                      "WinAPI, Can't find a suitable PixelFormat for Master");
    if(theSlave != NULL
    && ChoosePixelFormat(theSlave->hDC, &aPixFrmtDesc) != aPixFrmtId) {
        ST_ERROR_LOG("Slave window returns another pixel format! Try to ignore...");
    }

    if(theIsQuadStereo) {
        DescribePixelFormat(hDC, aPixFrmtId, sizeof(PIXELFORMATDESCRIPTOR), &aPixFrmtDesc);
        if((aPixFrmtDesc.dwFlags & PFD_STEREO) == 0) {
            ST_ERROR_LOG("WinAPI, Quad Buffered stereo not supported");
        } else {
            //bool isVistaPlus = StSys::isVistaPlus();
            //bool isWin8Plus  = StSys::isWin8Plus();
            ///myNeedsFullscr
        }
    }

    HMODULE aModule = GetModuleHandleW(NULL);
    hWinTmp = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_WINDOWEDGE | WS_EX_NOACTIVATE,
                              ClassTmp.toCString(), L"TmpWnd",
                              WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_DISABLED,
                              theRect.left() + 2, theRect.top() + 2, 4, 4,
                              NULL, NULL, aModule, NULL);
    ST_GL_ERROR_CHECK(hWinTmp != NULL, STWIN_ERROR_WIN32_GLDC,
                      "WinAPI, Temporary window creation error");

    HDC aDevCtxTmp = GetDC(hWinTmp);
    ST_GL_ERROR_CHECK(aPixFrmtId != 0, STWIN_ERROR_WIN32_PIXELFORMATF,
                      "WinAPI, Can't find a suitable PixelFormat for Tmp");

    ST_GL_ERROR_CHECK(SetPixelFormat(aDevCtxTmp, aPixFrmtId, &aPixFrmtDesc),
                      STWIN_ERROR_WIN32_PIXELFORMATS, "WinAPI, Can't set the PixelFormat for Master");
    StWinGlrcH aRendCtxTmp = new StWinGlrc(aDevCtxTmp, NULL);
    ST_GL_ERROR_CHECK(aRendCtxTmp->isValid(),
                      STWIN_ERROR_WIN32_GLRC_CREATE, "WinAPI, Can't create GL Rendering Context");
    ST_GL_ERROR_CHECK(aRendCtxTmp->makeCurrent(aDevCtxTmp),
                      STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Can't activate Tmp GL Rendering Context");

    StGLContext aCtx;
    ST_GL_ERROR_CHECK(aCtx.stglInit(),
                      STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Broken Tmp GL Rendering Context");

    if(aCtx.extAll->wglChoosePixelFormatARB != NULL) {
        const int aPixAttribs[] = {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
            WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
            WGL_STEREO_ARB,         theIsQuadStereo ? GL_TRUE : GL_FALSE,
            WGL_PIXEL_TYPE_ARB,     WGL_TYPE_RGBA_ARB,
            //WGL_SAMPLE_BUFFERS_ARB, 1,
            //WGL_SAMPLES_ARB,        8,
            // WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB       0x00000004
            WGL_COLOR_BITS_ARB,     24,
            WGL_DEPTH_BITS_ARB,     theDepthSize,
            WGL_STENCIL_BITS_ARB,   0,
            0, 0,
        };
        unsigned int aFrmtsNb = 0;
        aCtx.extAll->wglChoosePixelFormatARB(hDC, aPixAttribs, NULL, 1, &aPixFrmtId, &aFrmtsNb);
    }
    ST_GL_ERROR_CHECK(SetPixelFormat(hDC, aPixFrmtId, &aPixFrmtDesc),
                      STWIN_ERROR_WIN32_PIXELFORMATS, "WinAPI, Can't set the PixelFormat for Master");
    ST_GL_ERROR_CHECK(theSlave == NULL || SetPixelFormat(theSlave->hDC, aPixFrmtId, &aPixFrmtDesc),
                      STWIN_ERROR_WIN32_PIXELFORMATS, "WinAPI, Can't set the PixelFormat for Slave");

    HGLRC aRendCtx = NULL;
    if(aCtx.extAll->wglCreateContextAttribsARB != NULL) {
        // Beware! NVIDIA drivers reject context creation when WGL_CONTEXT_PROFILE_MASK_ARB are specified
        // but not WGL_CONTEXT_MAJOR_VERSION_ARB/WGL_CONTEXT_MINOR_VERSION_ARB
        int aCtxAttribs[] = {
            //WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
            //WGL_CONTEXT_MINOR_VERSION_ARB, 2,
            //WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, //WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
            WGL_CONTEXT_FLAGS_ARB,         theDebugCtx ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
            0, 0
        };

        aRendCtx = aCtx.extAll->wglCreateContextAttribsARB(hDC, NULL, aCtxAttribs);
    }

    aRendCtxTmp.nullify();
    destroyWindow(hWinTmp);

    hRC = new StWinGlrc(hDC, aRendCtx);
    ST_GL_ERROR_CHECK(hRC->isValid(),
                      STWIN_ERROR_WIN32_GLRC_CREATE, "WinAPI, Can't create GL Rendering Context");
    if(theSlave != NULL) {
        theSlave->hRC = hRC;
    }

    ST_GL_ERROR_CHECK(hRC->makeCurrent(hDC),
                      STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Can't activate Master GL Rendering Context");
    return STWIN_INIT_SUCCESS;
#elif defined(__linux__)
    // create an OpenGL rendering context
    hRC = new StWinGlrc(stXDisplay, theDebugCtx);
    ST_GL_ERROR_CHECK(hRC->isValid(),
                      STWIN_ERROR_X_GLRC_CREATE, "GLX, could not create rendering context for Master");
    if(theSlave != NULL) {
        theSlave->hRC = hRC;

        // bind the rendering context to the window
        ST_GL_ERROR_CHECK(hRC->makeCurrent(theSlave->hWindowGl),
                          STWIN_ERROR_X_GLRC_CREATE, "GLX, Can't activate Slave GL Rendering Context");
    }

    // bind the rendering context to the window
    ST_GL_ERROR_CHECK(hRC->makeCurrent(hWindowGl),
                      STWIN_ERROR_X_GLRC_CREATE, "GLX, Can't activate Master GL Rendering Context");
    return STWIN_INIT_SUCCESS;
#endif
}
void StGLStereoFrameBuffer::bindBufferRight(StGLContext& theCtx) {
    theCtx.stglBindFramebuffer(myGLFBufferIds[StGLStereoTexture::RIGHT_TEXTURE]);
}
void StGLStereoFrameBuffer::setupViewPort(StGLContext& theCtx) {
    theCtx.stglResizeViewport(myViewPortX, myViewPortY);
}
Esempio n. 10
0
bool StGLStereoFrameBuffer::init(StGLContext&  theCtx,
                                 const GLsizei theTextureSizeX,
                                 const GLsizei theTextureSizeY,
                                 const bool    theNeedDepthBuffer) {
    // release current objects
    release(theCtx);

    if(theCtx.arbFbo == NULL) {
        return false;
    }

    // create the textures
    if(!StGLStereoTexture::initTrash(theCtx, theTextureSizeX, theTextureSizeY)) {
        release(theCtx);
        return false;
    }

    const GLuint aFboBakDraw = theCtx.stglFramebufferDraw();
    const GLuint aFboBakRead = theCtx.stglFramebufferRead();
    theCtx.stglBindFramebuffer(StGLFrameBuffer::NO_FRAMEBUFFER);

    const GLint aDepthFormat = theCtx.isGlGreaterEqual(3, 0) ? GL_DEPTH24_STENCIL8 : GL_DEPTH_COMPONENT16;
    if(theNeedDepthBuffer) {
        theCtx.arbFbo->glGenRenderbuffers(2, myGLDepthRBIds);

        theCtx.arbFbo->glBindRenderbuffer(GL_RENDERBUFFER, myGLDepthRBIds[StGLStereoTexture::LEFT_TEXTURE]);
        theCtx.arbFbo->glRenderbufferStorage(GL_RENDERBUFFER, aDepthFormat, theTextureSizeX, theTextureSizeY);
    }

    // build FBOs
    theCtx.arbFbo->glGenFramebuffers(2, myGLFBufferIds);
    theCtx.stglBindFramebuffer(myGLFBufferIds[StGLStereoTexture::LEFT_TEXTURE]);

    // bind left texture to left FBO as color buffer
    theCtx.arbFbo->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                          StGLStereoTexture::myTextures[StGLStereoTexture::LEFT_TEXTURE].getTextureId(), 0);
    if(theNeedDepthBuffer) {
        // bind left render buffer to left FBO as depth buffer
        theCtx.arbFbo->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
                                                 myGLDepthRBIds[StGLStereoTexture::LEFT_TEXTURE]);
    }
    bool isOk = theCtx.arbFbo->glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
    theCtx.arbFbo->glBindRenderbuffer(GL_RENDERBUFFER, StGLFrameBuffer::NO_RENDERBUFFER);
    if(!isOk) {
        release(theCtx);
        theCtx.stglBindFramebufferDraw(aFboBakDraw);
        theCtx.stglBindFramebufferRead(aFboBakRead);
        return false;
    }
    theCtx.stglBindFramebuffer(StGLFrameBuffer::NO_FRAMEBUFFER);

    if(theNeedDepthBuffer) {
        // create right RenderBuffer (will be used as depth buffer)
        theCtx.arbFbo->glBindRenderbuffer(GL_RENDERBUFFER, myGLDepthRBIds[StGLStereoTexture::RIGHT_TEXTURE]);
        theCtx.arbFbo->glRenderbufferStorage(GL_RENDERBUFFER, aDepthFormat, theTextureSizeX, theTextureSizeY);
    }

    theCtx.stglBindFramebuffer(myGLFBufferIds[StGLStereoTexture::RIGHT_TEXTURE]);

    // bind right texture to rights FBO as color buffer
    theCtx.arbFbo->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                          StGLStereoTexture::myTextures[StGLStereoTexture::RIGHT_TEXTURE].getTextureId(), 0);

    if(theNeedDepthBuffer) {
        // bind right render buffer to right FBO as depth buffer
        theCtx.arbFbo->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER,
                                                 myGLDepthRBIds[StGLStereoTexture::RIGHT_TEXTURE]);
    }
    isOk = theCtx.arbFbo->glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE;
    theCtx.arbFbo->glBindRenderbuffer(GL_RENDERBUFFER, StGLFrameBuffer::NO_RENDERBUFFER);
    theCtx.stglBindFramebufferDraw(aFboBakDraw);
    theCtx.stglBindFramebufferRead(aFboBakRead);
    if(!isOk) {
        release(theCtx);
        return false;
    }

    ST_DEBUG_LOG("OpenGL, created StFrameBuffer(WxH= " + getSizeX() + 'x' + getSizeY() + ')');

    // create vertices buffers to draw simple textured quad
    StArray<StGLVec4> aQuad(4);
    aQuad[0] = StGLVec4( 1.0f, -1.0f, 0.0f, 1.0f); // top-right
    aQuad[1] = StGLVec4( 1.0f,  1.0f, 0.0f, 1.0f); // bottom-right
    aQuad[2] = StGLVec4(-1.0f, -1.0f, 0.0f, 1.0f); // top-left
    aQuad[3] = StGLVec4(-1.0f,  1.0f, 0.0f, 1.0f); // bottom-left
    myVerticesBuf.init(theCtx, aQuad);

    StArray<StGLVec2> aQuadTC(4);
    aQuadTC[0] = StGLVec2(1.0f, 0.0f);
    aQuadTC[1] = StGLVec2(1.0f, 1.0f);
    aQuadTC[2] = StGLVec2(0.0f, 0.0f);
    aQuadTC[3] = StGLVec2(0.0f, 1.0f);
    myTexCoordBuf.init(theCtx, aQuadTC);

    myViewPortX = theTextureSizeX;
    myViewPortY = theTextureSizeY;
    return true;
}