Atlas::Atlas(uint16_t _textureSize, uint16_t _maxRegionsCount) : m_usedLayers(0) , m_usedFaces(0) , m_textureSize(_textureSize) , m_regionCount(0) , m_maxRegionCount(_maxRegionsCount) { BX_CHECK(_textureSize >= 64 && _textureSize <= 4096, "Invalid _textureSize %d.", _textureSize); BX_CHECK(_maxRegionsCount >= 64 && _maxRegionsCount <= 32000, "Invalid _maxRegionsCount %d.", _maxRegionsCount); init(); m_layers = new PackedLayer[24]; for (int ii = 0; ii < 24; ++ii) { m_layers[ii].packer.init(_textureSize, _textureSize); } m_regions = new AtlasRegion[_maxRegionsCount]; m_textureBuffer = new uint8_t[ _textureSize * _textureSize * 6 * 4 ]; memset(m_textureBuffer, 0, _textureSize * _textureSize * 6 * 4); m_textureHandle = bgfx::createTextureCube(6 , _textureSize , 1 , bgfx::TextureFormat::BGRA8 ); }
bool Semaphore::wait(int32_t _msecs) { # if BX_PLATFORM_NACL || BX_PLATFORM_OSX BX_CHECK(-1 == _msecs, "NaCl and OSX don't support sem_timedwait at this moment."); BX_UNUSED(_msecs); return 0 == sem_wait(&m_handle); # else if (0 > _msecs) { int32_t result; do { result = sem_wait(&m_handle); } // keep waiting when interrupted by a signal handler... while (-1 == result && EINTR == errno); BX_CHECK(0 == result, "sem_wait failed. errno %d", errno); return 0 == result; } timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += _msecs/1000; ts.tv_nsec += (_msecs%1000)*1000; return 0 == sem_timedwait(&m_handle, &ts); # endif // BX_PLATFORM_ }
FontHandle FontManager::createScaledFontToPixelSize(FontHandle _baseFontHandle, uint32_t _pixelSize) { BX_CHECK(bgfx::isValid(_baseFontHandle), "Invalid handle used"); CachedFont& baseFont = m_cachedFonts[_baseFontHandle.idx]; FontInfo& fontInfo = baseFont.fontInfo; FontInfo newFontInfo = fontInfo; newFontInfo.pixelSize = _pixelSize; newFontInfo.scale = (float)_pixelSize / (float) fontInfo.pixelSize; newFontInfo.ascender = (newFontInfo.ascender * newFontInfo.scale); newFontInfo.descender = (newFontInfo.descender * newFontInfo.scale); newFontInfo.lineGap = (newFontInfo.lineGap * newFontInfo.scale); newFontInfo.maxAdvanceWidth = (newFontInfo.maxAdvanceWidth * newFontInfo.scale); newFontInfo.underlineThickness = (newFontInfo.underlineThickness * newFontInfo.scale); newFontInfo.underlinePosition = (newFontInfo.underlinePosition * newFontInfo.scale); uint16_t fontIdx = m_fontHandles.alloc(); BX_CHECK(fontIdx != bx::HandleAlloc::invalid, "Invalid handle used"); CachedFont& font = m_cachedFonts[fontIdx]; font.cachedGlyphs.clear(); font.fontInfo = newFontInfo; font.trueTypeFont = NULL; font.masterFontHandle = _baseFontHandle; FontHandle handle = { fontIdx }; return handle; }
FontHandle FontManager::createFontByPixelSize(TrueTypeHandle _ttfHandle, uint32_t _typefaceIndex, uint32_t _pixelSize, uint32_t _fontType) { BX_CHECK(bgfx::isValid(_ttfHandle), "Invalid handle used"); TrueTypeFont* ttf = new TrueTypeFont(); if (!ttf->init(m_cachedFiles[_ttfHandle.idx].buffer, m_cachedFiles[_ttfHandle.idx].bufferSize, _typefaceIndex, _pixelSize) ) { delete ttf; FontHandle invalid = { bx::HandleAlloc::invalid }; return invalid; } uint16_t fontIdx = m_fontHandles.alloc(); BX_CHECK(fontIdx != bx::HandleAlloc::invalid, "Invalid handle used"); CachedFont& font = m_cachedFonts[fontIdx]; font.trueTypeFont = ttf; font.fontInfo = ttf->getFontInfo(); font.fontInfo.fontType = _fontType; font.fontInfo.pixelSize = _pixelSize; font.cachedGlyphs.clear(); font.masterFontHandle.idx = bx::HandleAlloc::invalid; FontHandle handle = { fontIdx }; return handle; }
bool Semaphore::wait(int32_t _msecs) { int result = pthread_mutex_lock(&m_mutex); BX_CHECK(0 == result, "pthread_mutex_lock %d", result); # if BX_PLATFORM_NACL || BX_PLATFORM_OSX BX_UNUSED(_msecs); BX_CHECK(-1 == _msecs, "NaCl and OSX don't support pthread_cond_timedwait at this moment."); while (0 == result && 0 >= m_count) { result = pthread_cond_wait(&m_cond, &m_mutex); } # elif BX_PLATFORM_IOS if (-1 == _msecs) { while (0 == result && 0 >= m_count) { result = pthread_cond_wait(&m_cond, &m_mutex); } } else { timespec ts; ts.tv_sec = _msecs/1000; ts.tv_nsec = (_msecs%1000)*1000; while (0 == result && 0 >= m_count) { result = pthread_cond_timedwait_relative_np(&m_cond, &m_mutex, &ts); } } # else timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += _msecs/1000; ts.tv_nsec += (_msecs%1000)*1000; while (0 == result && 0 >= m_count) { result = pthread_cond_timedwait(&m_cond, &m_mutex, &ts); } # endif // BX_PLATFORM_NACL || BX_PLATFORM_OSX bool ok = 0 == result; if (ok) { --m_count; } result = pthread_mutex_unlock(&m_mutex); BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); BX_UNUSED(result); return ok; }
bool TrueTypeFont::init(const uint8_t* _buffer, uint32_t _bufferSize, int32_t _fontIndex, uint32_t _pixelHeight) { BX_CHECK(m_font == NULL, "TrueTypeFont already initialized"); BX_CHECK( (_bufferSize > 256 && _bufferSize < 100000000), "TrueType buffer size is suspicious"); BX_CHECK( (_pixelHeight > 4 && _pixelHeight < 128), "TrueType buffer size is suspicious"); FTHolder* holder = new FTHolder; FT_Error error = FT_Init_FreeType(&holder->library); BX_WARN(!error, "FT_Init_FreeType failed."); if (error) { goto err0; } error = FT_New_Memory_Face(holder->library, _buffer, _bufferSize, _fontIndex, &holder->face); BX_WARN(!error, "FT_Init_FreeType failed."); if (error) { if (FT_Err_Unknown_File_Format == error) { goto err0; } goto err1; } error = FT_Select_Charmap(holder->face, FT_ENCODING_UNICODE); BX_WARN(!error, "FT_Init_FreeType failed."); if (error) { goto err2; } error = FT_Set_Pixel_Sizes(holder->face, 0, _pixelHeight); BX_WARN(!error, "FT_Init_FreeType failed."); if (error) { goto err2; } m_font = holder; return true; err2: FT_Done_Face(holder->face); err1: FT_Done_FreeType(holder->library); err0: delete holder; return false; }
Semaphore::~Semaphore() { int result; result = pthread_cond_destroy(&m_cond); BX_CHECK(0 == result, "pthread_cond_destroy %d", result); result = pthread_mutex_destroy(&m_mutex); BX_CHECK(0 == result, "pthread_mutex_destroy %d", result); BX_UNUSED(result); }
Semaphore::Semaphore() : m_count(0) { int result; result = pthread_mutex_init(&m_mutex, NULL); BX_CHECK(0 == result, "pthread_mutex_init %d", result); result = pthread_cond_init(&m_cond, NULL); BX_CHECK(0 == result, "pthread_cond_init %d", result); BX_UNUSED(result); }
void RectanglePacker::init(uint32_t _width, uint32_t _height) { BX_CHECK(_width > 2, "_width must be > 2"); BX_CHECK(_height > 2, "_height must be > 2"); m_width = _width; m_height = _height; m_usedSpace = 0; m_skyline.clear(); // We want a one pixel border around the whole atlas to avoid any artifact when // sampling texture m_skyline.push_back(Node(1, 1, _width - 2) ); }
void TextMetrics::appendText(FontHandle _fontHandle, const char* _string) { const FontInfo& font = m_fontManager->getFontInfo(_fontHandle); if (font.lineGap > m_lineGap) { m_lineGap = font.lineGap; } if ( (font.ascender - font.descender) > m_lineHeight) { m_height -= m_lineHeight; m_lineHeight = font.ascender - font.descender; m_height += m_lineHeight; } CodePoint codepoint = 0; uint32_t state = 0; for (; *_string; ++_string) { if (!utf8_decode(&state, (uint32_t*)&codepoint, *_string) ) { const GlyphInfo* glyph = m_fontManager->getGlyphInfo(_fontHandle, codepoint); if (NULL != glyph) { if (codepoint == L'\n') { m_height += m_lineGap + font.ascender - font.descender; m_lineGap = font.lineGap; m_lineHeight = font.ascender - font.descender; m_x = 0; break; } m_x += glyph->advance_x; if(m_x > m_width) { m_width = m_x; } } else { BX_CHECK(false, "Glyph not found"); } } } BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed"); }
FontManager::~FontManager() { BX_CHECK(m_fontHandles.getNumHandles() == 0, "All the fonts must be destroyed before destroying the manager"); delete [] m_cachedFonts; BX_CHECK(m_filesHandles.getNumHandles() == 0, "All the font files must be destroyed before destroying the manager"); delete [] m_cachedFiles; delete [] m_buffer; if (m_ownAtlas) { delete m_atlas; } }
void add(const char* _name, ConsoleFn _fn, void* _userData) { uint32_t cmd = bx::hashMurmur2A(_name, (uint32_t)strlen(_name) ); BX_CHECK(m_lookup.end() == m_lookup.find(cmd), "Command \"%s\" already exist.", _name); Func fn = { _fn, _userData }; m_lookup.insert(stl::make_pair(cmd, fn) ); }
bgfx::ShaderHandle pumpkinLoadShader(bx::FileReaderI* _reader, const char* _name) { char filePath[512]; std::string shaderPath = "shaders/";//SHADER_FILE_PATH; switch (bgfx::getRendererType() ) { case bgfx::RendererType::Noop: case bgfx::RendererType::Direct3D9: shaderPath += "dx9/"; break; case bgfx::RendererType::Direct3D11: case bgfx::RendererType::Direct3D12: shaderPath += "dx11/"; break; case bgfx::RendererType::Gnm: shaderPath += "pssl/"; break; case bgfx::RendererType::Metal: shaderPath += "metal/"; break; case bgfx::RendererType::OpenGL: shaderPath += "glsl/"; break; case bgfx::RendererType::OpenGLES: shaderPath += "essl/"; break; case bgfx::RendererType::Vulkan: shaderPath += "spirv/"; break; case bgfx::RendererType::Count: BX_CHECK(false, "You should not be here!"); break; } strcpy(filePath, shaderPath.c_str()); strcat(filePath, _name); strcat(filePath, ".bin"); return bgfx::createShader(loadMem(_reader, filePath) ); }
Atlas::Atlas(uint16_t _textureSize, const uint8_t* _textureBuffer, uint16_t _regionCount, const uint8_t* _regionBuffer, uint16_t _maxRegionsCount) : m_usedLayers(24) , m_usedFaces(6) , m_textureSize(_textureSize) , m_regionCount(_regionCount) , m_maxRegionCount(_regionCount < _maxRegionsCount ? _regionCount : _maxRegionsCount) { BX_CHECK(_regionCount <= 64 && _maxRegionsCount <= 4096, "_regionCount %d, _maxRegionsCount %d", _regionCount, _maxRegionsCount); init(); m_regions = new AtlasRegion[_regionCount]; m_textureBuffer = new uint8_t[getTextureBufferSize()]; memcpy(m_regions, _regionBuffer, _regionCount * sizeof(AtlasRegion) ); memcpy(m_textureBuffer, _textureBuffer, getTextureBufferSize() ); m_textureHandle = bgfx::createTextureCube(6 , _textureSize , 1 , bgfx::TextureFormat::BGRA8 , BGFX_TEXTURE_NONE , bgfx::makeRef(m_textureBuffer, getTextureBufferSize() ) ); }
bool TrueTypeFont::bakeGlyphSubpixel(CodePoint _codePoint, GlyphInfo& _glyphInfo, uint8_t* _outBuffer) { BX_CHECK(m_font != NULL, "TrueTypeFont not initialized"); _glyphInfo.glyphIndex = FT_Get_Char_Index(m_font->face, _codePoint); FT_GlyphSlot slot = m_font->face->glyph; FT_Error error = FT_Load_Glyph(m_font->face, _glyphInfo.glyphIndex, FT_LOAD_DEFAULT); if (error) { return false; } FT_Glyph glyph; error = FT_Get_Glyph(slot, &glyph); if (error) { return false; } error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_LCD, 0, 1); if (error) { return false; } FT_BitmapGlyph bitmap = (FT_BitmapGlyph)glyph; glyphInfoInit(_glyphInfo, bitmap, slot, _outBuffer, 3); FT_Done_Glyph(glyph); return true; }
void* reallocStub(void* _ptr, size_t _size) { void* ptr = ::realloc(_ptr, _size); BX_CHECK(NULL != ptr, "Out of memory!"); // BX_TRACE("alloc %d, %p", _size, ptr); return ptr; }
void TextLineMetrics::getVisibleText(const char* _string, float _top, float _bottom, const char*& _begin, const char*& _end) { CodePoint codepoint = 0; uint32_t state = 0; // y is bottom of a text line float y = m_lineHeight; while (*_string && (y < _top) ) { for (; *_string; ++_string) { if(utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT) { if(codepoint == L'\n') { y += m_lineHeight; ++_string; break; } } } } BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed"); _begin = _string; // y is now top of a text line y -= m_lineHeight; while ( (*_string) && (y < _bottom) ) { for (; *_string; ++_string) { if(utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT) { if(codepoint == L'\n') { y += m_lineHeight; ++_string; break; } } } } BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed"); _end = _string; }
const char* getName(SpvBuiltin::Enum _enum) { BX_CHECK(_enum <= SpvBuiltin::Count, "Unknown builtin id %d.", _enum); return _enum <= SpvBuiltin::Count ? s_spvBuiltin[_enum] : "?SpvBuiltin?" ; }
const char* getName(SpvStorageClass::Enum _enum) { BX_CHECK(_enum <= SpvStorageClass::Count, "Unknown storage class id %d.", _enum); return _enum <= SpvStorageClass::Count ? s_spvStorageClass[_enum] : "?SpvStorageClass?" ; }
const char* getName(SpvDecoration::Enum _enum) { BX_CHECK(_enum <= SpvDecoration::Count, "Unknown decoration id %d.", _enum); return _enum <= SpvDecoration::Count ? s_spvDecoration[_enum] : "?SpvDecoration?" ; }
void getAabb(EmitterHandle _handle, Aabb& _outAabb) { BX_CHECK(m_emitterAlloc.isValid(_handle.idx) , "getAabb handle %d is not valid." , _handle.idx ); _outAabb = m_emitter[_handle.idx].m_aabb; }
void FontManager::destroyTtf(TrueTypeHandle _handle) { BX_CHECK(bgfx::isValid(_handle), "Invalid handle used"); delete m_cachedFiles[_handle.idx].buffer; m_cachedFiles[_handle.idx].bufferSize = 0; m_cachedFiles[_handle.idx].buffer = NULL; m_filesHandles.free(_handle.idx); }
VRImplOVR::~VRImplOVR() { if (NULL != g_platformData.session) { return; } BX_CHECK(NULL == m_session, "OVR not shutdown properly."); }
Semaphore::Semaphore() { #if BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT m_handle = CreateSemaphoreExW(NULL, 0, LONG_MAX, NULL, 0, SEMAPHORE_ALL_ACCESS); #else m_handle = CreateSemaphoreA(NULL, 0, LONG_MAX, NULL); #endif BX_CHECK(NULL != m_handle, "Failed to create Semaphore!"); }
void Semaphore::post(uint32_t _count) { int result = pthread_mutex_lock(&m_mutex); BX_CHECK(0 == result, "pthread_mutex_lock %d", result); for (uint32_t ii = 0; ii < _count; ++ii) { result = pthread_cond_signal(&m_cond); BX_CHECK(0 == result, "pthread_cond_signal %d", result); } m_count += _count; result = pthread_mutex_unlock(&m_mutex); BX_CHECK(0 == result, "pthread_mutex_unlock %d", result); BX_UNUSED(result); }
FontInfo TrueTypeFont::getFontInfo() { BX_CHECK(m_font != NULL, "TrueTypeFont not initialized"); BX_CHECK(FT_IS_SCALABLE(m_font->face), "Font is unscalable"); FT_Size_Metrics metrics = m_font->face->size->metrics; FontInfo outFontInfo; outFontInfo.scale = 1.0f; outFontInfo.ascender = metrics.ascender / 64.0f; outFontInfo.descender = metrics.descender / 64.0f; outFontInfo.lineGap = (metrics.height - metrics.ascender + metrics.descender) / 64.0f; outFontInfo.maxAdvanceWidth = metrics.max_advance/ 64.0f; outFontInfo.underlinePosition = FT_MulFix(m_font->face->underline_position, metrics.y_scale) / 64.0f; outFontInfo.underlineThickness = FT_MulFix(m_font->face->underline_thickness, metrics.y_scale) / 64.0f; return outFontInfo; }
void TextLineMetrics::getSubText(const char* _string, uint32_t _firstLine, uint32_t _lastLine, const char*& _begin, const char*& _end) { CodePoint codepoint = 0; uint32_t state = 0; // y is bottom of a text line uint32_t currentLine = 0; while(*_string && (currentLine < _firstLine) ) { for (; *_string; ++_string) { if (utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT) { if (codepoint == L'\n') { ++currentLine; ++_string; break; } } } } BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed"); _begin = _string; while ( (*_string) && (currentLine < _lastLine) ) { for (; *_string; ++_string) { if(utf8_decode(&state, (uint32_t*)&codepoint, *_string) == UTF8_ACCEPT) { if(codepoint == L'\n') { ++currentLine; ++_string; break; } } } } BX_CHECK(state == UTF8_ACCEPT, "The string is not well-formed"); _end = _string; }
void Semaphore::post(uint32_t _count) { int32_t result; for (uint32_t ii = 0; ii < _count; ++ii) { result = sem_post(&m_handle); BX_CHECK(0 == result, "sem_post failed. errno %d", errno); } BX_UNUSED(result); }
void GlContext::create(uint32_t _width, uint32_t _height) { BX_UNUSED(_width, _height); s_opengl = bx::dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"); BX_CHECK(NULL != s_opengl, "OpenGL dynamic library is not found!"); bgfx_GlContext_create((GlCtx*)this, g_bgfxNSWindow, _width, _height); import(); }
void destroyEmitter(EmitterHandle _handle) { BX_CHECK(m_emitterAlloc.isValid(_handle.idx) , "destroyEmitter handle %d is not valid." , _handle.idx ); m_emitter[_handle.idx].destroy(); m_emitterAlloc->free(_handle.idx); }