this *shouldn't* matter, but due to some Mesa bug is does:
If the shaders have been loaded already (with R_LoadARBProgram()),
then loading them again (like from the `reloadARBprograms` console cmd
or as it happens if the `r_gammaInShader` has been modified) will
cause glitches with the open source radeonsi driver (maybe also with
others? at least the open source intel driver seems unaffected).
As r_gammaInShader was marked as modified at startup (before the shaders
were even loaded) they were loaded twice: First as expected when OpenGL
is initialized, then again in R_CheckCvars() which is executed each
frame. Marking as at not modified in R_InitOpenGL() prevents this and
thus works around the bug.
However this means that changing r_gammaInShader at runtime will still
trigger this bug (while with non-broken drivers it switches seamlessly
between gamma in shader and gamma in hardware without a vid_restart).
Originally sound updates only happened about every 100ms and
`sampleTime` (or `newSoundTime`) was a multiple of 4096
(`MIXBUFFER_SAMPLES`).
After I changed this to updates every 16ms and made the calculation of
`sampleTime` a lot simpler, it could be any value (as it's current
amount of milliseconds multiplied by 44.1).
It generally seemed to work, but it seems advisable to make it a
multiple of 8 (see also "Fix endless loop when decoding OGGs" commit).
So I round it to the nearest multiple of 8 now. Furthermore I increased
the accuracy when the game has been running for a long time by using
double instead of float, and tried to make sure that `sampleTime` is
always positive (or at least as long as `inTime` is positive).
idStr is used in both the main thread and the async sound thread, so
it should better be thread-safe.. idDynamicBlockAlloc is not.
Use realloc() and free() instead.
For some reason this caused a lot more crashes (due to inconsistencies
in the allocator's heap) with newer Linux distros (like XUbuntu 20.04)
and when using GCC9, while they rarely reproduced with GCC7 or on
XUbuntu 18.04
fixes#391
In idSampleDecoderLocal::DecodeOGG() `totalSamples` was 1 and
`reqSamples` was 0, which caused an endless loop.. this was caused by
idSoundWorldLocal::ReadFromSaveGame() setting
`chan->openalStreamingOffset` to an odd number, I think due to
`currentSoundTime` being an odd number.
To fix that, I round up `chan->openalStreamingOffset` to a (very) even
number, and to be double-sure I also added a check in DecodeOgg() to
make sure it exits the loop if `reqSamples` is 0.
If those functions (e.g. called by common->Printf(), common->Error())
weren't called from the mainthread and win_outputEditString was set to 1,
a deadlock could occur.
Specifically, the async thread (handling sound) was calling
common->Warning() -> Sys_Printf() -> Conbuf_AppendText() which called
SendMessageA() which blocks until the main thread handles the message.
The main thread however was in idSampleDecoderLocal::Decode() trying to
enter CRITICAL_SECTION_ONE, which was held by the async thread
(it's used to synchronize sound handling between main and async thread).
So now if Sys_Printf() (or Sys_Error() which should have the same problem)
is not called by the main thread, the text is buffered and
Conbuf_AppendText() is called for the buffered lines in the next frame
in Win_Frame().
In idSampleDecoderLocal::DecodeOGG() sometimes (esp. in The Lost Mission
mod) it happens that stb_vorbis_get_samples_float() decodes one sample
less than expected so one is left and when trying to decode that,
stb_vorbis_get_samples_float() returns 0, which we interpreted as an error.
This case is now handled more gracefully: No warning is printed (except
if developer 1) and failed is not set (setting it would prevent the sound
from being played again, I think).
the script paths were wrong, on Linux they were like
"pak000.pk4/script/doom_util.script" while on Windows it's only
"script/doom_util.script".
Fixed idFileSystemLocal::OSPathToRelativePath() to skip ...pk4/
also fixed GCC compile error in Common.cpp
only override cmd->viewDef in RB_DrawView() if we're drawing the
primary view (which for several calculations before actual drawing
was set to the saved/locked render view)
Note that r_lockSurfaces is more useful with r_useScissor 0 (otherwise
there's black bars over the screen when moving) and r_shadows 0 (otherwise
areas that weren't visible when locking are black because the lights
there are skipped)
remaining bug: gui surfaces move around the screen when looking around