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; }
/** * Create context. */ bool create(const StString& theFile) { if(myFormat == NULL) { return false; } #if !defined(ST_LIBAV_FORK) avformat_alloc_output_context2(&Context, myFormat, NULL, theFile.toCString()); #else Context = avformat_alloc_context(); if(Context == NULL) { return false; } Context->oformat = myFormat; if(Context->oformat->priv_data_size > 0) { Context->priv_data = av_mallocz(Context->oformat->priv_data_size); if(!Context->priv_data) { //goto nomem; } if(Context->oformat->priv_class) { *(const AVClass**)Context->priv_data = Context->oformat->priv_class; //av_opt_set_defaults(aCtxOut->priv_data); } } else { Context->priv_data = NULL; } const size_t aStrLen = stMin(theFile.Size + 1, size_t(1024)); stMemCpy(Context->filename, theFile.toCString(), aStrLen); Context->filename[1023] = '\0'; #endif return Context != NULL; }
void StGLStereoFrameBuffer::setVPDimensions(StGLContext& theCtx, const GLsizei theSizeX, const GLsizei theSizeY) { GLsizei aVPSizeX = stMin(theSizeX, getSizeX()); GLsizei aVPSizeY = stMin(theSizeY, getSizeY()); if(aVPSizeX != myViewPortX || aVPSizeY != myViewPortY) { GLfloat aDX = GLfloat(aVPSizeX) / GLfloat(getSizeX()); GLfloat aDY = GLfloat(aVPSizeY) / GLfloat(getSizeY()); StArray<StGLVec2> aTCoords(4); aTCoords[0] = StGLVec2(aDX, 0.0f); aTCoords[1] = StGLVec2(aDX, aDY); aTCoords[2] = StGLVec2(0.0f, 0.0f); aTCoords[3] = StGLVec2(0.0f, aDY); myTexCoordBuf.init(theCtx, aTCoords); myViewPortX = aVPSizeX; myViewPortY = aVPSizeY; } }
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!"); } } }
bool StGLScrollArea::doScroll(const int theDelta, const bool theIsFling) { if(!theIsFling) { myDragYDelta = 0.0; myFlingTimer.stop(); } if(!isScrollable()) { return false; } StGLWidget* aContent = myChildren.getStart(); const int aMinLim = 0; const int aMaxLim = getRectPx().height() - aContent->getRectPx().height(); const int aTopOld = aContent->getRectPx().top(); const int aTopNew = stMax(stMin(aMinLim, aTopOld + theDelta), aMaxLim); const int aDelta = aTopNew - aTopOld; if(aDelta == 0) { if(theIsFling) { myFlingTimer.stop(); } return false; } aContent->changeRectPx().top() += aDelta; aContent->changeRectPx().bottom() += aDelta; if(myIsLeftClick) { if(!theIsFling) { myDragYCumul += aDelta; if(std::abs(myDragYCumul) > myRoot->getClickThreshold() && !myHasDragged) { setClickedWithChildren(myChildren, ST_MOUSE_LEFT, false); myHasDragged = true; } } else { myDragYCumul = 0; } } myIsResized = true; return true; }
bool StPlayList::walkToNext(const bool theToForce) { StMutexAuto anAutoLock(myMutex); if(myCurrent == NULL || (myToLoopSingle && !theToForce)) { return false; } else if(myIsShuffle && myItemsCount >= 3) { StPlayItem* aPrev = myCurrent; if(!myStackNext.empty()) { myCurrent = myStackNext.front(); myStackNext.pop_front(); } else { if((myPlayedCount >= (myItemsCount - 1)) || (myPlayedCount == 0)) { // reset the playback counter #ifdef _WIN32 FILETIME aTime; GetSystemTimeAsFileTime(&aTime); myRandGen.setSeed(aTime.dwLowDateTime); #else timeval aTime; gettimeofday(&aTime, NULL); myRandGen.setSeed(aTime.tv_usec); #endif myPlayedCount = 0; myCurrent->setPlayedFlag(!myCurrent->getPlayedFlag()); ST_DEBUG_LOG("Restart the shuffle"); } // determine next random position const size_t aCurrPos = myCurrent->getPosition(); bool aCurrFlag = myCurrent->getPlayedFlag(); StPlayItem* aNextItem = myCurrent; const size_t aNextPos = stMin(size_t(myRandGen.next() * myItemsCount), myItemsCount - 1); if(aNextPos > aCurrPos) { // forward direction for(size_t aNextDiff = aNextPos - aCurrPos; aNextItem != NULL && aNextDiff != 0; --aNextDiff) { aNextItem = aNextItem->getNext(); } } else { // backward direction for(size_t aNextDiff = aCurrPos - aNextPos; aNextItem != NULL && aNextDiff != 0; --aNextDiff) { aNextItem = aNextItem->getPrev(); } } if(aCurrFlag == aNextItem->getPlayedFlag()) { // find nearest position not yet played - prefer item farther from current one StPlayItem* aNextItem1 = aNextPos > aCurrPos ? aNextItem->getNext() : aNextItem->getPrev(); StPlayItem* aNextItem2 = aNextPos > aCurrPos ? aNextItem->getPrev() : aNextItem->getNext(); for(; aNextItem1 != NULL || aNextItem2 != NULL;) { if(aNextItem1 != NULL) { if(aCurrFlag != aNextItem1->getPlayedFlag()) { aNextItem = aNextItem1; break; } aNextItem1 = aNextPos > aCurrPos ? aNextItem1->getNext() : aNextItem1->getPrev(); } if(aNextItem2 != NULL) { if(aCurrFlag != aNextItem2->getPlayedFlag()) { aNextItem = aNextItem2; break; } aNextItem2 = aNextPos > aCurrPos ? aNextItem2->getPrev() : aNextItem2->getNext(); } } if(aCurrFlag == aNextItem->getPlayedFlag()) { // something wrong! ST_DEBUG_LOG("Disaster - next shuffle position not found!"); aCurrFlag = !aCurrFlag; myPlayedCount = 0; } } ST_DEBUG_LOG(aCurrPos + " -> " + aNextItem->getPosition()); ++myPlayedCount; aNextItem->setPlayedFlag(aCurrFlag); myCurrent = aNextItem; } if(aPrev != myCurrent && aPrev != NULL) { myStackPrev.push_back(aPrev); if(myStackPrev.size() > THE_UNDO_LIMIT) { myStackPrev.pop_front(); } } const size_t anItemId = myCurrent->getPosition(); anAutoLock.unlock(); signals.onPositionChange(anItemId); return true; } else if(myCurrent != myLast) { myCurrent = myCurrent->getNext(); const size_t anItemId = myCurrent->getPosition(); anAutoLock.unlock(); signals.onPositionChange(anItemId); return true; } else if(myIsLoopFlag) { return walkToFirst(); } return false; }