void loom_asset_soundDtor(void *bits) { loom_asset_sound_t *sound = (loom_asset_sound_t*)bits; if (sound != NULL) { if (sound->buffer != NULL) lmFree(gAssetAllocator, sound->buffer); lmFree(gAssetAllocator, bits); } }
BitmapData::~BitmapData() { if (data != NULL) { lmFree(NULL, data); } }
void *loom_asset_imageDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor ) { loom_asset_image_t *img; lmAssert(buffer != NULL, "buffer should not be null"); img = (loom_asset_image_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_image_t)); // parse any orientation info from exif format img->orientation = exifinfo_parse_orientation(buffer, (unsigned int)bufferLen); img->bits = stbi_load_from_memory((const stbi_uc *)buffer, (int)bufferLen, &img->width, &img->height, &img->bpp, 4); *dtor = loom_asset_imageDtor; if(!img->bits) { lmLogError(gImageAssetGroup, "Image load failed due to this cryptic reason: %s", stbi_failure_reason()); lmFree(gAssetAllocator, img); return 0; } lmLogDebug(gImageAssetGroup, "Allocated %d bytes for an image!", img->width * img->height * 4); return img; }
void loom_mutex_destroy_real(const char *file, int line, MutexHandle m) { assert(m); DeleteCriticalSection((CRITICAL_SECTION *)m); tmSetLockStateEx(gTelemetryContext, file, line, m, TMLS_DESTROYED, "mutex_destroy"); lmFree(NULL, m); }
void LSCompiler::logVerbose(const char *format, ...) { char* buff; va_list args; lmLogArgs(args, buff, format); lmLog(compilerVerboseLogGroup, "%s", buff); lmFree(NULL, buff); }
~loom_assetBlob_t() { if(bits) { lmFree(gAssetAllocator, bits); bits = NULL; } }
void wipePendingData() { if (pendingFile) { lmFree(gAssetAllocator, (void *)pendingFile); pendingFile = NULL; } pendingFileLength = -1; pendingFilePath = ""; }
void Assembly::close() { utArray<Type *> types; getTypes(types); for (UTsize i = 0; i < types.size(); i++) { typeAssemblyLookup.remove(types.at(i)); lmFree(NULL, types.at(i)); } assemblies.remove(vm); }
static void *lsLuaAlloc(void *ud, void *ptr, size_t osize, size_t nsize) { (void)ud; (void)osize; /* not used */ if (nsize == 0 && ptr) { lmFree(NULL, ptr); return NULL; } else { if(osize == 0) return lmAlloc(NULL, nsize); else return lmRealloc(NULL, ptr, nsize); } }
void LSLog(LSLogLevel level, const char *format, ...) { char* buff; va_list args; if (level < logLevel) { return; } lmLogArgs(args, buff, format); if (externLog) { int elevel; switch (level) { case LSLogQuiet: elevel = externLogInfo; break; case LSLogInfo: elevel = externLogInfo; break; case LSLogWarn: elevel = externLogWarn; break; case LSLogError: elevel = externLogError; break; } externLog(externExtra, elevel, "%s", buff); } else { printf("%s\n", buff); } lmFree(NULL, buff); }
void QuadRenderer::destroyGraphicsResources() { for (int i = 0; i < MAXVERTEXBUFFERS; i++) { if (vertexBuffers[i].idx != bgfx::invalidHandle) { bgfx::destroyDynamicVertexBuffer(vertexBuffers[i]); vertexBuffers[i].idx = bgfx::invalidHandle; } } if (sIndexBufferHandle.idx != bgfx::invalidHandle) { bgfx::destroyIndexBuffer(sIndexBufferHandle); sIndexBufferHandle.idx = bgfx::invalidHandle; } if (sProgramPosColorTex.idx != bgfx::invalidHandle) { bgfx::destroyProgram(sProgramPosColorTex); } if (sUniformTexColor.idx != bgfx::invalidHandle) { bgfx::destroyUniform(sUniformTexColor); } if (sUniformNodeMatrixRemoveMe.idx != bgfx::invalidHandle) { bgfx::destroyUniform(sUniformNodeMatrixRemoveMe); } sUniformTexColor.idx = bgfx::invalidHandle; sUniformNodeMatrixRemoveMe.idx = bgfx::invalidHandle; sProgramPosColorTex.idx = bgfx::invalidHandle; if (vertexDataMemory) { lmFree(gQuadMemoryAllocator, vertexDataMemory); vertexDataMemory = NULL; } }
bool decRef() { refCount--; if(refCount == 0) { if(dtor) dtor(bits); else lmFree(gAssetAllocator, bits); refCount = 0xBAADF00D; length = -1; bits = NULL; lmDelete(gAssetAllocator, this); return true; } return false; }
void QuadRenderer::initializeGraphicsResources() { LOOM_PROFILE_SCOPE(quadInit); lmLogInfo(gGFXQuadRendererLogGroup, "Initializing Graphics Resources"); GL_Context* ctx = Graphics::context(); // create the single initial vertex buffer ctx->glGenBuffers(1, &vertexBufferId); ctx->glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId); ctx->glBufferData(GL_ARRAY_BUFFER, MAXBATCHQUADS * 4 * sizeof(VertexPosColorTex), 0, GL_STREAM_DRAW); ctx->glBindBuffer(GL_ARRAY_BUFFER, 0); // create the single, reused index buffer ctx->glGenBuffers(1, &indexBufferId); ctx->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId); uint16_t *pIndex = (uint16_t*)lmAlloc(gQuadMemoryAllocator, sizeof(unsigned short) * 6 * MAXBATCHQUADS); uint16_t *pStart = pIndex; int j = 0; for (int i = 0; i < 6 * MAXBATCHQUADS; i += 6, j += 4, pIndex += 6) { pIndex[0] = j; pIndex[1] = j + 2; pIndex[2] = j + 1; pIndex[3] = j + 1; pIndex[4] = j + 2; pIndex[5] = j + 3; } ctx->glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAXBATCHQUADS * 6 * sizeof(uint16_t), pStart, GL_STREAM_DRAW); ctx->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); lmFree(gQuadMemoryAllocator, pStart); // Create the system memory buffer for quads. batchedVertices = static_cast<VertexPosColorTex*>(lmAlloc(gQuadMemoryAllocator, MAXBATCHQUADS * 4 * sizeof(VertexPosColorTex))); }
void LoomProfiler::reset() { mEnabled = false; // in case we're in a profiler call. if (mDumpToConsole) { dump(); } while(mProfileList) { lmFree(gProfilerAllocator, mProfileList); mProfileList = NULL; } for(LoomProfilerRoot *walk = LoomProfilerRoot::sRootList; walk; walk = walk->mNextRoot) { walk->mFirstLoomProfilerEntry = 0; walk->mTotalTime = 0; walk->mSubTime = 0; walk->mMaxTime = 0; walk->mMinTime = INFINITY; walk->mTotalInvokeCount = 0; } mCurrentLoomProfilerEntry = mRootLoomProfilerEntry; mCurrentLoomProfilerEntry->mNextForRoot = 0; mCurrentLoomProfilerEntry->mFirstChild = 0; for(U32 i = 0; i < LoomProfilerEntry::HashTableSize; i++) mCurrentLoomProfilerEntry->mChildHash[i] = 0; mCurrentLoomProfilerEntry->mInvokeCount = 0; mCurrentLoomProfilerEntry->mTotalTime = 0; mCurrentLoomProfilerEntry->mSubTime = 0; mCurrentLoomProfilerEntry->mMaxTime = 0; mCurrentLoomProfilerEntry->mMinTime = INFINITY; mCurrentLoomProfilerEntry->mSubDepth = 0; mCurrentLoomProfilerEntry->mLastSeenProfiler = 0; }
static void jsonFree(void *ptr) { lmFree(NULL, ptr); }
virtual bool handleMessage(int fourcc, AssetProtocolHandler *handler, NetworkBuffer& buffer) { switch (fourcc) { case LOOM_FOURCC('F', 'I', 'L', 'E'): { // How many pending files? gPendingFiles = buffer.readInt(); loom_asset_notifyPendingCountChange(); // Read the filename. char *path; int fileStringLength; buffer.readString(&path, &fileStringLength); // And the file length. int bitsLength = buffer.readInt(); // Checkpoint at end! buffer.readCheckpoint(0xDEADBEE3); // Prepare the buffer! if (pendingFile != NULL) { lmLogError(gAssetLogGroup, "Got a new FILE '%s' while still processing existing file '%s'!", path, pendingFilePath.c_str()); wipePendingData(); } // Update the pending file state. pendingFilePath = path; lmFree(NULL, path); path = NULL; pendingFileLength = bitsLength; pendingFile = (const char *)lmAlloc(gAssetAllocator, pendingFileLength); // Log it. lmLogDebug(gAssetLogGroup, "FILE '%s' %d bytes incoming.", pendingFilePath.c_str(), bitsLength); // Awesome, sit back and wait for chunks to come in. return true; } case LOOM_FOURCC('F', 'C', 'H', 'K'): { // How many pending files? gPendingFiles = buffer.readInt(); loom_asset_notifyPendingCountChange(); // Get the offset. int chunkOffset = buffer.readInt(); // Read bits into the buffer. char *fileBits; int fileBitsLength; buffer.readString(&fileBits, &fileBitsLength); memcpy((void *)(pendingFile + chunkOffset), (void *)fileBits, fileBitsLength); lmFree(NULL, fileBits); // Checkpoint at end! buffer.readCheckpoint(0xDEADBEE2); int lastByteOffset = chunkOffset + fileBitsLength; // Log it. lmLogDebug(gAssetLogGroup, "FILE '%s' %d of %d bytes!", pendingFilePath.c_str(), lastByteOffset, pendingFileLength); // If it's the last one, instate it and wipe our buffer. if (lastByteOffset == pendingFileLength) { // And this resolves a file so decrement the pending count. This way // we will get to zero. gPendingFiles--; loom_asset_notifyPendingCountChange(); // Instate the new asset data. loom_asset_t *asset = loom_asset_getAssetByName(pendingFilePath.c_str(), 1); int assetType = loom_asset_recognizeAssetTypeFromPath(pendingFilePath); if (assetType == 0) { lmLogDebug(gAssetLogGroup, "Couldn't infer file type for '%s', ignoring.", pendingFilePath.c_str()); wipePendingData(); return true; } lmLogWarn(gAssetLogGroup, "Applying new version of '%s', %d bytes.", pendingFilePath.c_str(), pendingFileLength); LoomAssetCleanupCallback dtor = NULL; void *assetBits = loom_asset_deserializeAsset(pendingFilePath.c_str(), assetType, pendingFileLength, (void *)pendingFile, &dtor); asset->instate(assetType, assetBits, dtor); // And wipe the pending date. wipePendingData(); } } return true; } return false; }
LoomProfiler::~LoomProfiler() { reset(); lmFree(gProfilerAllocator, mRootLoomProfilerEntry); gLoomProfiler = NULL; }
void *loom_asset_soundDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor ) { loom_asset_sound_t *sound = (loom_asset_sound_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_sound_t)); memset(sound, 0, sizeof(loom_asset_sound_t)); unsigned char *charBuff = (unsigned char *)buffer; // Look for magic header in buffer. if(charBuff[0] == 0x4f && charBuff[1] == 0x67 && charBuff[2] == 0x67 && charBuff[3] == 0x53) { // It's an Ogg, assume vorbis and throw it to stb_vorbis. int channels = 0; short *outputBuffer = NULL; int sampleCount = stb_vorbis_decode_memory(charBuff, (int)bufferLen, &channels, &outputBuffer); if(sampleCount < 0) { lmLogError(gSoundAssetGroup, "Failed to decode Ogg Vorbis"); loom_asset_soundDtor(&sound); return NULL; } sound->channels = channels; sound->bytesPerSample = 2; sound->sampleCount = sampleCount; sound->bufferSize = sampleCount * channels * 2; sound->sampleRate = 44100; // TODO: This should be variable // We can skip this if we get clever about allocations in stbv. sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); memcpy(sound->buffer, outputBuffer, sound->bufferSize); free(outputBuffer); } else if((charBuff[0] == 0x49 // ID3 && charBuff[1] == 0x44 && charBuff[2] == 0x33) || (charBuff[0] == 0xff // Missing ID3 Tag && charBuff[1] == 0xfb)) { // It's an MP3, y'all! short *outBuffer = (short*)lmAlloc(gAssetAllocator, MP3_MAX_SAMPLES_PER_FRAME * 2); mp3_info_t mp3Info; // Decode once to get total size. size_t totalBytes = 0; size_t bytesRead = 0, bytesLeft = bufferLen; mp3_decoder_t decmp3 = mp3_create(); for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, (int)bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; totalBytes += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Great, set up the sound asset. // TODO: Warn about non 44.1khz mp3s. sound->channels = mp3Info.channels; sound->bytesPerSample = 2; sound->sampleCount = (int)totalBytes / sound->bytesPerSample; sound->bufferSize = sound->channels * sound->bytesPerSample * sound->sampleCount; sound->sampleRate = 44100; // TODO: This should be variable sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); // Decode again to get real samples. decmp3 = mp3_create(); bytesRead = 0; bytesLeft = bufferLen; int curBufferOffset = 0; for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, (int)bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; memcpy(((unsigned char*)sound->buffer) + curBufferOffset, outBuffer, mp3Info.audio_bytes); curBufferOffset += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Awesome, all set! lmFree(gAssetAllocator, outBuffer); } else if(charBuff[0] == 0x52 // 'RIFF' && charBuff[1] == 0x49 && charBuff[2] == 0x46 && charBuff[3] == 0x46) { // We've got a wav file wav_info wav; bool wavLoadSuccess = load_wav(charBuff, bufferLen, NULL, &wav); if (!wavLoadSuccess) { lmLogError(gSoundAssetGroup, "Failed to load wav format info"); loom_asset_soundDtor(sound); return 0; } sound->channels = wav.numChannels; sound->bytesPerSample = wav.sampleSize / 8; // wav sample size is in bits if (sound->bytesPerSample != 1 && sound->bytesPerSample != 2) { lmLogError(gSoundAssetGroup, "Unsupported wav format. Currently only 8-bit or 16-bit PCM are supported"); loom_asset_soundDtor(sound); return 0; } sound->bufferSize = wav.sampleDataSize; sound->sampleCount = sound->bufferSize / sound->bytesPerSample; sound->sampleRate = wav.samplesPerSecond; sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); bool dataCopySuccess = load_wav(charBuff, bufferLen, (uint8_t*)sound->buffer, NULL); if (!dataCopySuccess) { lmLogError(gSoundAssetGroup, "Failed to copy wav data"); loom_asset_soundDtor(sound); return 0; } } else { lmLogError(gSoundAssetGroup, "Failed to identify sound buffer by magic number!"); loom_asset_soundDtor(sound); return 0; } *dtor = loom_asset_soundDtor; if(!sound->buffer) { lmLogError(gSoundAssetGroup, "Sound load failed due to this cryptic reason: %s", "(unknown)"); lmFree(gAssetAllocator, sound); return 0; } lmLogDebug(gSoundAssetGroup, "Sound allocation: %d bytes", sound->bufferSize); return sound; }
void BinWriter::writeExecutable(const char *path, json_t *sjson) { stringPool.clear(); binWriters.clear(); utByteArray bytes; // reserve 32 megs bytes.reserve(1024 * 1024 * 32); const char *name = json_string_value(json_object_get(sjson, "name")); BinWriter *bexec = lmNew(NULL) BinWriter(name); bexec->writeAssembly(sjson); // write string pool bytes.writeInt((int)stringPool.size()); // calculate entire buffer size of string pool int stringBufferSize = 0; for (UTsize i = 0; i < stringPool.size(); i++) { stringBufferSize += sizeof(int); // length stringBufferSize += (int)strlen(stringPool.keyAt(i).str().c_str()); // characters } // length of entire string buffer bytes.writeInt(stringBufferSize); for (UTsize i = 0; i < stringPool.size(); i++) { bytes.writeString(stringPool.keyAt(i).str().c_str()); } // generate the type table utArray<TypeIndex *> types; for (UTsize i = 0; i < binWriters.size(); i++) { BinWriter *bref = binWriters.at(i); for (UTsize j = 0; j < bref->typeIndexes.size(); j++) { TypeIndex *tindex = bref->typeIndexes.at(j); tindex->refIdx = (int)i; types.push_back(tindex); } } // write the type table bytes.writeInt((int)types.size()); for (UTsize i = 0; i < types.size(); i++) { TypeIndex *tindex = types.at(i); bytes.writeInt(tindex->refIdx); bytes.writeInt(tindex->iFullName); bytes.writeInt(tindex->position); bytes.writeInt(tindex->length); } // write out the number of references bytes.writeInt((int)binWriters.size()); // write out reference table (which will allow random access if we want/need it) int position = bytes.getPosition() + (binWriters.size() * (sizeof(int) * 4)); for (UTsize i = 0; i < binWriters.size(); i++) { BinWriter *bref = binWriters.at(i); // (interned) name utHashedString uid = binWriters.keyAt(i); bytes.writeInt(poolString(binWriters.at(i)->name.c_str())); // uid bytes.writeInt(poolString(binWriters.keyAt(i).str().c_str())); // length int length = bref->bytes.getPosition(); bytes.writeInt(length); // position (offset from reference table) bytes.writeInt(position); position += length; } for (UTsize i = 0; i < binWriters.size(); i++) { BinWriter *bref = binWriters.at(i); bytes.writeBytes(&bref->bytes); } int dataLength = bytes.getPosition(); Bytef *compressed = (Bytef *) lmAlloc(gBinWriterAllocator, dataLength); uLongf length = (uLongf) dataLength; int ok = compress(compressed, &length, (Bytef *) bytes.getDataPtr(), (uLong) dataLength); lmAssert(ok == Z_OK, "problem compressing executable assemby"); bytes.clear(); bytes.writeUnsignedInt(LOOM_BINARY_ID); bytes.writeUnsignedInt(LOOM_BINARY_VERSION_MAJOR); bytes.writeUnsignedInt(LOOM_BINARY_VERSION_MINOR); bytes.writeUnsignedInt((unsigned int)dataLength); utFileStream binStream; binStream.open(path, utStream::SM_WRITE); // write header binStream.write(bytes.getDataPtr(), sizeof(unsigned int) * 4); // write compressed data binStream.write(compressed, length); binStream.close(); lmFree(gBinWriterAllocator, compressed); }
void QuadRenderer::initializeGraphicsResources() { lmLogInfo(gGFXQuadRendererLogGroup, "Initializing Graphics Resources"); //lmLogInfo(gGFXQuadRendererLogGroup, "OpenGL error %d", Graphics::context()->glGetError()); // Create the quad shader. GLuint vertShader = Graphics::context()->glCreateShader(GL_VERTEX_SHADER); //GLuint fragShader = Graphics::context()->glCreateShader(GL_FRAGMENT_SHADER); GLuint fragShaderColor = Graphics::context()->glCreateShader(GL_FRAGMENT_SHADER); GLuint quadProg = Graphics::context()->glCreateProgram(); GLuint quadProgColor = Graphics::context()->glCreateProgram(); char vertShaderSrc[] = "attribute vec4 a_position;\n" "attribute vec4 a_color0;\n" "attribute vec2 a_texcoord0;\n" "varying vec2 v_texcoord0;\n" "varying vec4 v_color0;\n" "uniform vec4 screenSize;\n" "void main()\n" "{\n" " gl_Position = a_position / vec4(screenSize.x / 2.0, -screenSize.y / 2.0, 1.0, 1.0) + vec4(-1, 1, 0.0, 0.0);\n" " v_color0 = a_color0;\n" " v_texcoord0 = a_texcoord0;\n" "}\n"; const int vertShaderLen = sizeof(vertShaderSrc); GLchar *vertShaderPtr = &vertShaderSrc[0]; /* */ char fragShaderColorSrc[] = #if LOOM_RENDERER_OPENGLES2 "precision mediump float;\n" #endif "uniform sampler2D u_texture;\n" "varying vec2 v_texcoord0;\n" "varying vec4 v_color0\n;" "void main()\n" "{\n" " gl_FragColor = v_color0 * texture2D(u_texture, v_texcoord0);\n" "}\n"; const int fragShaderColorLen = sizeof(fragShaderColorSrc); GLchar *fragShaderColorPtr = &fragShaderColorSrc[0]; Graphics::context()->glShaderSource(vertShader, 1, &vertShaderPtr, &vertShaderLen); Graphics::context()->glCompileShader(vertShader); char error[4096]; GLsizei outLen = 0; Graphics::context()->glGetShaderInfoLog(vertShader, 4096, &outLen, error); lmLogInfo(gGFXQuadRendererLogGroup, "Program info log %s", error); Graphics::context()->glShaderSource(fragShaderColor, 1, &fragShaderColorPtr, &fragShaderColorLen); Graphics::context()->glCompileShader(fragShaderColor); Graphics::context()->glGetShaderInfoLog(fragShaderColor, 4096, &outLen, error); lmLogInfo(gGFXQuadRendererLogGroup, "Program info log %s", error); Graphics::context()->glAttachShader(quadProgColor, fragShaderColor); Graphics::context()->glAttachShader(quadProgColor, vertShader); Graphics::context()->glLinkProgram(quadProgColor); Graphics::context()->glGetProgramInfoLog(quadProgColor, 4096, &outLen, error); lmLogInfo(gGFXQuadRendererLogGroup, "Program info log %s", error); /* char fragShaderSrc[] = #if LOOM_RENDERER_OPENGLES2 "precision mediump float;\n" #endif "uniform sampler2D u_texture;\n" "varying vec2 v_texcoord0;\n" "void main()\n" "{\n" " gl_FragColor = texture2D(u_texture, v_texcoord0);\n" "}\n"; const int fragShaderLen = sizeof(fragShaderSrc); GLchar *fragShaderPtr = &fragShaderSrc[0]; Graphics::context()->glShaderSource(fragShader, 1, &fragShaderPtr, &fragShaderLen); Graphics::context()->glCompileShader(fragShader); Graphics::context()->glGetShaderInfoLog(fragShader, 4096, &outLen, error); lmLogInfo(gGFXQuadRendererLogGroup, "Program info log %s", error); Graphics::context()->glAttachShader(quadProg, fragShader); Graphics::context()->glAttachShader(quadProg, vertShader); Graphics::context()->glLinkProgram(quadProg); Graphics::context()->glGetProgramInfoLog(quadProg, 4096, &outLen, error); lmLogInfo(gGFXQuadRendererLogGroup, "Program info log %s", error); */ // Get attributes and uniforms. sProgram_posAttribLoc = Graphics::context()->glGetAttribLocation(quadProgColor, "a_position"); sProgram_posColorLoc = Graphics::context()->glGetAttribLocation(quadProgColor, "a_color0"); sProgram_posTexCoordLoc = Graphics::context()->glGetAttribLocation(quadProgColor, "a_texcoord0"); sProgram_texUniform = Graphics::context()->glGetUniformLocation(quadProgColor, "u_texture"); sProgram_screenSize = Graphics::context()->glGetUniformLocation(quadProgColor, "screenSize"); // Save program for later! sProgramPosColorTex = sProgramPosTex = quadProgColor; // create the single initial vertex buffer numVertexBuffers = 0; _initializeNextVertexBuffer(); // create the single, reused index buffer Graphics::context()->glGenBuffers(1, &sIndexBufferHandle); Graphics::context()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sIndexBufferHandle); uint16_t *pIndex = (uint16_t*)lmAlloc(gQuadMemoryAllocator, sizeof(unsigned short) * 6 * MAXBATCHQUADS); uint16_t *pStart = pIndex; int j = 0; for (int i = 0; i < 6 * MAXBATCHQUADS; i += 6, j += 4, pIndex += 6) { pIndex[0] = j; pIndex[1] = j + 2; pIndex[2] = j + 1; pIndex[3] = j + 1; pIndex[4] = j + 2; pIndex[5] = j + 3; } Graphics::context()->glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAXBATCHQUADS * 6 * sizeof(uint16_t), pStart, GL_STATIC_DRAW); Graphics::context()->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); lmFree(gQuadMemoryAllocator, pStart); // Create the system memory buffer for quads. vertexDataMemory = lmAlloc(gQuadMemoryAllocator, MAXVERTEXBUFFERS * MAXBATCHQUADS * 4 * sizeof(VertexPosColorTex)); for(int i=0; i<MAXVERTEXBUFFERS; i++) vertexData[i] = ((VertexPosColorTex*)vertexDataMemory) + (MAXBATCHQUADS * 4) * i; }
void *loom_asset_soundDeserializer( void *buffer, size_t bufferLen, LoomAssetCleanupCallback *dtor ) { loom_asset_sound_t *sound = (loom_asset_sound_t*)lmAlloc(gAssetAllocator, sizeof(loom_asset_sound_t)); unsigned char *charBuff = (unsigned char *)buffer; // Look for magic header in buffer. if(charBuff[0] == 0x4f && charBuff[1] == 0x67 && charBuff[2] == 0x67 && charBuff[3] == 0x53) { // It's an Ogg, assume vorbis and throw it to stb_vorbis. int channels = 0; short *outputBuffer = NULL; int sampleCount = stb_vorbis_decode_memory(charBuff, bufferLen, &channels, &outputBuffer); if(sampleCount < 0) { lmLogError(gSoundAssetGroup, "Failed to decode Ogg Vorbis!"); return NULL; } sound->channels = channels; sound->bytesPerSample = 2; sound->sampleCount = sampleCount; sound->bufferSize = sampleCount * channels * 2; // We can skip this if we get clever about allocations in stbv. sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); memcpy(sound->buffer, outputBuffer, sound->bufferSize); free(outputBuffer); } else if((charBuff[0] == 0x49 // ID3 && charBuff[1] == 0x44 && charBuff[2] == 0x33) || (charBuff[0] == 0xff // Missing ID3 Tag && charBuff[1] == 0xfb)) { // It's an MP3, y'all! short *outBuffer = (short*)lmAlloc(gAssetAllocator, MP3_MAX_SAMPLES_PER_FRAME * 2); mp3_info_t mp3Info; // Decode once to get total size. int totalBytes = 0; int bytesRead = 0, bytesLeft = bufferLen; mp3_decoder_t decmp3 = mp3_create(); for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; totalBytes += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Great, set up the sound asset. // TODO: Warn about non 44.1khz mp3s. sound->channels = mp3Info.channels; sound->bytesPerSample = 2; sound->sampleCount = totalBytes / sound->bytesPerSample; sound->bufferSize = sound->channels * sound->bytesPerSample * sound->sampleCount; sound->buffer = lmAlloc(gAssetAllocator, sound->bufferSize); // Decode again to get real samples. decmp3 = mp3_create(); bytesRead = 0; bytesLeft = bufferLen; int curBufferOffset = 0; for(;;) { int bytesDecoded = mp3_decode(decmp3, charBuff + bytesRead, bytesLeft, outBuffer, &mp3Info); bytesRead += bytesDecoded; bytesLeft -= bytesDecoded; memcpy(((unsigned char*)sound->buffer) + curBufferOffset, outBuffer, mp3Info.audio_bytes); curBufferOffset += mp3Info.audio_bytes; if(bytesDecoded > 0) continue; // Clean up. mp3_done(decmp3); break; } // Awesome, all set! lmFree(gAssetAllocator, outBuffer); } else { lmLogError(gSoundAssetGroup, "Failed to identify sound buffer by magic number!"); return 0; } *dtor = loom_asset_soundDtor; if(!sound->buffer) { lmLogError(gSoundAssetGroup, "Sound load failed due to this cryptic reason: %s", "(unknown)"); lmFree(gAssetAllocator, sound); return 0; } lmLogError(gSoundAssetGroup, "Allocated %d bytes for a sound!", sound->bufferSize); return sound; }
void loom_asset_soundDtor(void *bits) { loom_asset_sound_t *sound = (loom_asset_sound_t*)bits; lmFree(gAssetAllocator, sound->buffer); lmFree(gAssetAllocator, bits); }
static void customFree(void* mem) { lmFree(NULL, mem); }
void loom_asset_imageDtor(void *bits) { loom_asset_image_t *img = (loom_asset_image_t*)bits; stbi_image_free(img->bits); lmFree(gAssetAllocator, bits); }
void loom_destroyTimer(loom_precision_timer_t timer) { loom_mach_precisionTimer_t *t = (loom_mach_precisionTimer_t *)timer; lmFree(NULL, t); }
Assembly *BinReader::loadExecutable(LSLuaState *_vm, utByteArray *byteArray) { sBytes = byteArray; vm = _vm; // load up the string pool readStringPool(); // read the type table int numTypes = sBytes->readInt(); for (UTsize i = 0; i < (UTsize)numTypes; i++) { TypeIndex *tindex = lmNew(NULL) TypeIndex; tindex->type = NULL; tindex->refIdx = sBytes->readInt(); tindex->fullName = readPoolString(); // within the ref tindex->position = sBytes->readInt(); tindex->length = sBytes->readInt(); types.insert(utHashedString(tindex->fullName), tindex); } // load up reference assemblies // write out the number of references int numRefs = sBytes->readInt(); for (int i = 0; i < numRefs; i++) { Reference *ref = lmNew(NULL) Reference; ref->name = readPoolString(); lmAssert(ref->name[0] != 0, "Assembly reference name is empty, try recompiling the .loom executable"); ref->length = sBytes->readInt(); ref->position = sBytes->readInt(); ref->loaded = false; ref->assembly = NULL; references.insert(utHashedString(ref->name), ref); // offset the types to global position for (UTsize j = 0; j < types.size(); j++) { TypeIndex *tindex = types.at(j); if (tindex->refIdx == (int)i) { tindex->position += ref->position; } } } Assembly *assembly = NULL; // declare types for (UTsize i = 0; i < types.size(); i++) { TypeIndex *tindex = types.at(i); tindex->type = lmNew(NULL) Type(); } for (UTsize i = 0; i < references.size(); i++) { Reference *ref = references.at(i); if (ref->loaded) { continue; } sBytes->setPosition(ref->position); BinReader reader; Assembly *rassembly = reader.readAssembly(vm, sBytes); ref->assembly = rassembly; if (!assembly) { assembly = rassembly; } } // cleanup for (UTsize i = 0; i < references.size(); i++) { Reference *ref = references.at(i); if (!ref->assembly) continue; ref->assembly->freeByteCode(); } sBytes = NULL; if (stringBuffer) { lmFree(NULL, (void*)stringBuffer); stringBuffer = NULL; } stringPool.clear(); references.clear(); types.clear(); vm = NULL; return assembly; }