Beispiel #1
0
StJNIEnv::StJNIEnv(JavaVM* theJavaVM)
: myJavaVM(theJavaVM),
  myJniEnv(NULL),
  myToDetach(false) {
    if(myJavaVM == NULL) {
        return;
    }

    void* aJniEnv = NULL;
    switch(myJavaVM->GetEnv(&aJniEnv, JNI_VERSION_1_6)) {
        case JNI_EDETACHED: {
            if(myJavaVM->AttachCurrentThread(&myJniEnv, NULL) < 0) {
                myJniEnv = NULL;
                ST_ERROR_LOG("Failed to attach working thread to Java VM");
                return;
            }
            myToDetach = true;
            break;
        }
        case JNI_OK: {
            myJniEnv   = (JNIEnv* )aJniEnv;
            myToDetach = false;
            break;
        }
        case JNI_EVERSION: {
            ST_ERROR_LOG("Failed to attach working thread to Java VM - JNI version is not supported");
            break;
        }
        default: {
            ST_ERROR_LOG("Failed to attach working thread to Java VM");
            break;
        }
    }
}
Beispiel #2
0
bool StAndroidGlue::writeCommand(const int8_t theCmd) {
    if(::write(myMsgWrite, &theCmd, sizeof(theCmd)) != sizeof(theCmd)) {
        ST_ERROR_LOG("Failure writing StAndroidGlue cmd: " + strerror(errno));
        return false;
    }
    return true;
}
Beispiel #3
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;
}
Beispiel #4
0
void StAndroidGlue::postExit() {
    if(myThJniEnv == NULL) {
        return;
    }

    jclass  aJClassAct = myThJniEnv->GetObjectClass(myActivity->clazz);
    if(aJClassAct == NULL) {
        ST_ERROR_LOG("StAndroidGlue::postExit() - class is unavailable!");
        return;
    }

    jmethodID aJMetId = myThJniEnv->GetMethodID(aJClassAct, "postExit", "()V");
    if(aJMetId == NULL) {
        ST_ERROR_LOG("StAndroidGlue::postExit() - method is unavailable!");
        return;
    }

    myThJniEnv->CallVoidMethod(myActivity->clazz, aJMetId);
}
Beispiel #5
0
void StAndroidGlue::postMessage(const char* theInfo) {
    if(myThJniEnv == NULL) {
        return;
    }

    jclass  aJClassAct = myThJniEnv->GetObjectClass(myActivity->clazz);
    if(aJClassAct == NULL) {
        ST_ERROR_LOG("StAndroidGlue::postMessage() - class is unavailable!");
        return;
    }

    jmethodID aJMetId = myThJniEnv->GetMethodID(aJClassAct, "postMessage", "(Ljava/lang/String;)V");
    if(aJMetId == NULL) {
        ST_ERROR_LOG("StAndroidGlue::postMessage() - method is unavailable!");
        return;
    }

    jstring aJStr = myThJniEnv->NewStringUTF(theInfo);
    myThJniEnv->CallVoidMethod(myActivity->clazz, aJMetId, aJStr);
    myThJniEnv->DeleteLocalRef (aJStr);
}
Beispiel #6
0
    /**
     * Copy OCCT resource file.
     */
    ST_LOCAL bool copyResource(const StHandle<StResourceManager>& theResMgr,
                               const StString& theResFolder,
                               const StString& theDestFolder,
                               const StString& theFileName) {
        StString aFileResPath = theResFolder + SYS_FS_SPLITTER + theFileName;
        StHandle<StResource> aRes = theResMgr->getResource(aFileResPath);
        if( aRes.isNull()
        || !aRes->read()) {
            ST_ERROR_LOG(StString("Can not read resource file ") + aFileResPath);
            return false;
        }

        StRawFile aFileOut;
        StString  aFileOutPath = theDestFolder + SYS_FS_SPLITTER + theFileName;
        if(!aFileOut.openFile(StRawFile::WRITE, aFileOutPath)) {
            ST_ERROR_LOG(StString("Can not create resource file ") + aFileOutPath);
            return false;
        }
        if(!aFileOut.write((const char* )aRes->getData(), aRes->getSize()) != aRes->getSize()) {
            ST_ERROR_LOG(StString("Can not write resource file ") + aFileOutPath);
            return false;
        }
        return true;
    }
Beispiel #7
0
StWinGlrc::~StWinGlrc() {
    if(myRC != EGL_NO_CONTEXT) {
        if(eglMakeCurrent(myDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE) {
            ST_DEBUG_LOG("EGL, FAILED to release OpenGL context");
        }
        eglDestroyContext(myDisplay, myRC);
        myRC = EGL_NO_CONTEXT;
    }

    if(myDisplay != EGL_NO_DISPLAY) {
        if(eglTerminate(myDisplay) != EGL_TRUE) {
            ST_ERROR_LOG("EGL, eglTerminate FAILED");
        }
        myDisplay = EGL_NO_DISPLAY;
    }
}
Beispiel #8
0
StWinGlrc::~StWinGlrc() {
    if(myRC == NULL) {
        return;
    }

    if(wglMakeCurrent(NULL, NULL) == FALSE) {
        // this is not a problem in most cases;
        // also this happens when wglMakeCurrent(NULL, NULL) called twice
        //ST_DEBUG_LOG("WinAPI, FAILED to release DC and RC contexts");
    }

    //ST_ASSERT_SLIP(wglDeleteContext(myRC) != FALSE, "WinAPI, FAILED to delete RC", return);
    if(wglDeleteContext(myRC) == FALSE) {
        ST_ERROR_LOG("WinAPI, FAILED to delete RC");
    }
}
Beispiel #9
0
int StAndroidGlue::openFileDescriptor(const StString& thePath) {
    if(myJavaVM == NULL) {
        return -1;
    }

    StJNIEnv aJniEnv(myJavaVM);
    if(aJniEnv.isNull()) {
        return -1;
    }

    jclass    aJClass_Activity = aJniEnv->GetObjectClass(myActivity->clazz);
    jmethodID aJMet_openFileDescriptor = aJniEnv->GetMethodID(aJClass_Activity, "openFileDescriptor", "(Ljava/lang/String;)I");
    if(aJMet_openFileDescriptor == NULL) {
        ST_ERROR_LOG("StAndroidGlue::openFileDescriptor() - method is unavailable!");
        return -1;
    }

    jstring aJStr = aJniEnv->NewStringUTF(thePath.toCString());
    int aFileDesc = aJniEnv->CallIntMethod(myActivity->clazz, aJMet_openFileDescriptor, aJStr);
    aJniEnv->DeleteLocalRef(aJStr);

    return aFileDesc;
}
Beispiel #10
0
// function create GUI window
bool StWindowImpl::create() {
    myKeysState.reset();

    // replace default XError handler to ignore some errors
    XSetErrorHandler(stXErrorHandler);

    myInitState = STWIN_INITNOTSTART;
    // X-server implementation
    // create window on unix systems throw X-server
    int dummy;

    // open a connection to the X server
    StXDisplayH stXDisplay = new StXDisplay();
    if(!stXDisplay->isOpened()) {
        stXDisplay.nullify();
        stError("X, could not open display");
        myInitState = STWIN_ERROR_X_OPENDISPLAY;
        return false;
    }
    myMaster.stXDisplay = stXDisplay;
    Display* hDisplay = stXDisplay->hDisplay;

#if defined(ST_HAVE_EGL)
    myMaster.hRC = new StWinGlrc(eglGetDisplay(hDisplay), attribs.IsGlDebug, attribs.GlDepthSize);
    if(!myMaster.hRC->isValid()) {
        myMaster.close();
        mySlave.close();
        myInitState = STWIN_ERROR_X_GLRC_CREATE;
        return false;
    }

    XVisualInfo aVisInfo;
    aVisInfo.visualid = 0;
    if (eglGetConfigAttrib(myMaster.hRC->getDisplay(),
                           myMaster.hRC->getConfig(),
                           EGL_NATIVE_VISUAL_ID,
                           (EGLint* )&aVisInfo.visualid) != EGL_TRUE) {
        myMaster.close();
        mySlave.close();
        myInitState = STWIN_ERROR_X_GLRC_CREATE;
        return false;
    }

    int aNbVisuals = 0;
    stXDisplay->hVisInfo = XGetVisualInfo(hDisplay, VisualIDMask, &aVisInfo, &aNbVisuals);

#else // GLX

    // make sure OpenGL's GLX extension supported
    if(!glXQueryExtension(hDisplay, &dummy, &dummy)) {
        myMaster.close();
        stError("X, server has no OpenGL GLX extension");
        myInitState = STWIN_ERROR_X_NOGLX;
        return false;
    }

    int anAttribsBuff[] = {
        GLX_STEREO,        attribs.IsGlStereo ? True : False,
        GLX_X_RENDERABLE,  True,
        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
        GLX_RENDER_TYPE,   GLX_RGBA_BIT,
        GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
        GLX_RED_SIZE,      8,
        GLX_GREEN_SIZE,    8,
        GLX_BLUE_SIZE,     8,
        GLX_ALPHA_SIZE,    0,
        GLX_DEPTH_SIZE,    attribs.GlDepthSize,
        GLX_STENCIL_SIZE,  0,
        GLX_DOUBLEBUFFER,  True,
        //GLX_SAMPLE_BUFFERS, 1,
        //GLX_SAMPLES,        4,
        None
    };

    // FBConfigs were added in GLX version 1.3
    int aGlxMajor = 0;
    int aGlxMinor = 0;
    const bool hasFBCfg = glXQueryVersion(hDisplay, &aGlxMajor, &aGlxMinor)
                       && ((aGlxMajor == 1 && aGlxMinor >= 3) || (aGlxMajor > 1));

    int aFBCount = 0;
    GLXFBConfig* aFBCfgList = NULL;
    if(hasFBCfg) {
        aFBCfgList = glXChooseFBConfig(hDisplay, DefaultScreen(hDisplay),
                                       anAttribsBuff, &aFBCount);
    }
    if(aFBCfgList == NULL
    && hasFBCfg
    && attribs.IsGlStereo) {
        ST_ERROR_LOG("X, no Quad Buffered visual");
        anAttribsBuff[1] = False;
        aFBCfgList = glXChooseFBConfig(hDisplay, DefaultScreen(hDisplay),
                                       anAttribsBuff, &aFBCount);
    }
    if(aFBCfgList != NULL
    && aFBCount >= 1) {
        stXDisplay->FBCfg    = aFBCfgList[0];
        stXDisplay->hVisInfo = glXGetVisualFromFBConfig(hDisplay, stXDisplay->FBCfg);
    } else {
        // try to use glXChooseVisual... pointless?
        int aDblBuff[] = {
            GLX_RGBA,
            GLX_DEPTH_SIZE, attribs.GlDepthSize,
            GLX_DOUBLEBUFFER,
            None
        };
        if(attribs.IsGlStereo) {
            // find an appropriate visual
            int aQuadBuff[] = {
                GLX_RGBA,
                GLX_DEPTH_SIZE, attribs.GlDepthSize,
                GLX_DOUBLEBUFFER,
                GLX_STEREO,
                None
            };

            stXDisplay->hVisInfo = glXChooseVisual(hDisplay, DefaultScreen(hDisplay), aQuadBuff);
            if(stXDisplay->hVisInfo == NULL) {
                ST_ERROR_LOG("X, no Quad Buffered visual");
                stXDisplay->hVisInfo = glXChooseVisual(hDisplay, DefaultScreen(hDisplay), aDblBuff);
                if(stXDisplay->hVisInfo == NULL) {
                    myMaster.close();
                    stError("X, no RGB visual with depth buffer");
                    myInitState = STWIN_ERROR_X_NORGB;
                    return false;
                }
            }
        } else {
            // find an appropriate visual
            // find an OpenGL-capable RGB visual with depth buffer
            stXDisplay->hVisInfo = glXChooseVisual(hDisplay, DefaultScreen(hDisplay), aDblBuff);
            if(stXDisplay->hVisInfo == NULL) {
                myMaster.close();
                stError("X, no RGB visual with depth buffer");
                myInitState = STWIN_ERROR_X_NORGB;
                return false;
            }
        }
    }
    XFree(aFBCfgList);
#endif

    if(attribs.Slave != StWinSlave_slaveOff) {
        // just copy handle
        mySlave.stXDisplay = stXDisplay;
    }

    // create an X window with the selected visual
    XSetWindowAttributes aWinAttribsX = createDefaultAttribs(stXDisplay);
    updateChildRect();

    Window aParentWin = (Window )myParentWin;
    if(aParentWin == 0 && !attribs.IsNoDecor) {
        aWinAttribsX.override_redirect = False;
        myMaster.hWindow = XCreateWindow(hDisplay, stXDisplay->getRootWindow(),
                                         myRectNorm.left(),  myRectNorm.top(),
                                         myRectNorm.width(), myRectNorm.height(),
                                         0, stXDisplay->getDepth(),
                                         InputOutput,
                                         stXDisplay->getVisual(),
                                         CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX);

        if(myMaster.hWindow == 0) {
            myMaster.close();
            stError("X, XCreateWindow failed for Master");
            myInitState = STWIN_ERROR_X_CREATEWIN;
            return false;
        }
        aParentWin = myMaster.hWindow;

        XSetStandardProperties(hDisplay, myMaster.hWindow,
                               myWindowTitle.toCString(),
                               myWindowTitle.toCString(),
                               None, NULL, 0, NULL);

        // setup WM_CLASS in sync with .desktop StartupWMClass entity
        // to ensure Window Manager would show an propriate icon for application
        XClassHint* aClassHint = XAllocClassHint();
        if(aClassHint != NULL) {
            StString aName = StProcess::getProcessName();
            StString aClass("sView");
            // const_cast should be harmless here and it seems to be just broken signature of XClassHint structure
            aClassHint->res_name  = const_cast<char* >(aName.toCString());
            aClassHint->res_class = const_cast<char* >(aClass.toCString());
            XSetClassHint(hDisplay, myMaster.hWindow, aClassHint);
            XFree(aClassHint);
        }
    }

    aWinAttribsX.override_redirect = True; // GL window always undecorated
    myMaster.hWindowGl = XCreateWindow(hDisplay, (aParentWin != 0) ? aParentWin : stXDisplay->getRootWindow(),
                                       0, 0, myRectNorm.width(), myRectNorm.height(),
                                       0, stXDisplay->getDepth(),
                                       InputOutput,
                                       stXDisplay->getVisual(),
                                       CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX);
    if(myMaster.hWindowGl == 0) {
        myMaster.close();
        stError("X, XCreateWindow failed for Master");
        myInitState = STWIN_ERROR_X_CREATEWIN;
        return false;
    }

    XSetStandardProperties(hDisplay, myMaster.hWindowGl,
                           "master window", "master window",
                           None, NULL, 0, NULL);

    if(attribs.Slave != StWinSlave_slaveOff) {
        aWinAttribsX.event_mask = NoEventMask; // we do not parse any events to slave window!
        aWinAttribsX.override_redirect = True; // slave window always undecorated
        mySlave.hWindowGl = XCreateWindow(hDisplay, stXDisplay->getRootWindow(),
                                          getSlaveLeft(),  getSlaveTop(),
                                          getSlaveWidth(), getSlaveHeight(),
                                          0, stXDisplay->getDepth(),
                                          InputOutput,
                                          stXDisplay->getVisual(),
                                          CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX);

        if(mySlave.hWindowGl == 0) {
            myMaster.close();
            mySlave.close();
            stError("X, XCreateWindow failed for Slave");
            myInitState = STWIN_ERROR_X_CREATEWIN;
            return false;
        }

        XSetStandardProperties(hDisplay, mySlave.hWindowGl,
                               "slave window", "slave window",
                               None, NULL, 0, NULL);
    }

    int isGlCtx = myMaster.glCreateContext(attribs.Slave != StWinSlave_slaveOff ? &mySlave : NULL,
                                           myRectNorm,
                                           attribs.GlDepthSize,
                                           attribs.IsGlStereo,
                                           attribs.IsGlDebug);
    if(isGlCtx != STWIN_INIT_SUCCESS) {
        myMaster.close();
        mySlave.close();
        myInitState = isGlCtx;
        return false;
    }

    myGlContext = new StGLContext(myResMgr);
    if(!myGlContext->stglInit()) {
        myMaster.close();
        mySlave.close();
        stError("Critical error - broken GL context!\nInvalid OpenGL driver?");
        myInitState = STWIN_ERROR_X_GLRC_CREATE;
        return false;
    }

    // handle close window event
    if(myMaster.hWindow != 0) {
        XSetWMProtocols(hDisplay, myMaster.hWindow, &(stXDisplay->wndDestroyAtom), 1);
    }

    // Announce XDND support
    myMaster.setupXDND();

    // Initialize XRandr events reception
    if(XRRQueryExtension(hDisplay, &myMaster.xrandrEventBase, &dummy)) {
        XRRSelectInput(hDisplay,
                       stXDisplay->getRootWindow(),
                       RRScreenChangeNotifyMask |
                       RRCrtcChangeNotifyMask   |
                       RROutputPropertyNotifyMask);
        myMaster.isRecXRandrEvents = true;
    } else {
        myMaster.isRecXRandrEvents = false;
    }

    // request the X window to be displayed on the screen
    if(attribs.Slave != StWinSlave_slaveOff) {

        // request the X window to be displayed on the screen
        if(!attribs.IsSlaveHidden && (!isSlaveIndependent() || myMonitors.size() > 1)) {
            XMapWindow(hDisplay, mySlave.hWindowGl);
            //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )mySlave.hWindowGl);
        }
        // always hise mouse cursor on slave window
        mySlave.setupNoCursor();
    }
    if(!attribs.IsHidden) {
        if(myMaster.hWindow != 0) {
            XMapWindow(hDisplay, myMaster.hWindow);
            //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindow);
        }
        XMapWindow(hDisplay, myMaster.hWindowGl);
        //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindowGl);
    }

    // setup default icon
    if((Window )myParentWin == 0) {
        XpmCreatePixmapFromData(hDisplay, myMaster.hWindow, (char** )sview_xpm, &myMaster.iconImage, &myMaster.iconShape, NULL);
        XWMHints anIconHints;
        anIconHints.flags       = IconPixmapHint | IconMaskHint;
        anIconHints.icon_pixmap = myMaster.iconImage;
        anIconHints.icon_mask   = myMaster.iconShape;
        XSetWMHints(hDisplay, myMaster.hWindow, &anIconHints);
    }

    // we need this call to go around bugs
    if(!attribs.IsFullScreen && myMaster.hWindow != 0) {
        XMoveResizeWindow(hDisplay, myMaster.hWindow,
                          myRectNorm.left(),  myRectNorm.top(),
                          myRectNorm.width(), myRectNorm.height());
    }
    // flushes the output buffer, most client apps needn't use this cause buffer is automatically flushed as needed by calls to XNextEvent()...
    XFlush(hDisplay);
    myMonitors.registerUpdater(true);
    myIsUpdated = true;
    myInitState = STWIN_INIT_SUCCESS;
    return true;
}
Beispiel #11
0
bool StAVImage::load(const StString& theFilePath,
                     ImageType       theImageType,
                     uint8_t*        theDataPtr,
                     int             theDataSize) {

    // reset current data
    StImage::nullify();
    setState();
    close();
    myMetadata.clear();

    switch(theImageType) {
        case ST_TYPE_PNG:
        case ST_TYPE_PNS: {
            myCodec = avcodec_find_decoder_by_name("png");
            break;
        }
        case ST_TYPE_JPEG:
        case ST_TYPE_MPO:
        case ST_TYPE_JPS: {
            myCodec = avcodec_find_decoder_by_name("mjpeg");
            break;
        }
        case ST_TYPE_EXR: {
            myCodec = avcodec_find_decoder_by_name("exr");
            break;
        }
        case ST_TYPE_WEBP:
        case ST_TYPE_WEBPLL: {
            myCodec = avcodec_find_decoder_by_name("webp");
            break;
        }
        default: {
            break;
        }
    }

    if(theImageType == ST_TYPE_NONE
    || (theDataPtr == NULL && !StFileNode::isFileExists(theFilePath))) {
        // open image file and detect its type, its could be non local file!
    #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0))
        int avErrCode = avformat_open_input(&myFormatCtx, theFilePath.toCString(), myImageFormat, NULL);
    #else
        int avErrCode = av_open_input_file (&myFormatCtx, theFilePath.toCString(), myImageFormat, 0, NULL);
    #endif
        if(avErrCode != 0
        || myFormatCtx->nb_streams < 1
        || myFormatCtx->streams[0]->codec->codec_id == 0) {
            if(myFormatCtx != NULL) {
            #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 17, 0))
                avformat_close_input(&myFormatCtx);
            #else
                av_close_input_file(myFormatCtx);
                myFormatCtx = NULL;
            #endif
            }

        #if(LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(53, 2, 0))
            avErrCode = avformat_open_input(&myFormatCtx, theFilePath.toCString(), NULL, NULL);
        #else
            avErrCode = av_open_input_file(&myFormatCtx, theFilePath.toCString(), NULL, 0, NULL);
        #endif
        }

        if(avErrCode != 0
        || myFormatCtx->nb_streams < 1) {
            setState(StString("AVFormat library, couldn't open image file. Error: ") + stAV::getAVErrorDescription(avErrCode));
            close();
            return false;
        }

        // find the decoder for the video stream
        myCodecCtx = myFormatCtx->streams[0]->codec;
        if(theImageType == ST_TYPE_NONE) {
            myCodec = avcodec_find_decoder(myCodecCtx->codec_id);
        }
    }

    if(myCodec == NULL) {
        setState("AVCodec library, video codec not found");
        close();
        return false;
    } else if(myFormatCtx == NULL) {
        // use given image type to load decoder
    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
        myCodecCtx = avcodec_alloc_context3(myCodec);
    #else
        myCodecCtx = avcodec_alloc_context();
    #endif
    }

    // stupid check
    if(myCodecCtx == NULL) {
        setState("AVCodec library, codec context is NULL");
        close();
        return false;
    }

    // open VIDEO codec
#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
    if(avcodec_open2(myCodecCtx, myCodec, NULL) < 0) {
#else
    if(avcodec_open(myCodecCtx, myCodec) < 0) {
#endif
        setState("AVCodec library, could not open video codec");
        close();
        return false;
    }

    // read one packet or file
    StRawFile aRawFile(theFilePath);
    StAVPacket anAvPkt;
    if(theDataPtr != NULL && theDataSize != 0) {
        anAvPkt.getAVpkt()->data = theDataPtr;
        anAvPkt.getAVpkt()->size = theDataSize;
    } else {
        if(myFormatCtx != NULL) {
            if(av_read_frame(myFormatCtx, anAvPkt.getAVpkt()) < 0) {
                setState("AVFormat library, could not read first packet");
                close();
                return false;
            }
        } else {
            if(!aRawFile.readFile()) {
                setState("StAVImage, could not read the file");
                close();
                return false;
            }
            anAvPkt.getAVpkt()->data = (uint8_t* )aRawFile.getBuffer();
            anAvPkt.getAVpkt()->size = (int )aRawFile.getSize();
        }
    }
    anAvPkt.setKeyFrame();

    // decode one frame
    int isFrameFinished = 0;
#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 23, 0))
    avcodec_decode_video2(myCodecCtx, myFrame.Frame, &isFrameFinished, anAvPkt.getAVpkt());
#else
    avcodec_decode_video(myCodecCtx, myFrame.Frame, &isFrameFinished,
                         theDataPtr, theDataSize);
#endif

    if(isFrameFinished == 0) {
        // thats not an image!!! try to decode more packets???
        setState("AVCodec library, input file is not an Image!");
        close();
        return false;
    }

    // check frame size
    if(myCodecCtx->width <= 0 || myCodecCtx->height <= 0) {
        setState("AVCodec library, codec returns wrong frame size");
        close();
        return false;
    }

    // read aspect ratio
    if(myCodecCtx->sample_aspect_ratio.num == 0
    || myCodecCtx->sample_aspect_ratio.den == 0) {
        setPixelRatio(1.0f);
    } else {
        const GLfloat aRatio = GLfloat(myCodecCtx->sample_aspect_ratio.num) / GLfloat(myCodecCtx->sample_aspect_ratio.den);
        if(aRatio > 70.0f) {
            ST_DEBUG_LOG("AVCodec library, igning wrong PAR " + myCodecCtx->sample_aspect_ratio.num + ":" + myCodecCtx->sample_aspect_ratio.den);
            setPixelRatio(1.0f);
        } else {
            setPixelRatio(aRatio);
        }
    }

#ifdef ST_AV_NEWSTEREO
    // currently it is unlikelly... but maybe in future?
    AVFrameSideData* aSideData = av_frame_get_side_data(myFrame.Frame, AV_FRAME_DATA_STEREO3D);
    if(aSideData != NULL) {
        AVStereo3D* aStereo = (AVStereo3D* )aSideData->data;
        mySrcFormat = stAV::stereo3dAvToSt(aStereo->type);
        if(aStereo->flags & AV_STEREO3D_FLAG_INVERT) {
            mySrcFormat = st::formatReversed(mySrcFormat);
        }
    } else {
        mySrcFormat = StFormat_AUTO;
    }
#endif

    // it is unlikely that there would be any metadata from format...
    // but lets try
    if(myFormatCtx != NULL) {
        for(stAV::meta::Tag* aTag = stAV::meta::findTag(myFormatCtx->metadata, "", NULL, stAV::meta::SEARCH_IGNORE_SUFFIX);
            aTag != NULL;
            aTag = stAV::meta::findTag(myFormatCtx->metadata, "", aTag, stAV::meta::SEARCH_IGNORE_SUFFIX)) {
            myMetadata.add(StDictEntry(aTag->key, aTag->value));
        }
        for(stAV::meta::Tag* aTag = stAV::meta::findTag(myFormatCtx->streams[0]->metadata, "", NULL, stAV::meta::SEARCH_IGNORE_SUFFIX);
            aTag != NULL;
            aTag = stAV::meta::findTag(myFormatCtx->streams[0]->metadata, "", aTag, stAV::meta::SEARCH_IGNORE_SUFFIX)) {
            myMetadata.add(StDictEntry(aTag->key, aTag->value));
        }
    }

    // collect metadata from the frame
    stAV::meta::Dict* aFrameMetadata = stAV::meta::getFrameMetadata(myFrame.Frame);
    for(stAV::meta::Tag* aTag = stAV::meta::findTag(aFrameMetadata, "", NULL, stAV::meta::SEARCH_IGNORE_SUFFIX);
        aTag != NULL;
        aTag = stAV::meta::findTag(aFrameMetadata, "", aTag, stAV::meta::SEARCH_IGNORE_SUFFIX)) {
        myMetadata.add(StDictEntry(aTag->key, aTag->value));
    }

    stAV::dimYUV aDimsYUV;
    if(myCodecCtx->pix_fmt == stAV::PIX_FMT::RGB24) {
        setColorModel(StImage::ImgColor_RGB);
        changePlane(0).initWrapper(StImagePlane::ImgRGB, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::BGR24) {
        setColorModel(StImage::ImgColor_RGB);
        changePlane(0).initWrapper(StImagePlane::ImgBGR, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::RGBA32) {
        setColorModel(StImage::ImgColor_RGBA);
        changePlane(0).initWrapper(StImagePlane::ImgRGBA, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::BGRA32) {
        setColorModel(StImage::ImgColor_RGBA);
        changePlane(0).initWrapper(StImagePlane::ImgBGRA, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::GRAY8) {
        setColorModel(StImage::ImgColor_GRAY);
        changePlane(0).initWrapper(StImagePlane::ImgGray, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::GRAY16) {
        setColorModel(StImage::ImgColor_GRAY);
        changePlane(0).initWrapper(StImagePlane::ImgGray16, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::RGB48) {
        setColorModel(StImage::ImgColor_RGB);
        changePlane(0).initWrapper(StImagePlane::ImgRGB48, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(myCodecCtx->pix_fmt == stAV::PIX_FMT::RGBA64) {
        setColorModel(StImage::ImgColor_RGBA);
        changePlane(0).initWrapper(StImagePlane::ImgRGBA64, myFrame.getPlane(0),
                                   myCodecCtx->width, myCodecCtx->height,
                                   myFrame.getLineSize(0));
    } else if(stAV::isFormatYUVPlanar(myCodecCtx, aDimsYUV)) {
    #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(52, 29, 0))
        if(myCodecCtx->color_range == AVCOL_RANGE_JPEG) {
            aDimsYUV.isFullScale = true;
        }
    #endif
        setColorModel(StImage::ImgColor_YUV);
        setColorScale(aDimsYUV.isFullScale ? StImage::ImgScale_Full : StImage::ImgScale_Mpeg);
        StImagePlane::ImgFormat aPlaneFrmt = StImagePlane::ImgGray;
        if(aDimsYUV.bitsPerComp == 9) {
            aPlaneFrmt = StImagePlane::ImgGray16;
            setColorScale(aDimsYUV.isFullScale ? StImage::ImgScale_Jpeg9  : StImage::ImgScale_Mpeg9);
        } else if(aDimsYUV.bitsPerComp == 10) {
            aPlaneFrmt = StImagePlane::ImgGray16;
            setColorScale(aDimsYUV.isFullScale ? StImage::ImgScale_Jpeg10 : StImage::ImgScale_Mpeg10);
        } else if(aDimsYUV.bitsPerComp == 16) {
            aPlaneFrmt = StImagePlane::ImgGray16;
        }

        changePlane(0).initWrapper(aPlaneFrmt, myFrame.getPlane(0),
                                   size_t(aDimsYUV.widthY), size_t(aDimsYUV.heightY), myFrame.getLineSize(0));
        changePlane(1).initWrapper(aPlaneFrmt, myFrame.getPlane(1),
                                   size_t(aDimsYUV.widthU), size_t(aDimsYUV.heightU), myFrame.getLineSize(1));
        changePlane(2).initWrapper(aPlaneFrmt, myFrame.getPlane(2),
                                   size_t(aDimsYUV.widthV), size_t(aDimsYUV.heightV), myFrame.getLineSize(2));
    } else {
        ///ST_DEBUG_LOG("StAVImage, perform conversion from Pixel format '" + avcodec_get_pix_fmt_name(myCodecCtx->pix_fmt) + "' to RGB");
        // initialize software scaler/converter
        SwsContext* pToRgbCtx = sws_getContext(myCodecCtx->width, myCodecCtx->height, myCodecCtx->pix_fmt,    // source
                                               myCodecCtx->width, myCodecCtx->height, stAV::PIX_FMT::RGB24, // destination
                                               SWS_BICUBIC, NULL, NULL, NULL);
        if(pToRgbCtx == NULL) {
            setState("SWScale library, failed to create SWScaler context");
            close();
            return false;
        }

        // initialize additional buffer for converted RGB data
        setColorModel(StImage::ImgColor_RGB);
        changePlane(0).initTrash(StImagePlane::ImgRGB,
                                 myCodecCtx->width, myCodecCtx->height);

        uint8_t* rgbData[4]; stMemZero(rgbData,     sizeof(rgbData));
        int  rgbLinesize[4]; stMemZero(rgbLinesize, sizeof(rgbLinesize));
        rgbData[0]     = changePlane(0).changeData();
        rgbLinesize[0] = (int )changePlane(0).getSizeRowBytes();

        sws_scale(pToRgbCtx,
                  myFrame.Frame->data, myFrame.Frame->linesize,
                  0, myCodecCtx->height,
                  rgbData, rgbLinesize);
        // reset original data
        closeAvCtx();

        sws_freeContext(pToRgbCtx);
    }

    // set debug information
    StString aDummy, aFileName;
    StFileNode::getFolderAndFile(theFilePath, aDummy, aFileName);
    setState(StString("AVCodec library, loaded image '") + aFileName + "' " + getDescription());

    // we should not close the file because decoded image data is in codec context cache
    return true;
}

bool StAVImage::save(const StString& theFilePath,
                     ImageType       theImageType,
                     StFormat        theSrcFormat) {
    close();
    setState();
    if(isNull()) {
        return false;
    }

    PixelFormat aPFormatAV = (PixelFormat )getAVPixelFormat(*this);
    StImage anImage;
    switch(theImageType) {
        case ST_TYPE_PNG:
        case ST_TYPE_PNS: {
            myCodec = avcodec_find_encoder_by_name("png");
            if(myCodec == NULL) {
                setState("AVCodec library, video codec 'png' not found");
                close();
                return false;
            }
            if(aPFormatAV == stAV::PIX_FMT::RGB24
            || aPFormatAV == stAV::PIX_FMT::RGBA32
            || aPFormatAV == stAV::PIX_FMT::GRAY8) {
                anImage.initWrapper(*this);
            } else {
                // convert to compatible pixel format
                anImage.changePlane().initTrash(StImagePlane::ImgRGB, getSizeX(), getSizeY(), getAligned(getSizeX() * 3));
                PixelFormat aPFrmtTarget = stAV::PIX_FMT::RGB24;
                if(!convert(*this,   aPFormatAV,
                            anImage, aPFrmtTarget)) {
                    setState("SWScale library, failed to create SWScaler context");
                    close();
                    return false;
                }
                aPFormatAV = aPFrmtTarget;
            }
        #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
            myCodecCtx = avcodec_alloc_context3(myCodec);
        #else
            myCodecCtx = avcodec_alloc_context();
        #endif

            // setup encoder
            myCodecCtx->pix_fmt = aPFormatAV;
            myCodecCtx->width   = (int )anImage.getSizeX();
            myCodecCtx->height  = (int )anImage.getSizeY();
            myCodecCtx->compression_level = 9; // 0..9
            break;
        }
        case ST_TYPE_JPEG:
        case ST_TYPE_MPO:
        case ST_TYPE_JPS: {
            myCodec = avcodec_find_encoder_by_name("mjpeg");
            if(myCodec == NULL) {
                setState("AVCodec library, video codec 'mjpeg' not found");
                close();
                return false;
            }

            if(aPFormatAV == stAV::PIX_FMT::YUVJ420P
            || aPFormatAV == stAV::PIX_FMT::YUVJ422P
            //|| aPFormatAV == stAV::PIX_FMT::YUVJ444P not supported by FFmpeg... yet?
            //|| aPFormatAV == stAV::PIX_FMT::YUVJ440P
               ) {
                anImage.initWrapper(*this);
            } else {
                // convert to compatible pixel format
                PixelFormat aPFrmtTarget = aPFormatAV == stAV::PIX_FMT::YUV420P ? stAV::PIX_FMT::YUVJ420P : stAV::PIX_FMT::YUVJ422P;
                anImage.setColorModel(StImage::ImgColor_YUV);
                anImage.setColorScale(StImage::ImgScale_Mpeg);
                anImage.changePlane(0).initTrash(StImagePlane::ImgGray, getSizeX(), getSizeY(), getAligned(getSizeX()));
                stMemSet(anImage.changePlane(0).changeData(), '\0', anImage.getPlane(0).getSizeBytes());
                anImage.changePlane(1).initTrash(StImagePlane::ImgGray, getSizeX(), getSizeY(), getAligned(getSizeX()));
                stMemSet(anImage.changePlane(1).changeData(), '\0', anImage.getPlane(1).getSizeBytes());
                anImage.changePlane(2).initTrash(StImagePlane::ImgGray, getSizeX(), getSizeY(), getAligned(getSizeX()));
                stMemSet(anImage.changePlane(2).changeData(), '\0', anImage.getPlane(2).getSizeBytes());
                if(!convert(*this,   aPFormatAV,
                            anImage, aPFrmtTarget)) {
                    setState("SWScale library, failed to create SWScaler context");
                    close();
                    return false;
                }
                aPFormatAV = aPFrmtTarget;
            }

        #if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
            myCodecCtx = avcodec_alloc_context3(myCodec);
        #else
            myCodecCtx = avcodec_alloc_context();
        #endif
            myCodecCtx->pix_fmt = aPFormatAV;
            myCodecCtx->width   = (int )anImage.getSizeX();
            myCodecCtx->height  = (int )anImage.getSizeY();
            myCodecCtx->time_base.num = 1;
            myCodecCtx->time_base.den = 1;
            myCodecCtx->qmin = myCodecCtx->qmax = 5; // quality factor - lesser is better
            break;
        }
        case ST_TYPE_NONE:
        default:
            close();
            return false;
    }

    // open VIDEO codec
#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(53, 8, 0))
    if(avcodec_open2(myCodecCtx, myCodec, NULL) < 0) {
#else
    if(avcodec_open(myCodecCtx, myCodec) < 0) {
#endif
        setState("AVCodec library, could not open video codec");
        close();
        return false;
    }

    // wrap own data into AVFrame
    myFrame.Frame->format = myCodecCtx->pix_fmt;
    myFrame.Frame->width  = myCodecCtx->width;
    myFrame.Frame->height = myCodecCtx->height;
    fillPointersAV(anImage, myFrame.Frame->data, myFrame.Frame->linesize);

#ifdef ST_AV_NEWSTEREO
    bool isReversed = false;
    AVStereo3DType anAvStereoType = stAV::stereo3dStToAv(theSrcFormat, isReversed);
    if(anAvStereoType != (AVStereo3DType )-1) {
        AVStereo3D* aStereo = av_stereo3d_create_side_data(myFrame.Frame);
        if(aStereo != NULL) {
            aStereo->type = anAvStereoType;
            if(isReversed) {
                aStereo->flags |= AV_STEREO3D_FLAG_INVERT;
            }
        }
    }
#endif

    StJpegParser aRawFile(theFilePath);
    if(!aRawFile.openFile(StRawFile::WRITE)) {
        setState("Can not open the file for writing");
        close();
        return false;
    }

    // allocate the buffer, large enough (stupid formula copied from ffmpeg.c)
    int aBuffSize = int(getSizeX() * getSizeY() * 10);
    aRawFile.initBuffer(aBuffSize);

    // encode the image
    StAVPacket aPacket;
    aPacket.getAVpkt()->data = (uint8_t* )aRawFile.changeBuffer();
    aPacket.getAVpkt()->size = aBuffSize;
#if(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 2, 100))
    int isGotPacket = 0;
    int anEncSize   = avcodec_encode_video2(myCodecCtx, aPacket.getAVpkt(), myFrame.Frame, &isGotPacket);
    if(anEncSize == 0 && isGotPacket != 0) {
        anEncSize = aPacket.getSize();
    }
#else
    int anEncSize = avcodec_encode_video(myCodecCtx, aPacket.changeData(), aPacket.getSize(), myFrame.Frame);
#endif
    if(anEncSize <= 0) {
        setState("AVCodec library, fail to encode the image");
        close();
        return false;
    }
    aRawFile.setDataSize((size_t )anEncSize);

    // save metadata when possible
    if(theImageType == ST_TYPE_JPEG
    || theImageType == ST_TYPE_JPS) {
        if(aRawFile.parse()) {
            if(theSrcFormat != StFormat_AUTO) {
                aRawFile.setupJps(theSrcFormat);
            }
        } else {
            ST_ERROR_LOG("AVCodec library, created JPEG can not be parsed!");
        }
    }

    // store current content
    aRawFile.writeFile();
    // and finally close the file handle
    aRawFile.closeFile();

    close();

    // set debug information
    StString aDummy, aFileName;
    StFileNode::getFolderAndFile(theFilePath, aDummy, aFileName);
    setState(StString("AVCodec library, saved image '") + aFileName + "' " + getDescription());

    return true;
}
Beispiel #12
0
void StAndroidGlue::processCommand() {
    int8_t aCmd = -1;
    if(::read(myMsgRead, &aCmd, sizeof(aCmd)) == sizeof(aCmd)) {
        switch(aCmd) {
            case CommandId_SaveState:
                freeSavedState();
                break;
        }
    } else {
        ST_ERROR_LOG("No data on command pipe!");
        return;
    }

    // preprocessing
    switch(aCmd) {
        case CommandId_InputChanged: {
            pthread_mutex_lock(&myMutex);
            if(myInputQueue != NULL) {
                AInputQueue_detachLooper(myInputQueue);
            }
            myInputQueue = myInputQueuePending;
            if(myInputQueue != NULL) {
                AInputQueue_attachLooper(myInputQueue,
                                         myLooper, LooperId_INPUT, NULL,
                                         &myInputPollSource);
            }
            pthread_cond_broadcast(&myCond);
            pthread_mutex_unlock(&myMutex);
            break;
        }
        case CommandId_WindowChanged:
        case CommandId_WindowInit: {
            pthread_mutex_lock(&myMutex);
            myWindow = myWindowPending;
            pthread_cond_broadcast(&myCond);
            pthread_mutex_unlock(&myMutex);
            break;
        }
        case CommandId_WindowTerm: {
            pthread_cond_broadcast(&myCond);
            break;
        }
        case CommandId_Resume:
        case CommandId_Start:
        case CommandId_Pause:
        case CommandId_Stop: {
            pthread_mutex_lock(&myMutex);
            myActivityState = aCmd;
            pthread_cond_broadcast(&myCond);
            pthread_mutex_unlock(&myMutex);
            break;
        }
        case CommandId_ConfigChanged: {
            AConfiguration_fromAssetManager(myConfig, myActivity->assetManager);
            updateMonitors();
            printConfig();
            break;
        }
        case CommandId_Destroy: {
            myToDestroy = true;
            break;
        }
    }

    signals.onAppCmd(aCmd);

    // post-processing
    switch(aCmd) {
        case CommandId_WindowTerm: {
            pthread_mutex_lock(&myMutex);
            myWindow = NULL;
            pthread_cond_broadcast(&myCond);
            pthread_mutex_unlock(&myMutex);
            break;
        }
        case CommandId_WindowChanged: {
            pthread_mutex_lock(&myMutex);
            myWindowPending = NULL;
            pthread_cond_broadcast(&myCond);
            pthread_mutex_unlock(&myMutex);
            break;
        }
        case CommandId_SaveState: {
            pthread_mutex_lock(&myMutex);
            myIsStateSaved = true;
            pthread_cond_broadcast(&myCond);
            pthread_mutex_unlock(&myMutex);
            break;
        }
        case CommandId_Resume: {
            freeSavedState();
            break;
        }
    }
}
Beispiel #13
0
void StWindowImpl::setFullScreen(bool theFullscreen) {
    if(attribs.IsFullScreen != theFullscreen) {
        attribs.IsFullScreen = theFullscreen;
        if(attribs.IsFullScreen) {
            myFullScreenWinNb.increment();
        } else {
            myFullScreenWinNb.decrement();
        }
    }

    if(attribs.IsHidden) {
        // TODO (Kirill Gavrilov#9) parse correctly
        // do nothing, just set the flag
        return;
    } else if(myMaster.stXDisplay.isNull()) {
        return;
    }

    Display* hDisplay = myMaster.stXDisplay->hDisplay;
    if(attribs.IsFullScreen) {
        const StMonitor& stMon = (myMonMasterFull == -1) ? myMonitors[myRectNorm.center()] : myMonitors[myMonMasterFull];
        myRectFull = stMon.getVRect();
        XUnmapWindow(hDisplay, myMaster.hWindowGl); // workaround for strange bugs
        StRectI_t aRect = myRectFull;

        // use tiled Master+Slave layout within single window if possible
        if(attribs.Slave != StWinSlave_slaveOff && isSlaveIndependent() && myMonitors.size() > 1) {
            StRectI_t aRectSlave;
            aRectSlave.left()   = getSlaveLeft();
            aRectSlave.top()    = getSlaveTop();
            aRectSlave.right()  = aRectSlave.left() + myRectFull.width();
            aRectSlave.bottom() = aRectSlave.top()  + myRectFull.height();
            myTiledCfg = TiledCfg_Separate;
            if(myRectFull.top()   == aRectSlave.top()) {
                if(myRectFull.right() == aRectSlave.left()) {
                    myTiledCfg = TiledCfg_MasterSlaveX;
                } else if(myRectFull.left() == aRectSlave.right()) {
                    myTiledCfg = TiledCfg_SlaveMasterX;
                }
            } else if(myRectFull.left() == aRectSlave.left()) {
                if(myRectFull.bottom() == aRectSlave.top()) {
                    myTiledCfg = TiledCfg_MasterSlaveY;
                } else if(myRectFull.top() == aRectSlave.bottom()) {
                    myTiledCfg = TiledCfg_SlaveMasterY;
                }
            }
        }

        if(myTiledCfg != TiledCfg_Separate) {
            XUnmapWindow(hDisplay, mySlave.hWindowGl);
            getTiledWinRect(aRect);
        } else if(attribs.Split == StWinSlave_splitHorizontal) {
            myTiledCfg = TiledCfg_MasterSlaveX;
            myRectFull.right() -= myRectFull.width() / 2;
        } else if(attribs.Split == StWinSlave_splitVertical) {
            myTiledCfg = TiledCfg_MasterSlaveY;
            myRectFull.bottom() -= myRectFull.height() / 2;
        }

        if((Window )myParentWin != 0 || myMaster.hWindow != 0) {
            XReparentWindow(hDisplay, myMaster.hWindowGl, myMaster.stXDisplay->getRootWindow(), 0, 0);
            XMoveResizeWindow(hDisplay, myMaster.hWindowGl,
                              aRect.left(),  aRect.top(),
                              aRect.width(), aRect.height());
            XFlush(hDisplay);
            XMapWindow(hDisplay, myMaster.hWindowGl);
            //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindowGl);
        } else {
            XMoveResizeWindow(hDisplay, myMaster.hWindowGl,
                              aRect.left(),  aRect.top(),
                              aRect.width(), aRect.height());
            XFlush(hDisplay);
            XMapWindow(hDisplay, myMaster.hWindowGl);
            //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindowGl);
        }

        if(attribs.Slave != StWinSlave_slaveOff
        && myTiledCfg == TiledCfg_Separate
        && (!isSlaveIndependent() || myMonitors.size() > 1)) {
            XMoveResizeWindow(hDisplay, mySlave.hWindowGl,
                              getSlaveLeft(),  getSlaveTop(),
                              getSlaveWidth(), getSlaveHeight());
        }
    } else {
        Window aParent = ((Window )myParentWin != 0) ? (Window )myParentWin : myMaster.hWindow;
        if(aParent != 0) {
            // workaround bugs in some OpenGL drivers (Catalyst etc.) - entirely re-create window but not GL context
            XSetWindowAttributes aWinAttribsX = createDefaultAttribs(myMaster.stXDisplay);
            aWinAttribsX.override_redirect = True; // GL window always undecorated
            Window aWin = XCreateWindow(hDisplay, aParent,
                                        0, 0, myRectNorm.width(), myRectNorm.height(),
                                        0, myMaster.stXDisplay->getDepth(),
                                        InputOutput,
                                        myMaster.stXDisplay->getVisual(),
                                        CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect, &aWinAttribsX);
        #if defined(ST_HAVE_EGL)
            EGLSurface anEglSurf = eglCreateWindowSurface(myMaster.hRC->getDisplay(), myMaster.hRC->getConfig(), aWin, NULL);
            if(anEglSurf == EGL_NO_SURFACE
            || !myMaster.hRC->makeCurrent(anEglSurf)) {
                if(anEglSurf == EGL_NO_SURFACE) {
                    eglDestroySurface(myMaster.hRC->getDisplay(), anEglSurf);
                }
        #else
            if(!myMaster.hRC->makeCurrent(aWin)) {
        #endif
                ST_ERROR_LOG("X, FAILED to bind rendering context to NEW master window");
                XDestroyWindow(hDisplay, aWin);
                XReparentWindow(hDisplay, myMaster.hWindowGl, aParent, 0, 0);
            } else {
                XUnmapWindow  (hDisplay, myMaster.hWindowGl);
                XDestroyWindow(hDisplay, myMaster.hWindowGl);
                myMaster.hWindowGl = aWin;
            #if defined(ST_HAVE_EGL)
                eglDestroySurface(myMaster.hRC->getDisplay(), myMaster.eglSurface);
                myMaster.eglSurface = anEglSurf;
            #endif
                XSetStandardProperties(hDisplay, myMaster.hWindowGl,
                                       "master window", "master window",
                                       None, NULL, 0, NULL);
                myMaster.setupXDND();
                if(attribs.ToHideCursor) {
                    myMaster.setupNoCursor();
                }
                XMapWindow(hDisplay, myMaster.hWindowGl);
            }
            myIsUpdated = true;
        } else {
            XUnmapWindow(hDisplay, myMaster.hWindowGl); // workaround for strange bugs
            XResizeWindow(hDisplay, myMaster.hWindowGl, 256, 256);
            if(attribs.Slave != StWinSlave_slaveOff && (!isSlaveIndependent() || myMonitors.size() > 1)) {
                XUnmapWindow (hDisplay, mySlave.hWindowGl);
                XResizeWindow(hDisplay, mySlave.hWindowGl, 256, 256);
            }
            XFlush(hDisplay);
            XMapWindow(hDisplay, myMaster.hWindowGl);
            //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )myMaster.hWindowGl);
            if(attribs.Slave != StWinSlave_slaveOff && (!isSlaveIndependent() || myMonitors.size() > 1)) {
                XMapWindow(hDisplay, mySlave.hWindowGl);
                //XIfEvent(hDisplay, &myXEvent, stXWaitMapped, (char* )mySlave.hWindowGl);
            }
            XFlush(hDisplay);
            XMoveResizeWindow(hDisplay, myMaster.hWindowGl,
                              myRectNorm.left(),  myRectNorm.top(),
                              myRectNorm.width(), myRectNorm.height());
        }
    }
    XSetInputFocus(hDisplay, myMaster.hWindowGl, RevertToParent, CurrentTime);

    const StRectI_t& aRect = attribs.IsFullScreen ? myRectFull : myRectNorm;
    myStEvent.Type       = stEvent_Size;
    myStEvent.Size.Time  = getEventTime();
    myStEvent.Size.SizeX = aRect.width();
    myStEvent.Size.SizeY = aRect.height();
    signals.onResize->emit(myStEvent.Size);

    // flushes the output buffer, most client apps needn't use this cause buffer is automatically flushed as needed by calls to XNextEvent()...
    XFlush(hDisplay);
}

void StWindowImpl::parseXDNDClientMsg() {
    const StXDisplayH& aDisplay = myMaster.stXDisplay;
    // myMaster.hWindow or myMaster.hWindowGl
    Window aWinReciever = ((XClientMessageEvent* )&myXEvent)->window;
    if(myXEvent.xclient.message_type == aDisplay->xDNDEnter) {
        myMaster.xDNDVersion = (myXEvent.xclient.data.l[1] >> 24);
        bool isMoreThan3 = myXEvent.xclient.data.l[1] & 1;
        Window aSrcWin = myXEvent.xclient.data.l[0];
        /*ST_DEBUG_LOG(
            "Xdnd: Source window = 0x" + (int )myXEvent.xclient.data.l[0] + "\n"
            + "Supports > 3 types = " + (more_than_3) + "\n"
            + "Protocol version = " + myMaster.xDNDVersion + "\n"
            + "Type 1 = " + myMaster.getAtomName(myXEvent.xclient.data.l[2]) + "\n"
            + "Type 2 = " + myMaster.getAtomName(myXEvent.xclient.data.l[3]) + "\n"
            + "Type 3 = " + myMaster.getAtomName(myXEvent.xclient.data.l[4]) + "\n"
        );*/
        if(isMoreThan3) {
            Property aProperty = aDisplay->readProperty(aSrcWin, aDisplay->xDNDTypeList);
            Atom* anAtomList = (Atom* )aProperty.data;
            for(int anIter = 0; anIter < aProperty.nitems; ++anIter) {
                if(anAtomList[anIter] == aDisplay->xDNDUriList) {
                    myMaster.xDNDRequestType = aDisplay->xDNDUriList;
                    break;
                } else if(anAtomList[anIter] == aDisplay->xDNDPlainText) {
                    myMaster.xDNDRequestType = aDisplay->xDNDPlainText;
                    break;
                }
            }
            XFree(aProperty.data);
        } else if((Atom )myXEvent.xclient.data.l[2] == aDisplay->xDNDPlainText
               || (Atom )myXEvent.xclient.data.l[3] == aDisplay->xDNDPlainText
               || (Atom )myXEvent.xclient.data.l[4] == aDisplay->xDNDPlainText) {
            myMaster.xDNDRequestType = aDisplay->xDNDPlainText;
        } else {
            myMaster.xDNDRequestType = XA_STRING;
        }
    } else if(myXEvent.xclient.message_type == aDisplay->xDNDPosition) {
Beispiel #14
0
StWinGlrc::StWinGlrc(EGLDisplay theDisplay,
                     const bool theDebugCtx,
                     int8_t     theGlDepthSize)
: myDisplay(theDisplay),
  myConfig(NULL),
  myRC(EGL_NO_CONTEXT) {
    if(theDisplay == EGL_NO_DISPLAY) {
        return;
    }

    EGLint aVerMajor = 0; EGLint aVerMinor = 0;
    if(eglInitialize(myDisplay, &aVerMajor, &aVerMinor) != EGL_TRUE) {
        ST_ERROR_LOG("EGL, FAILED to initialize Display");
        return;
    }

    ST_DEBUG_LOG("EGL info\n"
               + "  Version:     " + aVerMajor + "." + aVerMinor + " (" + eglQueryString(myDisplay, EGL_VERSION) + ")\n"
               + "  Vendor:      " + eglQueryString(myDisplay, EGL_VENDOR) + "\n"
               + "  Client APIs: " + eglQueryString(myDisplay, EGL_CLIENT_APIS) + "\n"
               + "  Extensions:  " + eglQueryString(myDisplay, EGL_EXTENSIONS));

    const EGLint aConfigAttribs[] = {
        EGL_RED_SIZE,   8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE,  8,
        EGL_ALPHA_SIZE, 0,
        EGL_DEPTH_SIZE, theGlDepthSize,
    #if defined(GL_ES_VERSION_2_0)
        EGL_CONFORMANT,      EGL_OPENGL_ES2_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
    #else
        EGL_CONFORMANT,      EGL_OPENGL_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
    #endif
        EGL_NONE
    };

    EGLint aNbConfigs = 0;
    if(eglChooseConfig(myDisplay, aConfigAttribs, &myConfig, 1, &aNbConfigs) != EGL_TRUE) {
        ST_ERROR_LOG("EGL, eglChooseConfig FAILED");
        return;
    }

    /*EGLenum aEglApi = eglQueryAPI();
    switch(aEglApi) {
        case EGL_OPENGL_ES_API: ST_DEBUG_LOG("EGL API: OpenGL ES\n"); break;
        case EGL_OPENGL_API:    ST_DEBUG_LOG("EGL API: OpenGL\n");    break;
        case EGL_OPENVG_API:    ST_DEBUG_LOG("EGL API: OpenNVG\n");   break;
        case EGL_NONE:          ST_DEBUG_LOG("EGL API: NONE\n");      break;
    }*/

#if defined(GL_ES_VERSION_2_0)
    if(eglBindAPI(EGL_OPENGL_ES_API) != EGL_TRUE) {
        ST_ERROR_LOG("EGL, EGL_OPENGL_ES_API is unavailable!");
        return;
    }
#else
    if(eglBindAPI(EGL_OPENGL_API) != EGL_TRUE) {
        ST_ERROR_LOG("EGL, EGL_OPENGL_API is unavailable!");
        return;
    }
#endif

    #define ST_EGL_CONTEXT_MAJOR_VERSION_KHR                      0x3098
    #define ST_EGL_CONTEXT_MINOR_VERSION_KHR                      0x30FB
    #define ST_EGL_CONTEXT_FLAGS_KHR                              0x30FC
    #define ST_EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR                0x30FD
    #define ST_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD

    // for EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
    #define ST_EGL_NO_RESET_NOTIFICATION_KHR 0x31BE
    #define ST_EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF

    // for EGL_CONTEXT_FLAGS_KHR
    #define ST_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR                 0x00000001
    #define ST_EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR    0x00000002
    #define ST_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR         0x00000004

    // for EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR
    #define ST_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR          0x00000001
    #define ST_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002

    const char* anEglExts = eglQueryString(myDisplay, EGL_EXTENSIONS);
    if(StGLContext::stglCheckExtension(anEglExts, "EGL_KHR_create_context")) {
        const EGLint anEglCtxAttribs[] = {
            ST_EGL_CONTEXT_FLAGS_KHR, theDebugCtx ? ST_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0,
        #if defined(GL_ES_VERSION_2_0)
            EGL_CONTEXT_CLIENT_VERSION, 2,
        #endif
            //EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, ST_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR,
            EGL_NONE
        };

        myRC = eglCreateContext(myDisplay, myConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
    }

    if(myRC == EGL_NO_CONTEXT) {
    #if defined(GL_ES_VERSION_2_0)
        EGLint anEglCtxAttribs[] = {
            EGL_CONTEXT_CLIENT_VERSION, 2,
            EGL_NONE
        };
    #else
        EGLint* anEglCtxAttribs = NULL;
    #endif
        myRC = eglCreateContext(myDisplay, myConfig, EGL_NO_CONTEXT, anEglCtxAttribs);
    /*#if defined(GL_ES_VERSION_2_0)
        if(myRC == EGL_NO_CONTEXT) {
            myRC = eglCreateContext(myDisplay, myConfig, EGL_NO_CONTEXT, NULL);
            if(myRC != EGL_NO_CONTEXT) {
                ST_ERROR_LOG("EGL, eglCreateContext FAILED when ES 2.0 is requested!");
            }
        }
    #endif*/
    }

    if(myRC == EGL_NO_CONTEXT) {
        ST_ERROR_LOG("EGL, eglCreateContext FAILED");
    }
}
Beispiel #15
0
void StAndroidGlue::threadEntry() {
    if(myJavaVM->AttachCurrentThread(&myThJniEnv, NULL) < 0) {
        ST_ERROR_LOG("Failed to attach working thread to Java VM");
        return;
    }

    THE_ANDROID_GLUE = this;
    StMessageBox::setCallback(msgBoxCallback);

    myConfig = AConfiguration_new();
    AConfiguration_fromAssetManager(myConfig, myActivity->assetManager);
    updateMonitors();
    printConfig();

    ALooper* aLooper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
    ALooper_addFd(aLooper, myMsgRead, LooperId_MAIN, ALOOPER_EVENT_INPUT, NULL, &myCmdPollSource);
    myLooper = aLooper;

    pthread_mutex_lock(&myMutex);
    myIsRunning = true;
    pthread_cond_broadcast(&myCond);
    pthread_mutex_unlock(&myMutex);

    // try to load stereo APIs
    /**jclass aJClass_Real3D = myThJniEnv->FindClass("com/lge/real3d/Real3D");
    if(aJClass_Real3D != NULL) {
        jmethodID aJMet_isStereoDisplayAvailable = myThJniEnv->GetStaticMethodID(aJClass_Real3D, "isStereoDisplayAvailable", "(Landroid/content/Contex;)Z");
        postMessage("com.lge.real3d.Real3D !!!");
    }

    jclass aJClass_HTC = myThJniEnv->FindClass("com/htc/view/DisplaySetting");
    if(aJClass_HTC != NULL) {
        jmethodID aJMet_isStereoDisplayAvailable = myThJniEnv->GetStaticMethodID(aJClass_HTC, "setStereoscopic3DFormat", "(Landroid/view/Surface;I)Z");
        postMessage("com.htc.view.DisplaySetting !!!");
    }

    jclass aJClass_Sharp = myThJniEnv->FindClass("jp/co/sharp/android/stereo3dlcd/SurfaceController");
    if(aJClass_Sharp != NULL) {
        jmethodID aJMet_setStereoView = myThJniEnv->GetMethodID(aJClass_Sharp, "setStereoView", "(Z)V");
        postMessage("jp.co.sharp.android.stereo3dlcd !!!");
    }*/

    createApplication();
    if(!myApp.isNull()) {
        if(!myApp->open()) {
            stError("Error: application can not be executed!");
        }
        myApp->exec();
    } else {
        stError("Error: no application to execute!");
    }
    myApp.nullify();

    // application is done but we are waiting for destroying event...
    bool isFirstWait = true;
    for(; !myToDestroy; ) {
        if(isFirstWait) {
            postExit();
            isFirstWait = false;
        }

        StAndroidPollSource* aSource = NULL;
        int aNbEvents = 0;
        ALooper_pollAll(-1, NULL, &aNbEvents, (void** )&aSource);
        if(aSource != NULL) {
            aSource->process(this, aSource);
        }
    }

    freeSavedState();
    pthread_mutex_lock(&myMutex);
    if(myInputQueue != NULL) {
        AInputQueue_detachLooper(myInputQueue);
    }
    AConfiguration_delete(myConfig);
    pthread_cond_broadcast(&myCond);
    pthread_mutex_unlock(&myMutex);

    myThJniEnv = NULL;
    StMessageBox::setCallback(NULL);
    THE_ANDROID_GLUE = NULL;

    myJavaVM->DetachCurrentThread();
}
Beispiel #16
0
int StWinHandles::glCreateContext(StWinHandles*    theSlave,
                                  const StRectI_t& theRect,
                                  const int        theDepthSize,
                                  const bool       theIsQuadStereo,
                                  const bool       theDebugCtx) {
    (void )theRect;
#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");
    }

    HGLRC aRendCtx = NULL;
    {
      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;
      }

      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,
                                // always create temporary window on main screen
                                // to workaround sporadic bugs (access violation) in AMD Catalyst drivers
                                2, 2, 4, 4, //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);
      int aPixFrmtIdTmp = ChoosePixelFormat(aDevCtxTmp, &aPixFrmtDesc);
      ST_GL_ERROR_CHECK(aPixFrmtIdTmp != 0, STWIN_ERROR_WIN32_PIXELFORMATF,
                        "WinAPI, Can't find a suitable PixelFormat for Tmp");

      ST_GL_ERROR_CHECK(SetPixelFormat(aDevCtxTmp, aPixFrmtIdTmp, &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(false);
      ST_GL_ERROR_CHECK(aCtx.stglInit(),
                        STWIN_ERROR_WIN32_GLRC_ACTIVATE, "WinAPI, Broken Tmp GL Rendering Context");

      int aPixFrmtId = 0;
      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);
          if(theSlave != NULL) {
              int aPixFrmtIdSlave = 0;
              aCtx.extAll->wglChoosePixelFormatARB(theSlave->hDC, aPixAttribs, NULL, 1, &aPixFrmtIdSlave, &aFrmtsNb);
              if(aPixFrmtIdSlave != aPixFrmtId) {
                  ST_ERROR_LOG("Slave window returns another pixel format! Try to ignore...");
              }
          }
      } else {
          aPixFrmtId = ChoosePixelFormat(hDC, &aPixFrmtDesc);
          if(theSlave != NULL
          && ChoosePixelFormat(theSlave->hDC, &aPixFrmtDesc) != aPixFrmtId) {
              ST_ERROR_LOG("Slave window returns another pixel format! Try to ignore...");
          }
      }
      ST_GL_ERROR_CHECK(aPixFrmtId != 0, STWIN_ERROR_WIN32_PIXELFORMATF,
                        "WinAPI, Can't find a suitable PixelFormat for Master");
      DescribePixelFormat(hDC, aPixFrmtId, sizeof(PIXELFORMATDESCRIPTOR), &aPixFrmtDesc);
      if(theIsQuadStereo) {
          if((aPixFrmtDesc.dwFlags & PFD_STEREO) == 0) {
              ST_ERROR_LOG("WinAPI, Quad Buffered stereo is not supported");
          }
      }
      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");
      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
#if defined(ST_HAVE_EGL) || defined(__ANDROID__)
    // GL context is created beforehand for EGL
    ST_GL_ERROR_CHECK(!hRC.isNull() && hRC->isValid(),
                      STWIN_ERROR_X_GLRC_CREATE, "EGL, could not create rendering context for Master");

#if defined(__ANDROID__)
    EGLint aFormat = 0;
    eglGetConfigAttrib(hRC->getDisplay(), hRC->getConfig(), EGL_NATIVE_VISUAL_ID, &aFormat);
    ANativeWindow_setBuffersGeometry(hWindowGl, 0, 0, aFormat);
#endif

    eglSurface = eglCreateWindowSurface(hRC->getDisplay(), hRC->getConfig(), hWindowGl, NULL);
    if(theSlave != NULL) {
        theSlave->hRC = hRC;
        theSlave->eglSurface = eglCreateWindowSurface(hRC->getDisplay(), hRC->getConfig(), theSlave->hWindowGl, NULL);

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

    // bind the rendering context to the window
    ST_GL_ERROR_CHECK(hRC->makeCurrent(eglSurface),
                      STWIN_ERROR_X_GLRC_CREATE, "EGL, Can't activate Master GL Rendering Context");
    return STWIN_INIT_SUCCESS;
#else // GLX
    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 // GLX or EGL
#endif
}
Beispiel #17
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
}
Beispiel #18
0
StAndroidGlue::StAndroidGlue(ANativeActivity* theActivity,
                             void*            theSavedState,
                             size_t           theSavedStateSize)
: myActivity(theActivity),
  myConfig(NULL),
  myLooper(NULL),
  myInputQueue(NULL),
  myInputQueuePending(NULL),
  myWindow(NULL),
  myWindowPending(NULL),
  myIsChangingSurface(false),
  myWindowFlags(0),
  myActivityState(0),
  myMemoryClassMiB(0),
  mySavedState(NULL),
  mySavedStateSize(0),
  myJavaVM(NULL),
  myThJniEnv(NULL),
  myMsgRead(0),
  myMsgWrite(0),
  myToEnableStereoHW(false),
  myHasOrientSensor(false),
  myIsPoorOrient(false),
  myToTrackOrient(false),
  myIsRunning(false),
  myIsStateSaved(false),
  myToDestroy(false) {
    theActivity->instance = this;
    theActivity->env->GetJavaVM(&myJavaVM);

    // allow FFmpeg to use JNI calls
    stAV::setJavaVM(myJavaVM);

    JNIEnv* aJniEnv = myActivity->env;

    jclass    aJClass_Activity       = aJniEnv->GetObjectClass(myActivity->clazz);
    jmethodID aJMet_getSystemService = aJniEnv->GetMethodID(aJClass_Activity, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
    jstring   aJStr_activity         = aJniEnv->NewStringUTF("activity");
    jobject   aJActivityMgr          = aJniEnv->CallObjectMethod(myActivity->clazz, aJMet_getSystemService, aJStr_activity);
    aJniEnv->DeleteLocalRef(aJStr_activity);
    if(aJActivityMgr != NULL) {
        // getLargeMemoryClass()
        jclass aJClass_ActivityManager = aJniEnv->GetObjectClass(aJActivityMgr);
        jmethodID aJMet_getMemoryClass = aJniEnv->GetMethodID(aJClass_ActivityManager, "getMemoryClass", "()I");
        myMemoryClassMiB = aJniEnv->CallIntMethod(aJActivityMgr, aJMet_getMemoryClass);
    }

    jmethodID aJMet_getStAppClass = aJniEnv->GetMethodID(aJClass_Activity, "getStAppClass", "()Ljava/lang/String;");
    myStAppClass = stStringFromJava(aJniEnv, (jstring )aJniEnv->CallObjectMethod(myActivity->clazz, aJMet_getStAppClass));

    jmethodID aJMet_getStereoApiInfo = aJniEnv->GetMethodID(aJClass_Activity, "getStereoApiInfo", "()Ljava/lang/String;");
    myStereoApiId = stStringFromJava(aJniEnv, (jstring )aJniEnv->CallObjectMethod(myActivity->clazz, aJMet_getStereoApiInfo));

    // workaround NativeActivity design issues - notify Java StActivity class about C++ pointer to StAndroidGlue instance
    jmethodID aJMet_setCppInstance = aJniEnv->GetMethodID(aJClass_Activity, "setCppInstance", "(J)V");
    aJniEnv->CallVoidMethod(myActivity->clazz, aJMet_setCppInstance, (jlong )this);

    readOpenPath();

    myCmdPollSource.id        = LooperId_MAIN;
    myCmdPollSource.app       = this;
    myCmdPollSource.process   = StAndroidGlue::processCommandWrapper;
    myInputPollSource.id      = LooperId_INPUT;
    myInputPollSource.app     = this;
    myInputPollSource.process = StAndroidGlue::processInputWrapper;

    theActivity->callbacks->onDestroy               = StAndroidGlue::onDestroy;
    theActivity->callbacks->onStart                 = StAndroidGlue::onStart;
    theActivity->callbacks->onResume                = StAndroidGlue::onResume;
    theActivity->callbacks->onSaveInstanceState     = StAndroidGlue::onSaveInstanceState;
    theActivity->callbacks->onPause                 = StAndroidGlue::onPause;
    theActivity->callbacks->onStop                  = StAndroidGlue::onStop;
    theActivity->callbacks->onConfigurationChanged  = StAndroidGlue::onConfigurationChanged;
    theActivity->callbacks->onLowMemory             = StAndroidGlue::onLowMemory;
    theActivity->callbacks->onWindowFocusChanged    = StAndroidGlue::onWindowFocusChanged;
    theActivity->callbacks->onNativeWindowCreated   = StAndroidGlue::onNativeWindowCreated;
    theActivity->callbacks->onNativeWindowDestroyed = StAndroidGlue::onNativeWindowDestroyed;
    theActivity->callbacks->onInputQueueCreated     = StAndroidGlue::onInputQueueCreated;
    theActivity->callbacks->onInputQueueDestroyed   = StAndroidGlue::onInputQueueDestroyed;

    pthread_mutex_init(&myMutex, NULL);
    pthread_cond_init (&myCond,  NULL);

    if(theSavedState != NULL) {
        mySavedState     = ::malloc(theSavedStateSize);
        mySavedStateSize = theSavedStateSize;
        memcpy(mySavedState, theSavedState, theSavedStateSize);
    }

    int aMsgPipe[2];
    if(::pipe(aMsgPipe)) {
        ST_ERROR_LOG("could not create pipe: " + strerror(errno));
        return;
    }
    myMsgRead  = aMsgPipe[0];
    myMsgWrite = aMsgPipe[1];
}