dd_bool B_ParseKeyId(const char* desc, int* id) { LOG_AS("B_ParseKeyId"); // The possibilies: symbolic key name, or "codeNNN". if(!strncasecmp(desc, "code", 4) && strlen(desc) == 7) { if(desc[4] == 'x' || desc[4] == 'X') { // Hexadecimal. *id = strtoul(desc + 5, NULL, 16); } else { // Decimal. *id = strtoul(desc + 4, NULL, 10); if(*id <= 0 || *id > 255) { LOGDEV_INPUT_WARNING("Key code %i out of range") << *id; return false; } } } else { // Symbolic key name. *id = B_KeyForShortName(desc); if(!*id) { LOG_INPUT_WARNING("Unknown key \"%s\"") << desc; return false; } } return true; }
uint8_t const* Zip::cacheLump(int lumpIdx) { LOG_AS("Zip::cacheLump"); if(!isValidIndex(lumpIdx)) throw NotFoundError("Zip::cacheLump", invalidIndexMessage(lumpIdx, lastIndex())); ZipFile& file = reinterpret_cast<ZipFile&>(lump(lumpIdx)); LOG_TRACE("\"%s:%s\" (%u bytes%s)") << de::NativePath(composePath()).pretty() << de::NativePath(file.composePath()).pretty() << (unsigned long) file.info().size << (file.info().isCompressed()? ", compressed" : ""); // Time to create the cache? if(!d->lumpCache) { d->lumpCache = new LumpCache(lumpCount()); } uint8_t const* data = d->lumpCache->data(lumpIdx); if(data) return data; uint8_t* region = (uint8_t*) Z_Malloc(file.info().size, PU_APPSTATIC, 0); if(!region) throw Error("Zip::cacheLump", QString("Failed on allocation of %1 bytes for cache copy of lump #%2").arg(file.info().size).arg(lumpIdx)); readLump(lumpIdx, region, false); d->lumpCache->insert(lumpIdx, region); return region; }
void AbstractLink::socketDisconnected() { LOG_AS("AbstractLink"); if (d->status == Connecting) { if (d->startedTryingAt.since() < d->timeout) { // Let's try again a bit later. QTimer::singleShot(500, d->socket.get(), SLOT(reconnect())); return; } d->socket->setQuiet(false); } else { if (!d->peerAddress.isNull()) { LOG_NET_NOTE("Disconnected from %s") << d->peerAddress; } else { LOG_NET_NOTE("Disconnected"); } } d->status = Disconnected; emit disconnected(); // Slots have now had an opportunity to observe the total // duration of the connection that has just ended. d->connectedAt = Time::invalidTime(); }
File1& Zip::lump(int lumpIdx) { LOG_AS("Zip"); if(!isValidIndex(lumpIdx)) throw NotFoundError("Zip::lump", invalidIndexMessage(lumpIdx, lastIndex())); d->buildLumpNodeLut(); return *reinterpret_cast<ZipFile*>((*d->lumpNodeLut)[lumpIdx]->userPointer()); }
QVariant parse() { LOG_AS("JSONParser"); if(atEnd()) return QVariant(); QChar c = peek(); if(c == '{') { return parseObject(); } else if(c == '[') { return parseArray(); } else if(c == '\"') { return parseString(); } else if(c == '-' || c.isDigit()) { return parseNumber(); } else { return parseKeyword(); } }
void getAllOpenGLEntryPoints() { static bool haveProcs = false; if(haveProcs) return; #define GET_PROC(name) *((void**)&name) = wglGetProcAddress(#name); DENG2_ASSERT(name != 0) LOG_AS("getAllOpenGLEntryPoints"); LOG_VERBOSE("GL_VERSION: ") << (char const *) glGetString(GL_VERSION); GET_PROC(glActiveTexture); GET_PROC(glAttachShader); GET_PROC(glBindAttribLocation); GET_PROC(glBindBuffer); GET_PROC(glBindFramebuffer); GET_PROC(glBindRenderbuffer); GET_PROC(glBlendEquation); GET_PROC(glBufferData); GET_PROC(glCheckFramebufferStatus); GET_PROC(glCompileShader); GET_PROC(glCreateProgram); GET_PROC(glCreateShader); GET_PROC(glDeleteBuffers); GET_PROC(glDeleteFramebuffers); GET_PROC(glDeleteProgram); GET_PROC(glDeleteRenderbuffers); GET_PROC(glDeleteShader); GET_PROC(glDetachShader); GET_PROC(glDisableVertexAttribArray); GET_PROC(glEnableVertexAttribArray); GET_PROC(glFramebufferRenderbuffer); GET_PROC(glFramebufferTexture2D); GET_PROC(glGenBuffers); GET_PROC(glGenFramebuffers); GET_PROC(glGenerateMipmap); GET_PROC(glGenRenderbuffers); GET_PROC(glGetAttribLocation); GET_PROC(glGetProgramInfoLog); GET_PROC(glGetProgramiv); GET_PROC(glGetShaderInfoLog); GET_PROC(glGetShaderiv); GET_PROC(glGetShaderSource); GET_PROC(glGetUniformLocation); GET_PROC(glIsBuffer); GET_PROC(glLinkProgram); GET_PROC(glRenderbufferStorage); GET_PROC(glShaderSource); GET_PROC(glUniform1f); GET_PROC(glUniform1i); GET_PROC(glUniform2f); GET_PROC(glUniform3f); GET_PROC(glUniform4f); GET_PROC(glUniformMatrix3fv); GET_PROC(glUniformMatrix4fv); GET_PROC(glUseProgram); GET_PROC(glVertexAttribPointer); haveProcs = true; }
void parseRawUri(String rawUri, QChar sep, resourceclassid_t defaultResourceClass) { LOG_AS("Uri::parseRawUri"); clearCachedResolved(); scheme = extractScheme(rawUri); // scheme removed if(sep != '/') rawUri.replace(sep, '/'); // force slashes as separator path = rawUri; strPath = path.toString(); // for legacy code if(!scheme.isEmpty()) { if(defaultResourceClass == RC_NULL || App_FileSystem().knownScheme(scheme)) { // Scheme is accepted as is. return; } LOG_RES_WARNING("Unknown scheme \"%s\" for path \"%s\", using default scheme instead") << scheme << strPath; } // Attempt to guess the scheme by interpreting the path? if(defaultResourceClass == RC_UNKNOWN) { defaultResourceClass = DD_GuessFileTypeFromFileName(strPath).defaultClass(); } if(VALID_RESOURCECLASSID(defaultResourceClass)) { FS1::Scheme &fsScheme = App_FileSystem().scheme(ResourceClass::classForId(defaultResourceClass).defaultScheme()); scheme = fsScheme.name(); } }
bool Zip::uncompressRaw(uint8_t* in, size_t inSize, uint8_t* out, size_t outSize) { LOG_AS("Zip::uncompressRaw"); z_stream stream; int result; memset(&stream, 0, sizeof(stream)); stream.next_in = (Bytef*) in; stream.avail_in = (uInt) inSize; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.next_out = (Bytef*) out; stream.avail_out = (uInt) outSize; if(inflateInit2(&stream, -MAX_WBITS) != Z_OK) return false; // Do the inflation in one call. result = inflate(&stream, Z_FINISH); if(stream.total_out != outSize) { inflateEnd(&stream); LOG_WARNING("Failure due to %s (result code %i).") << (result == Z_DATA_ERROR ? "corrupt data" : "zlib error") << result; return false; } // We're done. inflateEnd(&stream); return true; }
res::AnimGroup &AnimGroups::newAnimGroup(dint flags) { LOG_AS("AnimGroups"); dint const uniqueId = d->animGroups.count() + 1; // 1-based. // Allocating one by one is inefficient but it doesn't really matter. d->animGroups.append(new res::AnimGroup(uniqueId, flags)); return *d->animGroups.last(); }
void CanvasWindow::hideEvent(QHideEvent *ev) { LOG_AS("CanvasWindow"); QMainWindow::hideEvent(ev); LOG_DEBUG("Hide event (hidden:%b)") << isHidden(); }
size_t Zip::readLump(int lumpIdx, uint8_t* buffer, size_t startOffset, size_t length, bool tryCache) { LOG_AS("Zip::readLump"); ZipFile const& file = reinterpret_cast<ZipFile&>(lump(lumpIdx)); LOG_TRACE("\"%s:%s\" (%u bytes%s) [%u +%u]") << de::NativePath(composePath()).pretty() << de::NativePath(file.composePath()).pretty() << (unsigned long) file.size() << (file.isCompressed()? ", compressed" : "") << startOffset << length; // Try to avoid a file system read by checking for a cached copy. if(tryCache) { uint8_t const* data = d->lumpCache? d->lumpCache->data(lumpIdx) : 0; LOG_TRACE("Cache %s on #%i") << (data? "hit" : "miss") << lumpIdx; if(data) { size_t readBytes = MIN_OF(file.size(), length); memcpy(buffer, data + startOffset, readBytes); return readBytes; } } size_t readBytes; if(!startOffset && length == file.size()) { // Read it straight to the caller's data buffer. readBytes = d->bufferLump(file, buffer); } else { // Allocate a temporary buffer and read the whole lump into it(!). uint8_t* lumpData = (uint8_t*) M_Malloc(file.size()); if(!lumpData) throw Error("Zip::readLumpSection", QString("Failed on allocation of %1 bytes for work buffer").arg(file.size())); if(d->bufferLump(file, lumpData)) { readBytes = MIN_OF(file.size(), length); memcpy(buffer, lumpData + startOffset, readBytes); } else { readBytes = 0; } M_Free(lumpData); } /// @todo Do not check the read length here. if(readBytes < MIN_OF(file.size(), length)) throw Error("Zip::readLumpSection", QString("Only read %1 of %2 bytes of lump #%3").arg(readBytes).arg(length).arg(lumpIdx)); return readBytes; }
res::AnimGroup *AnimGroups::animGroup(dint uniqueId) { LOG_AS("AnimGroups::animGroup"); if (uniqueId > 0 && uniqueId <= d->animGroups.count()) { return d->animGroups.at(uniqueId - 1); } LOGDEV_RES_WARNING("Invalid group #%i, returning NULL") << uniqueId; return nullptr; }
void AbstractLink::socketConnected() { LOG_AS("AbstractLink"); LOG_NET_VERBOSE("Successfully connected to server %s") << d->socket->peerAddress(); initiateCommunications(); d->status = Connected; d->connectedAt = Time(); d->peerAddress = d->socket->peerAddress(); emit connected(); }
static void Mouse_Init(void) { if(CommandLine_Check("-nomouse") || novideo) return; LOG_AS("Mouse_Init"); DENG_ASSERT(iMouse); iMouse->init(); // Init was successful. useMouse = true; }
String resolve() const { LOG_AS("Uri::resolve"); String result; // Keep scanning the path for embedded expressions. QStringRef expression; int expEnd = 0, expBegin; while((expBegin = strPath.indexOf('$', expEnd)) >= 0) { // Is the next char the start-of-expression character? if(strPath.at(expBegin + 1) == '(') { // Copy everything up to the '$'. result += strPath.mid(expEnd, expBegin - expEnd); // Skip over the '$'. ++expBegin; // Find the end-of-expression character. expEnd = strPath.indexOf(')', expBegin); if(expEnd < 0) { LOG_RES_WARNING("Ignoring expression \"" + strPath + "\": " "missing a closing ')'"); expEnd = strPath.length(); } // Skip over the '('. ++expBegin; // The range of the expression substring is now known. expression = strPath.midRef(expBegin, expEnd - expBegin); result += parseExpression(expression); } else { // No - copy the '$' and continue. result += '$'; } ++expEnd; } // Copy anything remaining. result += strPath.mid(expEnd); return result; }
void Task::run() { try { runTask(); } catch (Error const &er) { LOG_AS("Task"); LOG_WARNING("Aborted due to exception: ") << er.asText(); } // Cleanup. if (_pool) _pool->taskFinishedRunning(*this); Log::disposeThreadLog(); }
static void Mouse_Win32_Trap(dd_bool enabled) { LOG_AS("Mouse_Win32"); DENG_ASSERT(didMouse); mouseTrapped = (enabled != 0); if(enabled) { LOG_INPUT_VERBOSE("Acquiring the mouse"); didMouse->Acquire(); } else { LOG_INPUT_VERBOSE("Unacquiring the mouse"); didMouse->Unacquire(); } }
void Loop::nextLoopIteration() { try { if (d->running) { DENG2_FOR_AUDIENCE2(Iteration, i) i->loopIteration(); } } catch (Error const &er) { LOG_AS("Loop"); // This is called from Qt's event loop, we mustn't let exceptions // out of here uncaught. App::app().handleUncaughtException("Uncaught exception during loop iteration:\n" + er.asText()); } }
/** * Given a package identifier, pick one of the available versions of the package * based on predefined criteria. * * @param packageId Package identifier. * * @return Selected package, or @c NULL if a version could not be selected. */ File const *selectPackage(String const &packageId) const { LOG_AS("selectPackage"); FS::FoundFiles found; if(!findAllVariants(packageId, found)) { // None found. return 0; } // Each must have a version specified. DENG2_FOR_EACH_CONST(FS::FoundFiles, i, found) { File *pkg = *i; Package::parseMetadata(*pkg); Package::validateMetadata(pkg->info().subrecord("package")); }
FileHandle* FileHandleBuilder::fromLump(File1& lump, bool dontBuffer) { LOG_AS("FileHandle::fromLump"); de::FileHandle* hndl = new de::FileHandle(); // Init and load in the lump data. hndl->d->file = &lump; hndl->d->flags.open = true; if(!dontBuffer) { hndl->d->size = lump.size(); hndl->d->pos = hndl->d->data = (uint8_t*) M_Malloc(hndl->d->size); if(!hndl->d->data) Con_Error("FileHandleBuilder::fromFileLump: Failed on allocation of %lu bytes for data buffer.", (unsigned long) hndl->d->size); LOG_DEV_TRACE("[%p] Buffering \"%s:%s\"...", dintptr(hndl) << NativePath(lump.container().composePath()).pretty() << NativePath(lump.composePath()).pretty()); lump.read((uint8_t*)hndl->d->data, 0, lump.size()); } return hndl; }
void Zip::unlockLump(int lumpIdx) { LOG_AS("Zip::unlockLump"); LOG_TRACE("\"%s:%s\"") << de::NativePath(composePath()).pretty() << lump(lumpIdx).composePath(); if(isValidIndex(lumpIdx)) { if(d->lumpCache) { d->lumpCache->unlock(lumpIdx); } else { LOG_DEBUG("LumpCache not in use, ignoring."); } } else { QString msg = invalidIndexMessage(lumpIdx, lastIndex()); LOG_DEBUG(msg + ", ignoring."); } }
void Zip::clearCachedLump(int lumpIdx, bool* retCleared) { LOG_AS("Zip::clearCachedLump"); if(retCleared) *retCleared = false; if(isValidIndex(lumpIdx)) { if(d->lumpCache) { d->lumpCache->remove(lumpIdx, retCleared); } else { LOG_DEBUG("LumpCache not in use, ignoring."); } } else { QString msg = invalidIndexMessage(lumpIdx, lastIndex()); LOG_DEBUG(msg + ", ignoring."); } }
void *WAV_Load(char const *filename, int *bits, int *rate, int *samples) { try { // Relative paths are relative to the native working directory. de::String path = (de::NativePath::workPath() / de::NativePath(filename).expand()).withSeparators('/'); QScopedPointer<de::FileHandle> hndl(&App_FileSystem().openFile(path, "rb")); // Read in the whole thing. size_t size = hndl->length(); LOG_AS("WAV_Load"); LOGDEV_RES_XVERBOSE("Loading from \"%s\" (size %i, fpos %i)") << de::NativePath(hndl->file().composePath()).pretty() << size << hndl->tell(); uint8_t *data = (uint8_t *) M_Malloc(size); hndl->read(data, size); App_FileSystem().releaseFile(hndl->file()); // Parse the RIFF data. void *sampledata = WAV_MemoryLoad((byte const *) data, size, bits, rate, samples); if(!sampledata) { LOG_RES_WARNING("Failed to load \"%s\"") << filename; } M_Free(data); return sampledata; } catch(de::FS1::NotFoundError const &) {} // Ignore. return 0; }
uint8_t* Zip::uncompress(uint8_t* in, size_t inSize, size_t* outSize) { #define INF_CHUNK_SIZE 4096 // Uncompress in 4KB chunks. LOG_AS("Zip::uncompress"); z_stream stream; uint8_t chunk[INF_CHUNK_SIZE]; size_t allocSize = INF_CHUNK_SIZE; uint8_t* output = (uint8_t*) M_Malloc(allocSize); // some initial space int result; int have; DENG2_ASSERT(outSize); *outSize = 0; memset(&stream, 0, sizeof(stream)); stream.next_in = (Bytef*) in; stream.avail_in = (uInt) inSize; result = inflateInit(&stream); if(result != Z_OK) { M_Free(output); return 0; } // Uncompress until all the input data has been exhausted. do { stream.next_out = chunk; stream.avail_out = INF_CHUNK_SIZE; result = inflate(&stream, Z_FINISH); if(result == Z_STREAM_ERROR) { M_Free(output); *outSize = 0; return 0; } have = INF_CHUNK_SIZE - stream.avail_out; if(have) { // Need more memory? if(*outSize + have > allocSize) { // Need more memory. allocSize *= 2; output = (uint8_t*) M_Realloc(output, allocSize); } // Append. memcpy(output + *outSize, chunk, have); *outSize += have; } } while(!stream.avail_out); // output chunk full, more data may follow // We should now be at the end. DENG2_ASSERT(result == Z_STREAM_END); inflateEnd(&stream); return output; #undef INF_CHUNK_SIZE }
size_t Zip::readLump(int lumpIdx, uint8_t* buffer, bool tryCache) { LOG_AS("Zip::readLump"); if(!isValidIndex(lumpIdx)) return 0; return readLump(lumpIdx, buffer, 0, lump(lumpIdx).size(), tryCache); }
void FontBank::addFromInfo(File const &file) { LOG_AS("FontBank"); parse(file); addFromInfoBlocks("font"); }
void Config::read() { if (d->configPath.isEmpty()) return; LOG_AS("Config::read"); // Current version. Version verInfo = Version::currentBuild(); QScopedPointer<ArrayValue> version(new ArrayValue); *version << NumberValue(verInfo.major) << NumberValue(verInfo.minor) << NumberValue(verInfo.patch) << NumberValue(verInfo.build); File &scriptFile = App::rootFolder().locate<File>(d->configPath); bool shouldRunScript = App::commandLine().has("-reconfig"); try { // If we already have a saved copy of the config, read it. d->refuge.read(); LOG_DEBUG("Found serialized Config:\n") << objectNamespace(); // If the saved config is from a different version, rerun the script. if (objectNamespace().has("__version__")) { Value const &oldVersion = objectNamespace()["__version__"].value(); d->setOldVersion(oldVersion); if (oldVersion.compare(*version)) { // Version mismatch: store the old version in a separate variable. d->config.globals().add(new Variable("__oldversion__", oldVersion.duplicate(), Variable::AllowArray | Variable::ReadOnly)); shouldRunScript = true; } else { // Versions match. LOG_MSG("") << d->refuge.path() << " matches version " << version->asText(); } } else { // Don't know what version this is, run script to be sure. shouldRunScript = true; } // Also check the timestamp of written config vs. the config script. // If script is newer, it should be rerun. if (scriptFile.status().modifiedAt > d->refuge.lastWrittenAt()) { LOG_MSG("%s is newer than %s, rerunning the script") << d->configPath << d->refuge.path(); shouldRunScript = true; } // Check the container, too. if (!shouldRunScript && Package::containerOfFileModifiedAt(scriptFile) > d->refuge.lastWrittenAt()) { LOG_MSG("Package '%s' is newer than %s, rerunning the script") << Package::identifierForContainerOfFile(scriptFile) << d->refuge.path(); shouldRunScript = true; } } catch (Archive::NotFoundError const &) { // It is missing from persist.pack if the config hasn't been written yet. shouldRunScript = true; } catch (IByteArray::OffsetError const &) { // Empty or missing serialization? shouldRunScript = true; } catch (Error const &error) { LOG_WARNING(error.what()); // Something is wrong, maybe rerunning will fix it. shouldRunScript = true; } // The version of libcore is automatically included in the namespace. d->config.globals().add(new Variable("__version__", version.take(), Variable::AllowArray | Variable::ReadOnly)); if (shouldRunScript) { // Read the main configuration. Script script(scriptFile); d->config.run(script); d->config.execute(); } }
void* WAV_MemoryLoad(const byte* data, size_t datalength, int* bits, int* rate, int* samples) { const byte* end = data + datalength; byte* sampledata = NULL; chunk_hdr_t riff_chunk; wav_format_t wave_format; LOG_AS("WAV_MemoryLoad"); if(!WAV_CheckFormat((const char*)data)) { LOG_RES_WARNING("Not WAV format data"); return NULL; } // Read the RIFF header. data += sizeof(riff_hdr_t); data += 4; // "WAVE" already verified above #ifdef _DEBUG assert(sizeof(wave_format) == 16); assert(sizeof(riff_chunk) == 8); #endif // Start readin' the chunks, baby! while(data < end) { // Read next chunk header. WReadAndAdvance(data, &riff_chunk, sizeof(riff_chunk)); // Correct endianness. riff_chunk.len = DD_ULONG(riff_chunk.len); // What have we got here? if(!strncmp(riff_chunk.id, "fmt ", 4)) { // Read format chunk. WReadAndAdvance(data, &wave_format, sizeof(wave_format)); // Correct endianness. wave_format.wFormatTag = DD_USHORT(wave_format.wFormatTag ); wave_format.wChannels = DD_USHORT(wave_format.wChannels ); wave_format.dwSamplesPerSec = DD_ULONG (wave_format.dwSamplesPerSec ); wave_format.dwAvgBytesPerSec = DD_ULONG (wave_format.dwAvgBytesPerSec); wave_format.wBlockAlign = DD_USHORT(wave_format.wBlockAlign ); wave_format.wBitsPerSample = DD_USHORT(wave_format.wBitsPerSample ); assert(wave_format.wFormatTag == WAVE_FORMAT_PCM); // linear PCM // Check that it's a format we know how to read. if(wave_format.wFormatTag != WAVE_FORMAT_PCM) { LOG_RES_WARNING("Unsupported format (%i)") << wave_format.wFormatTag; return NULL; } if(wave_format.wChannels != 1) { LOG_RES_WARNING("Too many channels (only mono supported)"); return NULL; } // Read the extra format information. //WReadAndAdvance(&data, &wave_format2, sizeof(*wave_format2)); /*if(wave_format->wBitsPerSample == 0) { // We'll have to guess... *bits = 8*wave_format->dwAvgBytesPerSec/ wave_format->dwSamplesPerSec; } else { */ if(wave_format.wBitsPerSample != 8 && wave_format.wBitsPerSample != 16) { LOG_RES_WARNING("Must have 8 or 16 bits per sample"); return NULL; } // Now we know some information about the sample. *bits = wave_format.wBitsPerSample; *rate = wave_format.dwSamplesPerSec; } else if(!strncmp(riff_chunk.id, "data", 4)) { if(!wave_format.wFormatTag) { LOG_RES_WARNING("Malformed WAV data"); return NULL; } // Read data chunk. *samples = riff_chunk.len / wave_format.wBlockAlign; // Allocate the sample buffer. sampledata = (byte *) Z_Malloc(riff_chunk.len, PU_APPSTATIC, 0); memcpy(sampledata, data, riff_chunk.len); #ifdef __BIG_ENDIAN__ // Correct endianness. /*if(wave_format->wBitsPerSample == 16) { ushort* sample = sampledata; for(; sample < ((short*)sampledata) + *samples; ++sample) *sample = DD_USHORT(*sample); }*/ #endif // We're satisfied with this! Let's get out of here. break; } else { // Unknown chunk, just skip it. data += riff_chunk.len; } } return sampledata; }
uint8_t* Zip::compressAtLevel(uint8_t* in, size_t inSize, size_t* outSize, int level) { #define CHUNK_SIZE 32768 LOG_AS("Zip::compressAtLevel"); z_stream stream; uint8_t chunk[CHUNK_SIZE]; size_t allocSize = CHUNK_SIZE; uint8_t* output = (uint8_t*) M_Malloc(allocSize); // some initial space int result; int have; DENG2_ASSERT(outSize); *outSize = 0; memset(&stream, 0, sizeof(stream)); stream.next_in = (Bytef*) in; stream.avail_in = (uInt) inSize; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.opaque = Z_NULL; if(level < Z_NO_COMPRESSION) { level = Z_NO_COMPRESSION; } if(level > Z_BEST_COMPRESSION) { level = Z_BEST_COMPRESSION; } result = deflateInit(&stream, level); if(result != Z_OK) { M_Free(output); return 0; } // Compress until all the data has been exhausted. do { stream.next_out = chunk; stream.avail_out = CHUNK_SIZE; result = deflate(&stream, Z_FINISH); if(result == Z_STREAM_ERROR) { M_Free(output); *outSize = 0; return 0; } have = CHUNK_SIZE - stream.avail_out; if(have) { // Need more memory? if(*outSize + have > allocSize) { // Need more memory. allocSize *= 2; output = (uint8_t*) M_Realloc(output, allocSize); } // Append. memcpy(output + *outSize, chunk, have); *outSize += have; } } while(!stream.avail_out); // output chunk full, more data may follow DENG2_ASSERT(result == Z_STREAM_END); DENG2_ASSERT(stream.total_out == *outSize); deflateEnd(&stream); return output; #undef CHUNK_SIZE }
void init() { LOG_AS("GLInfo"); if (inited) return; if (!initializeOpenGLFunctions()) { throw InitError("GLInfo::init", "Failed to initialize OpenGL"); } // Extensions. ext.ARB_draw_instanced = query("GL_ARB_draw_instanced"); ext.ARB_instanced_arrays = query("GL_ARB_instanced_arrays"); ext.ARB_texture_env_combine = query("GL_ARB_texture_env_combine") || query("GL_EXT_texture_env_combine"); ext.ARB_texture_non_power_of_two = query("GL_ARB_texture_non_power_of_two"); ext.EXT_blend_subtract = query("GL_EXT_blend_subtract"); ext.EXT_framebuffer_blit = query("GL_EXT_framebuffer_blit"); ext.EXT_framebuffer_multisample = query("GL_EXT_framebuffer_multisample"); ext.EXT_framebuffer_object = query("GL_EXT_framebuffer_object"); ext.EXT_packed_depth_stencil = query("GL_EXT_packed_depth_stencil"); ext.EXT_texture_compression_s3tc = query("GL_EXT_texture_compression_s3tc"); ext.EXT_texture_filter_anisotropic = query("GL_EXT_texture_filter_anisotropic"); ext.EXT_timer_query = query("GL_EXT_timer_query"); ext.ATI_texture_env_combine3 = query("GL_ATI_texture_env_combine3"); ext.NV_framebuffer_multisample_coverage = query("GL_NV_framebuffer_multisample_coverage"); ext.NV_texture_env_combine4 = query("GL_NV_texture_env_combine4"); ext.SGIS_generate_mipmap = query("GL_SGIS_generate_mipmap"); #ifdef WIN32 ext.Windows_ARB_multisample = query("WGL_ARB_multisample"); ext.Windows_EXT_swap_control = query("WGL_EXT_swap_control"); if (ext.Windows_EXT_swap_control) { wglSwapIntervalEXT = de::function_cast<decltype(wglSwapIntervalEXT)> (QOpenGLContext::currentContext()->getProcAddress("wglSwapIntervalEXT")); } #endif #ifdef DENG_X11 ext.X11_EXT_swap_control = query("GLX_EXT_swap_control"); ext.X11_SGI_swap_control = query("GLX_SGI_swap_control"); ext.X11_MESA_swap_control = query("GLX_MESA_swap_control"); if (ext.X11_EXT_swap_control) { glXSwapIntervalEXT = de::function_cast<decltype(glXSwapIntervalEXT)> (glXGetProcAddress(reinterpret_cast<GLubyte const *>("glXSwapIntervalEXT"))); } if (ext.X11_SGI_swap_control) { glXSwapIntervalSGI = de::function_cast<decltype(glXSwapIntervalSGI)> (glXGetProcAddress(reinterpret_cast<GLubyte const *>("glXSwapIntervalSGI"))); } if (ext.X11_MESA_swap_control) { glXSwapIntervalMESA = de::function_cast<decltype(glXSwapIntervalMESA)> (glXGetProcAddress(reinterpret_cast<GLubyte const *>("glXSwapIntervalMESA"))); } #endif if (ext.ARB_draw_instanced) { ARB_draw_instanced.reset(new QOpenGLExtension_ARB_draw_instanced); ARB_draw_instanced->initializeOpenGLFunctions(); } if (ext.ARB_instanced_arrays) { ARB_instanced_arrays.reset(new QOpenGLExtension_ARB_instanced_arrays); ARB_instanced_arrays->initializeOpenGLFunctions(); } if (ext.EXT_framebuffer_blit) { EXT_framebuffer_blit.reset(new QOpenGLExtension_EXT_framebuffer_blit); EXT_framebuffer_blit->initializeOpenGLFunctions(); } if (ext.EXT_framebuffer_multisample) { EXT_framebuffer_multisample.reset(new QOpenGLExtension_EXT_framebuffer_multisample); EXT_framebuffer_multisample->initializeOpenGLFunctions(); } if (ext.EXT_framebuffer_object) { EXT_framebuffer_object.reset(new QOpenGLExtension_EXT_framebuffer_object); EXT_framebuffer_object->initializeOpenGLFunctions(); } if (ext.NV_framebuffer_multisample_coverage) { NV_framebuffer_multisample_coverage.reset(new QOpenGLExtension_NV_framebuffer_multisample_coverage); NV_framebuffer_multisample_coverage->initializeOpenGLFunctions(); } // Limits. glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &lim.maxTexSize); glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint *) &lim.maxTexUnits); if (ext.EXT_texture_filter_anisotropic) { glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint *) &lim.maxTexFilterAniso); } // Set a custom maximum size? if (CommandLine_CheckWith("-maxtex", 1)) { lim.maxTexSize = min(ceilPow2(String(CommandLine_Next()).toInt()), lim.maxTexSize); LOG_GL_NOTE("Using requested maximum texture size of %i x %i") << lim.maxTexSize << lim.maxTexSize; } // Check default OpenGL format attributes. QOpenGLContext const *ctx = QOpenGLContext::currentContext(); QSurfaceFormat form = ctx->format(); LOGDEV_GL_MSG("Initial OpenGL format:"); LOGDEV_GL_MSG(" - version: %i.%i") << form.majorVersion() << form.minorVersion(); LOGDEV_GL_MSG(" - profile: %s") << (form.profile() == QSurfaceFormat::CompatibilityProfile? "Compatibility" : "Core"); LOGDEV_GL_MSG(" - color: R%i G%i B%i A%i bits") << form.redBufferSize() << form.greenBufferSize() << form.blueBufferSize() << form.alphaBufferSize(); LOGDEV_GL_MSG(" - depth: %i bits") << form.depthBufferSize(); LOGDEV_GL_MSG(" - stencil: %i bits") << form.stencilBufferSize(); LOGDEV_GL_MSG(" - samples: %i") << form.samples(); LOGDEV_GL_MSG(" - swap behavior: %i") << form.swapBehavior(); inited = true; }