diff --git a/.gitignore b/.gitignore index 15a84aa7..1c9a7e10 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,6 @@ profile # Microsoft Visual Studio #################### -*.sdf \ No newline at end of file +*.sdf +*.opensdf +*.suo diff --git a/Makefile b/Makefile index 7ed2cd4b..2c22c19e 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ COMPILE_PLATFORM=$(shell uname|sed -e s/_.*//|tr '[:upper:]' '[:lower:]'|sed -e 's/\//_/g') -COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/) +COMPILE_ARCH=$(shell uname -m | sed -e s/i.86/x86/ | sed -e 's/^arm.*/arm/') ifeq ($(COMPILE_PLATFORM),sunos) # Solaris uname and GNU uname differ @@ -52,11 +52,22 @@ endif ############################################################################# -include Makefile.local +ifeq ($(COMPILE_PLATFORM),cygwin) + PLATFORM=mingw32 +endif + ifndef PLATFORM PLATFORM=$(COMPILE_PLATFORM) endif export PLATFORM +ifeq ($(PLATFORM),mingw32) + MINGW=1 +endif +ifeq ($(PLATFORM),mingw64) + MINGW=1 +endif + ifeq ($(COMPILE_ARCH),i86pc) COMPILE_ARCH=x86 endif @@ -160,7 +171,7 @@ USE_CURL=1 endif ifndef USE_CURL_DLOPEN - ifeq ($(PLATFORM),mingw32) + ifdef MINGW USE_CURL_DLOPEN=0 else USE_CURL_DLOPEN=1 @@ -187,32 +198,36 @@ ifndef USE_FREETYPE USE_FREETYPE=0 endif +ifndef USE_INTERNAL_LIBS +USE_INTERNAL_LIBS=1 +endif + ifndef USE_INTERNAL_SPEEX -USE_INTERNAL_SPEEX=1 +USE_INTERNAL_SPEEX=$(USE_INTERNAL_LIBS) endif ifndef USE_INTERNAL_OGG -USE_INTERNAL_OGG=1 +USE_INTERNAL_OGG=$(USE_INTERNAL_LIBS) endif ifndef USE_INTERNAL_VORBIS -USE_INTERNAL_VORBIS=1 +USE_INTERNAL_VORBIS=$(USE_INTERNAL_LIBS) endif ifndef USE_INTERNAL_OPUS -USE_INTERNAL_OPUS=1 +USE_INTERNAL_OPUS=$(USE_INTERNAL_LIBS) endif ifndef USE_INTERNAL_ZLIB -USE_INTERNAL_ZLIB=1 +USE_INTERNAL_ZLIB=$(USE_INTERNAL_LIBS) endif ifndef USE_INTERNAL_JPEG -USE_INTERNAL_JPEG=1 +USE_INTERNAL_JPEG=$(USE_INTERNAL_LIBS) endif ifndef USE_LOCAL_HEADERS -USE_LOCAL_HEADERS=1 +USE_LOCAL_HEADERS=$(USE_INTERNAL_LIBS) endif ifndef USE_RENDERER_DLOPEN @@ -266,19 +281,23 @@ ifneq ($(BUILD_CLIENT),0) # set PKG_CONFIG_PATH to influence this, e.g. # PKG_CONFIG_PATH=/opt/cross/i386-mingw32msvc/lib/pkgconfig ifneq ($(call bin_path, pkg-config),) - CURL_CFLAGS=$(shell pkg-config --silence-errors --cflags libcurl) - CURL_LIBS=$(shell pkg-config --silence-errors --libs libcurl) - OPENAL_CFLAGS=$(shell pkg-config --silence-errors --cflags openal) - OPENAL_LIBS=$(shell pkg-config --silence-errors --libs openal) - SDL_CFLAGS=$(shell pkg-config --silence-errors --cflags sdl2|sed 's/-Dmain=SDL_main//') - SDL_LIBS=$(shell pkg-config --silence-errors --libs sdl2) - FREETYPE_CFLAGS=$(shell pkg-config --silence-errors --cflags freetype2) + CURL_CFLAGS ?= $(shell pkg-config --silence-errors --cflags libcurl) + CURL_LIBS ?= $(shell pkg-config --silence-errors --libs libcurl) + OPENAL_CFLAGS ?= $(shell pkg-config --silence-errors --cflags openal) + OPENAL_LIBS ?= $(shell pkg-config --silence-errors --libs openal) + SDL_CFLAGS ?= $(shell pkg-config --silence-errors --cflags sdl2|sed 's/-Dmain=SDL_main//') + SDL_LIBS ?= $(shell pkg-config --silence-errors --libs sdl2) + FREETYPE_CFLAGS ?= $(shell pkg-config --silence-errors --cflags freetype2) + else + # assume they're in the system default paths (no -I or -L needed) + CURL_LIBS ?= -lcurl + OPENAL_LIBS ?= -lopenal endif - # Use sdl-config if all else fails + # Use sdl2-config if all else fails ifeq ($(SDL_CFLAGS),) ifneq ($(call bin_path, sdl2-config),) - SDL_CFLAGS=$(shell sdl2-config --cflags) - SDL_LIBS=$(shell sdl2-config --libs) + SDL_CFLAGS ?= $(shell sdl2-config --cflags) + SDL_LIBS ?= $(shell sdl2-config --libs) endif endif endif @@ -298,42 +317,30 @@ endif # SETUP AND BUILD -- LINUX ############################################################################# -## Defaults -LIB=lib - INSTALL=install MKDIR=mkdir +EXTRA_FILES= +CLIENT_EXTRA_FILES= -ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu")) - - ifeq ($(ARCH),x86_64) - LIB=lib64 - else - ifeq ($(ARCH),ppc64) - LIB=lib64 - else - ifeq ($(ARCH),s390x) - LIB=lib64 - endif - endif - endif +ifneq (,$(findstring "$(COMPILE_PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu")) + TOOLS_CFLAGS += -DARCH_STRING=\"$(COMPILE_ARCH)\" +endif +ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu" "gnu")) BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes \ - -pipe -DUSE_ICON -DREACTION + -pipe -DUSE_ICON -DARCH_STRING=\\\"$(ARCH)\\\" -DREACTION CLIENT_CFLAGS += $(SDL_CFLAGS) -DREACTION - OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer + OPTIMIZEVM = -O3 OPTIMIZE = $(OPTIMIZEVM) -ffast-math ifeq ($(ARCH),x86_64) - OPTIMIZEVM = -O3 -fomit-frame-pointer -funroll-loops \ - -falign-functions=2 -fstrength-reduce + OPTIMIZEVM = -O3 OPTIMIZE = $(OPTIMIZEVM) -ffast-math HAVE_VM_COMPILED = true else ifeq ($(ARCH),x86) - OPTIMIZEVM = -O3 -march=i586 -fomit-frame-pointer \ - -funroll-loops -falign-functions=2 -fstrength-reduce + OPTIMIZEVM = -O3 -march=i586 OPTIMIZE = $(OPTIMIZEVM) -ffast-math HAVE_VM_COMPILED=true else @@ -370,13 +377,14 @@ ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu")) ifeq ($(USE_OPENAL),1) ifneq ($(USE_OPENAL_DLOPEN),1) - CLIENT_LIBS += -lopenal + CLIENT_LIBS += $(THREAD_LIBS) $(OPENAL_LIBS) endif endif ifeq ($(USE_CURL),1) + CLIENT_CFLAGS += $(CURL_CFLAGS) ifneq ($(USE_CURL_DLOPEN),1) - CLIENT_LIBS += -lcurl + CLIENT_LIBS += $(CURL_LIBS) endif endif @@ -384,10 +392,6 @@ ifneq (,$(findstring "$(PLATFORM)", "linux" "gnu_kfreebsd" "kfreebsd-gnu")) CLIENT_LIBS += -lrt endif - ifeq ($(USE_FREETYPE),1) - BASE_CFLAGS += $(FREETYPE_CFLAGS) - endif - ifeq ($(ARCH),x86) # linux32 make ... BASE_CFLAGS += -m32 @@ -409,14 +413,15 @@ ifeq ($(PLATFORM),darwin) RENDERER_LIBS= OPTIMIZEVM= - BASE_CFLAGS = -Wall -Wimplicit -Wstrict-prototypes -DREACTION + BASE_CFLAGS = -Wall -Wimplicit -Wstrict-prototypes -mmacosx-version-min=10.5 \ + -DMAC_OS_X_VERSION_MIN_REQUIRED=1050 -DREACTION ifeq ($(ARCH),ppc) - BASE_CFLAGS += -arch ppc -faltivec -mmacosx-version-min=10.2 + BASE_CFLAGS += -arch ppc -faltivec OPTIMIZEVM += -O3 endif ifeq ($(ARCH),ppc64) - BASE_CFLAGS += -arch ppc64 -faltivec -mmacosx-version-min=10.2 + BASE_CFLAGS += -arch ppc64 -faltivec endif ifeq ($(ARCH),x86) OPTIMIZEVM += -march=prescott -mfpmath=sse @@ -436,13 +441,13 @@ ifeq ($(PLATFORM),darwin) endif ifeq ($(CROSS_COMPILING),1) - ifeq ($(ARCH),ppc) - CC=powerpc-apple-darwin10-gcc - RANLIB=powerpc-apple-darwin10-ranlib + ifeq ($(ARCH),x86_64) + CC=x86_64-apple-darwin13-cc + RANLIB=x86_64-apple-darwin13-ranlib else ifeq ($(ARCH),x86) - CC=i686-apple-darwin10-gcc - RANLIB=i686-apple-darwin10-ranlib + CC=i386-apple-darwin13-cc + RANLIB=i386-apple-darwin13-ranlib else $(error Architecture $(ARCH) is not supported when cross compiling) endif @@ -460,15 +465,12 @@ ifeq ($(PLATFORM),darwin) endif ifeq ($(USE_CURL),1) + CLIENT_CFLAGS += $(CURL_CFLAGS) ifneq ($(USE_CURL_DLOPEN),1) - CLIENT_LIBS += -lcurl + CLIENT_LIBS += $(CURL_LIBS) endif endif - ifeq ($(USE_FREETYPE),1) - BASE_CFLAGS += $(FREETYPE_CFLAGS) - endif - BASE_CFLAGS += -D_THREAD_SAFE=1 ifeq ($(USE_LOCAL_HEADERS),1) @@ -482,6 +484,7 @@ ifeq ($(PLATFORM),darwin) CLIENT_LIBS += -framework IOKit \ $(LIBSDIR)/macosx/libSDL2-2.0.0.dylib RENDERER_LIBS += -framework OpenGL $(LIBSDIR)/macosx/libSDL2-2.0.0.dylib + CLIENT_EXTRA_FILES += $(LIBSDIR)/macosx/libSDL2-2.0.0.dylib OPTIMIZE = $(OPTIMIZEVM) -ffast-math @@ -498,7 +501,7 @@ else # ifeq darwin # SETUP AND BUILD -- MINGW32 ############################################################################# -ifeq ($(PLATFORM),mingw32) +ifdef MINGW ifeq ($(CROSS_COMPILING),1) # If CC is already set to something generic, we probably want to use @@ -512,7 +515,7 @@ ifeq ($(PLATFORM),mingw32) MINGW_PREFIXES=amd64-mingw32msvc x86_64-w64-mingw32 endif ifeq ($(ARCH),x86) - MINGW_PREFIXES=i586-mingw32msvc i686-w64-mingw32 + MINGW_PREFIXES=i586-mingw32msvc i686-w64-mingw32 i686-pc-mingw32 endif ifndef CC @@ -556,14 +559,12 @@ ifeq ($(PLATFORM),mingw32) endif ifeq ($(ARCH),x86_64) - OPTIMIZEVM = -O3 -fno-omit-frame-pointer \ - -funroll-loops -falign-functions=2 -fstrength-reduce - OPTIMIZE = $(OPTIMIZEVM) --fast-math + OPTIMIZEVM = -O3 + OPTIMIZE = $(OPTIMIZEVM) -ffast-math HAVE_VM_COMPILED = true endif ifeq ($(ARCH),x86) - OPTIMIZEVM = -O3 -march=i586 -fno-omit-frame-pointer \ - -funroll-loops -falign-functions=2 -fstrength-reduce + OPTIMIZEVM = -O3 -march=i586 OPTIMIZE = $(OPTIMIZEVM) -ffast-math HAVE_VM_COMPILED = true endif @@ -578,13 +579,21 @@ ifeq ($(PLATFORM),mingw32) TOOLS_BINEXT=.exe endif + ifeq ($(COMPILE_PLATFORM),cygwin) + TOOLS_BINEXT=.exe + TOOLS_CC=$(CC) + endif + LIBS= -lws2_32 -lwinmm -lpsapi - CLIENT_LDFLAGS += -mwindows + # clang 3.4 doesn't support this + ifneq ("$(CC)", $(findstring "$(CC)", "clang" "clang++")) + CLIENT_LDFLAGS += -mwindows + endif CLIENT_LIBS = -lgdi32 -lole32 RENDERER_LIBS = -lgdi32 -lole32 -lopengl32 ifeq ($(USE_FREETYPE),1) - BASE_CFLAGS += -Ifreetype2 + FREETYPE_CFLAGS = -Ifreetype2 endif ifeq ($(USE_CURL),1) @@ -622,12 +631,14 @@ ifeq ($(PLATFORM),mingw32) RENDERER_LIBS += $(LIBSDIR)/win32/libSDL2main.a \ $(LIBSDIR)/win32/libSDL2.dll.a SDLDLL=SDL2.dll + CLIENT_EXTRA_FILES += $(LIBSDIR)/win32/SDL2.dll else CLIENT_LIBS += $(LIBSDIR)/win64/libSDL264main.a \ $(LIBSDIR)/win64/libSDL264.dll.a RENDERER_LIBS += $(LIBSDIR)/win64/libSDL264main.a \ $(LIBSDIR)/win64/libSDL264.dll.a SDLDLL=SDL264.dll + CLIENT_EXTRA_FILES += $(LIBSDIR)/win64/SDL264.dll endif else CLIENT_CFLAGS += $(SDL_CFLAGS) @@ -636,7 +647,7 @@ ifeq ($(PLATFORM),mingw32) SDLDLL=SDL2.dll endif -else # ifeq mingw32 +else # ifdef MINGW ############################################################################# # SETUP AND BUILD -- FREEBSD @@ -651,7 +662,7 @@ ifeq ($(PLATFORM),freebsd) CLIENT_CFLAGS += $(SDL_CFLAGS) HAVE_VM_COMPILED = true - OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer + OPTIMIZEVM = -O3 OPTIMIZE = $(OPTIMIZEVM) -ffast-math SHLIBEXT=so @@ -670,13 +681,14 @@ ifeq ($(PLATFORM),freebsd) # optional features/libraries ifeq ($(USE_OPENAL),1) ifeq ($(USE_OPENAL_DLOPEN),1) - CLIENT_LIBS += $(THREAD_LIBS) -lopenal + CLIENT_LIBS += $(THREAD_LIBS) $(OPENAL_LIBS) endif endif ifeq ($(USE_CURL),1) + CLIENT_CFLAGS += $(CURL_CFLAGS) ifeq ($(USE_CURL_DLOPEN),1) - CLIENT_LIBS += -lcurl + CLIENT_LIBS += $(CURL_LIBS) endif endif @@ -703,18 +715,16 @@ ifeq ($(PLATFORM),openbsd) -pipe -DUSE_ICON -DMAP_ANONYMOUS=MAP_ANON -DREACTION CLIENT_CFLAGS += $(SDL_CFLAGS) - OPTIMIZEVM = -O3 -funroll-loops -fomit-frame-pointer + OPTIMIZEVM = -O3 OPTIMIZE = $(OPTIMIZEVM) -ffast-math ifeq ($(ARCH),x86_64) - OPTIMIZEVM = -O3 -fomit-frame-pointer -funroll-loops \ - -falign-functions=2 -fstrength-reduce + OPTIMIZEVM = -O3 OPTIMIZE = $(OPTIMIZEVM) -ffast-math HAVE_VM_COMPILED = true else ifeq ($(ARCH),x86) - OPTIMIZEVM = -O3 -march=i586 -fomit-frame-pointer \ - -funroll-loops -falign-functions=2 -fstrength-reduce + OPTIMIZEVM = -O3 -march=i586 OPTIMIZE = $(OPTIMIZEVM) -ffast-math HAVE_VM_COMPILED=true else @@ -761,13 +771,13 @@ ifeq ($(PLATFORM),openbsd) ifeq ($(USE_OPENAL),1) ifneq ($(USE_OPENAL_DLOPEN),1) - CLIENT_LIBS += $(THREAD_LIBS) -lopenal + CLIENT_LIBS += $(THREAD_LIBS) $(OPENAL_LIBS) endif endif ifeq ($(USE_CURL),1) ifneq ($(USE_CURL_DLOPEN),1) - CLIENT_LIBS += -lcurl + CLIENT_LIBS += $(CURL_LIBS) endif endif else # ifeq openbsd @@ -798,6 +808,7 @@ else # ifeq netbsd ############################################################################# ifeq ($(PLATFORM),irix64) + LIB=lib ARCH=mips @@ -888,7 +899,7 @@ else # ifeq sunos endif #Linux endif #darwin -endif #mingw32 +endif #MINGW endif #FreeBSD endif #OpenBSD endif #NetBSD @@ -910,10 +921,6 @@ endif TARGETS = -ifeq ($(USE_FREETYPE),1) - BASE_CFLAGS += -DBUILD_FREETYPE -endif - ifndef FULLBINEXT FULLBINEXT=.$(ARCH)$(BINEXT) endif @@ -929,12 +936,12 @@ endif ifneq ($(BUILD_CLIENT),0) ifneq ($(USE_RENDERER_DLOPEN),0) TARGETS += $(B)/$(CLIENTBIN)$(FULLBINEXT) $(B)/renderer_opengl1_$(SHLIBNAME) - ifneq ($(BUILD_RENDERER_OPENGL2), 0) + ifneq ($(BUILD_RENDERER_OPENGL2),0) TARGETS += $(B)/renderer_opengl2_$(SHLIBNAME) endif else TARGETS += $(B)/$(CLIENTBIN)$(FULLBINEXT) - ifneq ($(BUILD_RENDERER_OPENGL2), 0) + ifneq ($(BUILD_RENDERER_OPENGL2),0) TARGETS += $(B)/$(CLIENTBIN)_opengl2$(FULLBINEXT) endif endif @@ -984,40 +991,43 @@ ifeq ($(USE_CURL),1) endif endif -ifeq ($(USE_CODEC_VORBIS),1) - CLIENT_CFLAGS += -DUSE_CODEC_VORBIS - NEED_OGG=1 -endif - ifeq ($(USE_CODEC_OPUS),1) CLIENT_CFLAGS += -DUSE_CODEC_OPUS ifeq ($(USE_INTERNAL_OPUS),1) - CLIENT_CFLAGS += -DOPUS_BUILD -DHAVE_LRINTF -DFLOATING_POINT -DUSE_ALLOCA \ + OPUS_CFLAGS = -DOPUS_BUILD -DHAVE_LRINTF -DFLOATING_POINT -DUSE_ALLOCA \ -I$(OPUSDIR)/include -I$(OPUSDIR)/celt -I$(OPUSDIR)/silk \ - -I$(OPUSDIR)/silk/float - - CLIENT_CFLAGS += -I$(OPUSFILEDIR)/include + -I$(OPUSDIR)/silk/float -I$(OPUSFILEDIR)/include else - CLIENT_LIBS += -lopusfile -lopus + OPUS_CFLAGS ?= $(shell pkg-config --silence-errors --cflags opusfile opus || true) + OPUS_LIBS ?= $(shell pkg-config --silence-errors --libs opusfile opus || echo -lopusfile -lopus) endif + CLIENT_CFLAGS += $(OPUS_CFLAGS) + CLIENT_LIBS += $(OPUS_LIBS) + NEED_OGG=1 +endif + +ifeq ($(USE_CODEC_VORBIS),1) + CLIENT_CFLAGS += -DUSE_CODEC_VORBIS + ifeq ($(USE_INTERNAL_VORBIS),1) + CLIENT_CFLAGS += -I$(VORBISDIR)/include -I$(VORBISDIR)/lib + else + VORBIS_CFLAGS ?= $(shell pkg-config --silence-errors --cflags vorbisfile vorbis || true) + VORBIS_LIBS ?= $(shell pkg-config --silence-errors --libs vorbisfile vorbis || echo -lvorbisfile -lvorbis) + endif + CLIENT_CFLAGS += $(VORBIS_CFLAGS) + CLIENT_LIBS += $(VORBIS_LIBS) NEED_OGG=1 endif ifeq ($(NEED_OGG),1) ifeq ($(USE_INTERNAL_OGG),1) - CLIENT_CFLAGS += -I$(OGGDIR)/include + OGG_CFLAGS = -I$(OGGDIR)/include else - CLIENT_LIBS += -logg - endif -endif - -ifeq ($(USE_CODEC_VORBIS),1) - ifeq ($(USE_INTERNAL_VORBIS),1) - CLIENT_CFLAGS += -I$(VORBISDIR)/include -I$(VORBISDIR)/lib - - else - CLIENT_LIBS += -lvorbisfile -lvorbis + OGG_CFLAGS ?= $(shell pkg-config --silence-errors --cflags ogg || true) + OGG_LIBS ?= $(shell pkg-config --silence-errors --libs ogg || echo -logg) endif + CLIENT_CFLAGS += $(OGG_CFLAGS) + CLIENT_LIBS += $(OGG_LIBS) endif ifeq ($(USE_RENDERER_DLOPEN),1) @@ -1032,28 +1042,42 @@ ifeq ($(USE_VOIP),1) CLIENT_CFLAGS += -DUSE_VOIP SERVER_CFLAGS += -DUSE_VOIP ifeq ($(USE_INTERNAL_SPEEX),1) - CLIENT_CFLAGS += -DFLOATING_POINT -DUSE_ALLOCA -I$(SPEEXDIR)/include + SPEEX_CFLAGS += -DFLOATING_POINT -DUSE_ALLOCA -I$(SPEEXDIR)/include else - CLIENT_LIBS += -lspeex -lspeexdsp + SPEEX_CFLAGS ?= $(shell pkg-config --silence-errors --cflags speex speexdsp || true) + SPEEX_LIBS ?= $(shell pkg-config --silence-errors --libs speex speexdsp || echo -lspeex -lspeexdsp) endif + CLIENT_CFLAGS += $(SPEEX_CFLAGS) + CLIENT_LIBS += $(SPEEX_LIBS) endif ifeq ($(USE_INTERNAL_ZLIB),1) - BASE_CFLAGS += -DNO_GZIP - BASE_CFLAGS += -I$(ZDIR) + ZLIB_CFLAGS = -DNO_GZIP -I$(ZDIR) else - LIBS += -lz + ZLIB_CFLAGS ?= $(shell pkg-config --silence-errors --cflags zlib || true) + ZLIB_LIBS ?= $(shell pkg-config --silence-errors --libs zlib || echo -lz) endif +BASE_CFLAGS += $(ZLIB_CFLAGS) +LIBS += $(ZLIB_LIBS) ifeq ($(USE_INTERNAL_JPEG),1) BASE_CFLAGS += -DUSE_INTERNAL_JPEG BASE_CFLAGS += -I$(JPDIR) else - RENDERER_LIBS += -ljpeg + # IJG libjpeg doesn't have pkg-config, but libjpeg-turbo uses libjpeg.pc; + # we fall back to hard-coded answers if libjpeg.pc is unavailable + JPEG_CFLAGS ?= $(shell pkg-config --silence-errors --cflags libjpeg || true) + JPEG_LIBS ?= $(shell pkg-config --silence-errors --libs libjpeg || echo -ljpeg) + BASE_CFLAGS += $(JPEG_CFLAGS) + RENDERER_LIBS += $(JPEG_LIBS) endif ifeq ($(USE_FREETYPE),1) - RENDERER_LIBS += -lfreetype + FREETYPE_CFLAGS ?= $(shell pkg-config --silence-errors --cflags freetype2 || true) + FREETYPE_LIBS ?= $(shell pkg-config --silence-errors --libs freetype2 || echo -lfreetype) + + BASE_CFLAGS += -DBUILD_FREETYPE $(FREETYPE_CFLAGS) + RENDERER_LIBS += $(FREETYPE_LIBS) endif ifeq ("$(CC)", $(findstring "$(CC)", "clang" "clang++")) @@ -1207,11 +1231,34 @@ release: CLIENT_CFLAGS="$(CLIENT_CFLAGS)" SERVER_CFLAGS="$(SERVER_CFLAGS)" V=$(V) ifneq ($(call bin_path, tput),) - TERM_COLUMNS=$(shell echo $$((`tput cols`-4))) + TERM_COLUMNS=$(shell if c=`tput cols`; then echo $$(($$c-4)); else echo 76; fi) else TERM_COLUMNS=76 endif +define ADD_COPY_TARGET +TARGETS += $2 +$2: $1 + $(echo_cmd) "CP $$<" + @cp $1 $2 +endef + +# These functions allow us to generate rules for copying a list of files +# into the base directory of the build; this is useful for bundling libs, +# README files or whatever else +define GENERATE_COPY_TARGETS +$(foreach FILE,$1, \ + $(eval $(call ADD_COPY_TARGET, \ + $(FILE), \ + $(addprefix $(B)/,$(notdir $(FILE)))))) +endef + +$(call GENERATE_COPY_TARGETS,$(EXTRA_FILES)) + +ifneq ($(BUILD_CLIENT),0) + $(call GENERATE_COPY_TARGETS,$(CLIENT_EXTRA_FILES)) +endif + NAKED_TARGETS=$(shell echo $(TARGETS) | sed -e "s!$(B)/!!g") print_list=@for i in $(1); \ @@ -1591,7 +1638,7 @@ Q3OBJ = \ $(B)/client/con_log.o \ $(B)/client/sys_main.o -ifeq ($(PLATFORM),mingw32) +ifdef MINGW Q3OBJ += \ $(B)/client/con_passive.o else @@ -1612,11 +1659,11 @@ Q3R2OBJ = \ $(B)/renderergl2/tr_font.o \ $(B)/renderergl2/tr_glsl.o \ $(B)/renderergl2/tr_image.o \ - $(B)/renderergl2/tr_image_png.o \ - $(B)/renderergl2/tr_image_jpg.o \ $(B)/renderergl2/tr_image_bmp.o \ - $(B)/renderergl2/tr_image_tga.o \ + $(B)/renderergl2/tr_image_jpg.o \ $(B)/renderergl2/tr_image_pcx.o \ + $(B)/renderergl2/tr_image_png.o \ + $(B)/renderergl2/tr_image_tga.o \ $(B)/renderergl2/tr_init.o \ $(B)/renderergl2/tr_light.o \ $(B)/renderergl2/tr_main.o \ @@ -1678,11 +1725,11 @@ Q3ROBJ = \ $(B)/renderergl1/tr_flares.o \ $(B)/renderergl1/tr_font.o \ $(B)/renderergl1/tr_image.o \ - $(B)/renderergl1/tr_image_png.o \ - $(B)/renderergl1/tr_image_jpg.o \ $(B)/renderergl1/tr_image_bmp.o \ - $(B)/renderergl1/tr_image_tga.o \ + $(B)/renderergl1/tr_image_jpg.o \ $(B)/renderergl1/tr_image_pcx.o \ + $(B)/renderergl1/tr_image_png.o \ + $(B)/renderergl1/tr_image_tga.o \ $(B)/renderergl1/tr_init.o \ $(B)/renderergl1/tr_light.o \ $(B)/renderergl1/tr_main.o \ @@ -2035,7 +2082,7 @@ ifeq ($(HAVE_VM_COMPILED),true) endif endif -ifeq ($(PLATFORM),mingw32) +ifdef MINGW Q3OBJ += \ $(B)/client/win_resource.o \ $(B)/client/sys_win32.o @@ -2203,7 +2250,7 @@ ifeq ($(HAVE_VM_COMPILED),true) endif endif -ifeq ($(PLATFORM),mingw32) +ifdef MINGW Q3DOBJ += \ $(B)/ded/win_resource.o \ $(B)/ded/sys_win32.o \ @@ -2795,7 +2842,7 @@ distclean: clean toolsclean @rm -rf $(BUILD_DIR) installer: release -ifeq ($(PLATFORM),mingw32) +ifdef MINGW @$(MAKE) VERSION=$(VERSION) -C $(NSISDIR) V=$(V) \ SDLDLL=$(SDLDLL) \ USE_RENDERER_DLOPEN=$(USE_RENDERER_DLOPEN) \ diff --git a/README.md b/README.md index 35b72fe3..426e5c95 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ `---------- http://ioquake3.org --------' The intent of this project is to provide a baseline Quake 3 which may be used -for further development and baseq3 fun. +for further development and baseq3 fun. Some of the major features currently implemented are: * SDL backend @@ -38,6 +38,8 @@ The original id software readme that accompanied the Q3 source release has been renamed to id-readme.txt so as to prevent confusion. Please refer to the web-site for updated status. +More documentation is on: +http://wiki.ioquake3.org/ # Compilation and installation @@ -46,7 +48,7 @@ For *nix 2. Run 'make'. For Windows, - 1. Please refer to the excellent instructions here: + 1. Please refer to the excellent instructions here: http://wiki.ioquake3.org/Building_ioquake3 For Mac OS X, building a Universal Binary @@ -74,41 +76,46 @@ The following variables may be set, either on the command line or in Makefile.local: ``` - CFLAGS - use this for custom CFLAGS - V - set to show cc command line when building - DEFAULT_BASEDIR - extra path to search for baseq3 and such - BUILD_SERVER - build the 'ioq3ded' server binary - BUILD_CLIENT - build the 'ioquake3' client binary - BUILD_BASEGAME - build the 'baseq3' binaries - BUILD_MISSIONPACK - build the 'missionpack' binaries - BUILD_GAME_SO - build the game shared libraries - BUILD_GAME_QVM - build the game qvms - BUILD_STANDALONE - build binaries suited for stand-alone games - SERVERBIN - rename 'ioq3ded' server binary - CLIENTBIN - rename 'ioquake3' client binary - BASEGAME - rename 'baseq3' - BASEGAME_CFLAGS - custom CFLAGS for basegame - MISSIONPACK - rename 'missionpack' - MISSIONPACK_CFLAGS - custom CFLAGS for missionpack (default '-DMISSIONPACK') - USE_OPENAL - use OpenAL where available - USE_OPENAL_DLOPEN - link with OpenAL at runtime - USE_CURL - use libcurl for http/ftp download support - USE_CURL_DLOPEN - link with libcurl at runtime - USE_CODEC_VORBIS - enable Ogg Vorbis support - USE_CODEC_OPUS - enable Ogg Opus support - USE_MUMBLE - enable Mumble support - USE_VOIP - enable built-in VoIP support - USE_INTERNAL_SPEEX - build internal speex library instead of dynamically - linking against system libspeex - USE_FREETYPE - enable FreeType support for rendering fonts - USE_INTERNAL_ZLIB - build and link against internal zlib - USE_INTERNAL_JPEG - build and link against internal JPEG library - USE_INTERNAL_OGG - build and link against internal ogg library - USE_INTERNAL_OPUS - build and link against internal opus/opusfile libraries - USE_LOCAL_HEADERS - use headers local to ioq3 instead of system ones - DEBUG_CFLAGS - C compiler flags to use for building debug version - COPYDIR - the target installation directory - TEMPDIR - specify user defined directory for temp files + CFLAGS - use this for custom CFLAGS + V - set to show cc command line when building + DEFAULT_BASEDIR - extra path to search for baseq3 and such + BUILD_SERVER - build the 'ioq3ded' server binary + BUILD_CLIENT - build the 'ioquake3' client binary + BUILD_BASEGAME - build the 'baseq3' binaries + BUILD_MISSIONPACK - build the 'missionpack' binaries + BUILD_GAME_SO - build the game shared libraries + BUILD_GAME_QVM - build the game qvms + BUILD_STANDALONE - build binaries suited for stand-alone games + SERVERBIN - rename 'ioq3ded' server binary + CLIENTBIN - rename 'ioquake3' client binary + USE_RENDERER_DLOPEN - build and use the renderer in a library + BASEGAME - rename 'baseq3' + BASEGAME_CFLAGS - custom CFLAGS for basegame + MISSIONPACK - rename 'missionpack' + MISSIONPACK_CFLAGS - custom CFLAGS for missionpack (default '-DMISSIONPACK') + USE_OPENAL - use OpenAL where available + USE_OPENAL_DLOPEN - link with OpenAL at runtime + USE_CURL - use libcurl for http/ftp download support + USE_CURL_DLOPEN - link with libcurl at runtime + USE_CODEC_VORBIS - enable Ogg Vorbis support + USE_CODEC_OPUS - enable Ogg Opus support + USE_MUMBLE - enable Mumble support + USE_VOIP - enable built-in VoIP support + USE_INTERNAL_LIBS - build internal libraries instead of dynamically + linking against system libraries; this just sets + the default for USE_INTERNAL_SPEEX etc. + and USE_LOCAL_HEADERS + USE_INTERNAL_SPEEX - build internal speex library instead of dynamically + linking against system libspeex + USE_FREETYPE - enable FreeType support for rendering fonts + USE_INTERNAL_ZLIB - build and link against internal zlib + USE_INTERNAL_JPEG - build and link against internal JPEG library + USE_INTERNAL_OGG - build and link against internal ogg library + USE_INTERNAL_OPUS - build and link against internal opus/opusfile libraries + USE_LOCAL_HEADERS - use headers local to ioq3 instead of system ones + DEBUG_CFLAGS - C compiler flags to use for building debug version + COPYDIR - the target installation directory + TEMPDIR - specify user defined directory for temp files ``` The defaults for these variables differ depending on the target platform. @@ -203,9 +210,9 @@ The defaults for these variables differ depending on the target platform. com_maxfpsMinimized - Maximum frames per second when minimized com_busyWait - Will use a busy loop to wait for rendering next frame when set to non-zero value - com_pipefile - Specify filename to create a named pipe + com_pipefile - Specify filename to create a named pipe through which other processes can control - the server while it is running. + the server while it is running. Nonfunctional on Windows. com_gamename - Gamename sent to master server in getservers[Ext] query and infoResponse @@ -314,210 +321,12 @@ The defaults for these variables differ depending on the target platform. all bots even if someone is named "allbots") tell - send message to a single client (new to server) + + cvar_modified [filter] - list modified cvars, can filter results (such as "r*" + for renderer cvars) like cvarlist which lists all cvars ``` -# README for Users - -## Using shared libraries instead of qvm - -To force Q3 to use shared libraries instead of qvms run it with the following -parameters: `+set sv_pure 0 +set vm_cgame 0 +set vm_game 0 +set vm_ui 0` - -## Using Demo Data Files - -Copy demoq3/pak0.pk3 from the demo installer to your baseq3 directory. The -qvm files in this pak0.pk3 will not work, so you have to use the native -shared libraries or qvms from this project. To use the new qvms, they must be -put into a pk3 file. A pk3 file is just a zip file, so any compression tool -that can create such files will work. The shared libraries should already be -in the correct place. Use the instructions above to use them. - -Please bear in mind that you will not be able to play online using the demo -data, nor is it something that we like to spend much time maintaining or -supporting. - -## Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps! - -Ioquake3 now uses the select() system call to wait for the rendering of the -next frame when com_maxfps was hit. This will improve your CPU load -considerably in these cases. However, not all systems may support a -granularity for its timing functions that is required to perform this waiting -correctly. For instance, ioquake3 tells select() to wait 2 milliseconds, but -really it can only wait for a multiple of 5ms, i.e. 5, 10, 15, 20... ms. -In this case you can always revert back to the old behaviour by setting the -cvar com_busyWait to 1. - -## Using HTTP/FTP Download Support (Server) - -You can enable redirected downloads on your server even if it's not -an ioquake3 server. You simply need to use the 'sets' command to put -the sv_dlURL cvar into your SERVERINFO string and ensure sv_allowDownloads -is set to 1 - -sv_dlURL is the base of the URL that contains your custom .pk3 files -the client will append both fs_game and the filename to the end of -this value. For example, if you have sv_dlURL set to -`"http://ioquake3.org"`, fs_game is `"baseq3"`, and the client is -missing `"test.pk3"`, it will attempt to download from the URL -`"http://ioquake3.org/baseq3/test.pk3"` - -sv_allowDownload's value is now a bitmask made up of the following -flags: - - * 1 - ENABLE - * 4 - do not use UDP downloads - * 8 - do not ask the client to disconnect when using HTTP/FTP - -Server operators who are concerned about potential "leeching" from their -HTTP servers from other ioquake3 servers can make use of the HTTP_REFERER -that ioquake3 sets which is `"ioQ3://{SERVER_IP}:{SERVER_PORT}"`. For, -example, Apache's mod_rewrite can restrict access based on HTTP_REFERER. - -On a sidenote, downloading via UDP has been improved and yields higher data -rates now. You can configure the maximum bandwidth for UDP downloads via the -cvar sv_dlRate. Due to system-specific limits the download rate is capped -at about 1 Mbyte/s per client, so curl downloading may still be faster. - -## Using HTTP/FTP Download Support (Client) - -Simply setting cl_allowDownload to 1 will enable HTTP/FTP downloads -assuming ioquake3 was compiled with USE_CURL=1 (the default). -like sv_allowDownload, cl_allowDownload also uses a bitmask value -supporting the following flags: - - * 1 - ENABLE - * 2 - do not use HTTP/FTP downloads - * 4 - do not use UDP downloads - -When ioquake3 is built with USE_CURL_DLOPEN=1 (default on some platforms), -it will use the value of the cvar cl_cURLLib as the filename of the cURL -library to dynamically load. - -## Multiuser Support on Windows systems -On Windows, all user specific files such as autogenerated configuration, -demos, videos, screenshots, and autodownloaded pk3s are now saved in a -directory specific to the user who is running ioquake3. - -On NT-based such as Windows XP, this is usually a directory named: - - C:\Documents and Settings\%USERNAME%\Application Data\Quake3\ - -Windows 95, Windows 98, and Windows ME will use a directory like: - - C:\Windows\Application Data\Quake3 - -in single-user mode, or: - - C:\Windows\Profiles\%USERNAME%\Application Data\Quake3 - -if multiple logins have been enabled. - -In order to access this directory more easily, the installer may create a -Shortcut which has its target set to: - - %APPDATA%\Quake3\ - -This Shortcut would work for all users on the system regardless of the -locale settings. Unfortunately, this environment variable is only -present on Windows NT based systems. - -You can revert to the old single-user behaviour by setting the fs_homepath -cvar to the directory where ioquake3 is installed. For example: - - ioquake3.exe +set fs_homepath "c:\ioquake3" - -Note that this cvar MUST be set as a command line parameter. - -## SDL Keyboard Differences - -ioquake3 clients have different keyboard behaviour compared to the original -Quake3 clients. - - * "Caps Lock" and "Num Lock" can not be used as normal binds since they - do not send a KEYUP event until the key is pressed again. - - * SDL > 1.2.9 does not support disabling dead key recognition. In order to - send dead key characters (e.g. ~, ', `, and ^), you must key a Space (or - sometimes the same character again) after the character to send it on - many international keyboard layouts. - - * The SDL client supports many more keys than the original Quake3 client. - For example the keys: "Windows", "SysReq", "ScrollLock", and "Break". - For non-US keyboards, all of the so called "World" keys are now supported - as well as F13, F14, F15, and the country-specific mode/meta keys. - -On many international layouts the default console toggle keys are also dead -keys, meaning that dropping the console potentially results in -unintentionally initiating the keying of a dead key. Furthermore SDL 1.2's -dead key support is broken by design and Q3 doesn't support non-ASCII text -entry, so the chances are you won't get the correct character anyway. - -If you use such a keyboard layout, you can set the cvar cl_consoleKeys. This -is a space delimited list of key names that will toggle the console. The key -names are the usual Q3 names e.g. "~", "`", "c", "BACKSPACE", "PAUSE", -"WINDOWS" etc. It's also possible to use ASCII characters, by hexadecimal -number. Some example values for cl_consoleKeys: - - "~ ` 0x7e 0x60" Toggle on ~ or ` (the default) - "WINDOWS" Toggle on the Windows key - "c" Toggle on the c key - "0x43" Toggle on the C character (Shift-c) - "PAUSE F1 PGUP" Toggle on the Pause, F1 or Page Up keys - -Note that when you elect a set of console keys or characters, they cannot -then be used for binding, nor will they generate characters when entering -text. Also, in addition to the nominated console keys, Shift-ESC is hard -coded to always toggle the console. - -## QuakeLive mouse acceleration -(patch and this text written by TTimo from id) - -I've been using an experimental mouse acceleration code for a while, and -decided to make it available to everyone. Don't be too worried if you don't -understand the explanations below, this is mostly intended for advanced -players: -To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior) - -New style is controlled with 3 cvars: - -sensitivity -cl_mouseAccel -cl_mouseAccelOffset - -The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if -you have a base sensitivity setup, as soon as you set a non zero acceleration -your base sensitivity at low speeds will change as well. The other problem -with style 0 is that you are stuck on a square (power of two) acceleration -curve. - -The new code tries to solve both problems: - -Once you setup your sensitivity to feel comfortable and accurate enough for -low mouse deltas with no acceleration (cl_mouseAccel 0), you can start -increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the -amplification you want for high deltas with little effect on low mouse deltas. - -cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve -as style 0. The higher the value, the faster the amplification grows with the -mouse delta. - -cl_mouseAccelOffset sets how much base mouse delta will be doubled by -acceleration. The closer to zero you bring it, the more acceleration will -happen at low speeds. This is also very useful if you are changing to a new -mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your -cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely -gain in precision when you do that, but that is not related to mouse -acceleration). - -Mouse acceleration is tricky to configure, and when you do you'll have to -re-learn your aiming. But you will find that it's very much forth it in the -long run. - -If you try the new acceleration code and start using it, I'd be very -interested by your feedback. - - # README for Developers ## pk3dir @@ -574,12 +383,12 @@ your own binaries. Instead, you can just use the pre-built binaries on the website. Just make sure the game is called with: +set com_basegame - + in any links/scripts you install for your users to start the game. The binary must not detect any original quake3 game pak files. If this condition is met, the game will set com_standalone to 1 and is then running in stand alone mode. - + If you want the engine to use a different directory in your homepath than e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup by adding @@ -630,55 +439,6 @@ not prohibit commercial exploitation and all assets (e.g. textures, sounds, maps) created by yourself are your property and can be sold like every other game you find in stores. -## Network protocols - -There are now two cvars that give you some degree of freedom over the reported -protocol versions between clients and servers: "com_protocol" and -"com_legacyprotocol". -The reason for this is that some standalone games increased the protocol -number even though nothing really changed in their protocol and the ioquake3 -engine is still fully compatible. - -In order to harden the network protocol against UDP spoofing attacks a new -network protocol was introduced that defends against such attacks. -Unfortunately, this protocol will be incompatible to the original quake3 1.32c -which is the latest official release from id. -Luckily, ioquake3 has backwards compatibility, on the client as well as on the -server. This means ioquake3 players can play on old servers just as ioquake3 -servers are able to service old clients. - -The cvar "com_protocol" denotes the protocol version for the new hardened -protocol, whereas the "com_legacyprotocol" cvar denotes the protocol version -for the legacy protocol. -If the value for "com_protocol" and "com_legacyprotocol" is identical, then -the legacy protocol is always used. If "com_legacyprotocol" is set to 0, then -support for the legacy protocol is disabled. - -Mods that use a standalone engine obviously do not require dual protocol -support, and it is turned off if the engine is compiled with STANDALONE per -default. If you desire backwards compatibility to older versions of your -game you can still enable it in q_shared.h by defining -LEGACY_PROTOCOL. - -## cl_guid Support - -cl_guid is a cvar which is part of the client's USERINFO string. Its value -is a 32 character string made up of [a-f] and [0-9] characters. This -value is pseudo-unique for every player. Id's Quake 3 Arena client also -sets cl_guid, but only if Punkbuster is enabled on the client. - -If cl_guidServerUniq is non-zero (the default), then this value is also -pseudo-unique for each server a client connects to (based on IP:PORT of -the server). - -The purpose of cl_guid is to add an identifier for each player on -a server. This value can be reset by the client at any time so it's not -useful for blocking access. However, it can have at least two uses in -your mod's game code: - - 1. improve logging to allow statistical tools to index players by more - than just name - 2. granting some weak admin rights to players without requiring passwords ## PNG support @@ -713,18 +473,13 @@ directory, this restriction is lifted. # Contributing -Please send all patches to bugzilla (https://bugzilla.icculus.org), or join the -mailing list (http://lists.ioquake.org/listinfo.cgi/ioquake3-ioquake.org) and -submit your patch there. The best case scenario is that you submit your patch -to bugzilla, and then post the URL to the mailing list. +Please send all patches to bugzilla (https://bugzilla.icculus.org), or as a GitHub pull request and +submit your patch there. The focus for ioq3 is to develop a stable base suitable for further development -and provide players with the same Quake 3 experience they've had for years. As -such ioq3 does not have any significant graphical enhancements and none are -planned at this time. However, improved graphics and sound patches will be -accepted as long as they are entirely optional, do not require new media and -are off by default. +and provide players with the same Quake 3 experience they've had for years. +We do have graphical improvements with the new renderer, but they are off by default. # Building Official Installers @@ -783,4 +538,3 @@ Significant contributions from * Aaron Gyes -[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/6d196bd663b47049a25dcb8caef95949 "githalytics.com")](http://githalytics.com/ioquake/ioq3) diff --git a/code/asm/ftola.asm b/code/asm/ftola.asm index 321b6b5e..a3dc5551 100644 --- a/code/asm/ftola.asm +++ b/code/asm/ftola.asm @@ -21,10 +21,9 @@ ; MASM ftol conversion functions using SSE or FPU ; assume __cdecl calling convention is being used for x86, __fastcall for x64 +IFNDEF idx64 .686p .xmm - -IFNDEF idx64 .model flat, c ENDIF diff --git a/code/asm/snapvector.asm b/code/asm/snapvector.asm index 9e61bec6..59949f0f 100644 --- a/code/asm/snapvector.asm +++ b/code/asm/snapvector.asm @@ -24,10 +24,9 @@ ; function prototype: ; void qsnapvector(vec3_t vec) +IFNDEF idx64 .686p .xmm - -IFNDEF idx64 .model flat, c ENDIF @@ -37,17 +36,12 @@ ENDIF ssemask DWORD 0FFFFFFFFh, 0FFFFFFFFh, 0FFFFFFFFh, 00000000h ssecw DWORD 00001F80h -IFNDEF idx64 - fpucw WORD 037Fh -ENDIF - .code IFDEF idx64 ; qsnapvector using SSE qsnapvectorsse PROC - sub rsp, 8 movaps xmm1, ssemask ; initialize the mask register movups xmm0, [rcx] ; here is stored our vector. Read 4 values in one go movaps xmm2, xmm0 ; keep a copy of the original data diff --git a/code/botlib/be_aas_reach.c b/code/botlib/be_aas_reach.c index ed9ff76d..379948aa 100644 --- a/code/botlib/be_aas_reach.c +++ b/code/botlib/be_aas_reach.c @@ -2108,7 +2108,7 @@ int AAS_Reachability_Jump(int area1num, int area2num) int stopevent, areas[10], numareas; float phys_jumpvel, maxjumpdistance, maxjumpheight, height, bestdist, speed; vec_t *v1, *v2, *v3, *v4; - vec3_t beststart, beststart2, bestend, bestend2; + vec3_t beststart = {0}, beststart2 = {0}, bestend = {0}, bestend2 = {0}; vec3_t teststart, testend, dir, velocity, cmdmove, up = {0, 0, 1}, sidewards; aas_area_t *area1, *area2; aas_face_t *face1, *face2; @@ -3152,7 +3152,7 @@ aas_lreachability_t *AAS_FindFaceReachabilities(vec3_t *facepoints, int numpoint int facenum, edgenum, bestfacenum; float *v1, *v2, *v3, *v4; float bestdist, speed, hordist, dist; - vec3_t beststart, beststart2, bestend, bestend2, tmp, hordir, testpoint; + vec3_t beststart = {0}, beststart2 = {0}, bestend = {0}, bestend2 = {0}, tmp, hordir, testpoint; aas_lreachability_t *lreach, *lreachabilities; aas_area_t *area; aas_face_t *face; diff --git a/code/botlib/be_aas_route.c b/code/botlib/be_aas_route.c index d4287a04..bad375d4 100644 --- a/code/botlib/be_aas_route.c +++ b/code/botlib/be_aas_route.c @@ -1770,7 +1770,7 @@ int AAS_AreaRouteToGoalArea(int areanum, vec3_t origin, int goalareanum, int tra //=========================================================================== int AAS_AreaTravelTimeToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags) { - int traveltime, reachnum; + int traveltime, reachnum = 0; if (AAS_AreaRouteToGoalArea(areanum, origin, goalareanum, travelflags, &traveltime, &reachnum)) { @@ -1786,7 +1786,7 @@ int AAS_AreaTravelTimeToGoalArea(int areanum, vec3_t origin, int goalareanum, in //=========================================================================== int AAS_AreaReachabilityToGoalArea(int areanum, vec3_t origin, int goalareanum, int travelflags) { - int traveltime, reachnum; + int traveltime, reachnum = 0; if (AAS_AreaRouteToGoalArea(areanum, origin, goalareanum, travelflags, &traveltime, &reachnum)) { diff --git a/code/botlib/l_precomp.c b/code/botlib/l_precomp.c index bfa7564c..c0870dbe 100644 --- a/code/botlib/l_precomp.c +++ b/code/botlib/l_precomp.c @@ -995,14 +995,14 @@ int PC_Directive_include(source_t *source) script = LoadScriptFile(token.string); if (!script) { - strcpy(path, source->includepath); - strcat(path, token.string); + Q_strncpyz(path, source->includepath, sizeof(path)); + Q_strcat(path, sizeof(path), token.string); script = LoadScriptFile(path); } //end if } //end if else if (token.type == TT_PUNCTUATION && *token.string == '<') { - strcpy(path, source->includepath); + Q_strncpyz(path, source->includepath, sizeof(path)); while(PC_ReadSourceToken(source, &token)) { if (token.linescrossed > 0) @@ -1011,7 +1011,7 @@ int PC_Directive_include(source_t *source) break; } //end if if (token.type == TT_PUNCTUATION && *token.string == '>') break; - strncat(path, token.string, MAX_PATH - 1); + Q_strcat(path, sizeof(path), token.string); } //end while if (*token.string != '>') { @@ -2086,9 +2086,12 @@ int PC_EvaluateTokens(source_t *source, token_t *tokens, signed long int *intval //remove the second value if not question mark operator if (o->operator != P_QUESTIONMARK) v = v->next; // - if (v->prev) v->prev->next = v->next; - else firstvalue = v->next; - if (v->next) v->next->prev = v->prev; + if (v) + { + if (v->prev) v->prev->next = v->next; + else firstvalue = v->next; + if (v->next) v->next->prev = v->prev; + } //FreeMemory(v); FreeValue(v); } //end if @@ -2442,7 +2445,7 @@ int PC_Directive_eval(source_t *source) token.whitespace_p = source->scriptstack->script_p; token.endwhitespace_p = source->scriptstack->script_p; token.linescrossed = 0; - sprintf(token.string, "%d", abs(value)); + sprintf(token.string, "%ld", labs(value)); token.type = TT_NUMBER; token.subtype = TT_INTEGER|TT_LONG|TT_DECIMAL; PC_UnreadSourceToken(source, &token); @@ -2547,12 +2550,12 @@ int PC_DollarDirective_evalint(source_t *source) token.whitespace_p = source->scriptstack->script_p; token.endwhitespace_p = source->scriptstack->script_p; token.linescrossed = 0; - sprintf(token.string, "%d", abs(value)); + sprintf(token.string, "%ld", labs(value)); token.type = TT_NUMBER; token.subtype = TT_INTEGER|TT_LONG|TT_DECIMAL; #ifdef NUMBERVALUE - token.intvalue = abs(value); + token.intvalue = labs(value); token.floatvalue = token.intvalue; #endif //NUMBERVALUE @@ -2831,6 +2834,7 @@ int PC_ExpectTokenType(source_t *source, int type, int subtype, token_t *token) { if ((token->subtype & subtype) != subtype) { + strcpy(str, ""); if (subtype & TT_DECIMAL) strcpy(str, "decimal"); if (subtype & TT_HEX) strcpy(str, "hex"); if (subtype & TT_OCTAL) strcpy(str, "octal"); @@ -2954,10 +2958,14 @@ void PC_UnreadToken(source_t *source, token_t *token) //============================================================================ void PC_SetIncludePath(source_t *source, char *path) { - strncpy(source->includepath, path, MAX_PATH); + size_t len; + + Q_strncpyz(source->includepath, path, MAX_PATH-1); + + len = strlen(source->includepath); //add trailing path seperator - if (source->includepath[strlen(source->includepath)-1] != '\\' && - source->includepath[strlen(source->includepath)-1] != '/') + if (len > 0 && source->includepath[len-1] != '\\' && + source->includepath[len-1] != '/') { strcat(source->includepath, PATHSEPERATOR_STR); } //end if diff --git a/code/botlib/l_script.c b/code/botlib/l_script.c index cc74404a..ee9cddc0 100644 --- a/code/botlib/l_script.c +++ b/code/botlib/l_script.c @@ -828,7 +828,7 @@ int PS_ReadPrimitive(script_t *script, token_t *token) len = 0; while(*script->script_p > ' ' && *script->script_p != ';') { - if (len >= MAX_TOKEN) + if (len >= MAX_TOKEN - 1) { ScriptError(script, "primitive token longer than MAX_TOKEN = %d", MAX_TOKEN); return 0; @@ -956,6 +956,7 @@ int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token) if (token->type != type) { + strcpy(str, ""); if (type == TT_STRING) strcpy(str, "string"); if (type == TT_LITERAL) strcpy(str, "literal"); if (type == TT_NUMBER) strcpy(str, "number"); @@ -968,6 +969,7 @@ int PS_ExpectTokenType(script_t *script, int type, int subtype, token_t *token) { if ((token->subtype & subtype) != subtype) { + strcpy(str, ""); if (subtype & TT_DECIMAL) strcpy(str, "decimal"); if (subtype & TT_HEX) strcpy(str, "hex"); if (subtype & TT_OCTAL) strcpy(str, "octal"); @@ -1350,7 +1352,7 @@ script_t *LoadScriptFile(const char *filename) buffer = GetClearedMemory(sizeof(script_t) + length + 1); script = (script_t *) buffer; Com_Memset(script, 0, sizeof(script_t)); - strcpy(script->filename, filename); + Q_strncpyz(script->filename, filename, sizeof(script->filename)); script->buffer = (char *) buffer + sizeof(script_t); script->buffer[length] = 0; script->length = length; @@ -1396,7 +1398,7 @@ script_t *LoadScriptMemory(char *ptr, int length, char *name) buffer = GetClearedMemory(sizeof(script_t) + length + 1); script = (script_t *) buffer; Com_Memset(script, 0, sizeof(script_t)); - strcpy(script->filename, name); + Q_strncpyz(script->filename, name, sizeof(script->filename)); script->buffer = (char *) buffer + sizeof(script_t); script->buffer[length] = 0; script->length = length; diff --git a/code/cgame/cg_draw.c b/code/cgame/cg_draw.c index 613b7c8b..437f4653 100644 --- a/code/cgame/cg_draw.c +++ b/code/cgame/cg_draw.c @@ -734,6 +734,11 @@ static float CG_DrawAttacker(float y) return y; } + if ( !cgs.clientinfo[clientNum].infoValid ) { + cg.attackerTime = 0; + return y; + } + t = cg.time - cg.attackerTime; if (t > ATTACKER_HEAD_TIME) { cg.attackerTime = 0; diff --git a/code/cgame/cg_event.c b/code/cgame/cg_event.c index 02867f7a..2fe718ad 100644 --- a/code/cgame/cg_event.c +++ b/code/cgame/cg_event.c @@ -840,6 +840,10 @@ void CG_EntityEvent(centity_t * cent, vec3_t position) } } break; + case EV_USE_ITEM15: + DEBUGNAME("EV_USE_ITEM15"); + CG_UseItem( cent ); + break; // // weapon events diff --git a/code/cgame/cg_marks.c b/code/cgame/cg_marks.c index 511f4b6d..feb80fa1 100644 --- a/code/cgame/cg_marks.c +++ b/code/cgame/cg_marks.c @@ -105,7 +105,7 @@ CG_FreeMarkPoly */ void CG_FreeMarkPoly(markPoly_t * le) { - if (!le->prevMark) { + if (!le->prevMark || !le->nextMark) { CG_Error("CG_FreeLocalEntity: not active"); } // remove from the doubly linked active list diff --git a/code/cgame/cg_newDraw.c b/code/cgame/cg_newDraw.c index 5b26ce21..555bae55 100644 --- a/code/cgame/cg_newDraw.c +++ b/code/cgame/cg_newDraw.c @@ -327,8 +327,6 @@ static void CG_DrawPlayerHead(rectDef_t * rect, qboolean draw2D) cg.headEndYaw = 180 + 20 * cos(crandom() * M_PI); cg.headEndPitch = 5 * cos(crandom() * M_PI); } - - size = rect->w * 1.25; } // if the server was frozen for a while we may have a bad head start time @@ -564,8 +562,6 @@ static void CG_DrawSelectedPlayerPowerup(rectDef_t * rect, qboolean draw2D) item = BG_FindItemForPowerup(j); if (item) { CG_DrawPic(x, y, rect->w, rect->h, trap_R_RegisterShader(item->icon)); - x += 3; - y += 3; return; } } @@ -1332,7 +1328,7 @@ static void CG_Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4 } count = 0; while (s && *s && count < len) { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; if (Q_IsColorString(s)) { memcpy(newColor, g_color_table[ColorIndex(*(s + 1))], sizeof(newColor)); newColor[3] = color[3]; @@ -1342,7 +1338,7 @@ static void CG_Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4 } else { float yadj = useScale * glyph->top; - if (CG_Text_Width(s, useScale, 1) + x > max) { + if (CG_Text_Width(s, scale, 1) + x > max) { *maxX = 0; break; } diff --git a/code/cgame/cg_servercmds.c b/code/cgame/cg_servercmds.c index be790305..f18e76f3 100644 --- a/code/cgame/cg_servercmds.c +++ b/code/cgame/cg_servercmds.c @@ -734,7 +734,7 @@ static void CG_ConfigStringModified(void) cgs.teamVoteNo[num - CS_TEAMVOTE_NO] = atoi(str); cgs.teamVoteModified[num - CS_TEAMVOTE_NO] = qtrue; } else if (num >= CS_TEAMVOTE_STRING && num <= CS_TEAMVOTE_STRING + 1) { - Q_strncpyz(cgs.teamVoteString[num - CS_TEAMVOTE_STRING], str, sizeof(cgs.teamVoteString)); + Q_strncpyz(cgs.teamVoteString[num - CS_TEAMVOTE_STRING], str, sizeof(cgs.teamVoteString[0])); } else if (num == CS_INTERMISSION) { cg.intermissionStarted = atoi(str); } else if (num >= CS_MODELS && num < CS_MODELS + MAX_MODELS) { diff --git a/code/cgame/cg_snapshot.c b/code/cgame/cg_snapshot.c index 63e5d476..09b98dbb 100644 --- a/code/cgame/cg_snapshot.c +++ b/code/cgame/cg_snapshot.c @@ -191,7 +191,9 @@ static void CG_TransitionSnapshot(void) // if we had a map_restart, set everthing with initial if (!cg.snap) { + return; } + // clear the currentValid flag for all entities in the existing snapshot for (i = 0; i < cg.snap->numEntities; i++) { cent = &cg_entities[cg.snap->entities[i].number]; diff --git a/code/cgame/cg_weapons.c b/code/cgame/cg_weapons.c index 2265d61b..1ebcdbd9 100644 --- a/code/cgame/cg_weapons.c +++ b/code/cgame/cg_weapons.c @@ -740,25 +740,21 @@ void CG_RegisterWeapon(int weaponNum) weaponInfo->ammoIcon = trap_R_RegisterShader(ammo->icon); } - strcpy(path, item->world_model[0]); - COM_StripExtensionInPlace(path); - strcat(path, "_flash.md3"); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_flash.md3" ); weaponInfo->flashModel = trap_R_RegisterModel(path); - strcpy(path, item->world_model[0]); - COM_StripExtensionInPlace(path); - strcat(path, "_barrel.md3"); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_barrel.md3" ); weaponInfo->barrelModel = trap_R_RegisterModel(path); - strcpy(path, item->world_model[0]); - COM_StripExtensionInPlace(path); - strcat(path, "_hand.md3"); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_hand.md3" ); weaponInfo->handsModel = trap_R_RegisterModel(path); //Elder: added to cache 1st-person models - strcpy(path, item->world_model[0]); - COM_StripExtensionInPlace(path); - strcat(path, "_1st.md3"); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_1st.md3" ); weaponInfo->firstModel = trap_R_RegisterModel(path); if (!weaponInfo->handsModel) { @@ -2447,11 +2443,11 @@ void CG_MissileHitWall(int weapon, int clientNum, vec3_t origin, int r, duration, angle, contentType, sparkCount, i; qboolean alphaFade, isSprite; - mark = 0; - radius = 32; - sfx = 0; mod = 0; + mark = 0; shader = 0; + sfx = 0; + radius = 0; light = 0; lightColor[0] = 1; lightColor[1] = 1; diff --git a/code/client/cl_avi.c b/code/client/cl_avi.c index 3b0d7751..17fd371f 100644 --- a/code/client/cl_avi.c +++ b/code/client/cl_avi.c @@ -122,17 +122,6 @@ static ID_INLINE void WRITE_2BYTES( int x ) bufIndex += 2; } -/* -=============== -WRITE_1BYTES -=============== -*/ -static ID_INLINE void WRITE_1BYTES( int x ) -{ - buffer[ bufIndex ] = x; - bufIndex += 1; -} - /* =============== START_CHUNK diff --git a/code/client/cl_cin.c b/code/client/cl_cin.c index 599443c9..be4fb1bc 100644 --- a/code/client/cl_cin.c +++ b/code/client/cl_cin.c @@ -94,8 +94,8 @@ typedef struct { qboolean looping, holdAtEnd, dirty, alterGameState, silent, shader; fileHandle_t iFile; e_status status; - unsigned int startTime; - unsigned int lastTime; + int startTime; + int lastTime; long tfps; long RoQPlayed; long ROQSize; @@ -1158,7 +1158,7 @@ redump: if (cinTable[currentHandle].numQuads == -1) { readQuadInfo( framedata ); setupQuad( 0, 0 ); - cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds()*com_timescale->value; + cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds(); } if (cinTable[currentHandle].numQuads != 1) cinTable[currentHandle].numQuads = 0; break; @@ -1225,7 +1225,7 @@ redump: static void RoQ_init( void ) { - cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds()*com_timescale->value; + cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds(); cinTable[currentHandle].RoQPlayed = 24; @@ -1356,11 +1356,11 @@ e_status CIN_RunCinematic (int handle) return cinTable[currentHandle].status; } - thisTime = CL_ScaledMilliseconds()*com_timescale->value; + thisTime = CL_ScaledMilliseconds(); if (cinTable[currentHandle].shader && (abs(thisTime - cinTable[currentHandle].lastTime))>100) { cinTable[currentHandle].startTime += thisTime - cinTable[currentHandle].lastTime; } - cinTable[currentHandle].tfps = ((((CL_ScaledMilliseconds()*com_timescale->value) - cinTable[currentHandle].startTime)*3)/100); + cinTable[currentHandle].tfps = (((CL_ScaledMilliseconds() - cinTable[currentHandle].startTime)*3)/100); start = cinTable[currentHandle].startTime; while( (cinTable[currentHandle].tfps != cinTable[currentHandle].numQuads) @@ -1368,8 +1368,7 @@ e_status CIN_RunCinematic (int handle) { RoQInterrupt(); if (start != cinTable[currentHandle].startTime) { - cinTable[currentHandle].tfps = ((((CL_ScaledMilliseconds()*com_timescale->value) - - cinTable[currentHandle].startTime)*3)/100); + cinTable[currentHandle].tfps = (((CL_ScaledMilliseconds() - cinTable[currentHandle].startTime)*3)/100); start = cinTable[currentHandle].startTime; } } diff --git a/code/client/cl_console.c b/code/client/cl_console.c index d1b9fec1..7d806e94 100644 --- a/code/client/cl_console.c +++ b/code/client/cl_console.c @@ -583,8 +583,8 @@ void Con_DrawNotify (void) if ( ( text[x] & 0xff ) == ' ' ) { continue; } - if ( ( (text[x]>>8)&7 ) != currentColor ) { - currentColor = (text[x]>>8)&7; + if ( ColorIndexForNumber( text[x]>>8 ) != currentColor ) { + currentColor = ColorIndexForNumber( text[x]>>8 ); re.SetColor( g_color_table[currentColor] ); } SCR_DrawSmallChar( cl_conXOffset->integer + con.xadjust + (x+1)*SMALLCHAR_WIDTH, v, text[x] & 0xff ); @@ -677,7 +677,7 @@ void Con_DrawSolidConsole( float frac ) { // draw the text con.vislines = lines; - rows = (lines-SMALLCHAR_WIDTH)/SMALLCHAR_WIDTH; // rows of text to draw + rows = (lines-SMALLCHAR_HEIGHT)/SMALLCHAR_HEIGHT; // rows of text to draw y = lines - (SMALLCHAR_HEIGHT*3); @@ -717,8 +717,8 @@ void Con_DrawSolidConsole( float frac ) { continue; } - if ( ( (text[x]>>8)&7 ) != currentColor ) { - currentColor = (text[x]>>8)&7; + if ( ColorIndexForNumber( text[x]>>8 ) != currentColor ) { + currentColor = ColorIndexForNumber( text[x]>>8 ); re.SetColor( g_color_table[currentColor] ); } SCR_DrawSmallChar( con.xadjust + (x+1)*SMALLCHAR_WIDTH, y, text[x] & 0xff ); diff --git a/code/client/cl_curl.c b/code/client/cl_curl.c index 901ef999..3ff5a3d8 100644 --- a/code/client/cl_curl.c +++ b/code/client/cl_curl.c @@ -177,12 +177,20 @@ void CL_cURL_Shutdown( void ) void CL_cURL_Cleanup(void) { if(clc.downloadCURLM) { + CURLMcode result; + if(clc.downloadCURL) { - qcurl_multi_remove_handle(clc.downloadCURLM, + result = qcurl_multi_remove_handle(clc.downloadCURLM, clc.downloadCURL); + if(result != CURLM_OK) { + Com_DPrintf("qcurl_multi_remove_handle failed: %s\n", qcurl_multi_strerror(result)); + } qcurl_easy_cleanup(clc.downloadCURL); } - qcurl_multi_cleanup(clc.downloadCURLM); + result = qcurl_multi_cleanup(clc.downloadCURLM); + if(result != CURLM_OK) { + Com_DPrintf("CL_cURL_Cleanup: qcurl_multi_cleanup failed: %s\n", qcurl_multi_strerror(result)); + } clc.downloadCURLM = NULL; clc.downloadCURL = NULL; } @@ -209,8 +217,36 @@ static size_t CL_cURL_CallbackWrite(void *buffer, size_t size, size_t nmemb, return size*nmemb; } +CURLcode qcurl_easy_setopt_warn(CURL *curl, CURLoption option, ...) +{ + CURLcode result; + + va_list argp; + va_start(argp, option); + + if(option < CURLOPTTYPE_OBJECTPOINT) { + long longValue = va_arg(argp, long); + result = qcurl_easy_setopt(curl, option, longValue); + } else if(option < CURLOPTTYPE_OFF_T) { + void *pointerValue = va_arg(argp, void *); + result = qcurl_easy_setopt(curl, option, pointerValue); + } else { + curl_off_t offsetValue = va_arg(argp, curl_off_t); + result = qcurl_easy_setopt(curl, option, offsetValue); + } + + if(result != CURLE_OK) { + Com_DPrintf("qcurl_easy_setopt failed: %s\n", qcurl_easy_strerror(result)); + } + va_end(argp); + + return result; +} + void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) { + CURLMcode result; + clc.cURLUsed = qtrue; Com_Printf("URL: %s\n", remoteURL); Com_DPrintf("***** CL_cURL_BeginDownload *****\n" @@ -246,23 +282,23 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) } if(com_developer->integer) - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_VERBOSE, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_REFERER, va("ioQ3://%s", + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_VERBOSE, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_URL, clc.downloadURL); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_TRANSFERTEXT, 0); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_REFERER, va("ioQ3://%s", NET_AdrToString(clc.serverAddress))); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_USERAGENT, va("%s %s", Q3_VERSION, qcurl_version())); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEFUNCTION, + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEFUNCTION, CL_cURL_CallbackWrite); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_WRITEDATA, &clc.download); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_NOPROGRESS, 0); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSFUNCTION, CL_cURL_CallbackProgress); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FAILONERROR, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); - qcurl_easy_setopt(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_PROGRESSDATA, NULL); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FAILONERROR, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_FOLLOWLOCATION, 1); + qcurl_easy_setopt_warn(clc.downloadCURL, CURLOPT_MAXREDIRS, 5); clc.downloadCURLM = qcurl_multi_init(); if(!clc.downloadCURLM) { qcurl_easy_cleanup(clc.downloadCURL); @@ -271,7 +307,13 @@ void CL_cURL_BeginDownload( const char *localName, const char *remoteURL ) "failed"); return; } - qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); + result = qcurl_multi_add_handle(clc.downloadCURLM, clc.downloadCURL); + if(result != CURLM_OK) { + qcurl_easy_cleanup(clc.downloadCURL); + clc.downloadCURL = NULL; + Com_Error(ERR_DROP,"CL_cURL_BeginDownload: qcurl_multi_add_handle() failed: %s", qcurl_multi_strerror(result)); + return; + } if(!(clc.sv_allowDownload & DLF_NO_DISCONNECT) && !clc.cURLDisconnected) { diff --git a/code/client/cl_input.c b/code/client/cl_input.c index d35e3c31..6e19263c 100644 --- a/code/client/cl_input.c +++ b/code/client/cl_input.c @@ -604,10 +604,10 @@ usercmd_t CL_CreateCmd( void ) { // draw debug graphs of turning for mouse testing if ( cl_debugMove->integer ) { if ( cl_debugMove->integer == 1 ) { - SCR_DebugGraph( abs(cl.viewangles[YAW] - oldAngles[YAW]) ); + SCR_DebugGraph( fabs(cl.viewangles[YAW] - oldAngles[YAW]) ); } if ( cl_debugMove->integer == 2 ) { - SCR_DebugGraph( abs(cl.viewangles[PITCH] - oldAngles[PITCH]) ); + SCR_DebugGraph( fabs(cl.viewangles[PITCH] - oldAngles[PITCH]) ); } } diff --git a/code/client/cl_keys.c b/code/client/cl_keys.c index ce90801d..d68d8243 100644 --- a/code/client/cl_keys.c +++ b/code/client/cl_keys.c @@ -1207,7 +1207,7 @@ void CL_KeyDownEvent( int key, unsigned time ) { keys[key].down = qtrue; keys[key].repeats++; - if( keys[key].repeats == 1 && key != K_SCROLLOCK && key != K_KP_NUMLOCK && key != K_CAPSLOCK ) + if( keys[key].repeats == 1 ) anykeydown++; if( keys[K_ALT].down && key == K_ENTER ) @@ -1299,8 +1299,7 @@ void CL_KeyUpEvent( int key, unsigned time ) { keys[key].repeats = 0; keys[key].down = qfalse; - if (key != K_SCROLLOCK && key != K_KP_NUMLOCK && key != K_CAPSLOCK) - anykeydown--; + anykeydown--; if (anykeydown < 0) { anykeydown = 0; @@ -1385,9 +1384,6 @@ void Key_ClearStates (void) anykeydown = 0; for ( i=0 ; i < MAX_KEYS ; i++ ) { - if (i == K_SCROLLOCK || i == K_KP_NUMLOCK || i == K_CAPSLOCK) - continue; - if ( keys[i].down ) { CL_KeyEvent( i, qfalse, 0 ); diff --git a/code/client/cl_main.c b/code/client/cl_main.c index edeaf060..7567ae2e 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -149,7 +149,6 @@ typedef struct serverStatus_s } serverStatus_t; serverStatus_t cl_serverStatusList[MAX_SERVERSTATUSREQUESTS]; -int serverStatusCount; #if defined __USEA3D && defined __A3D_GEOM void hA3Dg_ExportRenderGeom (refexport_t *incoming_re); @@ -2301,9 +2300,9 @@ Resend a connect message if the last one has timed out ================= */ void CL_CheckForResend( void ) { - int port, i; + int port; char info[MAX_INFO_STRING]; - char data[MAX_INFO_STRING]; + char data[MAX_INFO_STRING + 10]; // don't send anything if playing back a demo if ( clc.demoplaying ) { @@ -2357,19 +2356,8 @@ void CL_CheckForResend( void ) { Info_SetValueForKey( info, "qport", va("%i", port ) ); Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) ); - strcpy(data, "connect "); - // TTimo adding " " around the userinfo string to avoid truncated userinfo on the server - // (Com_TokenizeString tokenizes around spaces) - data[8] = '"'; - - for(i=0;i -#include +#include #include #include #include @@ -146,7 +146,7 @@ void mumble_set_identity(const char* identity) size_t len; if (!lm) return; - len = MIN(sizeof(lm->identity), strlen(identity)+1); + len = MIN(sizeof(lm->identity)/sizeof(wchar_t), strlen(identity)+1); mbstowcs(lm->identity, identity, len); } @@ -164,7 +164,7 @@ void mumble_set_description(const char* description) size_t len; if (!lm) return; - len = MIN(sizeof(lm->description), strlen(description)+1); + len = MIN(sizeof(lm->description)/sizeof(wchar_t), strlen(description)+1); mbstowcs(lm->description, description, len); } diff --git a/code/client/snd_mix.c b/code/client/snd_mix.c index f4fa01a4..943c50fa 100644 --- a/code/client/snd_mix.c +++ b/code/client/snd_mix.c @@ -236,6 +236,10 @@ static void S_PaintChannelFrom16_altivec( channel_t *ch, const sfx_t *sc, int co short *samples; float ooff, fdata[2], fdiv, fleftvol, frightvol; + if (sc->soundChannels <= 0) { + return; + } + samp = &paintbuffer[ bufferOffset ]; if (ch->doppler) { @@ -422,6 +426,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou short *samples; float ooff, fdata[2], fdiv, fleftvol, frightvol; + if (sc->soundChannels <= 0) { + return; + } + samp = &paintbuffer[ bufferOffset ]; if (ch->doppler) { diff --git a/code/client/snd_openal.c b/code/client/snd_openal.c index a97641c1..bec291dc 100644 --- a/code/client/snd_openal.c +++ b/code/client/snd_openal.c @@ -2259,7 +2259,7 @@ void S_AL_StartBackgroundTrack( const char *intro, const char *loop ) issame = qfalse; // Copy the loop over - strncpy( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) ); + Q_strncpyz( s_backgroundLoop, loop, sizeof( s_backgroundLoop ) ); if(!issame) { @@ -3260,7 +3260,7 @@ qboolean S_AL_Init( soundInterface_t *si ) s_alGain = Cvar_Get( "s_alGain", "1.0", CVAR_ARCHIVE ); s_alSources = Cvar_Get( "s_alSources", "96", CVAR_ARCHIVE ); s_alDopplerFactor = Cvar_Get( "s_alDopplerFactor", "1.0", CVAR_ARCHIVE ); - s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "13512", CVAR_ARCHIVE ); + s_alDopplerSpeed = Cvar_Get( "s_alDopplerSpeed", "9000", CVAR_ARCHIVE ); s_alMinDistance = Cvar_Get( "s_alMinDistance", "120", CVAR_CHEAT ); s_alMaxDistance = Cvar_Get("s_alMaxDistance", "1024", CVAR_CHEAT); s_alRolloff = Cvar_Get( "s_alRolloff", "2", CVAR_CHEAT); diff --git a/code/client/snd_wavelet.c b/code/client/snd_wavelet.c index a325ffdc..3d8f5c7b 100644 --- a/code/client/snd_wavelet.c +++ b/code/client/snd_wavelet.c @@ -119,7 +119,7 @@ void NXPutc(NXStream *stream, char out) { void encodeWavelet( sfx_t *sfx, short *packets) { - float wksp[4097], temp; + float wksp[4097] = {0}, temp; int i, samples, size; sndBuffer *newchunk, *chunk; byte *out; @@ -169,7 +169,7 @@ void encodeWavelet( sfx_t *sfx, short *packets) { } void decodeWavelet(sndBuffer *chunk, short *to) { - float wksp[4097]; + float wksp[4097] = {0}; int i; byte *out; diff --git a/code/game/ai_dmq3.c b/code/game/ai_dmq3.c index a03df1a4..b9b09ae1 100644 --- a/code/game/ai_dmq3.c +++ b/code/game/ai_dmq3.c @@ -1460,7 +1460,7 @@ char *EasyClientName(int client, char *buf, int size) { int i; char *str1, *str2, *ptr, c; - char name[128]; + char name[128] = {0}; ClientName(client, name, sizeof(name)); for (i = 0; name[i]; i++) @@ -2822,6 +2822,7 @@ float BotEntityVisible(int viewer, vec3_t eye, vec3_t viewangles, float fov, int BotAI_Trace(&trace, start, NULL, NULL, end, passent, contents_mask); //if water was hit waterfactor = 1.0; + //note: trace.contents is always 0, see BotAI_Trace if (trace.contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) { //if the water surface is translucent if (1) { @@ -5133,6 +5134,7 @@ void BotCheckEvents(bot_state_t * bs, entityState_t * state) case EV_USE_ITEM12: case EV_USE_ITEM13: case EV_USE_ITEM14: + case EV_USE_ITEM15: break; } } diff --git a/code/game/ai_main.c b/code/game/ai_main.c index 9ee29c91..74d263b8 100644 --- a/code/game/ai_main.c +++ b/code/game/ai_main.c @@ -172,7 +172,8 @@ void BotAI_Trace(bsp_trace_t * bsptrace, vec3_t start, vec3_t mins, vec3_t maxs, VectorCopy(trace.plane.normal, bsptrace->plane.normal); bsptrace->plane.signbits = trace.plane.signbits; bsptrace->plane.type = trace.plane.type; - bsptrace->surface.value = trace.surfaceFlags; + bsptrace->surface.value = 0; + bsptrace->surface.flags = trace.surfaceFlags; bsptrace->ent = trace.entityNum; bsptrace->exp_dist = 0; bsptrace->sidenum = 0; @@ -1150,7 +1151,8 @@ void BotWriteSessionData(bot_state_t * bs) s = va("%i %i %i %i %i %i %i %i" " %f %f %f" " %f %f %f" - " %f %f %f", + " %f %f %f" + " %f", bs->lastgoal_decisionmaker, bs->lastgoal_ltgtype, bs->lastgoal_teammate, @@ -1165,7 +1167,10 @@ void BotWriteSessionData(bot_state_t * bs) bs->lastgoal_teamgoal.mins[0], bs->lastgoal_teamgoal.mins[1], bs->lastgoal_teamgoal.mins[2], - bs->lastgoal_teamgoal.maxs[0], bs->lastgoal_teamgoal.maxs[1], bs->lastgoal_teamgoal.maxs[2] + bs->lastgoal_teamgoal.maxs[0], + bs->lastgoal_teamgoal.maxs[1], + bs->lastgoal_teamgoal.maxs[2], + bs->formation_dist ); var = va("botsession%i", bs->client); @@ -1190,7 +1195,8 @@ void BotReadSessionData(bot_state_t * bs) "%i %i %i %i %i %i %i %i" " %f %f %f" " %f %f %f" - " %f %f %f", + " %f %f %f" + " %f", &bs->lastgoal_decisionmaker, &bs->lastgoal_ltgtype, &bs->lastgoal_teammate, @@ -1205,7 +1211,10 @@ void BotReadSessionData(bot_state_t * bs) &bs->lastgoal_teamgoal.mins[0], &bs->lastgoal_teamgoal.mins[1], &bs->lastgoal_teamgoal.mins[2], - &bs->lastgoal_teamgoal.maxs[0], &bs->lastgoal_teamgoal.maxs[1], &bs->lastgoal_teamgoal.maxs[2] + &bs->lastgoal_teamgoal.maxs[0], + &bs->lastgoal_teamgoal.maxs[1], + &bs->lastgoal_teamgoal.maxs[2], + &bs->formation_dist ); } @@ -1224,6 +1233,10 @@ int BotAISetupClient(int client, struct bot_settings_s *settings, qboolean resta botstates[client] = G_Alloc(sizeof(bot_state_t)); bs = botstates[client]; + if (!bs) { + return qfalse; + } + if (bs && bs->inuse) { BotAI_Print(PRT_FATAL, "BotAISetupClient: client %d already setup\n", client); return qfalse; diff --git a/code/game/ai_main.h b/code/game/ai_main.h index 988030b6..4917d43f 100644 --- a/code/game/ai_main.h +++ b/code/game/ai_main.h @@ -282,7 +282,7 @@ typedef struct bot_state_s { float leadmessage_time; //last time a messaged was sent to the team mate float leadbackup_time; //time backing up towards team mate // - char teamleader[32]; //netname of the team leader + char teamleader[MAX_NETNAME]; //netname of the team leader float askteamleader_time; //time asked for team leader float becometeamleader_time; //time the bot will become the team leader float teamgiveorders_time; //time to give team orders diff --git a/code/game/ai_team.c b/code/game/ai_team.c index 76d33002..0aa39d23 100644 --- a/code/game/ai_team.c +++ b/code/game/ai_team.c @@ -177,7 +177,7 @@ int BotSortTeamMatesByBaseTravelTime(bot_state_t * bs, int *teammates, int maxte if (atoi(Info_ValueForKey(buf, "t")) == TEAM_SPECTATOR) continue; // - if (BotSameTeam(bs, i)) { + if (BotSameTeam(bs, i) && goal) { // traveltime = BotClientTravelTimeToGoal(i, goal); // @@ -336,7 +336,7 @@ BotCTFOrders void BotCTFOrders_BothFlagsNotAtBase(bot_state_t * bs) { int numteammates, defenders, attackers, i, other; - int teammates[MAX_CLIENTS]; + int teammates[MAX_CLIENTS] = {0}; char name[MAX_NETNAME], carriername[MAX_NETNAME]; numteammates = BotSortTeamMatesByBaseTravelTime(bs, teammates, sizeof(teammates)); @@ -723,7 +723,7 @@ BotCTFOrders void BotCTFOrders_BothFlagsAtBase(bot_state_t * bs) { int numteammates, defenders, attackers, i; - int teammates[MAX_CLIENTS]; + int teammates[MAX_CLIENTS] = {0}; char name[MAX_NETNAME]; //sort team mates by travel time to base diff --git a/code/game/ai_vcmd.c b/code/game/ai_vcmd.c index 5de41c91..dc571656 100644 --- a/code/game/ai_vcmd.c +++ b/code/game/ai_vcmd.c @@ -507,7 +507,7 @@ int BotVoiceChatCommand(bot_state_t * bs, int mode, char *voiceChat) Q_strncpyz(buf, voiceChat, sizeof(buf)); cmd = buf; - for (ptr = cmd; *cmd && *cmd > ' '; cmd++); + for (; *cmd && *cmd > ' '; cmd++); while (*cmd && *cmd <= ' ') *cmd++ = '\0'; //voiceOnly = atoi(ptr); @@ -515,7 +515,7 @@ int BotVoiceChatCommand(bot_state_t * bs, int mode, char *voiceChat) while (*cmd && *cmd <= ' ') *cmd++ = '\0'; clientNum = atoi(ptr); - for (ptr = cmd; *cmd && *cmd > ' '; cmd++); + for (; *cmd && *cmd > ' '; cmd++); while (*cmd && *cmd <= ' ') *cmd++ = '\0'; //color = atoi(ptr); diff --git a/code/game/g_bot.c b/code/game/g_bot.c index d0cc81c1..9df6dd4e 100644 --- a/code/game/g_bot.c +++ b/code/game/g_bot.c @@ -869,7 +869,7 @@ static void G_SpawnBots(char *botList, int baseDelay) while (*p && *p == ' ') { p++; } - if (!p) { + if (!*p) { break; } // mark start of bot name diff --git a/code/game/g_cmds.c b/code/game/g_cmds.c index d50404d4..71d0f7af 100644 --- a/code/game/g_cmds.c +++ b/code/game/g_cmds.c @@ -1293,8 +1293,6 @@ to free floating spectator mode */ void StopFollowing(gentity_t * ent) { - vec3_t angle; - ent->client->ps.persistant[PERS_TEAM] = TEAM_SPECTATOR; ent->client->sess.sessionTeam = TEAM_SPECTATOR; ent->client->sess.spectatorState = SPECTATOR_FREE; @@ -1306,8 +1304,13 @@ void StopFollowing(gentity_t * ent) ent->client->ps.pm_flags &= ~PMF_FOLLOW; ent->r.svFlags &= ~SVF_BOT; ent->client->ps.clientNum = ent - g_entities; - angle[0] = angle[1] = angle[2] = 0.0; - SetClientViewAngle(ent, angle); + + SetClientViewAngle( ent, ent->client->ps.viewangles ); + + // don't use dead view angles + if ( ent->client->ps.stats[STAT_HEALTH] <= 0 ) { + ent->client->ps.stats[STAT_HEALTH] = 1; + } } /* diff --git a/code/game/g_items.c b/code/game/g_items.c index 5216b4b8..846ed592 100644 --- a/code/game/g_items.c +++ b/code/game/g_items.c @@ -476,6 +476,10 @@ RespawnItem */ void RespawnItem(gentity_t * ent) { + if (!ent) { + return; + } + // randomly select from teamed entities if (ent->team) { gentity_t *master; @@ -491,7 +495,11 @@ void RespawnItem(gentity_t * ent) choice = rand() % count; - for (count = 0, ent = master; count < choice; ent = ent->teamchain, count++); + for (count = 0, ent = master; ent && count < choice; ent = ent->teamchain, count++); + } + + if (!ent) { + return; } ent->r.contents = CONTENTS_TRIGGER; diff --git a/code/game/g_main.c b/code/game/g_main.c index 73729408..76fe119b 100644 --- a/code/game/g_main.c +++ b/code/game/g_main.c @@ -1629,6 +1629,7 @@ void AdjustTournamentScores(void) ClientUserinfoChanged(clientNum); } + trap_SetConfigstring( CS_INTERMISSION, "" ); } /* @@ -2730,7 +2731,7 @@ Runs thinking code for this frame if necessary */ void G_RunThink(gentity_t * ent) { - float thinktime; + int thinktime; thinktime = ent->nextthink; if (thinktime <= 0) { diff --git a/code/game/g_mover.c b/code/game/g_mover.c index 9f03c68a..bc1eda0c 100644 --- a/code/game/g_mover.c +++ b/code/game/g_mover.c @@ -1448,6 +1448,10 @@ void Think_SpawnNewDoorTrigger(gentity_t * ent) vec3_t mins, maxs; int i, best; + if (!ent) { + return; + } + // set all of the slaves as shootable // Makro - why ? for (other = ent; other; other = other->teamchain) { diff --git a/code/game/g_svcmds.c b/code/game/g_svcmds.c index 047c813d..953bb40c 100644 --- a/code/game/g_svcmds.c +++ b/code/game/g_svcmds.c @@ -148,10 +148,11 @@ UpdateIPBans */ static void UpdateIPBans(void) { - byte b[4], m[4]; + byte b[4] = {0}; + byte m[4] = {0}; int i, j; - char iplist_final[MAX_CVAR_VALUE_STRING]; - char ip[64]; + char iplist_final[MAX_CVAR_VALUE_STRING] = {0}; + char ip[64] = {0}; *iplist_final = 0; for (i = 0; i < numIPFilters; i++) { @@ -188,7 +189,7 @@ qboolean G_FilterPacket(char *from) { int i; unsigned in; - byte m[4]; + byte m[4] = {0}; char *p; i = 0; diff --git a/code/libcurl-7.35.0/curl/curlbuild.h b/code/libcurl-7.35.0/curl/curlbuild.h index 3ad2f018..d7790db5 100644 --- a/code/libcurl-7.35.0/curl/curlbuild.h +++ b/code/libcurl-7.35.0/curl/curlbuild.h @@ -528,7 +528,8 @@ #elif defined(__GNUC__) # if defined(__ILP32__) || \ - defined(__i386__) || defined(__ppc__) || defined(__arm__) + defined(__i386__) || defined(__ppc__) || defined(__powerpc__) || \ + defined(__arm__) || defined(__sparc__) # define CURL_SIZEOF_LONG 4 # define CURL_TYPEOF_CURL_OFF_T long long # define CURL_FORMAT_CURL_OFF_T "lld" @@ -538,7 +539,8 @@ # define CURL_SUFFIX_CURL_OFF_T LL # define CURL_SUFFIX_CURL_OFF_TU ULL # elif defined(__LP64__) || \ - defined(__x86_64__) || defined(__ppc64__) + defined(__x86_64__) || defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__sparc64__) # define CURL_SIZEOF_LONG 8 # define CURL_TYPEOF_CURL_OFF_T long # define CURL_FORMAT_CURL_OFF_T "ld" diff --git a/code/libs/macosx/macosx/libSDL2-2.0.0.dylib b/code/libs/macosx/libSDL2-2.0.0.dylib similarity index 100% rename from code/libs/macosx/macosx/libSDL2-2.0.0.dylib rename to code/libs/macosx/libSDL2-2.0.0.dylib diff --git a/code/libs/macosx/macosx/libSDL2main.a b/code/libs/macosx/libSDL2main.a similarity index 100% rename from code/libs/macosx/macosx/libSDL2main.a rename to code/libs/macosx/libSDL2main.a diff --git a/code/libs/win32/SDL.lib b/code/libs/win32/SDL.lib deleted file mode 100755 index 4fd5981e..00000000 Binary files a/code/libs/win32/SDL.lib and /dev/null differ diff --git a/code/libs/win32/SDLmain.lib b/code/libs/win32/SDLmain.lib deleted file mode 100755 index a78443d0..00000000 Binary files a/code/libs/win32/SDLmain.lib and /dev/null differ diff --git a/code/libs/win64/SDL.lib b/code/libs/win64/SDL.lib deleted file mode 100755 index 61bde540..00000000 Binary files a/code/libs/win64/SDL.lib and /dev/null differ diff --git a/code/libs/win64/SDLmain.lib b/code/libs/win64/SDLmain.lib deleted file mode 100755 index a83a2216..00000000 Binary files a/code/libs/win64/SDLmain.lib and /dev/null differ diff --git a/code/libvorbis-1.3.4/lib/floor1.c b/code/libvorbis-1.3.4/lib/floor1.c index 097c583d..c0515021 100644 --- a/code/libvorbis-1.3.4/lib/floor1.c +++ b/code/libvorbis-1.3.4/lib/floor1.c @@ -872,7 +872,7 @@ int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, /* generate the partition's first stage cascade value */ if(csubbits){ - int maxval[8]; + int maxval[8] = {0}; for(k=0;kclass_subbook[class][k]; if(booknum<0){ diff --git a/code/libvorbis-1.3.4/lib/lsp.c b/code/libvorbis-1.3.4/lib/lsp.c index 50031a7a..b1b3aa6e 100644 --- a/code/libvorbis-1.3.4/lib/lsp.c +++ b/code/libvorbis-1.3.4/lib/lsp.c @@ -309,7 +309,6 @@ static int comp(const void *a,const void *b){ #define EPSILON 10e-7 static int Laguerre_With_Deflation(float *a,int ord,float *r){ int i,m; - double lastdelta=0.f; double *defl=alloca(sizeof(*defl)*(ord+1)); for(i=0;i<=ord;i++)defl[i]=a[i]; @@ -346,7 +345,6 @@ static int Laguerre_With_Deflation(float *a,int ord,float *r){ if(delta<0.f)delta*=-1; if(fabs(delta/new)<10e-12)break; - lastdelta=delta; } r[m-1]=new; diff --git a/code/libvorbis-1.3.4/lib/vorbisfile.c b/code/libvorbis-1.3.4/lib/vorbisfile.c index 84bf8c31..a20d0428 100644 --- a/code/libvorbis-1.3.4/lib/vorbisfile.c +++ b/code/libvorbis-1.3.4/lib/vorbisfile.c @@ -1827,7 +1827,7 @@ vorbis_comment *ov_comment(OggVorbis_File *vf,int link){ } } -static int host_is_big_endian() { +static int host_is_big_endian(void) { ogg_int32_t pattern = 0xfeedface; /* deadbeef */ unsigned char *bytewise = (unsigned char *)&pattern; if (bytewise[0] == 0xfe) return 1; diff --git a/code/null/null_input.c b/code/null/null_input.c index 8a765557..c3a4e119 100644 --- a/code/null/null_input.c +++ b/code/null/null_input.c @@ -32,6 +32,3 @@ void IN_Shutdown( void ) { void IN_Restart( void ) { } -void Sys_SendKeyEvents (void) { -} - diff --git a/code/null/null_main.c b/code/null/null_main.c index 4043eb97..01c22bd2 100644 --- a/code/null/null_main.c +++ b/code/null/null_main.c @@ -19,7 +19,7 @@ along with Quake III Arena source code; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA =========================================================================== */ -// sys_null.h -- null system driver to aid porting efforts +// null_main.c -- null system driver to aid porting efforts #include #include @@ -30,26 +30,6 @@ int sys_curtime; //=================================================================== -void Sys_BeginStreamedFile( FILE *f, int readAhead ) { -} - -void Sys_EndStreamedFile( FILE *f ) { -} - -int Sys_StreamedRead( void *buffer, int size, int count, FILE *f ) { - return fread( buffer, size, count, f ); -} - -void Sys_StreamSeek( FILE *f, int offset, int origin ) { - fseek( f, offset, origin ); -} - - -//=================================================================== - - -void Sys_mkdir ( const char *path ) { -} void Sys_Error (char *error, ...) { va_list argptr; @@ -67,13 +47,6 @@ void Sys_Quit (void) { exit (0); } -void Sys_UnloadGame (void) { -} - -void *Sys_GetGameAPI (void *parms) { - return NULL; -} - char *Sys_GetClipboardData( void ) { return NULL; } @@ -89,26 +62,10 @@ FILE *Sys_FOpen(const char *ospath, const char *mode) { void Sys_Mkdir (char *path) { } -char *Sys_FindFirst (char *path, unsigned musthave, unsigned canthave) { - return NULL; -} - -char *Sys_FindNext (unsigned musthave, unsigned canthave) { - return NULL; -} - -void Sys_FindClose (void) { -} - void Sys_Init (void) { } -void Sys_EarlyOutput( char *string ) { - printf( "%s", string ); -} - - void main (int argc, char **argv) { Com_Init (argc, argv); diff --git a/code/opus-1.1/silk/float/solve_LS_FLP.c b/code/opus-1.1/silk/float/solve_LS_FLP.c index 7c90d665..b35f0a57 100644 --- a/code/opus-1.1/silk/float/solve_LS_FLP.c +++ b/code/opus-1.1/silk/float/solve_LS_FLP.c @@ -163,7 +163,7 @@ static OPUS_INLINE void silk_LDL_FLP( opus_int i, j, k, loop_count, err = 1; silk_float *ptr1, *ptr2; double temp, diag_min_value; - silk_float v[ MAX_MATRIX_SIZE ], D[ MAX_MATRIX_SIZE ]; /* temp arrays*/ + silk_float v[ MAX_MATRIX_SIZE ] = { 0 }, D[ MAX_MATRIX_SIZE ]; /* temp arrays*/ silk_assert( M <= MAX_MATRIX_SIZE ); diff --git a/code/opus-1.1/src/opus_decoder.c b/code/opus-1.1/src/opus_decoder.c index 919ba521..0ba3a058 100644 --- a/code/opus-1.1/src/opus_decoder.c +++ b/code/opus-1.1/src/opus_decoder.c @@ -33,7 +33,7 @@ # error "OPUS_BUILD _MUST_ be defined to build Opus. This probably means you need other defines as well, as in a config.h. See the included build files for details." #endif -#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) +#if defined(__GNUC__) && (__GNUC__ >= 2) && !defined(__OPTIMIZE__) && !defined(__APPLE__) # pragma message "You appear to be compiling without optimization, if so opus will be very slow." #endif @@ -215,7 +215,7 @@ static int opus_decode_frame(OpusDecoder *st, const unsigned char *data, VARDECL(opus_val16, pcm_transition_silk); int pcm_transition_celt_size; VARDECL(opus_val16, pcm_transition_celt); - opus_val16 *pcm_transition; + opus_val16 *pcm_transition=NULL; int redundant_audio_size; VARDECL(opus_val16, redundant_audio); diff --git a/code/opusfile-0.5/src/opusfile.c b/code/opusfile-0.5/src/opusfile.c index 392ddb29..73b95de6 100644 --- a/code/opusfile-0.5/src/opusfile.c +++ b/code/opusfile-0.5/src/opusfile.c @@ -317,7 +317,7 @@ struct OpusSeekRecord{ static int op_get_prev_page_serial(OggOpusFile *_of,OpusSeekRecord *_sr, opus_int64 _offset,ogg_uint32_t _serialno, const ogg_uint32_t *_serialnos,int _nserialnos){ - OpusSeekRecord preferred_sr; + OpusSeekRecord preferred_sr={0}; ogg_page og; opus_int64 begin; opus_int64 end; @@ -930,7 +930,7 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of, prev_packet_gp=pcm_start; for(pi=0;pinlinks; if(OP_UNLIKELY(_of->ready_state=0); @@ -2166,11 +2166,11 @@ static int op_pcm_seek_page(OggOpusFile *_of, ogg_int64_t _target_gp,int _li){ const OggOpusLink *link; ogg_page og; - ogg_int64_t pcm_pre_skip; + ogg_int64_t pcm_pre_skip=0; ogg_int64_t pcm_start; ogg_int64_t pcm_end; ogg_int64_t best_gp; - ogg_int64_t diff; + ogg_int64_t diff=0; ogg_uint32_t serialno; opus_int32 pre_skip; opus_int64 begin; @@ -2239,7 +2239,7 @@ static int op_pcm_seek_page(OggOpusFile *_of, } } else{ - ogg_int64_t prev_page_gp; + ogg_int64_t prev_page_gp=0; /*We might get lucky and already have the packet with the target buffered. Worth checking. @@ -2289,7 +2289,7 @@ static int op_pcm_seek_page(OggOpusFile *_of, d2=end-begin>>1; if(force_bisect)bisect=begin+(end-begin>>1); else{ - ogg_int64_t diff2; + ogg_int64_t diff2=0; OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start)); OP_ALWAYS_TRUE(!op_granpos_diff(&diff2,pcm_end,pcm_start)); /*Take a (pretty decent) guess.*/ @@ -2503,7 +2503,7 @@ static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of, ogg_int64_t _gp,int _li){ const OggOpusLink *links; ogg_int64_t pcm_offset; - ogg_int64_t delta; + ogg_int64_t delta=0; int li; links=_of->links; pcm_offset=0; diff --git a/code/q3_ui/ui_addbots.c b/code/q3_ui/ui_addbots.c index 8b9f4487..4fbad9c9 100644 --- a/code/q3_ui/ui_addbots.c +++ b/code/q3_ui/ui_addbots.c @@ -59,10 +59,16 @@ ADD BOTS MENU typedef struct { menuframework_s menu; + + menutext_s banner; + menubitmap_s background; + menubitmap_s arrows; menubitmap_s up; menubitmap_s down; + menutext_s bots[7]; + menulist_s skill; menulist_s team; menubitmap_s go; @@ -215,21 +221,6 @@ static void UI_AddBotsMenu_GetSortedBotNums( void ) { qsort( addBotsMenuInfo.sortedBotNums, addBotsMenuInfo.numBots, sizeof(addBotsMenuInfo.sortedBotNums[0]), UI_AddBotsMenu_SortCompare ); } - -/* -================= -UI_AddBotsMenu_Draw -================= -*/ -static void UI_AddBotsMenu_Draw( void ) { - UI_DrawBannerString( 320, 16, "ADD BOTS", UI_CENTER, color_white ); - UI_DrawNamedPic( 320-233, 240-166, 466, 332, ART_BACKGROUND ); - - // standard menu drawing - Menu_Draw( &addBotsMenuInfo.menu ); -} - - /* ================= UI_AddBotsMenu_Init @@ -266,7 +257,6 @@ static void UI_AddBotsMenu_Init( void ) { gametype = atoi( Info_ValueForKey( info,"g_gametype" ) ); memset( &addBotsMenuInfo, 0 ,sizeof(addBotsMenuInfo) ); - addBotsMenuInfo.menu.draw = UI_AddBotsMenu_Draw; addBotsMenuInfo.menu.fullscreen = qfalse; addBotsMenuInfo.menu.wrapAround = qtrue; addBotsMenuInfo.delay = 1000; @@ -276,6 +266,21 @@ static void UI_AddBotsMenu_Init( void ) { addBotsMenuInfo.numBots = UI_GetNumBots(); count = addBotsMenuInfo.numBots < 7 ? addBotsMenuInfo.numBots : 7; + addBotsMenuInfo.banner.generic.type = MTYPE_BTEXT; + addBotsMenuInfo.banner.generic.x = 320; + addBotsMenuInfo.banner.generic.y = 16; + addBotsMenuInfo.banner.string = "ADD BOTS"; + addBotsMenuInfo.banner.color = color_white; + addBotsMenuInfo.banner.style = UI_CENTER; + + addBotsMenuInfo.background.generic.type = MTYPE_BITMAP; + addBotsMenuInfo.background.generic.name = ART_BACKGROUND; + addBotsMenuInfo.background.generic.flags = QMF_INACTIVE; + addBotsMenuInfo.background.generic.x = 320-233; + addBotsMenuInfo.background.generic.y = 240-166; + addBotsMenuInfo.background.width = 466; + addBotsMenuInfo.background.height = 332; + addBotsMenuInfo.arrows.generic.type = MTYPE_BITMAP; addBotsMenuInfo.arrows.generic.name = ART_ARROWS; addBotsMenuInfo.arrows.generic.flags = QMF_INACTIVE; @@ -370,8 +375,9 @@ static void UI_AddBotsMenu_Init( void ) { UI_AddBotsMenu_GetSortedBotNums(); UI_AddBotsMenu_SetBotNames(); + Menu_AddItem( &addBotsMenuInfo.menu, &addBotsMenuInfo.background ); + Menu_AddItem( &addBotsMenuInfo.menu, &addBotsMenuInfo.banner ); Menu_AddItem( &addBotsMenuInfo.menu, &addBotsMenuInfo.arrows ); - Menu_AddItem( &addBotsMenuInfo.menu, &addBotsMenuInfo.up ); Menu_AddItem( &addBotsMenuInfo.menu, &addBotsMenuInfo.down ); for( n = 0; n < count; n++ ) { diff --git a/code/q3_ui/ui_controls2.c b/code/q3_ui/ui_controls2.c index 55d33289..f5806a19 100644 --- a/code/q3_ui/ui_controls2.c +++ b/code/q3_ui/ui_controls2.c @@ -216,7 +216,7 @@ typedef struct vec3_t playerMoveangles; int playerLegs; int playerTorso; - int playerWeapon; + weapon_t playerWeapon; qboolean playerChat; menubitmap_s back; @@ -434,7 +434,7 @@ static void Controls_UpdateModel( int anim ) { s_controls.playerMoveangles[YAW] = s_controls.playerViewangles[YAW]; s_controls.playerLegs = LEGS_IDLE; s_controls.playerTorso = TORSO_STAND; - s_controls.playerWeapon = -1; + s_controls.playerWeapon = WP_NUM_WEAPONS; s_controls.playerChat = qfalse; switch( anim ) { diff --git a/code/q3_ui/ui_gameinfo.c b/code/q3_ui/ui_gameinfo.c index d9deacd7..887a27be 100644 --- a/code/q3_ui/ui_gameinfo.c +++ b/code/q3_ui/ui_gameinfo.c @@ -659,7 +659,7 @@ Returns the next level the player has not won */ int UI_GetCurrentGame( void ) { int level; - int rank; + int rank = 0; int skill; const char *info; diff --git a/code/q3_ui/ui_mfield.c b/code/q3_ui/ui_mfield.c index d2862ff4..9eae7e01 100644 --- a/code/q3_ui/ui_mfield.c +++ b/code/q3_ui/ui_mfield.c @@ -253,7 +253,7 @@ void MField_CharEvent( mfield_t *edit, int ch ) { return; } - if ( !trap_Key_GetOverstrikeMode() ) { + if ( trap_Key_GetOverstrikeMode() ) { if ((edit->cursor == MAX_EDIT_LINE - 1) || (edit->maxchars && edit->cursor >= edit->maxchars)) return; } else { diff --git a/code/q3_ui/ui_players.c b/code/q3_ui/ui_players.c index 1271abd7..24e236e9 100644 --- a/code/q3_ui/ui_players.c +++ b/code/q3_ui/ui_players.c @@ -88,15 +88,13 @@ tryagain: } if ( weaponNum == WP_MACHINEGUN || weaponNum == WP_GAUNTLET || weaponNum == WP_BFG ) { - strcpy( path, item->world_model[0] ); - COM_StripExtension( path, path, sizeof(path) ); - strcat( path, "_barrel.md3" ); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_barrel.md3" ); pi->barrelModel = trap_R_RegisterModel( path ); } - strcpy( path, item->world_model[0] ); - COM_StripExtension( path, path, sizeof(path) ); - strcat( path, "_flash.md3" ); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_flash.md3" ); pi->flashModel = trap_R_RegisterModel( path ); switch( weaponNum ) { @@ -332,8 +330,8 @@ static void UI_PositionRotatedEntityOnTag( refEntity_t *entity, const refEntity_ } // cast away const because of compiler problems - MatrixMultiply( entity->axis, ((refEntity_t *)parent)->axis, tempAxis ); - MatrixMultiply( lerped.axis, tempAxis, entity->axis ); + MatrixMultiply( entity->axis, lerped.axis, tempAxis ); + MatrixMultiply( tempAxis, ((refEntity_t *)parent)->axis, entity->axis ); } @@ -689,12 +687,12 @@ UI_DrawPlayer */ void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) { refdef_t refdef; - refEntity_t legs; - refEntity_t torso; - refEntity_t head; - refEntity_t gun; - refEntity_t barrel; - refEntity_t flash; + refEntity_t legs = {0}; + refEntity_t torso = {0}; + refEntity_t head = {0}; + refEntity_t gun = {0}; + refEntity_t barrel = {0}; + refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = {-16, -16, -24}; @@ -845,10 +843,6 @@ void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int ti angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle( pi ); - if( pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) { - angles[PITCH] = angles[ROLL]; - angles[ROLL] = 0; - } AnglesToAxis( angles, barrel.axis ); UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel"); diff --git a/code/q3_ui/ui_preferences.c b/code/q3_ui/ui_preferences.c index ca0f628f..b65728a5 100644 --- a/code/q3_ui/ui_preferences.c +++ b/code/q3_ui/ui_preferences.c @@ -353,7 +353,6 @@ static void Preferences_MenuInit( void ) { s_preferences.allowdownload.generic.x = PREFERENCES_X_POS; s_preferences.allowdownload.generic.y = y; - y += BIGCHAR_HEIGHT+2; s_preferences.back.generic.type = MTYPE_BITMAP; s_preferences.back.generic.name = ART_BACK0; s_preferences.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; diff --git a/code/q3_ui/ui_splevel.c b/code/q3_ui/ui_splevel.c index e9898665..a23ef0c6 100644 --- a/code/q3_ui/ui_splevel.c +++ b/code/q3_ui/ui_splevel.c @@ -183,7 +183,7 @@ static void UI_SPLevelMenu_SetBots( void ) { while( *p && *p == ' ' ) { p++; } - if( !p ) { + if( !*p ) { break; } @@ -236,7 +236,7 @@ static void UI_SPLevelMenu_SetMenuArena( int n, int level, const char *arenaInfo levelMenuInfo.levelScores[n] = 8; } - strcpy( levelMenuInfo.levelPicNames[n], va( "levelshots/%s.tga", map ) ); + Com_sprintf( levelMenuInfo.levelPicNames[n], sizeof(levelMenuInfo.levelPicNames[n]), "levelshots/%s.tga", map ); if( !trap_R_RegisterShaderNoMip( levelMenuInfo.levelPicNames[n] ) ) { strcpy( levelMenuInfo.levelPicNames[n], ART_MAP_UNKNOWN ); } diff --git a/code/q3_ui/ui_startserver.c b/code/q3_ui/ui_startserver.c index ce9080c7..b5e6aec6 100644 --- a/code/q3_ui/ui_startserver.c +++ b/code/q3_ui/ui_startserver.c @@ -1076,7 +1076,7 @@ static void ServerOptions_InitBotNames( void ) { while( *p && *p == ' ' ) { p++; } - if( !p ) { + if( !*p ) { break; } diff --git a/code/q3_ui/ui_team.c b/code/q3_ui/ui_team.c index e15dde63..220bc856 100644 --- a/code/q3_ui/ui_team.c +++ b/code/q3_ui/ui_team.c @@ -150,7 +150,6 @@ void TeamMain_MenuInit( void ) { s_teammain.spectate.string = "SPECTATE"; s_teammain.spectate.style = UI_CENTER|UI_SMALLFONT; s_teammain.spectate.color = colorRed; - y += 20; trap_GetConfigString(CS_SERVERINFO, info, MAX_INFO_STRING); gametype = atoi( Info_ValueForKey( info,"g_gametype" ) ); diff --git a/code/q3_ui/ui_video.c b/code/q3_ui/ui_video.c index de248420..63540f22 100644 --- a/code/q3_ui/ui_video.c +++ b/code/q3_ui/ui_video.c @@ -1199,7 +1199,6 @@ void GraphicsOptions_MenuInit( void ) s_graphicsoptions.driverinfo.string = "Driver Info"; s_graphicsoptions.driverinfo.style = UI_CENTER|UI_SMALLFONT; s_graphicsoptions.driverinfo.color = color_red; - y += BIGCHAR_HEIGHT+2; s_graphicsoptions.back.generic.type = MTYPE_BITMAP; s_graphicsoptions.back.generic.name = GRAPHICSOPTIONS_BACK0; diff --git a/code/qcommon/cm_patch.c b/code/qcommon/cm_patch.c index 77cf368f..e4b90002 100644 --- a/code/qcommon/cm_patch.c +++ b/code/qcommon/cm_patch.c @@ -418,7 +418,7 @@ static int numPlanes; static patchPlane_t planes[MAX_PATCH_PLANES]; static int numFacets; -static facet_t facets[MAX_PATCH_PLANES]; //maybe MAX_FACETS ?? +static facet_t facets[MAX_FACETS]; #define NORMAL_EPSILON 0.0001 #define DIST_EPSILON 0.02 @@ -626,6 +626,9 @@ static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRI p1 = grid->points[i][j]; p2 = grid->points[i+1][j]; p = CM_GridPlane( gridPlanes, i, j, 0 ); + if ( p == -1 ) { + return -1; + } VectorMA( p1, 4, planes[ p ].plane, up ); return CM_FindPlane( p1, p2, up ); @@ -633,6 +636,9 @@ static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRI p1 = grid->points[i][j+1]; p2 = grid->points[i+1][j+1]; p = CM_GridPlane( gridPlanes, i, j, 1 ); + if ( p == -1 ) { + return -1; + } VectorMA( p1, 4, planes[ p ].plane, up ); return CM_FindPlane( p2, p1, up ); @@ -640,6 +646,9 @@ static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRI p1 = grid->points[i][j]; p2 = grid->points[i][j+1]; p = CM_GridPlane( gridPlanes, i, j, 1 ); + if ( p == -1 ) { + return -1; + } VectorMA( p1, 4, planes[ p ].plane, up ); return CM_FindPlane( p2, p1, up ); @@ -647,6 +656,9 @@ static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRI p1 = grid->points[i+1][j]; p2 = grid->points[i+1][j+1]; p = CM_GridPlane( gridPlanes, i, j, 0 ); + if ( p == -1 ) { + return -1; + } VectorMA( p1, 4, planes[ p ].plane, up ); return CM_FindPlane( p1, p2, up ); @@ -654,6 +666,9 @@ static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRI p1 = grid->points[i+1][j+1]; p2 = grid->points[i][j]; p = CM_GridPlane( gridPlanes, i, j, 0 ); + if ( p == -1 ) { + return -1; + } VectorMA( p1, 4, planes[ p ].plane, up ); return CM_FindPlane( p1, p2, up ); @@ -661,6 +676,9 @@ static int CM_EdgePlaneNum( cGrid_t *grid, int gridPlanes[MAX_GRID_SIZE][MAX_GRI p1 = grid->points[i][j]; p2 = grid->points[i+1][j+1]; p = CM_GridPlane( gridPlanes, i, j, 1 ); + if ( p == -1 ) { + return -1; + } VectorMA( p1, 4, planes[ p ].plane, up ); return CM_FindPlane( p1, p2, up ); @@ -858,7 +876,10 @@ void CM_AddFacetBevels( facet_t *facet ) { } if ( i == facet->numBorders ) { - if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n"); + if ( facet->numBorders >= 4 + 6 + 16 ) { + Com_Printf( "ERROR: too many bevels\n" ); + continue; + } facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped); facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = flipped; @@ -920,7 +941,10 @@ void CM_AddFacetBevels( facet_t *facet ) { } if ( i == facet->numBorders ) { - if (facet->numBorders > 4 + 6 + 16) Com_Printf("ERROR: too many bevels\n"); + if ( facet->numBorders >= 4 + 6 + 16 ) { + Com_Printf( "ERROR: too many bevels\n" ); + continue; + } facet->borderPlanes[facet->numBorders] = CM_FindPlane2(plane, &flipped); for ( k = 0 ; k < facet->numBorders ; k++ ) { @@ -958,6 +982,10 @@ void CM_AddFacetBevels( facet_t *facet ) { #ifndef BSPC //add opposite plane + if ( facet->numBorders >= 4 + 6 + 16 ) { + Com_Printf( "ERROR: too many bevels\n" ); + return; + } facet->borderPlanes[facet->numBorders] = facet->surfacePlane; facet->borderNoAdjust[facet->numBorders] = 0; facet->borderInward[facet->numBorders] = qtrue; diff --git a/code/qcommon/cmd.c b/code/qcommon/cmd.c index 717701db..45122e07 100644 --- a/code/qcommon/cmd.c +++ b/code/qcommon/cmd.c @@ -667,6 +667,7 @@ void Cmd_SetCommandCompletionFunc( const char *command, completionFunc_t complet for( cmd = cmd_functions; cmd; cmd = cmd->next ) { if( !Q_stricmp( command, cmd->name ) ) { cmd->complete = complete; + return; } } } @@ -743,8 +744,11 @@ void Cmd_CompleteArgument( const char *command, char *args, int argNum ) { cmd_function_t *cmd; for( cmd = cmd_functions; cmd; cmd = cmd->next ) { - if( !Q_stricmp( command, cmd->name ) && cmd->complete ) { - cmd->complete( args, argNum ); + if( !Q_stricmp( command, cmd->name ) ) { + if ( cmd->complete ) { + cmd->complete( args, argNum ); + } + return; } } } diff --git a/code/qcommon/common.c b/code/qcommon/common.c index e796cefe..53bb1713 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -1537,6 +1537,7 @@ void Com_InitHunkMemory( void ) { // allocate the stack based hunk allocator cv = Cvar_Get( "com_hunkMegs", DEF_COMHUNKMEGS_S, CVAR_LATCH | CVAR_ARCHIVE ); + Cvar_SetDescription(cv, "The size of the hunk memory segment"); // if we are not dedicated min allocation is 56, otherwise min is 1 if (com_dedicated && com_dedicated->integer) { @@ -3551,7 +3552,7 @@ void Com_RandomBytes( byte *string, int len ) Com_Printf( "Com_RandomBytes: using weak randomization\n" ); for( i = 0; i < len; i++ ) - string[i] = (unsigned char)( rand() % 255 ); + string[i] = (unsigned char)( rand() % 256 ); } diff --git a/code/qcommon/cvar.c b/code/qcommon/cvar.c index 53a36845..f07705db 100644 --- a/code/qcommon/cvar.c +++ b/code/qcommon/cvar.c @@ -438,6 +438,7 @@ cvar_t *Cvar_Get( const char *var_name, const char *var_value, int flags ) { var->integer = atoi(var->string); var->resetString = CopyString( var_value ); var->validate = qfalse; + var->description = NULL; // link the variable in var->next = cvar_vars; @@ -489,6 +490,10 @@ void Cvar_Print( cvar_t *v ) { if ( v->latchedString ) { Com_Printf( "latched: \"%s\"\n", v->latchedString ); } + + if ( v->description ) { + Com_Printf( "%s\n", v->description ); + } } /* @@ -1016,6 +1021,90 @@ void Cvar_List_f( void ) { Com_Printf ("%i cvar indexes\n", cvar_numIndexes); } +/* +============ +Cvar_ListModified_f +============ +*/ +void Cvar_ListModified_f( void ) { + cvar_t *var; + int totalModified; + char *value; + char *match; + + if ( Cmd_Argc() > 1 ) { + match = Cmd_Argv( 1 ); + } else { + match = NULL; + } + + totalModified = 0; + for (var = cvar_vars ; var ; var = var->next) + { + if ( !var->name || !var->modificationCount ) + continue; + + value = var->latchedString ? var->latchedString : var->string; + if ( !strcmp( value, var->resetString ) ) + continue; + + totalModified++; + + if (match && !Com_Filter(match, var->name, qfalse)) + continue; + + if (var->flags & CVAR_SERVERINFO) { + Com_Printf("S"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_SYSTEMINFO) { + Com_Printf("s"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_USERINFO) { + Com_Printf("U"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_ROM) { + Com_Printf("R"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_INIT) { + Com_Printf("I"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_ARCHIVE) { + Com_Printf("A"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_LATCH) { + Com_Printf("L"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_CHEAT) { + Com_Printf("C"); + } else { + Com_Printf(" "); + } + if (var->flags & CVAR_USER_CREATED) { + Com_Printf("?"); + } else { + Com_Printf(" "); + } + + Com_Printf (" %s \"%s\", default \"%s\"\n", var->name, value, var->resetString); + } + + Com_Printf ("\n%i total modified cvars\n", totalModified); +} + /* ============ Cvar_Unset @@ -1028,6 +1117,9 @@ cvar_t *Cvar_Unset(cvar_t *cv) { cvar_t *next = cv->next; + // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) + cvar_modifiedFlags |= cv->flags; + if(cv->name) Z_Free(cv->name); if(cv->string) @@ -1036,6 +1128,8 @@ cvar_t *Cvar_Unset(cvar_t *cv) Z_Free(cv->latchedString); if(cv->resetString) Z_Free(cv->resetString); + if(cv->description) + Z_Free(cv->description); if(cv->prev) cv->prev->next = cv->next; @@ -1205,6 +1299,23 @@ void Cvar_CheckRange( cvar_t *var, float min, float max, qboolean integral ) Cvar_Set( var->name, var->string ); } +/* +===================== +Cvar_SetDescription +===================== +*/ +void Cvar_SetDescription( cvar_t *var, const char *var_description ) +{ + if( var_description && var_description[0] != '\0' ) + { + if( var->description != NULL ) + { + Z_Free( var->description ); + } + var->description = CopyString( var_description ); + } +} + /* ===================== Cvar_Register @@ -1319,5 +1430,6 @@ void Cvar_Init (void) Cmd_SetCommandCompletionFunc("unset", Cvar_CompleteCvarName); Cmd_AddCommand ("cvarlist", Cvar_List_f); + Cmd_AddCommand ("cvar_modified", Cvar_ListModified_f); Cmd_AddCommand ("cvar_restart", Cvar_Restart_f); } diff --git a/code/qcommon/files.c b/code/qcommon/files.c index bffaa60f..5ca4e32c 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -250,6 +250,7 @@ static cvar_t *fs_homepath; // Also search the .app bundle for .pk3 files static cvar_t *fs_apppath; #endif +static cvar_t *fs_steampath; static cvar_t *fs_basepath; static cvar_t *fs_basegame; @@ -533,7 +534,9 @@ qboolean FS_CreatePath (char *OSPath) { // Skip creation of the root directory as it will always be there ofs = strchr( path, PATH_SEP ); - ofs++; + if ( ofs != NULL ) { + ofs++; + } for (; ofs != NULL && *ofs ; ofs++) { if (*ofs == PATH_SEP) { @@ -746,6 +749,21 @@ long FS_SV_FOpenFileRead(const char *filename, fileHandle_t *fp) fsh[f].handleSync = qfalse; } + // Check fs_steampath too + if (!fsh[f].handleFiles.file.o && fs_steampath->string[0]) + { + ospath = FS_BuildOSPath( fs_steampath->string, filename, "" ); + ospath[strlen(ospath)-1] = '\0'; + + if ( fs_debug->integer ) + { + Com_Printf( "FS_SV_FOpenFileRead (fs_steampath): %s\n", ospath ); + } + + fsh[f].handleFiles.file.o = Sys_FOpen( ospath, "rb" ); + fsh[f].handleSync = qfalse; + } + if ( !fsh[f].handleFiles.file.o ) { f = 0; @@ -2484,6 +2502,8 @@ int FS_GetModList( char *listbuf, int bufsize ) { int dummy; char **pFiles0 = NULL; char **pFiles1 = NULL; + char **pFiles2 = NULL; + char **pFiles3 = NULL; qboolean bDrop = qfalse; *listbuf = 0; @@ -2491,9 +2511,12 @@ int FS_GetModList( char *listbuf, int bufsize ) { pFiles0 = Sys_ListFiles( fs_homepath->string, NULL, NULL, &dummy, qtrue ); pFiles1 = Sys_ListFiles( fs_basepath->string, NULL, NULL, &dummy, qtrue ); + pFiles2 = Sys_ListFiles( fs_steampath->string, NULL, NULL, &dummy, qtrue ); // we searched for mods in the three paths // it is likely that we have duplicate names now, which we will cleanup below - pFiles = Sys_ConcatenateFileLists( pFiles0, pFiles1 ); + pFiles3 = Sys_ConcatenateFileLists( pFiles0, pFiles1 ); + pFiles = Sys_ConcatenateFileLists( pFiles2, pFiles3 ); + nPotential = Sys_CountFileList(pFiles); for ( i = 0 ; i < nPotential ; i++ ) { @@ -2535,6 +2558,15 @@ int FS_GetModList( char *listbuf, int bufsize ) { Sys_FreeFileList( pPaks ); } + /* try on steam path */ + if ( nPaks <= 0 ) + { + path = FS_BuildOSPath( fs_steampath->string, name, "" ); + nPaks = 0; + pPaks = Sys_ListFiles( path, ".pk3", NULL, &nPaks, qfalse ); + Sys_FreeFileList( pPaks ); + } + if (nPaks > 0) { nLen = strlen(name) + 1; // nLen is the length of the mod path @@ -2741,7 +2773,7 @@ void FS_Path_f( void ) { searchpath_t *s; int i; - Com_Printf ("Current search path:\n"); + Com_Printf ("We are looking in the current search path:\n"); for (s = fs_searchpaths; s; s = s->next) { if (s->pack) { Com_Printf ("%s (%i files)\n", s->pack->pakFilename, s->pack->numfiles); @@ -3278,6 +3310,10 @@ static void FS_Startup( const char *gameName ) fs_gamedirvar = Cvar_Get ("fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO ); // add search path elements in reverse priority order + fs_steampath = Cvar_Get ("fs_steampath", Sys_SteamPath(), CVAR_INIT|CVAR_PROTECTED ); + if (fs_steampath->string[0]) { + FS_AddGameDirectory( fs_steampath->string, gameName ); + } if (fs_basepath->string[0]) { FS_AddGameDirectory( fs_basepath->string, gameName ); } @@ -3298,6 +3334,9 @@ static void FS_Startup( const char *gameName ) // check for additional base game so mods can be based upon other mods if ( fs_basegame->string[0] && Q_stricmp( fs_basegame->string, gameName ) ) { + if (fs_steampath->string[0]) { + FS_AddGameDirectory(fs_steampath->string, fs_basegame->string); + } if (fs_basepath->string[0]) { FS_AddGameDirectory(fs_basepath->string, fs_basegame->string); } @@ -3308,6 +3347,9 @@ static void FS_Startup( const char *gameName ) // check for additional game folder for mods if ( fs_gamedirvar->string[0] && Q_stricmp( fs_gamedirvar->string, gameName ) ) { + if (fs_steampath->string[0]) { + FS_AddGameDirectory(fs_steampath->string, fs_gamedirvar->string); + } if (fs_basepath->string[0]) { FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string); } diff --git a/code/qcommon/md4.c b/code/qcommon/md4.c index b37c87b4..0eb23a50 100644 --- a/code/qcommon/md4.c +++ b/code/qcommon/md4.c @@ -177,12 +177,10 @@ static void mdfour_update(struct mdfour *md, byte *in, int n) static void mdfour_result(struct mdfour *md, byte *out) { - m = md; - - copy4(out, m->A); - copy4(out+4, m->B); - copy4(out+8, m->C); - copy4(out+12, m->D); + copy4(out, md->A); + copy4(out+4, md->B); + copy4(out+8, md->C); + copy4(out+12, md->D); } static void mdfour(byte *out, byte *in, int n) diff --git a/code/qcommon/msg.c b/code/qcommon/msg.c index 5623b9bb..397c603e 100644 --- a/code/qcommon/msg.c +++ b/code/qcommon/msg.c @@ -246,7 +246,7 @@ int MSG_ReadBits( msg_t *msg, int bits ) { } msg->readcount = (msg->bit>>3)+1; } - if ( sgn ) { + if ( sgn && bits > 0 && bits < 32 ) { if ( value & ( 1 << ( bits - 1 ) ) ) { value |= -1 ^ ( ( 1 << bits ) - 1 ); } diff --git a/code/qcommon/net_ip.c b/code/qcommon/net_ip.c index 4ef3e345..98555b99 100644 --- a/code/qcommon/net_ip.c +++ b/code/qcommon/net_ip.c @@ -1619,7 +1619,7 @@ Called from NET_Sleep which uses select() to determine which sockets have seen a void NET_Event(fd_set *fdr) { byte bufData[MAX_MSGLEN + 1]; - netadr_t from; + netadr_t from = {0}; msg_t netmsg; while(1) diff --git a/code/qcommon/q_platform.h b/code/qcommon/q_platform.h index 999dd39a..3ed5357f 100644 --- a/code/qcommon/q_platform.h +++ b/code/qcommon/q_platform.h @@ -169,50 +169,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //================================================================= LINUX === -#if defined(__linux__) || defined(__FreeBSD_kernel__) +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__GNU__) #include #if defined(__linux__) #define OS_STRING "linux" -#else +#elif defined(__FreeBSD_kernel__) #define OS_STRING "kFreeBSD" +#else +#define OS_STRING "GNU" #endif #define ID_INLINE inline #define PATH_SEP '/' -#if defined __i386__ -#define ARCH_STRING "x86" -#elif defined __x86_64__ +#if !defined(ARCH_STRING) +# error ARCH_STRING should be defined by the Makefile +#endif + +#if defined __x86_64__ #undef idx64 #define idx64 1 -#define ARCH_STRING "x86_64" -#elif defined __powerpc64__ -#define ARCH_STRING "ppc64" -#elif defined __powerpc__ -#define ARCH_STRING "ppc" -#elif defined __s390__ -#define ARCH_STRING "s390" -#elif defined __s390x__ -#define ARCH_STRING "s390x" -#elif defined __ia64__ -#define ARCH_STRING "ia64" -#elif defined __alpha__ -#define ARCH_STRING "alpha" -#elif defined __sparc__ -#define ARCH_STRING "sparc" -#elif defined __arm__ -#define ARCH_STRING "arm" -#elif defined __cris__ -#define ARCH_STRING "cris" -#elif defined __hppa__ -#define ARCH_STRING "hppa" -#elif defined __mips__ -#define ARCH_STRING "mips" -#elif defined __sh__ -#define ARCH_STRING "sh" #endif #if __FLOAT_WORD_ORDER == __BIG_ENDIAN diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index 690838cc..820c862c 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -600,6 +600,10 @@ void SkipRestOfLine ( char **data ) { int c; p = *data; + + if ( !*p ) + return; + while ( (c = *p++) != 0 ) { if ( c == '\n' ) { com_lines++; @@ -1252,7 +1256,7 @@ void Info_RemoveKey_Big( char *s, const char *key ) { if (!strcmp (key, pkey) ) { - strcpy (start, s); // remove this part + memmove(start, s, strlen(s) + 1); // remove this part return; } diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index f3375d7e..2f74ef6d 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -27,23 +27,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // A user mod should never modify this file #ifdef STANDALONE - #define PRODUCT_NAME "Reaction" - #define BASEGAME "Boomstick" - #define CLIENT_WINDOW_TITLE "Reaction" - #define CLIENT_WINDOW_MIN_TITLE "Reaction" + #define PRODUCT_NAME "Reaction" + #define BASEGAME "Boomstick" + #define CLIENT_WINDOW_TITLE "Reaction" + #define CLIENT_WINDOW_MIN_TITLE "Reaction" #define HOMEPATH_NAME_UNIX ".Reaction" - #define HOMEPATH_NAME_WIN "Reaction" + #define HOMEPATH_NAME_WIN "Reaction" #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN +// #define STEAMPATH_NAME "Foo Bar" +// #define STEAMPATH_APPID "" #define GAMENAME_FOR_MASTER "Reaction" // #define LEGACY_PROTOCOL // You probably don't need this for your standalone game #else - #define PRODUCT_NAME "Reaction" - #define BASEGAME "Boomstick" - #define CLIENT_WINDOW_TITLE "Reaction" - #define CLIENT_WINDOW_MIN_TITLE "Reaction" + #define PRODUCT_NAME "Reaction" + #define BASEGAME "Boomstick" + #define CLIENT_WINDOW_TITLE "Reaction" + #define CLIENT_WINDOW_MIN_TITLE "Reaction" #define HOMEPATH_NAME_UNIX ".Reaction" - #define HOMEPATH_NAME_WIN "Reaction" + #define HOMEPATH_NAME_WIN "Reaction" #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN +// #define STEAMPATH_NAME "Foo Bar" +// #define STEAMPATH_APPID "" #define GAMENAME_FOR_MASTER "Reaction" // #define LEGACY_PROTOCOL #endif @@ -410,8 +414,8 @@ extern vec4_t colorDkGrey; #define COLOR_CYAN '5' #define COLOR_MAGENTA '6' #define COLOR_WHITE '7' -//#define ColorIndex(c) (((c) - '0') & 0x07) -#define ColorIndex(c) ( ( (c) - '0' ) & 7 ) +#define ColorIndexForNumber(c) ((c) & 0x07) +#define ColorIndex(c) (ColorIndexForNumber((c) - '0')) //Makro - reset color #define S_COLOR_RESET "^*" @@ -952,6 +956,7 @@ struct cvar_s { qboolean integral; float min; float max; + char *description; cvar_t *next; cvar_t *prev; diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index 244fc062..017ac47f 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -562,6 +562,7 @@ char *Cvar_InfoString_Big( int bit ); // in their flags ( CVAR_USERINFO, CVAR_SERVERINFO, CVAR_SYSTEMINFO, etc ) void Cvar_InfoStringBuffer( int bit, char *buff, int buffsize ); void Cvar_CheckRange( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ); +void Cvar_SetDescription( cvar_t *var, const char *var_description ); void Cvar_Restart(qboolean unsetVM); void Cvar_Restart_f( void ); @@ -1098,6 +1099,7 @@ FILE *Sys_Mkfifo( const char *ospath ); char *Sys_Cwd( void ); void Sys_SetDefaultInstallPath(const char *path); char *Sys_DefaultInstallPath(void); +char *Sys_SteamPath(void); #ifdef MACOS_X char *Sys_DefaultAppPath(void); diff --git a/code/qcommon/unzip.c b/code/qcommon/unzip.c index 4fb2d3a9..b5043c19 100644 --- a/code/qcommon/unzip.c +++ b/code/qcommon/unzip.c @@ -1,4 +1,10 @@ /* unzip.c -- IO for uncompress .zip files using zlib + + Modified for Quake III Arena to use the Z_Malloc() memory pool; + this means a system copy of minizip is not a suitable replacement. + + Based on minizip: + Version 1.01e, February 12th, 2005 Copyright (C) 1998-2005 Gilles Vollant diff --git a/code/qcommon/vm_x86.c b/code/qcommon/vm_x86.c index b896883d..9ee26799 100644 --- a/code/qcommon/vm_x86.c +++ b/code/qcommon/vm_x86.c @@ -203,19 +203,25 @@ static void EmitRexString(byte rex, const char *string) #define MASK_REG(modrm, mask) \ - EmitString("81"); \ - EmitString((modrm)); \ - Emit4((mask)) + do { \ + EmitString("81"); \ + EmitString((modrm)); \ + Emit4((mask)); \ + } while(0) // add bl, bytes #define STACK_PUSH(bytes) \ - EmitString("80 C3"); \ - Emit1(bytes) + do { \ + EmitString("80 C3"); \ + Emit1(bytes); \ + } while(0) // sub bl, bytes #define STACK_POP(bytes) \ - EmitString("80 EB"); \ - Emit1(bytes) + do { \ + EmitString("80 EB"); \ + Emit1(bytes); \ + } while(0) static void EmitCommand(ELastCommand command) { @@ -412,23 +418,24 @@ static void DoSyscall(void) if(vm_syscallNum < 0) { - int *data; + int *data, *ret; #if idx64 int index; intptr_t args[MAX_VMSYSCALL_ARGS]; #endif data = (int *) (savedVM->dataBase + vm_programStack + 4); + ret = &vm_opStackBase[vm_opStackOfs + 1]; #if idx64 args[0] = ~vm_syscallNum; for(index = 1; index < ARRAY_LEN(args); index++) args[index] = data[index]; - vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall(args); + *ret = savedVM->systemCall(args); #else data[0] = ~vm_syscallNum; - vm_opStackBase[vm_opStackOfs + 1] = savedVM->systemCall((intptr_t *) data); + *ret = savedVM->systemCall((intptr_t *) data); #endif } else @@ -1087,8 +1094,9 @@ void VM_Compile(vm_t *vm, vmHeader_t *header) // ensure that the optimisation pass knows about all the jump // table targets + pc = -1; // a bogus value to be printed in out-of-bounds error messages for( i = 0; i < vm->numJumpTableTargets; i++ ) { - jused[ *(int *)(vm->jumpTableTargets + ( i * sizeof( int ) ) ) ] = 1; + JUSED( *(int *)(vm->jumpTableTargets + ( i * sizeof( int ) ) ) ); } // Start buffer with x86-VM specific procedures diff --git a/code/renderercommon/qgl.h b/code/renderercommon/qgl.h index 02045a49..252e0bb2 100644 --- a/code/renderercommon/qgl.h +++ b/code/renderercommon/qgl.h @@ -381,8 +381,8 @@ extern void (APIENTRYP qglUnlockArraysEXT) (void); extern void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); // GL_EXT_multi_draw_arrays -extern void (APIENTRY * qglMultiDrawArraysEXT) (GLenum, GLint *, GLsizei *, GLsizei); -extern void (APIENTRY * qglMultiDrawElementsEXT) (GLenum, const GLsizei *, GLenum, const GLvoid **, GLsizei); +extern void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +extern void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); // GL_ARB_shading_language_100 #ifndef GL_ARB_shading_language_100 @@ -726,6 +726,17 @@ extern void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs); #define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F #endif +// GL_ARB_vertex_array_object +extern void (APIENTRY * qglBindVertexArrayARB)(GLuint array); +extern void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays); +extern void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays); +extern GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array); +#ifndef GL_ARB_vertex_array_object +#define GL_ARB_vertex_array_object +#define GL_VERTEX_ARRAY_BINDING_ARB 0x85B5 +#endif + + #if defined(WIN32) // WGL_ARB_create_context #ifndef WGL_ARB_create_context diff --git a/code/renderercommon/tr_common.h b/code/renderercommon/tr_common.h index 31de1a8f..59184978 100644 --- a/code/renderercommon/tr_common.h +++ b/code/renderercommon/tr_common.h @@ -134,6 +134,20 @@ void R_InitFreeType( void ); void R_DoneFreeType( void ); void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font); +/* +============================================================= + +IMAGE LOADERS + +============================================================= +*/ + +void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); +void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); +void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); +void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); +void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); + /* ==================================================================== diff --git a/code/renderercommon/tr_font.c b/code/renderercommon/tr_font.c index 4b641bac..0f89d5ad 100644 --- a/code/renderercommon/tr_font.c +++ b/code/renderercommon/tr_font.c @@ -397,7 +397,7 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { // Com_Memcpy(font, faceData, sizeof(fontInfo_t)); Q_strncpyz(font->name, name, sizeof(font->name)); - for (i = GLYPH_START; i < GLYPH_END; i++) { + for (i = GLYPH_START; i <= GLYPH_END; i++) { font->glyphs[i].glyph = RE_RegisterShaderNoMip(font->glyphs[i].shaderName); } Com_Memcpy(®isteredFont[registeredFontCount++], font, sizeof(fontInfo_t)); @@ -445,7 +445,7 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { maxHeight = 0; - for (i = GLYPH_START; i < GLYPH_END; i++) { + for (i = GLYPH_START; i <= GLYPH_END; i++) { RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qtrue); } @@ -455,11 +455,16 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { lastStart = i; imageNumber = 0; - while ( i <= GLYPH_END ) { + while ( i <= GLYPH_END + 1 ) { - glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse); + if ( i == GLYPH_END + 1 ) { + // upload/save current image buffer + xOut = yOut = -1; + } else { + glyph = RE_ConstructGlyphInfo(out, &xOut, &yOut, &maxHeight, face, (unsigned char)i, qfalse); + } - if (xOut == -1 || yOut == -1 || i == GLYPH_END) { + if (xOut == -1 || yOut == -1) { // ran out of room // we need to create an image from the bitmap, set all the handles in the glyphs to this point // @@ -504,7 +509,7 @@ void RE_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) { xOut = 0; yOut = 0; ri.Free(imageBuff); - if(i == GLYPH_END) + if ( i == GLYPH_END + 1 ) i++; } else { Com_Memcpy(&font->glyphs[i], glyph, sizeof(glyphInfo_t)); diff --git a/code/renderercommon/tr_public.h b/code/renderercommon/tr_public.h index b93bbdbb..38d647f6 100644 --- a/code/renderercommon/tr_public.h +++ b/code/renderercommon/tr_public.h @@ -133,6 +133,7 @@ typedef struct { void (*Cvar_Set)( const char *name, const char *value ); void (*Cvar_SetValue) (const char *name, float value); void (*Cvar_CheckRange)( cvar_t *cv, float minVal, float maxVal, qboolean shouldBeIntegral ); + void (*Cvar_SetDescription)( cvar_t *cv, const char *description ); int (*Cvar_VariableIntegerValue) (const char *var_name); diff --git a/code/renderergl1/tr_animation.c b/code/renderergl1/tr_animation.c index 7bcc5bdf..b01cf813 100644 --- a/code/renderergl1/tr_animation.c +++ b/code/renderergl1/tr_animation.c @@ -346,7 +346,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface ) oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames + backEnd.currentEntity->e.oldframe * frameSize ); - RB_CheckOverflow( surface->numVerts, surface->numTriangles ); + RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles * 3 ); triangles = (int *) ((byte *)surface + surface->ofsTriangles); indexes = surface->numTriangles * 3; diff --git a/code/renderergl1/tr_backend.c b/code/renderergl1/tr_backend.c index 0a3fe036..a1122456 100644 --- a/code/renderergl1/tr_backend.c +++ b/code/renderergl1/tr_backend.c @@ -474,7 +474,7 @@ void RB_BeginDrawingView (void) { // clip to the plane of the portal if ( backEnd.viewParms.isPortal ) { float plane[4]; - double plane2[4]; + GLdouble plane2[4]; plane[0] = backEnd.viewParms.portalPlane.normal[0]; plane[1] = backEnd.viewParms.portalPlane.normal[1]; @@ -710,7 +710,7 @@ void RB_SetGL2D (void) { GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - qglDisable( GL_CULL_FACE ); + GL_Cull( CT_TWO_SIDED ); qglDisable( GL_CLIP_PLANE0 ); // set time for 2D shaders diff --git a/code/renderergl1/tr_bsp.c b/code/renderergl1/tr_bsp.c index 64f6a565..1e660f28 100644 --- a/code/renderergl1/tr_bsp.c +++ b/code/renderergl1/tr_bsp.c @@ -927,7 +927,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { for (m = 0; m < 2; m++) { - if ( grid2->width >= MAX_GRID_SIZE ) + if ( !grid2 || grid2->width >= MAX_GRID_SIZE ) break; if (m) offset2 = (grid2->height-1) * grid2->width; else offset2 = 0; @@ -971,7 +971,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { } for (m = 0; m < 2; m++) { - if (grid2->height >= MAX_GRID_SIZE) + if (!grid2 || grid2->height >= MAX_GRID_SIZE) break; if (m) offset2 = grid2->width-1; else offset2 = 0; @@ -1026,7 +1026,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { for (k = grid1->height-1; k > 1; k -= 2) { for (m = 0; m < 2; m++) { - if ( grid2->width >= MAX_GRID_SIZE ) + if ( !grid2 || grid2->width >= MAX_GRID_SIZE ) break; if (m) offset2 = (grid2->height-1) * grid2->width; else offset2 = 0; @@ -1070,7 +1070,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { } for (m = 0; m < 2; m++) { - if (grid2->height >= MAX_GRID_SIZE) + if (!grid2 || grid2->height >= MAX_GRID_SIZE) break; if (m) offset2 = grid2->width-1; else offset2 = 0; diff --git a/code/renderergl1/tr_image.c b/code/renderergl1/tr_image.c index dc7860ea..7905842b 100644 --- a/code/renderergl1/tr_image.c +++ b/code/renderergl1/tr_image.c @@ -899,7 +899,6 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode ); - // FIXME: this stops fog from setting border color? glState.currenttextures[glState.currenttmu] = 0; qglBindTexture( GL_TEXTURE_2D, 0 ); @@ -1168,7 +1167,6 @@ static void R_CreateFogImage( void ) { int x,y; byte *data; float d; - float borderColor[4]; data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 ); @@ -1183,18 +1181,8 @@ static void R_CreateFogImage( void ) { data[(y*FOG_S+x)*4+3] = 255*d; } } - // standard openGL clamping doesn't really do what we want -- it includes - // the border color at the edges. OpenGL 1.2 has clamp-to-edge, which does - // what we want. tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 ); ri.Hunk_FreeTempMemory( data ); - - borderColor[0] = 1.0; - borderColor[1] = 1.0; - borderColor[2] = 1.0; - borderColor[3] = 1; - - qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor ); } /* @@ -1443,12 +1431,15 @@ static char *CommaParse( char **data_p ) { // skip double slash comments if ( c == '/' && data[1] == '/' ) { - while (*data && *data != '\n') + data += 2; + while (*data && *data != '\n') { data++; + } } // skip /* */ comments else if ( c=='/' && data[1] == '*' ) { + data += 2; while ( *data && ( *data != '*' || data[1] != '/' ) ) { data++; @@ -1481,7 +1472,7 @@ static char *CommaParse( char **data_p ) { *data_p = ( char * ) data; return com_token; } - if (len < MAX_TOKEN_CHARS) + if (len < MAX_TOKEN_CHARS - 1) { com_token[len] = c; len++; @@ -1492,7 +1483,7 @@ static char *CommaParse( char **data_p ) { // parse a regular word do { - if (len < MAX_TOKEN_CHARS) + if (len < MAX_TOKEN_CHARS - 1) { com_token[len] = c; len++; @@ -1501,11 +1492,6 @@ static char *CommaParse( char **data_p ) { c = *data; } while (c>32 && c != ',' ); - if (len == MAX_TOKEN_CHARS) - { -// ri.Printf (PRINT_DEVELOPER, "Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS); - len = 0; - } com_token[len] = 0; *data_p = ( char * ) data; @@ -1569,7 +1555,7 @@ qhandle_t RE_RegisterSkin( const char *name ) { // If not a .skin file, load as a single shader if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue ); return hSkin; } @@ -1640,7 +1626,7 @@ void R_InitSkins( void ) { skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } diff --git a/code/renderergl1/tr_light.c b/code/renderergl1/tr_light.c index fc6af6a9..80b55f5a 100644 --- a/code/renderergl1/tr_light.c +++ b/code/renderergl1/tr_light.c @@ -151,7 +151,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { frac[i] = v - pos[i]; if ( pos[i] < 0 ) { pos[i] = 0; - } else if ( pos[i] >= tr.world->lightGridBounds[i] - 1 ) { + } else if ( pos[i] > tr.world->lightGridBounds[i] - 1 ) { pos[i] = tr.world->lightGridBounds[i] - 1; } } @@ -182,6 +182,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { data = gridData; for ( j = 0 ; j < 3 ; j++ ) { if ( i & (1< tr.world->lightGridBounds[j] - 1 ) { + break; // ignore values outside lightgrid + } factor *= frac[j]; data += gridStep[j]; } else { @@ -189,6 +192,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { } } + if ( j != 3 ) { + continue; + } if ( !(data[0]+data[1]+data[2]) ) { continue; // ignore samples in walls } diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h index c0c62f03..aedf1a4f 100644 --- a/code/renderergl1/tr_local.h +++ b/code/renderergl1/tr_local.h @@ -477,7 +477,6 @@ typedef enum { SF_IQM, SF_FLARE, SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity - SF_DISPLAY_LIST, SF_NUM_SURFACE_TYPES, SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int ) @@ -503,11 +502,6 @@ typedef struct srfPoly_s { polyVert_t *verts; } srfPoly_t; -typedef struct srfDisplayList_s { - surfaceType_t surfaceType; - int listNum; -} srfDisplayList_t; - typedef struct srfFlare_s { surfaceType_t surfaceType; @@ -1397,20 +1391,6 @@ int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, int startFrame, int endFrame, float frac, const char *tagName ); -/* -============================================================= - -IMAGE LOADERS - -============================================================= -*/ - -void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); -void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); -void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); -void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); -void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); - /* ============================================================= ============================================================= diff --git a/code/renderergl1/tr_main.c b/code/renderergl1/tr_main.c index 6a2118f1..e33eb952 100644 --- a/code/renderergl1/tr_main.c +++ b/code/renderergl1/tr_main.c @@ -1011,6 +1011,10 @@ int R_SpriteFogNum( trRefEntity_t *ent ) { return 0; } + if ( ent->e.renderfx & RF_CROSSHAIR ) { + return 0; + } + for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { diff --git a/code/renderergl1/tr_model_iqm.c b/code/renderergl1/tr_model_iqm.c index 0f99f160..6c47ed07 100644 --- a/code/renderergl1/tr_model_iqm.c +++ b/code/renderergl1/tr_model_iqm.c @@ -144,7 +144,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na unsigned short *framedata; char *str; int i, j; - float jointInvMats[IQM_MAX_JOINTS * 12]; + float jointInvMats[IQM_MAX_JOINTS * 12] = {0.0f}; float *mat, *matInv; size_t size, joint_names; iqmData_t *iqmData; diff --git a/code/renderergl1/tr_shade.c b/code/renderergl1/tr_shade.c index 08648b2e..9bdf1e39 100644 --- a/code/renderergl1/tr_shade.c +++ b/code/renderergl1/tr_shade.c @@ -421,7 +421,7 @@ static void ProjectDlightTexture_altivec( void ) { byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; - unsigned hitIndexes[SHADER_MAX_INDEXES]; + glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; @@ -593,7 +593,7 @@ static void ProjectDlightTexture_scalar( void ) { byte clipBits[SHADER_MAX_VERTEXES]; float texCoordsArray[SHADER_MAX_VERTEXES][2]; byte colorArray[SHADER_MAX_VERTEXES][4]; - unsigned hitIndexes[SHADER_MAX_INDEXES]; + glIndex_t hitIndexes[SHADER_MAX_INDEXES]; int numIndexes; float scale; float radius; diff --git a/code/renderergl1/tr_shade_calc.c b/code/renderergl1/tr_shade_calc.c index e8f43e4f..ae33c7fb 100644 --- a/code/renderergl1/tr_shade_calc.c +++ b/code/renderergl1/tr_shade_calc.c @@ -771,7 +771,7 @@ void RB_CalcModulateAlphasByFog( unsigned char *colors ) { */ void RB_CalcModulateRGBAsByFog( unsigned char *colors ) { int i; - float texCoords[SHADER_MAX_VERTEXES][2]; + float texCoords[SHADER_MAX_VERTEXES][2] = {{0.0f}}; // calculate texcoords so we can derive density // this is not wasted, because it would only have diff --git a/code/renderergl1/tr_shader.c b/code/renderergl1/tr_shader.c index de3a45c4..c931326f 100644 --- a/code/renderergl1/tr_shader.c +++ b/code/renderergl1/tr_shader.c @@ -847,6 +847,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) { vec3_t color; + VectorClear( color ); + ParseVector( text, 3, color ); stage->constantColor[0] = 255 * color[0]; stage->constantColor[1] = 255 * color[1]; @@ -1010,8 +1012,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) token = COM_ParseExt( text, qfalse ); if ( token[0] == 0 ) break; - strcat( buffer, token ); - strcat( buffer, " " ); + Q_strcat( buffer, sizeof (buffer), token ); + Q_strcat( buffer, sizeof (buffer), " " ); } ParseTexMod( buffer, stage ); @@ -1457,7 +1459,7 @@ static qboolean ParseShader( char **text ) else if ( token[0] == '{' ) { if ( s >= MAX_SHADER_STAGES ) { - ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name ); + ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s (max is %i)\n", shader.name, MAX_SHADER_STAGES ); return qfalse; } @@ -1566,6 +1568,23 @@ static qboolean ParseShader( char **text ) return qfalse; } + if ( r_greyscale->integer ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + VectorSet( shader.fogParms.color, luminance, luminance, luminance ); + } + else if ( r_greyscale->value ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + shader.fogParms.color[0] = LERP( shader.fogParms.color[0], luminance, r_greyscale->value ); + shader.fogParms.color[1] = LERP( shader.fogParms.color[1], luminance, r_greyscale->value ); + shader.fogParms.color[2] = LERP( shader.fogParms.color[2], luminance, r_greyscale->value ); + } + token = COM_ParseExt( text, qfalse ); if ( !token[0] ) { @@ -2143,6 +2162,26 @@ static void VertexLightingCollapse( void ) { } } +/* +=============== +InitShader +=============== +*/ +static void InitShader( const char *name, int lightmapIndex ) { + int i; + + // clear the global shader + Com_Memset( &shader, 0, sizeof( shader ) ); + Com_Memset( &stages, 0, sizeof( stages ) ); + + Q_strncpyz( shader.name, name, sizeof( shader.name ) ); + shader.lightmapIndex = lightmapIndex; + + for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { + stages[i].bundle[0].texMods = texMods[i]; + } +} + /* ========================= FinishShader @@ -2462,7 +2501,7 @@ most world construction surfaces. */ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) { char strippedName[MAX_QPATH]; - int i, hash; + int hash; char *shaderText; image_t *image; shader_t *sh; @@ -2500,14 +2539,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag } } - // clear the global shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - Q_strncpyz(shader.name, strippedName, sizeof(shader.name)); - shader.lightmapIndex = lightmapIndex; - for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { - stages[i].bundle[0].texMods = texMods[i]; - } + InitShader( strippedName, lightmapIndex ); // FIXME: set these "need" values apropriately shader.needsNormal = qtrue; @@ -2617,7 +2649,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) { - int i, hash; + int hash; shader_t *sh; hash = generateHashValue(name, FILE_HASH_SIZE); @@ -2645,14 +2677,7 @@ qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_ } } - // clear the global shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - Q_strncpyz(shader.name, name, sizeof(shader.name)); - shader.lightmapIndex = lightmapIndex; - for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { - stages[i].bundle[0].texMods = texMods[i]; - } + InitShader( name, lightmapIndex ); // FIXME: set these "need" values apropriately shader.needsNormal = qtrue; @@ -2913,7 +2938,7 @@ a single large text block that can be scanned for shader names static void ScanAndLoadShaderFiles( void ) { char **shaderFiles; - char *buffers[MAX_SHADER_FILES]; + char *buffers[MAX_SHADER_FILES] = {0}; char *p; int numShaderFiles; int i; @@ -3070,12 +3095,7 @@ static void CreateInternalShaders( void ) { tr.numShaders = 0; // init the default shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - - Q_strncpyz( shader.name, "", sizeof( shader.name ) ); - - shader.lightmapIndex = LIGHTMAP_NONE; + InitShader( "", LIGHTMAP_NONE ); stages[0].bundle[0].image[0] = tr.defaultImage; stages[0].active = qtrue; stages[0].stateBits = GLS_DEFAULT; diff --git a/code/renderergl1/tr_shadows.c b/code/renderergl1/tr_shadows.c index f412b00d..13fbfdf7 100644 --- a/code/renderergl1/tr_shadows.c +++ b/code/renderergl1/tr_shadows.c @@ -44,6 +44,7 @@ typedef struct { static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS]; static int numEdgeDefs[SHADER_MAX_VERTEXES]; static int facing[SHADER_MAX_INDEXES/3]; +static vec3_t shadowXyz[SHADER_MAX_VERTEXES]; void R_AddEdgeDef( int i1, int i2, int facing ) { int c; @@ -80,13 +81,13 @@ void R_RenderShadowEdges( void ) { qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i1 ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i2 ] ); qglVertex3fv( tess.xyz[ i3 ] ); - qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i3 ] ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i1 ] ); qglEnd(); } #else @@ -126,9 +127,9 @@ void R_RenderShadowEdges( void ) { if ( hit[ 1 ] == 0 ) { qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i ] ); - qglVertex3fv( tess.xyz[ i + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i2 ] ); qglEnd(); c_edges++; } else { @@ -157,11 +158,6 @@ void RB_ShadowTessEnd( void ) { vec3_t lightDir; GLboolean rgba[4]; - // we can only do this if we have enough space in the vertex buffers - if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) { - return; - } - if ( glConfig.stencilBits < 4 ) { return; } @@ -170,7 +166,7 @@ void RB_ShadowTessEnd( void ) { // project vertexes away from light direction for ( i = 0 ; i < tess.numVertexes ; i++ ) { - VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] ); + VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] ); } // decide which triangles face the light @@ -211,7 +207,6 @@ void RB_ShadowTessEnd( void ) { // draw the silhouette edges GL_Bind( tr.whiteImage ); - qglEnable( GL_CULL_FACE ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor3f( 0.2f, 0.2f, 0.2f ); @@ -222,28 +217,15 @@ void RB_ShadowTessEnd( void ) { qglEnable( GL_STENCIL_TEST ); qglStencilFunc( GL_ALWAYS, 1, 255 ); - // mirrors have the culling order reversed - if ( backEnd.viewParms.isMirror ) { - qglCullFace( GL_FRONT ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); + GL_Cull( CT_BACK_SIDED ); + qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - R_RenderShadowEdges(); + R_RenderShadowEdges(); - qglCullFace( GL_BACK ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); + GL_Cull( CT_FRONT_SIDED ); + qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - R_RenderShadowEdges(); - } else { - qglCullFace( GL_BACK ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - - R_RenderShadowEdges(); - - qglCullFace( GL_FRONT ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - - R_RenderShadowEdges(); - } + R_RenderShadowEdges(); // reenable writing to the color buffer @@ -272,7 +254,7 @@ void RB_ShadowFinish( void ) { qglStencilFunc( GL_NOTEQUAL, 0, 255 ); qglDisable (GL_CLIP_PLANE0); - qglDisable (GL_CULL_FACE); + GL_Cull( CT_TWO_SIDED ); GL_Bind( tr.whiteImage ); diff --git a/code/renderergl1/tr_surface.c b/code/renderergl1/tr_surface.c index 1879fe2c..79852f05 100644 --- a/code/renderergl1/tr_surface.c +++ b/code/renderergl1/tr_surface.c @@ -907,7 +907,8 @@ RB_SurfaceFace */ static void RB_SurfaceFace( srfSurfaceFace_t *surf ) { int i; - unsigned *indices, *tessIndexes; + unsigned *indices; + glIndex_t *tessIndexes; float *v; float *normal; int ndx; @@ -1217,12 +1218,6 @@ static void RB_SurfaceFlare(srfFlare_t *surf) RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); } -static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { - // all apropriate state must be set in RB_BeginSurface - // this isn't implemented yet... - qglCallList( surf->listNum ); -} - static void RB_SurfaceSkip( void *surf ) { } @@ -1238,6 +1233,5 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = { (void(*)(void*))RB_MDRSurfaceAnim, // SF_MDR, (void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM, (void(*)(void*))RB_SurfaceFlare, // SF_FLARE, - (void(*)(void*))RB_SurfaceEntity, // SF_ENTITY - (void(*)(void*))RB_SurfaceDisplayList // SF_DISPLAY_LIST + (void(*)(void*))RB_SurfaceEntity // SF_ENTITY }; diff --git a/code/renderergl2/glsl/dlight_vp.glsl b/code/renderergl2/glsl/dlight_vp.glsl index 9566a04c..c326bd78 100644 --- a/code/renderergl2/glsl/dlight_vp.glsl +++ b/code/renderergl2/glsl/dlight_vp.glsl @@ -74,7 +74,7 @@ vec3 DeformPosition(const vec3 pos, const vec3 normal, const vec2 st) void main() { vec3 position = attr_Position; - vec3 normal = attr_Normal * 2.0 - vec3(1.0); + vec3 normal = attr_Normal; #if defined(USE_DEFORM_VERTEXES) position = DeformPosition(position, normal, attr_TexCoord0.st); diff --git a/code/renderergl2/glsl/fogpass_vp.glsl b/code/renderergl2/glsl/fogpass_vp.glsl index 8f7bc728..c8ec9a93 100644 --- a/code/renderergl2/glsl/fogpass_vp.glsl +++ b/code/renderergl2/glsl/fogpass_vp.glsl @@ -102,10 +102,9 @@ void main() #if defined(USE_VERTEX_ANIMATION) vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp); vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp); - normal = normalize(normal - vec3(0.5)); #else vec3 position = attr_Position; - vec3 normal = attr_Normal * 2.0 - vec3(1.0); + vec3 normal = attr_Normal; #endif #if defined(USE_DEFORM_VERTEXES) diff --git a/code/renderergl2/glsl/generic_fp.glsl b/code/renderergl2/glsl/generic_fp.glsl index aefa33c3..50db0785 100644 --- a/code/renderergl2/glsl/generic_fp.glsl +++ b/code/renderergl2/glsl/generic_fp.glsl @@ -1,45 +1,12 @@ uniform sampler2D u_DiffuseMap; -#if defined(USE_LIGHTMAP) -uniform sampler2D u_LightMap; - -uniform int u_Texture1Env; -#endif - varying vec2 var_DiffuseTex; -#if defined(USE_LIGHTMAP) -varying vec2 var_LightTex; -#endif - varying vec4 var_Color; void main() { vec4 color = texture2D(u_DiffuseMap, var_DiffuseTex); -#if defined(USE_LIGHTMAP) - vec4 color2 = texture2D(u_LightMap, var_LightTex); - #if defined(RGBM_LIGHTMAP) - color2.rgb *= color2.a; - color2.a = 1.0; - #endif - - if (u_Texture1Env == TEXENV_MODULATE) - { - color *= color2; - } - else if (u_Texture1Env == TEXENV_ADD) - { - color += color2; - } - else if (u_Texture1Env == TEXENV_REPLACE) - { - color = color2; - } - - //color = color * (u_Texture1Env.xxxx + color2 * u_Texture1Env.z) + color2 * u_Texture1Env.y; -#endif - gl_FragColor = color * var_Color; } diff --git a/code/renderergl2/glsl/generic_vp.glsl b/code/renderergl2/glsl/generic_vp.glsl index 0e5b38b4..bbe08e84 100644 --- a/code/renderergl2/glsl/generic_vp.glsl +++ b/code/renderergl2/glsl/generic_vp.glsl @@ -9,7 +9,7 @@ attribute vec3 attr_Normal2; attribute vec4 attr_Color; attribute vec4 attr_TexCoord0; -#if defined(USE_LIGHTMAP) || defined(USE_TCGEN) +#if defined(USE_TCGEN) attribute vec4 attr_TexCoord1; #endif @@ -57,9 +57,6 @@ uniform float u_VertexLerp; #endif varying vec2 var_DiffuseTex; -#if defined(USE_LIGHTMAP) -varying vec2 var_LightTex; -#endif varying vec4 var_Color; #if defined(USE_DEFORM_VERTEXES) @@ -193,7 +190,7 @@ float CalcFog(vec3 position) float t = dot(vec4(position, 1.0), u_FogDepth); float eyeOutside = float(u_FogEyeT < 0.0); - float fogged = float(t < eyeOutside); + float fogged = float(t >= eyeOutside); t += 1e-6; t *= fogged / (t - u_FogEyeT * eyeOutside); @@ -207,10 +204,9 @@ void main() #if defined(USE_VERTEX_ANIMATION) vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp); vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp); - normal = normalize(normal - vec3(0.5)); #else vec3 position = attr_Position; - vec3 normal = attr_Normal * 2.0 - vec3(1.0); + vec3 normal = attr_Normal; #endif #if defined(USE_DEFORM_VERTEXES) @@ -231,10 +227,6 @@ void main() var_DiffuseTex = tex; #endif -#if defined(USE_LIGHTMAP) - var_LightTex = attr_TexCoord1.st; -#endif - #if defined(USE_RGBAGEN) var_Color = CalcColor(position, normal); #else diff --git a/code/renderergl2/glsl/lightall_fp.glsl b/code/renderergl2/glsl/lightall_fp.glsl index 7c62d664..d1182781 100644 --- a/code/renderergl2/glsl/lightall_fp.glsl +++ b/code/renderergl2/glsl/lightall_fp.glsl @@ -100,6 +100,12 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap) // best match found (starts with last position 1.0) float bestDepth = 1.0; + // texture depth at best depth + float texDepth = 0.0; + + float prevT = SampleDepth(normalMap, dp); + float prevTexDepth = prevT; + // search front to back for first point inside object for(int i = 0; i < linearSearchSteps - 1; ++i) { @@ -109,11 +115,20 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap) if(bestDepth > 0.996) // if no depth found yet if(depth >= t) + { bestDepth = depth; // store best depth + texDepth = t; + prevTexDepth = prevT; + } + prevT = t; } depth = bestDepth; - + +#if !defined (USE_RELIEFMAP) + float div = 1.0 / (1.0 + (prevTexDepth - texDepth) * float(linearSearchSteps)); + bestDepth -= (depth - size - prevTexDepth) * div; +#else // recurse around first point (depth) for closest match for(int i = 0; i < binarySearchSteps; ++i) { @@ -129,6 +144,7 @@ float RayIntersectDisplaceMap(vec2 dp, vec2 ds, sampler2D normalMap) depth += size; } +#endif return bestDepth; } @@ -164,7 +180,7 @@ vec3 EnvironmentBRDF(float gloss, float NE, vec3 specular) { #if 1 // from http://blog.selfshadow.com/publications/s2013-shading-course/lazarov/s2013_pbs_black_ops_2_notes.pdf - vec4 t = vec4( 1/0.96, 0.475, (0.0275 - 0.25 * 0.04)/0.96,0.25 ) * gloss; + vec4 t = vec4( 1.0/0.96, 0.475, (0.0275 - 0.25 * 0.04)/0.96,0.25 ) * gloss; t += vec4( 0.0, 0.0, (0.015 - 0.75 * 0.04)/0.96,0.75 ); float a0 = t.x * min( t.y, exp2( -9.28 * NE ) ) + t.z; float a1 = t.w; @@ -357,7 +373,7 @@ void main() vec2 texCoords = var_TexCoords.xy; #if defined(USE_PARALLAXMAP) - vec3 offsetDir = normalize(E * tangentToWorld); + vec3 offsetDir = viewDir * tangentToWorld; offsetDir.xy *= -u_NormalScale.a / offsetDir.z; diff --git a/code/renderergl2/glsl/lightall_vp.glsl b/code/renderergl2/glsl/lightall_vp.glsl index b9e839de..59051d7c 100644 --- a/code/renderergl2/glsl/lightall_vp.glsl +++ b/code/renderergl2/glsl/lightall_vp.glsl @@ -167,11 +167,6 @@ void main() #endif #endif - normal = normal * 2.0 - vec3(1.0); -#if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) - tangent = tangent * 2.0 - vec3(1.0); -#endif - #if defined(USE_TCGEN) vec2 texCoords = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1); #else @@ -195,13 +190,13 @@ void main() #endif #if defined(USE_VERT_TANGENT_SPACE) && defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) - vec3 bitangent = cross(normal, tangent) * (attr_Tangent.w * 2.0 - 1.0); + vec3 bitangent = cross(normal, tangent) * attr_Tangent.w; #endif #if defined(USE_LIGHT_VECTOR) vec3 L = u_LightOrigin.xyz - (position * u_LightOrigin.w); #elif defined(USE_LIGHT) && !defined(USE_FAST_LIGHT) - vec3 L = attr_LightDirection * 2.0 - vec3(1.0); + vec3 L = attr_LightDirection; #if defined(USE_MODELMATRIX) L = (u_ModelMatrix * vec4(L, 0.0)).xyz; #endif diff --git a/code/renderergl2/glsl/pshadow_vp.glsl b/code/renderergl2/glsl/pshadow_vp.glsl index 0f9940cd..07a49855 100644 --- a/code/renderergl2/glsl/pshadow_vp.glsl +++ b/code/renderergl2/glsl/pshadow_vp.glsl @@ -11,5 +11,5 @@ void main() gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); var_Position = attr_Position; - var_Normal = attr_Normal * 2.0 - vec3(1.0); + var_Normal = attr_Normal; } diff --git a/code/renderergl2/glsl/shadowfill_vp.glsl b/code/renderergl2/glsl/shadowfill_vp.glsl index 7a5cc571..7de901ba 100644 --- a/code/renderergl2/glsl/shadowfill_vp.glsl +++ b/code/renderergl2/glsl/shadowfill_vp.glsl @@ -80,7 +80,6 @@ void main() { vec3 position = mix(attr_Position, attr_Position2, u_VertexLerp); vec3 normal = mix(attr_Normal, attr_Normal2, u_VertexLerp); - normal = normalize(normal - vec3(0.5)); position = DeformPosition(position, normal, attr_TexCoord0.st); diff --git a/code/renderergl2/glsl/shadowmask_fp.glsl b/code/renderergl2/glsl/shadowmask_fp.glsl index b489fef5..053907cf 100644 --- a/code/renderergl2/glsl/shadowmask_fp.glsl +++ b/code/renderergl2/glsl/shadowmask_fp.glsl @@ -1,15 +1,17 @@ uniform sampler2D u_ScreenDepthMap; -uniform sampler2D u_ShadowMap; +uniform sampler2DShadow u_ShadowMap; #if defined(USE_SHADOW_CASCADE) -uniform sampler2D u_ShadowMap2; -uniform sampler2D u_ShadowMap3; +uniform sampler2DShadow u_ShadowMap2; +uniform sampler2DShadow u_ShadowMap3; +uniform sampler2DShadow u_ShadowMap4; #endif uniform mat4 u_ShadowMvp; #if defined(USE_SHADOW_CASCADE) uniform mat4 u_ShadowMvp2; uniform mat4 u_ShadowMvp3; +uniform mat4 u_ShadowMvp4; #endif uniform vec3 u_ViewOrigin; @@ -39,94 +41,103 @@ float random( const vec2 p ) return mod( 123456789., 1e-7 + 256. * dot(p,r) ); } -float PCF(const sampler2D shadowmap, const vec2 st, const float dist) +float PCF(const sampler2DShadow shadowmap, const vec2 st, const float dist) { float mult; float scale = 2.0 / r_shadowMapSize; +#if 0 + // from http://http.developer.nvidia.com/GPUGems/gpugems_ch11.html + vec2 offset = vec2(greaterThan(fract(var_DepthTex.xy * r_FBufScale * 0.5), vec2(0.25))); + offset.y += offset.x; + if (offset.y > 1.1) offset.y = 0.0; + + mult = shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, 0.5)) * scale, dist)).r + + shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, 0.5)) * scale, dist)).r + + shadow2D(shadowmap, vec3(st + (offset + vec2(-1.5, -1.5)) * scale, dist)).r + + shadow2D(shadowmap, vec3(st + (offset + vec2( 0.5, -1.5)) * scale, dist)).r; + + mult *= 0.25; +#endif + #if defined(USE_SHADOW_FILTER) float r = random(var_DepthTex.xy); float sinr = sin(r) * scale; float cosr = cos(r) * scale; mat2 rmat = mat2(cosr, sinr, -sinr, cosr); - mult = step(dist, texture2D(shadowmap, st + rmat * vec2(-0.7055767, 0.196515)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.3524343, -0.7791386)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.2391056, 0.9189604)).r); + mult = shadow2D(shadowmap, vec3(st + rmat * vec2(-0.7055767, 0.196515), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.3524343, -0.7791386), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.2391056, 0.9189604), dist)).r; #if defined(USE_SHADOW_FILTER2) - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.07580382, -0.09224417)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.5784913, -0.002528916)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.192888, 0.4064181)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.6335801, -0.5247476)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(-0.5579782, 0.7491854)).r); - mult += step(dist, texture2D(shadowmap, st + rmat * vec2(0.7320465, 0.6317794)).r); + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.07580382, -0.09224417), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.5784913, -0.002528916), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.192888, 0.4064181), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.6335801, -0.5247476), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(-0.5579782, 0.7491854), dist)).r; + mult += shadow2D(shadowmap, vec3(st + rmat * vec2(0.7320465, 0.6317794), dist)).r; mult *= 0.11111; #else mult *= 0.33333; #endif #else - mult = step(dist, texture2D(shadowmap, st).r); + mult = shadow2D(shadowmap, vec3(st, dist)).r; #endif - + return mult; } float getLinearDepth(sampler2D depthMap, vec2 tex, float zFarDivZNear) { - float sampleZDivW = texture2D(depthMap, tex).r; - sampleZDivW -= DEPTH_MAX_ERROR; - return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); + float sampleZDivW = texture2D(depthMap, tex).r - DEPTH_MAX_ERROR; + return 1.0 / mix(zFarDivZNear, 1.0, sampleZDivW); } void main() { float result; - + float depth = getLinearDepth(u_ScreenDepthMap, var_DepthTex, u_ViewInfo.x); - float sampleZ = u_ViewInfo.y * depth; - vec4 biasPos = vec4(u_ViewOrigin + var_ViewDir * (depth - 0.5 / u_ViewInfo.x), 1.0); - - vec4 shadowpos = u_ShadowMvp * biasPos; - -#if defined(USE_SHADOW_CASCADE) - const float fadeTo = 1.0; - result = fadeTo; -#else - result = 0.0; -#endif - if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w))))) - { - shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5; - result = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z); - } + vec4 shadowpos = u_ShadowMvp * biasPos; + #if defined(USE_SHADOW_CASCADE) + if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w))))) + { +#endif + shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + vec3(0.5); + result = PCF(u_ShadowMap, shadowpos.xy, shadowpos.z); +#if defined(USE_SHADOW_CASCADE) + } else { shadowpos = u_ShadowMvp2 * biasPos; - if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w))))) + if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w))))) { - shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5; + shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + vec3(0.5); result = PCF(u_ShadowMap2, shadowpos.xy, shadowpos.z); } else { shadowpos = u_ShadowMvp3 * biasPos; - if (all(lessThanEqual(abs(shadowpos.xyz), vec3(abs(shadowpos.w))))) + if (all(lessThan(abs(shadowpos.xyz), vec3(abs(shadowpos.w))))) { - shadowpos.xyz = shadowpos.xyz / shadowpos.w * 0.5 + 0.5; + shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + vec3(0.5); result = PCF(u_ShadowMap3, shadowpos.xy, shadowpos.z); - - float fade = clamp(sampleZ / r_shadowCascadeZFar * 10.0 - 9.0, 0.0, 1.0); - result = mix(result, fadeTo, fade); + } + else + { + shadowpos = u_ShadowMvp4 * biasPos; + shadowpos.xyz = shadowpos.xyz * (0.5 / shadowpos.w) + vec3(0.5); + result = PCF(u_ShadowMap4, shadowpos.xy, shadowpos.z); } } } #endif - + gl_FragColor = vec4(vec3(result), 1.0); } diff --git a/code/renderergl2/glsl/texturecolor_fp.glsl b/code/renderergl2/glsl/texturecolor_fp.glsl index e077e7da..7c9046e1 100644 --- a/code/renderergl2/glsl/texturecolor_fp.glsl +++ b/code/renderergl2/glsl/texturecolor_fp.glsl @@ -1,5 +1,3 @@ -#version 120 - uniform sampler2D u_DiffuseMap; uniform vec4 u_Color; diff --git a/code/renderergl2/glsl/texturecolor_vp.glsl b/code/renderergl2/glsl/texturecolor_vp.glsl index 7a5750a5..552cd938 100644 --- a/code/renderergl2/glsl/texturecolor_vp.glsl +++ b/code/renderergl2/glsl/texturecolor_vp.glsl @@ -1,5 +1,3 @@ -#version 120 - attribute vec3 attr_Position; attribute vec4 attr_TexCoord0; diff --git a/code/renderergl2/glsl/tonemap_fp.glsl b/code/renderergl2/glsl/tonemap_fp.glsl index 4c914aca..1368c5bd 100644 --- a/code/renderergl2/glsl/tonemap_fp.glsl +++ b/code/renderergl2/glsl/tonemap_fp.glsl @@ -3,14 +3,16 @@ uniform sampler2D u_LevelsMap; uniform vec4 u_Color; + uniform vec2 u_AutoExposureMinMax; uniform vec3 u_ToneMinAvgMaxLinear; varying vec2 var_TexCoords; +varying float var_InvWhite; const vec3 LUMINANCE_VECTOR = vec3(0.2125, 0.7154, 0.0721); //vec3(0.299, 0.587, 0.114); -vec3 FilmicTonemap(vec3 x) +float FilmicTonemap(float x) { const float SS = 0.22; // Shoulder Strength const float LS = 0.30; // Linear Strength @@ -18,40 +20,35 @@ vec3 FilmicTonemap(vec3 x) const float TS = 0.20; // Toe Strength const float TAN = 0.01; // Toe Angle Numerator const float TAD = 0.30; // Toe Angle Denominator - - vec3 SSxx = SS * x * x; - vec3 LSx = LS * x; - vec3 LALSx = LSx * LA; - - return ((SSxx + LALSx + TS * TAN) / (SSxx + LSx + TS * TAD)) - TAN / TAD; - - //return ((x*(SS*x+LA*LS)+TS*TAN)/(x*(SS*x+LS)+TS*TAD)) - TAN/TAD; + return ((x*(SS*x+LA*LS)+TS*TAN)/(x*(SS*x+LS)+TS*TAD)) - TAN/TAD; } void main() { vec4 color = texture2D(u_TextureMap, var_TexCoords) * u_Color; - #if defined(r_framebufferGamma) +#if defined(r_framebufferGamma) color.rgb = pow(color.rgb, vec3(r_framebufferGamma)); - #endif +#endif vec3 minAvgMax = texture2D(u_LevelsMap, var_TexCoords).rgb; vec3 logMinAvgMaxLum = clamp(minAvgMax * 20.0 - 10.0, -u_AutoExposureMinMax.y, -u_AutoExposureMinMax.x); - - float avgLum = exp2(logMinAvgMaxLum.y); - //float maxLum = exp2(logMinAvgMaxLum.z); - color.rgb *= u_ToneMinAvgMaxLinear.y / avgLum; - color.rgb = max(vec3(0.0), color.rgb - vec3(u_ToneMinAvgMaxLinear.x)); + float invAvgLum = u_ToneMinAvgMaxLinear.y * exp2(-logMinAvgMaxLum.y); - vec3 fWhite = 1.0 / FilmicTonemap(vec3(u_ToneMinAvgMaxLinear.z - u_ToneMinAvgMaxLinear.x)); - color.rgb = FilmicTonemap(color.rgb) * fWhite; - - #if defined(r_tonemapGamma) + color.rgb = color.rgb * invAvgLum - u_ToneMinAvgMaxLinear.xxx; + color.rgb = max(vec3(0.0), color.rgb); + + color.r = FilmicTonemap(color.r); + color.g = FilmicTonemap(color.g); + color.b = FilmicTonemap(color.b); + + color.rgb = clamp(color.rgb * var_InvWhite, 0.0, 1.0); + +#if defined(r_tonemapGamma) color.rgb = pow(color.rgb, vec3(1.0 / r_tonemapGamma)); - #endif - - gl_FragColor = clamp(color, 0.0, 1.0); +#endif + + gl_FragColor = color; } diff --git a/code/renderergl2/glsl/tonemap_vp.glsl b/code/renderergl2/glsl/tonemap_vp.glsl index bdaa74af..577c0a1a 100644 --- a/code/renderergl2/glsl/tonemap_vp.glsl +++ b/code/renderergl2/glsl/tonemap_vp.glsl @@ -2,12 +2,26 @@ attribute vec3 attr_Position; attribute vec4 attr_TexCoord0; uniform mat4 u_ModelViewProjectionMatrix; +uniform vec3 u_ToneMinAvgMaxLinear; varying vec2 var_TexCoords; +varying float var_InvWhite; +float FilmicTonemap(float x) +{ + const float SS = 0.22; // Shoulder Strength + const float LS = 0.30; // Linear Strength + const float LA = 0.10; // Linear Angle + const float TS = 0.20; // Toe Strength + const float TAN = 0.01; // Toe Angle Numerator + const float TAD = 0.30; // Toe Angle Denominator + + return ((x*(SS*x+LA*LS)+TS*TAN)/(x*(SS*x+LS)+TS*TAD)) - TAN/TAD; +} void main() { gl_Position = u_ModelViewProjectionMatrix * vec4(attr_Position, 1.0); var_TexCoords = attr_TexCoord0.st; + var_InvWhite = 1.0 / FilmicTonemap(u_ToneMinAvgMaxLinear.z - u_ToneMinAvgMaxLinear.x); } diff --git a/code/renderergl2/tr_animation.c b/code/renderergl2/tr_animation.c index 3c49e146..53e5ee99 100644 --- a/code/renderergl2/tr_animation.c +++ b/code/renderergl2/tr_animation.c @@ -350,7 +350,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface ) oldFrame = (mdrFrame_t *)((byte *)header + header->ofsFrames + backEnd.currentEntity->e.oldframe * frameSize ); - RB_CheckOverflow( surface->numVerts, surface->numTriangles ); + RB_CHECKOVERFLOW( surface->numVerts, surface->numTriangles * 3 ); triangles = (int *) ((byte *)surface + surface->ofsTriangles); indexes = surface->numTriangles * 3; @@ -412,7 +412,7 @@ void RB_MDRSurfaceAnim( mdrSurface_t *surface ) tess.xyz[baseVertex + j][1] = tempVert[1]; tess.xyz[baseVertex + j][2] = tempVert[2]; - tess.normal[baseVertex + j] = R_VboPackNormal(tempNormal); + R_VaoPackNormal((byte *)&tess.normal[baseVertex + j], tempNormal); tess.texCoords[baseVertex + j][0][0] = v->texCoords[0]; tess.texCoords[baseVertex + j][0][1] = v->texCoords[1]; diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c index e4431cf5..c8c7200f 100644 --- a/code/renderergl2/tr_backend.c +++ b/code/renderergl2/tr_backend.c @@ -77,6 +77,9 @@ void GL_SelectTexture( int unit ) if (!(unit >= 0 && unit <= 31)) ri.Error( ERR_DROP, "GL_SelectTexture: unit = %i", unit ); + if (!qglActiveTextureARB) + ri.Error( ERR_DROP, "GL_SelectTexture: multitexture disabled" ); + qglActiveTextureARB( GL_TEXTURE0_ARB + unit ); glState.currenttmu = unit; @@ -118,30 +121,24 @@ void GL_Cull( int cullType ) { return; } - glState.faceCulling = cullType; - if ( cullType == CT_TWO_SIDED ) { qglDisable( GL_CULL_FACE ); } else { - qboolean cullFront; - qglEnable( GL_CULL_FACE ); + qboolean cullFront = (cullType == CT_FRONT_SIDED); - cullFront = (cullType == CT_FRONT_SIDED); - if ( backEnd.viewParms.isMirror ) - { - cullFront = !cullFront; - } + if ( glState.faceCulling == CT_TWO_SIDED ) + qglEnable( GL_CULL_FACE ); - if ( backEnd.currentEntity && backEnd.currentEntity->mirrored ) - { - cullFront = !cullFront; - } + if ( glState.faceCullFront != cullFront ) + qglCullFace( cullFront ? GL_FRONT : GL_BACK ); - qglCullFace( cullFront ? GL_FRONT : GL_BACK ); + glState.faceCullFront = cullFront; } + + glState.faceCulling = cullType; } /* @@ -216,10 +213,26 @@ void GL_State( unsigned long stateBits ) // if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) { - GLenum srcFactor = GL_ONE, dstFactor = GL_ONE; + uint32_t oldState = glState.glStateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); + uint32_t newState = stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); + uint32_t storedState = glState.storedGlState & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); - if ( stateBits & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) + if (oldState == 0) { + qglEnable( GL_BLEND ); + } + else if (newState == 0) + { + qglDisable( GL_BLEND ); + } + + if (newState != 0 && storedState != newState) + { + GLenum srcFactor = GL_ONE, dstFactor = GL_ONE; + + glState.storedGlState &= ~( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ); + glState.storedGlState |= newState; + switch ( stateBits & GLS_SRCBLEND_BITS ) { case GLS_SRCBLEND_ZERO: @@ -285,13 +298,8 @@ void GL_State( unsigned long stateBits ) break; } - qglEnable( GL_BLEND ); qglBlendFunc( srcFactor, dstFactor ); } - else - { - qglDisable( GL_BLEND ); - } } // @@ -344,26 +352,36 @@ void GL_State( unsigned long stateBits ) // if ( diff & GLS_ATEST_BITS ) { - switch ( stateBits & GLS_ATEST_BITS ) + uint32_t oldState = glState.glStateBits & GLS_ATEST_BITS; + uint32_t newState = stateBits & GLS_ATEST_BITS; + uint32_t storedState = glState.storedGlState & GLS_ATEST_BITS; + + if (oldState == 0) { - case 0: - qglDisable( GL_ALPHA_TEST ); - break; - case GLS_ATEST_GT_0: - qglEnable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_GREATER, 0.0f ); - break; - case GLS_ATEST_LT_80: - qglEnable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_LESS, 0.5f ); - break; - case GLS_ATEST_GE_80: - qglEnable( GL_ALPHA_TEST ); - qglAlphaFunc( GL_GEQUAL, 0.5f ); - break; - default: - assert( 0 ); - break; + qglEnable(GL_ALPHA_TEST); + } + else if (newState == 0) + { + qglDisable(GL_ALPHA_TEST); + } + + if (newState != 0 && storedState != newState) + { + glState.storedGlState &= ~GLS_ATEST_BITS; + glState.storedGlState |= newState; + + switch ( newState ) + { + case GLS_ATEST_GT_0: + qglAlphaFunc( GL_GREATER, 0.0f ); + break; + case GLS_ATEST_LT_80: + qglAlphaFunc( GL_LESS, 0.5f ); + break; + case GLS_ATEST_GE_80: + qglAlphaFunc( GL_GEQUAL, 0.5f ); + break; + } } } @@ -402,6 +420,7 @@ static void RB_Hyperspace( void ) { c = ( backEnd.refdef.time & 255 ) / 255.0f; qglClearColor( c, c, c, 1 ); qglClear( GL_COLOR_BUFFER_BIT ); + qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); backEnd.isHyperspace = qtrue; } @@ -486,25 +505,12 @@ void RB_BeginDrawingView (void) { if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) ) { clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used -#ifdef _DEBUG - qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky -#else - qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky -#endif - } - - // clear to white for shadow maps - if (backEnd.viewParms.flags & VPF_SHADOWMAP) - { - clearBits |= GL_COLOR_BUFFER_BIT; - qglClearColor( 1.0f, 1.0f, 1.0f, 1.0f ); } // clear to black for cube maps if (tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) { clearBits |= GL_COLOR_BUFFER_BIT; - qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); } qglClear( clearBits ); @@ -519,8 +525,6 @@ void RB_BeginDrawingView (void) { backEnd.isHyperspace = qfalse; } - glState.faceCulling = -1; // force face culling to set next time - // we will only draw a sun if there was sky rendered in this view backEnd.skyRenderedThisView = qfalse; @@ -528,7 +532,7 @@ void RB_BeginDrawingView (void) { if ( backEnd.viewParms.isPortal ) { #if 0 float plane[4]; - double plane2[4]; + GLdouble plane2[4]; plane[0] = backEnd.viewParms.portalPlane.normal[0]; plane[1] = backEnd.viewParms.portalPlane.normal[1]; @@ -798,7 +802,7 @@ void RB_SetGL2D (void) { GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); - qglDisable( GL_CULL_FACE ); + GL_Cull( CT_TWO_SIDED ); qglDisable( GL_CLIP_PLANE0 ); // set time for 2D shaders @@ -1122,13 +1126,24 @@ const void *RB_DrawSurfs( const void *data ) { GLSL_BindProgram(&tr.shadowmaskShader); GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP); - GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP); - GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2); - GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3); + + if (r_shadowCascadeZFar->integer != 0) + { + GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP); + GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2); + GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3); + GL_BindToTMU(tr.sunShadowDepthImage[3], TB_SHADOWMAP4); - GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]); - GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]); - GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]); + GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]); + GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]); + GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]); + GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP4, backEnd.refdef.sunShadowMvp[3]); + } + else + { + GL_BindToTMU(tr.sunShadowDepthImage[3], TB_SHADOWMAP); + GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[3]); + } GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg); { @@ -1642,7 +1657,7 @@ const void *RB_PostProcess(const void *data) if (srcFbo) { - if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer)) + if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer) && qglActiveTextureARB) { autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer; RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure); @@ -1681,6 +1696,8 @@ const void *RB_PostProcess(const void *data) FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, NULL, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 256, 0, 128, 128); FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, NULL, dstBox, NULL, NULL, 0); + VectorSet4(dstBox, 384, 0, 128, 128); + FBO_BlitFromTexture(tr.sunShadowDepthImage[3], NULL, NULL, NULL, dstBox, NULL, NULL, 0); } if (0) diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index 63824284..cf4ddca0 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -599,9 +599,7 @@ static void R_LoadVisibility( lump_t *l ) { int len; byte *buf; - len = ( s_worldData.numClusters + 63 ) & ~63; - - len = l->filelen; + len = l->filelen; if ( !len ) { return; } @@ -1473,7 +1471,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { for (m = 0; m < 2; m++) { - if ( grid2->width >= MAX_GRID_SIZE ) + if ( !grid2 || grid2->width >= MAX_GRID_SIZE ) break; if (m) offset2 = (grid2->height-1) * grid2->width; else offset2 = 0; @@ -1517,7 +1515,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { } for (m = 0; m < 2; m++) { - if (grid2->height >= MAX_GRID_SIZE) + if (!grid2 || grid2->height >= MAX_GRID_SIZE) break; if (m) offset2 = grid2->width-1; else offset2 = 0; @@ -1572,7 +1570,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { for (k = grid1->height-1; k > 1; k -= 2) { for (m = 0; m < 2; m++) { - if ( grid2->width >= MAX_GRID_SIZE ) + if (!grid2 || grid2->width >= MAX_GRID_SIZE ) break; if (m) offset2 = (grid2->height-1) * grid2->width; else offset2 = 0; @@ -1616,7 +1614,7 @@ int R_StitchPatches( int grid1num, int grid2num ) { } for (m = 0; m < 2; m++) { - if (grid2->height >= MAX_GRID_SIZE) + if (!grid2 || grid2->height >= MAX_GRID_SIZE) break; if (m) offset2 = grid2->width-1; else offset2 = 0; @@ -1810,6 +1808,19 @@ static int BSPSurfaceCompare(const void *a, const void *b) else if(aa->cubemapIndex > bb->cubemapIndex) return 1; + // by leaf + if (s_worldData.surfacesViewCount[aa - s_worldData.surfaces] < s_worldData.surfacesViewCount[bb - s_worldData.surfaces]) + return -1; + + else if (s_worldData.surfacesViewCount[aa - s_worldData.surfaces] > s_worldData.surfacesViewCount[bb - s_worldData.surfaces]) + return 1; + + // by surface number + if (aa < bb) + return -1; + + else if (aa > bb) + return 1; return 0; } @@ -1817,40 +1828,26 @@ static int BSPSurfaceCompare(const void *a, const void *b) static void CopyVert(const srfVert_t * in, srfVert_t * out) { - int j; - - for(j = 0; j < 3; j++) - { - out->xyz[j] = in->xyz[j]; + VectorCopy(in->xyz, out->xyz); #ifdef USE_VERT_TANGENT_SPACE - out->tangent[j] = in->tangent[j]; - //out->bitangent[j] = in->bitangent[j]; + VectorCopy4(in->tangent, out->tangent); #endif - out->normal[j] = in->normal[j]; - out->lightdir[j] = in->lightdir[j]; - } + VectorCopy(in->normal, out->normal); + VectorCopy(in->lightdir, out->lightdir); - out->tangent[3] = in->tangent[3]; + VectorCopy2(in->st, out->st); + VectorCopy2(in->lightmap, out->lightmap); - for(j = 0; j < 2; j++) - { - out->st[j] = in->st[j]; - out->lightmap[j] = in->lightmap[j]; - } - - for(j = 0; j < 4; j++) - { - out->vertexColors[j] = in->vertexColors[j]; - } + VectorCopy4(in->vertexColors, out->vertexColors); } /* =============== -R_CreateWorldVBOs +R_CreateWorldVaos =============== */ -static void R_CreateWorldVBOs(void) +static void R_CreateWorldVaos(void) { int i, j, k; @@ -1864,30 +1861,77 @@ static void R_CreateWorldVBOs(void) msurface_t *surface, **firstSurf, **lastSurf, **currSurf; msurface_t **surfacesSorted; - VBO_t *vbo; - IBO_t *ibo; + vao_t *vao; int maxVboSize = 4 * 1024 * 1024; - int maxIboSize = 4 * 1024 * 1024; int startTime, endTime; startTime = ri.Milliseconds(); + // mark surfaces with best matching leaf, using overlapping bounds + // using surfaceViewCount[] as leaf number, and surfacesDlightBits[] as coverage * 256 + for (i = 0; i < s_worldData.numWorldSurfaces; i++) + { + s_worldData.surfacesViewCount[i] = -1; + } + + for (i = 0; i < s_worldData.numWorldSurfaces; i++) + { + s_worldData.surfacesDlightBits[i] = 0; + } + + for (i = s_worldData.numDecisionNodes; i < s_worldData.numnodes; i++) + { + mnode_t *leaf = s_worldData.nodes + i; + + for (j = leaf->firstmarksurface; j < leaf->firstmarksurface + leaf->nummarksurfaces; j++) + { + int surfaceNum = s_worldData.marksurfaces[j]; + msurface_t *surface = s_worldData.surfaces + surfaceNum; + float coverage = 1.0f; + int iCoverage; + + for (k = 0; k < 3; k++) + { + float left, right; + + if (leaf->mins[k] > surface->cullinfo.bounds[1][k] || surface->cullinfo.bounds[0][k] > leaf->maxs[k]) + { + coverage = 0.0f; + break; + } + + left = MAX(leaf->mins[k], surface->cullinfo.bounds[0][k]); + right = MIN(leaf->maxs[k], surface->cullinfo.bounds[1][k]); + + // nudge a bit in case this is an axis aligned wall + coverage *= right - left + 1.0f/256.0f; + } + + iCoverage = coverage * 256; + + if (iCoverage > s_worldData.surfacesDlightBits[surfaceNum]) + { + s_worldData.surfacesDlightBits[surfaceNum] = iCoverage; + s_worldData.surfacesViewCount[surfaceNum] = i - s_worldData.numDecisionNodes; + } + } + } + + for (i = 0; i < s_worldData.numWorldSurfaces; i++) + { + s_worldData.surfacesDlightBits[i] = 0; + } + // count surfaces numSortedSurfaces = 0; - for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++) + for(surface = s_worldData.surfaces; surface < s_worldData.surfaces + s_worldData.numWorldSurfaces; surface++) { srfBspSurface_t *bspSurf; shader_t *shader = surface->shader; - if (shader->isPortal) - continue; - - if (shader->isSky) - continue; - - if (ShaderRequiresCPUDeforms(shader)) + if (shader->isPortal || shader->isSky || ShaderRequiresCPUDeforms(shader)) continue; // check for this now so we can use srfBspSurface_t* universally in the rest of the function @@ -1906,18 +1950,12 @@ static void R_CreateWorldVBOs(void) surfacesSorted = ri.Malloc(numSortedSurfaces * sizeof(*surfacesSorted)); j = 0; - for(surface = &s_worldData.surfaces[0]; surface < &s_worldData.surfaces[s_worldData.numsurfaces]; surface++) + for(surface = s_worldData.surfaces; surface < s_worldData.surfaces + s_worldData.numWorldSurfaces; surface++) { srfBspSurface_t *bspSurf; shader_t *shader = surface->shader; - if (shader->isPortal) - continue; - - if (shader->isSky) - continue; - - if (ShaderRequiresCPUDeforms(shader)) + if (shader->isPortal || shader->isSky || ShaderRequiresCPUDeforms(shader)) continue; // check for this now so we can use srfBspSurface_t* universally in the rest of the function @@ -1935,37 +1973,34 @@ static void R_CreateWorldVBOs(void) qsort(surfacesSorted, numSortedSurfaces, sizeof(*surfacesSorted), BSPSurfaceCompare); k = 0; - for(firstSurf = lastSurf = surfacesSorted; firstSurf < &surfacesSorted[numSortedSurfaces]; firstSurf = lastSurf) + for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + numSortedSurfaces; firstSurf = lastSurf) { - int currVboSize, currIboSize; + int currVboSize; - // Find range of surfaces to merge by: - // - Collecting a number of surfaces which fit under maxVboSize/maxIboSize, or - // - All the surfaces with a single shader which go over maxVboSize/maxIboSize - currVboSize = currIboSize = 0; - while (currVboSize < maxVboSize && currIboSize < maxIboSize && lastSurf < &surfacesSorted[numSortedSurfaces]) + // Find range of surfaces to place in a VAO by: + // - Collecting a number of surfaces which fit under maxVboSize, or + // - All the surfaces with a single shader which go over maxVboSize + currVboSize = 0; + while (currVboSize < maxVboSize && lastSurf < surfacesSorted + numSortedSurfaces) { - int addVboSize, addIboSize, currShaderIndex; + int addVboSize, currShaderIndex; - addVboSize = addIboSize = 0; + addVboSize = 0; currShaderIndex = (*lastSurf)->shader->sortedIndex; - for(currSurf = lastSurf; currSurf < &surfacesSorted[numSortedSurfaces] && (*currSurf)->shader->sortedIndex == currShaderIndex; currSurf++) + for(currSurf = lastSurf; currSurf < surfacesSorted + numSortedSurfaces && (*currSurf)->shader->sortedIndex == currShaderIndex; currSurf++) { srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; addVboSize += bspSurf->numVerts * sizeof(srfVert_t); - addIboSize += bspSurf->numIndexes * sizeof(glIndex_t); } - if ((currVboSize != 0 && addVboSize + currVboSize > maxVboSize) - || (currIboSize != 0 && addIboSize + currIboSize > maxIboSize)) + if (currVboSize != 0 && addVboSize + currVboSize > maxVboSize) break; lastSurf = currSurf; currVboSize += addVboSize; - currIboSize += addIboSize; } // count verts/indexes/surfaces @@ -1981,7 +2016,7 @@ static void R_CreateWorldVBOs(void) numSurfaces++; } - ri.Printf(PRINT_ALL, "...calculating world VBO %d ( %i verts %i tris )\n", k, numVerts, numIndexes / 3); + ri.Printf(PRINT_ALL, "...calculating world VAO %d ( %i verts %i tris )\n", k, numVerts, numIndexes / 3); // create arrays verts = ri.Hunk_AllocateTempMemory(numVerts * sizeof(srfVert_t)); @@ -2014,25 +2049,14 @@ static void R_CreateWorldVBOs(void) } } -#ifdef USE_VERT_TANGENT_SPACE - vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts, - ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | ATTR_TANGENT | - ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC); -#else - vbo = R_CreateVBO2(va("staticBspModel0_VBO %i", k), numVerts, verts, - ATTR_POSITION | ATTR_TEXCOORD | ATTR_LIGHTCOORD | - ATTR_NORMAL | ATTR_COLOR | ATTR_LIGHTDIRECTION, VBO_USAGE_STATIC); -#endif + vao = R_CreateVao2(va("staticBspModel%i_VAO", k), numVerts, verts, numIndexes, indexes); - ibo = R_CreateIBO2(va("staticBspModel0_IBO %i", k), numIndexes, indexes, VBO_USAGE_STATIC); - - // point bsp surfaces to VBO + // point bsp surfaces to VAO for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) { srfBspSurface_t *bspSurf = (srfBspSurface_t *) (*currSurf)->data; - bspSurf->vbo = vbo; - bspSurf->ibo = ibo; + bspSurf->vao = vao; } ri.Hunk_FreeTempMemory(indexes); @@ -2041,10 +2065,144 @@ static void R_CreateWorldVBOs(void) k++; } + if (r_mergeLeafSurfaces->integer) + { + msurface_t *mergedSurf; + + // count merged surfaces + int numMergedSurfaces = 0, numUnmergedSurfaces = 0; + for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + numSortedSurfaces; firstSurf = lastSurf) + { + for (lastSurf++ ; lastSurf < surfacesSorted + numSortedSurfaces; lastSurf++) + { + int lastSurfLeafIndex, firstSurfLeafIndex; + + if ((*lastSurf)->shader != (*firstSurf)->shader + || (*lastSurf)->fogIndex != (*firstSurf)->fogIndex + || (*lastSurf)->cubemapIndex != (*firstSurf)->cubemapIndex) + break; + + lastSurfLeafIndex = s_worldData.surfacesViewCount[*lastSurf - s_worldData.surfaces]; + firstSurfLeafIndex = s_worldData.surfacesViewCount[*firstSurf - s_worldData.surfaces]; + + if (lastSurfLeafIndex != firstSurfLeafIndex) + break; + } + + // don't merge single surfaces + if (firstSurf + 1 == lastSurf) + { + numUnmergedSurfaces++; + continue; + } + + numMergedSurfaces++; + } + + // Allocate merged surfaces + s_worldData.mergedSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low); + s_worldData.mergedSurfacesViewCount = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, h_low); + s_worldData.mergedSurfacesDlightBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * numMergedSurfaces, h_low); + s_worldData.mergedSurfacesPshadowBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * numMergedSurfaces, h_low); + s_worldData.numMergedSurfaces = numMergedSurfaces; + + // view surfaces are like mark surfaces, except negative ones represent merged surfaces + // -1 represents 0, -2 represents 1, and so on + s_worldData.viewSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, h_low); + + // copy view surfaces into mark surfaces + for (i = 0; i < s_worldData.nummarksurfaces; i++) + { + s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i]; + } + + // actually merge surfaces + mergedSurf = s_worldData.mergedSurfaces; + for(firstSurf = lastSurf = surfacesSorted; firstSurf < surfacesSorted + numSortedSurfaces; firstSurf = lastSurf) + { + srfBspSurface_t *bspSurf, *vaoSurf; + + for ( lastSurf++ ; lastSurf < surfacesSorted + numSortedSurfaces; lastSurf++) + { + int lastSurfLeafIndex, firstSurfLeafIndex; + + if ((*lastSurf)->shader != (*firstSurf)->shader + || (*lastSurf)->fogIndex != (*firstSurf)->fogIndex + || (*lastSurf)->cubemapIndex != (*firstSurf)->cubemapIndex) + break; + + lastSurfLeafIndex = s_worldData.surfacesViewCount[*lastSurf - s_worldData.surfaces]; + firstSurfLeafIndex = s_worldData.surfacesViewCount[*firstSurf - s_worldData.surfaces]; + + if (lastSurfLeafIndex != firstSurfLeafIndex) + break; + } + + // don't merge single surfaces + if (firstSurf + 1 == lastSurf) + continue; + + bspSurf = (srfBspSurface_t *)(*firstSurf)->data; + + vaoSurf = ri.Hunk_Alloc(sizeof(*vaoSurf), h_low); + memset(vaoSurf, 0, sizeof(*vaoSurf)); + vaoSurf->surfaceType = SF_VAO_MESH; + + vaoSurf->vao = bspSurf->vao; + + vaoSurf->firstIndex = bspSurf->firstIndex; + vaoSurf->minIndex = bspSurf->minIndex; + vaoSurf->maxIndex = bspSurf->maxIndex; + + ClearBounds(vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]); + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) + { + srfBspSurface_t *currBspSurf = (srfBspSurface_t *)(*currSurf)->data; + + vaoSurf->numVerts += currBspSurf->numVerts; + vaoSurf->numIndexes += currBspSurf->numIndexes; + vaoSurf->minIndex = MIN(vaoSurf->minIndex, currBspSurf->minIndex); + vaoSurf->maxIndex = MAX(vaoSurf->maxIndex, currBspSurf->maxIndex); + AddPointToBounds((*currSurf)->cullinfo.bounds[0], vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]); + AddPointToBounds((*currSurf)->cullinfo.bounds[1], vaoSurf->cullBounds[0], vaoSurf->cullBounds[1]); + } + + VectorCopy(vaoSurf->cullBounds[0], mergedSurf->cullinfo.bounds[0]); + VectorCopy(vaoSurf->cullBounds[1], mergedSurf->cullinfo.bounds[1]); + + mergedSurf->cullinfo.type = CULLINFO_BOX; + mergedSurf->data = (surfaceType_t *)vaoSurf; + mergedSurf->fogIndex = (*firstSurf)->fogIndex; + mergedSurf->cubemapIndex = (*firstSurf)->cubemapIndex; + mergedSurf->shader = (*firstSurf)->shader; + + // redirect view surfaces to this surf + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) + s_worldData.surfacesViewCount[*currSurf - s_worldData.surfaces] = -2; + + for (k = 0; k < s_worldData.nummarksurfaces; k++) + { + if (s_worldData.surfacesViewCount[s_worldData.marksurfaces[k]] == -2) + s_worldData.viewSurfaces[k] = -((int)(mergedSurf - s_worldData.mergedSurfaces) + 1); + } + + for (currSurf = firstSurf; currSurf < lastSurf; currSurf++) + s_worldData.surfacesViewCount[*currSurf - s_worldData.surfaces] = -1; + + mergedSurf++; + } + + ri.Printf(PRINT_ALL, "Processed %d mergeable surfaces into %d merged, %d unmerged\n", + numSortedSurfaces, numMergedSurfaces, numUnmergedSurfaces); + } + + for (i = 0; i < s_worldData.numWorldSurfaces; i++) + s_worldData.surfacesViewCount[i] = -1; + ri.Free(surfacesSorted); endTime = ri.Milliseconds(); - ri.Printf(PRINT_ALL, "world VBOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0); + ri.Printf(PRINT_ALL, "world VAOs calculation time = %5.2f seconds\n", (endTime - startTime) / 1000.0); } /* @@ -2108,7 +2266,7 @@ static void R_LoadSurfaces( lump_t *surfs, lump_t *verts, lump_t *indexLump ) { // Two passes, allocate surfaces first, then load them full of data - // This ensures surfaces are close together to reduce L2 cache misses when using VBOs, + // This ensures surfaces are close together to reduce L2 cache misses when using VAOs, // which don't actually use the verts and indexes in = (void *)(fileBase + surfs->fileofs); out = s_worldData.surfaces; @@ -2231,7 +2389,7 @@ static void R_LoadSubmodels( lump_t *l ) { if(i == 0) { - // Add this for limiting VBO surface creation + // Add this for limiting VAO surface creation s_worldData.numWorldSurfaces = out->numSurfaces; } } @@ -2916,336 +3074,6 @@ void R_RenderAllCubemaps(void) } -/* -================= -R_MergeLeafSurfaces - -Merges surfaces that share a common leaf -================= -*/ -void R_MergeLeafSurfaces(void) -{ - int i, j, k; - int numWorldSurfaces; - int mergedSurfIndex; - int numMergedSurfaces; - int numUnmergedSurfaces; - VBO_t *vbo; - IBO_t *ibo; - - msurface_t *mergedSurf; - - glIndex_t *iboIndexes, *outIboIndexes; - int numIboIndexes; - - int startTime, endTime; - - startTime = ri.Milliseconds(); - - numWorldSurfaces = s_worldData.numWorldSurfaces; - - // use viewcount to keep track of mergers - for (i = 0; i < numWorldSurfaces; i++) - { - s_worldData.surfacesViewCount[i] = -1; - } - - // mark matching surfaces - for (i = 0; i < s_worldData.numnodes - s_worldData.numDecisionNodes; i++) - { - mnode_t *leaf = s_worldData.nodes + s_worldData.numDecisionNodes + i; - - for (j = 0; j < leaf->nummarksurfaces; j++) - { - msurface_t *surf1; - shader_t *shader1; - int fogIndex1; - int cubemapIndex1; - int surfNum1; - - surfNum1 = *(s_worldData.marksurfaces + leaf->firstmarksurface + j); - - if (s_worldData.surfacesViewCount[surfNum1] != -1) - continue; - - surf1 = s_worldData.surfaces + surfNum1; - - if ((*surf1->data != SF_GRID) && (*surf1->data != SF_TRIANGLES) && (*surf1->data != SF_FACE)) - continue; - - shader1 = surf1->shader; - - if(shader1->isSky) - continue; - - if(shader1->isPortal) - continue; - - if(ShaderRequiresCPUDeforms(shader1)) - continue; - - fogIndex1 = surf1->fogIndex; - cubemapIndex1 = surf1->cubemapIndex; - - s_worldData.surfacesViewCount[surfNum1] = surfNum1; - - for (k = j + 1; k < leaf->nummarksurfaces; k++) - { - msurface_t *surf2; - shader_t *shader2; - int fogIndex2; - int cubemapIndex2; - int surfNum2; - - surfNum2 = *(s_worldData.marksurfaces + leaf->firstmarksurface + k); - - if (s_worldData.surfacesViewCount[surfNum2] != -1) - continue; - - surf2 = s_worldData.surfaces + surfNum2; - - if ((*surf2->data != SF_GRID) && (*surf2->data != SF_TRIANGLES) && (*surf2->data != SF_FACE)) - continue; - - shader2 = surf2->shader; - - if (shader1 != shader2) - continue; - - fogIndex2 = surf2->fogIndex; - - if (fogIndex1 != fogIndex2) - continue; - - cubemapIndex2 = surf2->cubemapIndex; - - if (cubemapIndex1 != cubemapIndex2) - continue; - - s_worldData.surfacesViewCount[surfNum2] = surfNum1; - } - } - } - - // don't add surfaces that don't merge to any others to the merged list - for (i = 0; i < numWorldSurfaces; i++) - { - qboolean merges = qfalse; - - if (s_worldData.surfacesViewCount[i] != i) - continue; - - for (j = 0; j < numWorldSurfaces; j++) - { - if (j == i) - continue; - - if (s_worldData.surfacesViewCount[j] == i) - { - merges = qtrue; - break; - } - } - - if (!merges) - s_worldData.surfacesViewCount[i] = -1; - } - - // count merged/unmerged surfaces - numMergedSurfaces = 0; - numUnmergedSurfaces = 0; - for (i = 0; i < numWorldSurfaces; i++) - { - if (s_worldData.surfacesViewCount[i] == i) - { - numMergedSurfaces++; - } - else if (s_worldData.surfacesViewCount[i] == -1) - { - numUnmergedSurfaces++; - } - } - - // Allocate merged surfaces - s_worldData.mergedSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfaces) * numMergedSurfaces, h_low); - s_worldData.mergedSurfacesViewCount = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesViewCount) * numMergedSurfaces, h_low); - s_worldData.mergedSurfacesDlightBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesDlightBits) * numMergedSurfaces, h_low); - s_worldData.mergedSurfacesPshadowBits = ri.Hunk_Alloc(sizeof(*s_worldData.mergedSurfacesPshadowBits) * numMergedSurfaces, h_low); - s_worldData.numMergedSurfaces = numMergedSurfaces; - - // view surfaces are like mark surfaces, except negative ones represent merged surfaces - // -1 represents 0, -2 represents 1, and so on - s_worldData.viewSurfaces = ri.Hunk_Alloc(sizeof(*s_worldData.viewSurfaces) * s_worldData.nummarksurfaces, h_low); - - // copy view surfaces into mark surfaces - for (i = 0; i < s_worldData.nummarksurfaces; i++) - { - s_worldData.viewSurfaces[i] = s_worldData.marksurfaces[i]; - } - - // need to be synched here - R_IssuePendingRenderCommands(); - - // actually merge surfaces - numIboIndexes = 0; - mergedSurfIndex = 0; - mergedSurf = s_worldData.mergedSurfaces; - for (i = 0; i < numWorldSurfaces; i++) - { - msurface_t *surf1; - - vec3_t bounds[2]; - - int numSurfsToMerge; - int numIndexes; - int numVerts; - int firstIndex; - - srfBspSurface_t *vboSurf; - - if (s_worldData.surfacesViewCount[i] != i) - continue; - - surf1 = s_worldData.surfaces + i; - - // retrieve vbo - vbo = ((srfBspSurface_t *)(surf1->data))->vbo; - - // count verts, indexes, and surfaces - numSurfsToMerge = 0; - numIndexes = 0; - numVerts = 0; - for (j = i; j < numWorldSurfaces; j++) - { - msurface_t *surf2; - srfBspSurface_t *bspSurf; - - if (s_worldData.surfacesViewCount[j] != i) - continue; - - surf2 = s_worldData.surfaces + j; - - bspSurf = (srfBspSurface_t *) surf2->data; - numIndexes += bspSurf->numIndexes; - numVerts += bspSurf->numVerts; - numSurfsToMerge++; - } - - if (numVerts == 0 || numIndexes == 0 || numSurfsToMerge < 2) - { - continue; - } - - // create ibo - ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); - memset(ibo, 0, sizeof(*ibo)); - Q_strncpyz(ibo->name, va("staticWorldMesh_IBO_mergedSurfs%i", tr.numIBOs++), sizeof(ibo->name)); - numIboIndexes = 0; - - // allocate indexes - iboIndexes = outIboIndexes = ri.Malloc(numIndexes * sizeof(*outIboIndexes)); - - // Merge surfaces (indexes) and calculate bounds - ClearBounds(bounds[0], bounds[1]); - firstIndex = numIboIndexes; - for (j = i; j < numWorldSurfaces; j++) - { - msurface_t *surf2; - srfBspSurface_t *bspSurf; - - if (s_worldData.surfacesViewCount[j] != i) - continue; - - surf2 = s_worldData.surfaces + j; - - AddPointToBounds(surf2->cullinfo.bounds[0], bounds[0], bounds[1]); - AddPointToBounds(surf2->cullinfo.bounds[1], bounds[0], bounds[1]); - - bspSurf = (srfBspSurface_t *) surf2->data; - for (k = 0; k < bspSurf->numIndexes; k++) - { - *outIboIndexes++ = bspSurf->indexes[k] + bspSurf->firstVert; - numIboIndexes++; - } - break; - } - - vboSurf = ri.Hunk_Alloc(sizeof(*vboSurf), h_low); - memset(vboSurf, 0, sizeof(*vboSurf)); - vboSurf->surfaceType = SF_VBO_MESH; - - vboSurf->vbo = vbo; - vboSurf->ibo = ibo; - - vboSurf->numIndexes = numIndexes; - vboSurf->numVerts = numVerts; - vboSurf->firstIndex = firstIndex; - - vboSurf->minIndex = *(iboIndexes + firstIndex); - vboSurf->maxIndex = *(iboIndexes + firstIndex); - - for (j = 0; j < numIndexes; j++) - { - vboSurf->minIndex = MIN(vboSurf->minIndex, *(iboIndexes + firstIndex + j)); - vboSurf->maxIndex = MAX(vboSurf->maxIndex, *(iboIndexes + firstIndex + j)); - } - - VectorCopy(bounds[0], vboSurf->cullBounds[0]); - VectorCopy(bounds[1], vboSurf->cullBounds[1]); - - VectorCopy(bounds[0], mergedSurf->cullinfo.bounds[0]); - VectorCopy(bounds[1], mergedSurf->cullinfo.bounds[1]); - - mergedSurf->cullinfo.type = CULLINFO_BOX; - mergedSurf->data = (surfaceType_t *)vboSurf; - mergedSurf->fogIndex = surf1->fogIndex; - mergedSurf->cubemapIndex = surf1->cubemapIndex; - mergedSurf->shader = surf1->shader; - - // finish up the ibo - qglGenBuffersARB(1, &ibo->indexesVBO); - - R_BindIBO(ibo); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, numIboIndexes * sizeof(*iboIndexes), iboIndexes, GL_STATIC_DRAW_ARB); - R_BindNullIBO(); - - GL_CheckErrors(); - - ri.Free(iboIndexes); - - // redirect view surfaces to this surf - for (j = 0; j < numWorldSurfaces; j++) - { - if (s_worldData.surfacesViewCount[j] != i) - continue; - - for (k = 0; k < s_worldData.nummarksurfaces; k++) - { - int *mark = s_worldData.marksurfaces + k; - int *view = s_worldData.viewSurfaces + k; - - if (*mark == j) - *view = -(mergedSurfIndex + 1); - } - } - - mergedSurfIndex++; - mergedSurf++; - } - - endTime = ri.Milliseconds(); - - ri.Printf(PRINT_ALL, "Processed %d surfaces into %d merged, %d unmerged in %5.2f seconds\n", - numWorldSurfaces, numMergedSurfaces, numUnmergedSurfaces, (endTime - startTime) / 1000.0f); - - // reset viewcounts - for (i = 0; i < numWorldSurfaces; i++) - { - s_worldData.surfacesViewCount[i] = -1; - } -} - - void R_CalcVertexLightDirs( void ) { int i, k; @@ -3313,6 +3141,9 @@ void RE_LoadWorldMap( const char *name ) { tr.toneMinAvgMaxLevel[1] = -2.0f; tr.toneMinAvgMaxLevel[2] = 0.0f; + // reset last cascade sun direction so last shadow cascade is rerendered + VectorClear(tr.lastCascadeSunDirection); + tr.worldMapLoaded = qtrue; // load it @@ -3567,21 +3398,16 @@ void RE_LoadWorldMap( const char *name ) { } } - // create static VBOS from the world - R_CreateWorldVBOs(); - if (r_mergeLeafSurfaces->integer) - { - R_MergeLeafSurfaces(); - } + // create static VAOS from the world + R_CreateWorldVaos(); s_worldData.dataSize = (byte *)ri.Hunk_Alloc(0, h_low) - startMarker; // only set tr.world now that we know the entire level has loaded properly tr.world = &s_worldData; - // make sure the VBO glState entries are safe - R_BindNullVBO(); - R_BindNullIBO(); + // make sure the VAO glState entry is safe + R_BindNullVao(); // Render all cubemaps if (r_cubeMapping->integer && tr.numCubemaps) diff --git a/code/renderergl2/tr_cmds.c b/code/renderergl2/tr_cmds.c index 139a3430..18fd69c3 100644 --- a/code/renderergl2/tr_cmds.c +++ b/code/renderergl2/tr_cmds.c @@ -66,8 +66,8 @@ void R_PerformanceCounters( void ) { } else if (r_speeds->integer == 7 ) { - ri.Printf( PRINT_ALL, "VBO draws: static %i dynamic %i\nMultidraws: %i merged %i\n", - backEnd.pc.c_staticVboDraws, backEnd.pc.c_dynamicVboDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged ); + ri.Printf( PRINT_ALL, "VAO draws: static %i dynamic %i\nMultidraws: %i merged %i\n", + backEnd.pc.c_staticVaoDraws, backEnd.pc.c_dynamicVaoDraws, backEnd.pc.c_multidraws, backEnd.pc.c_multidrawsMerged ); ri.Printf( PRINT_ALL, "GLSL binds: %i draws: gen %i light %i fog %i dlight %i\n", backEnd.pc.c_glslShaderBinds, backEnd.pc.c_genericDraws, backEnd.pc.c_lightallDraws, backEnd.pc.c_fogDraws, backEnd.pc.c_dlightDraws); } @@ -425,7 +425,6 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { backEnd.colorMask[1] = GL_FALSE; backEnd.colorMask[2] = GL_FALSE; backEnd.colorMask[3] = GL_FALSE; - qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); if (glRefConfig.framebufferObject) { diff --git a/code/renderergl2/tr_extensions.c b/code/renderergl2/tr_extensions.c index 10a1cb3a..357d4795 100644 --- a/code/renderergl2/tr_extensions.c +++ b/code/renderergl2/tr_extensions.c @@ -33,8 +33,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA void (APIENTRY * qglDrawRangeElementsEXT) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices); // GL_EXT_multi_draw_arrays -void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); -void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount); +void (APIENTRY * qglMultiDrawArraysEXT) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); +void (APIENTRY * qglMultiDrawElementsEXT) (GLenum mode, const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount); // GL_ARB_vertex_shader void (APIENTRY * qglBindAttribLocationARB) (GLhandleARB programObj, GLuint index, const GLcharARB * name); @@ -178,6 +178,12 @@ void (APIENTRY * qglRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei sa // GL_ARB_draw_buffers void (APIENTRY * qglDrawBuffersARB)(GLsizei n, const GLenum *bufs); +// GL_ARB_vertex_array_object +void (APIENTRY * qglBindVertexArrayARB)(GLuint array); +void (APIENTRY * qglDeleteVertexArraysARB)(GLsizei n, const GLuint *arrays); +void (APIENTRY * qglGenVertexArraysARB)(GLsizei n, GLuint *arrays); +GLboolean (APIENTRY * qglIsVertexArrayARB)(GLuint array); + static qboolean GLimp_HaveExtension(const char *ext) { const char *ptr = Q_stristr( glConfig.extensions_string, ext ); @@ -667,11 +673,11 @@ void GLimp_InitExtraExtensions() // GL_ARB_vertex_type_2_10_10_10_rev extension = "GL_ARB_vertex_type_2_10_10_10_rev"; - glRefConfig.packedNormalDataType = GL_UNSIGNED_BYTE; + glRefConfig.packedNormalDataType = GL_BYTE; if( GLimp_HaveExtension( extension ) ) { if (r_arb_vertex_type_2_10_10_10_rev->integer) - glRefConfig.packedNormalDataType = GL_UNSIGNED_INT_2_10_10_10_REV; + glRefConfig.packedNormalDataType = GL_INT_2_10_10_10_REV; ri.Printf(PRINT_ALL, result[r_arb_vertex_type_2_10_10_10_rev->integer ? 1 : 0], extension); } @@ -682,4 +688,48 @@ void GLimp_InitExtraExtensions() // use float lightmaps? glRefConfig.floatLightmap = (glRefConfig.textureFloat && glRefConfig.halfFloatPixel && r_floatLightmap->integer && r_hdr->integer); + + // GL_ARB_vertex_array_object + extension = "GL_ARB_vertex_array_object"; + glRefConfig.vertexArrayObject = qfalse; + if( GLimp_HaveExtension( extension ) ) + { + qglBindVertexArrayARB = (void *) SDL_GL_GetProcAddress("glBindVertexArray"); + qglDeleteVertexArraysARB = (void *) SDL_GL_GetProcAddress("glDeleteVertexArrays"); + qglGenVertexArraysARB = (void *) SDL_GL_GetProcAddress("glGenVertexArrays"); + qglIsVertexArrayARB = (void *) SDL_GL_GetProcAddress("glIsVertexArray"); + + if (r_arb_vertex_array_object->integer) + glRefConfig.vertexArrayObject = qtrue; + + ri.Printf(PRINT_ALL, result[glRefConfig.vertexArrayObject ? 1 : 0], extension); + } + else + { + ri.Printf(PRINT_ALL, result[2], extension); + } + + // GL_ARB_half_float_vertex + extension = "GL_ARB_half_float_vertex"; + glRefConfig.packedTexcoordDataType = GL_FLOAT; + glRefConfig.packedTexcoordDataSize = sizeof(float) * 2; + glRefConfig.packedColorDataType = GL_FLOAT; + glRefConfig.packedColorDataSize = sizeof(float) * 4; + if( GLimp_HaveExtension( extension ) ) + { + if (r_arb_half_float_vertex->integer) + { + glRefConfig.packedTexcoordDataType = GL_HALF_FLOAT; + glRefConfig.packedTexcoordDataSize = sizeof(uint16_t) * 2; + glRefConfig.packedColorDataType = GL_HALF_FLOAT; + glRefConfig.packedColorDataSize = sizeof(uint16_t) * 4; + } + + ri.Printf(PRINT_ALL, result[r_arb_half_float_vertex->integer ? 1 : 0], extension); + } + else + { + ri.Printf(PRINT_ALL, result[2], extension); + } + } diff --git a/code/renderergl2/tr_extramath.c b/code/renderergl2/tr_extramath.c index b844678f..bded7570 100644 --- a/code/renderergl2/tr_extramath.c +++ b/code/renderergl2/tr_extramath.c @@ -199,42 +199,35 @@ int NextPowerOfTwo(int in) return out; } -unsigned short FloatToHalf(float in) -{ - unsigned short out; - - union - { - float f; - unsigned int i; - } f32; +union f32_u { + float f; + uint32_t i; + struct { + unsigned int fraction:23; + unsigned int exponent:8; + unsigned int sign:1; + } pack; +}; - int sign, inExponent, inFraction; - int outExponent, outFraction; +union f16_u { + uint16_t i; + struct { + unsigned int fraction:10; + unsigned int exponent:5; + unsigned int sign:1; + } pack; +}; + +uint16_t FloatToHalf(float in) +{ + union f32_u f32; + union f16_u f16; f32.f = in; - sign = (f32.i & 0x80000000) >> 31; - inExponent = (f32.i & 0x7F800000) >> 23; - inFraction = f32.i & 0x007FFFFF; + f16.pack.exponent = CLAMP((int)(f32.pack.exponent) - 112, 0, 31); + f16.pack.fraction = f32.pack.fraction >> 13; + f16.pack.sign = f32.pack.sign; - outExponent = CLAMP(inExponent - 127, -15, 16) + 15; - - outFraction = 0; - if (outExponent == 0x1F) - { - if (inExponent == 0xFF && inFraction != 0) - outFraction = 0x3FF; - } - else if (outExponent == 0x00) - { - if (inExponent == 0x00 && inFraction != 0) - outFraction = 0x3FF; - } - else - outFraction = inFraction >> 13; - - out = (sign << 15) | (outExponent << 10) | outFraction; - - return out; + return f16.i; } diff --git a/code/renderergl2/tr_extramath.h b/code/renderergl2/tr_extramath.h index 0223c640..93271537 100644 --- a/code/renderergl2/tr_extramath.h +++ b/code/renderergl2/tr_extramath.h @@ -56,9 +56,6 @@ void Mat4SimpleInverse( const mat4_t in, mat4_t out); #define ByteToFloat(a) ((float)(a) * 1.0f/255.0f) #define FloatToByte(a) (byte)((a) * 255.0f) -#define RGBtosRGB(a) (((a) < 0.0031308f) ? (12.92f * (a)) : (1.055f * pow((a), 0.41666f) - 0.055f)) -#define sRGBtoRGB(a) (((a) <= 0.04045f) ? ((a) / 12.92f) : (pow((((a) + 0.055f) / 1.055f), 2.4)) ) - static ID_INLINE int VectorCompare4(const vec4_t v1, const vec4_t v2) { if(v1[0] != v2[0] || v1[1] != v2[1] || v1[2] != v2[2] || v1[3] != v2[3]) diff --git a/code/renderergl2/tr_fbo.c b/code/renderergl2/tr_fbo.c index c642b732..c8ea0aeb 100644 --- a/code/renderergl2/tr_fbo.c +++ b/code/renderergl2/tr_fbo.c @@ -47,9 +47,6 @@ qboolean R_CheckFBO(const FBO_t * fbo) // an error occured switch (code) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: ri.Printf(PRINT_WARNING, "R_CheckFBO: (%s) Unsupported framebuffer format\n", fbo->name); break; @@ -447,7 +444,6 @@ void FBO_Init(void) if (tr.renderFbo) { FBO_Bind(tr.renderFbo); - qglClearColor( 1, 0, 0.5, 1 ); qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); FBO_Bind(NULL); } @@ -484,7 +480,7 @@ void FBO_Init(void) if (tr.sunShadowDepthImage[0]) { - for ( i = 0; i < 3; i++) + for ( i = 0; i < 4; i++) { tr.sunShadowFbo[i] = FBO_Create("_sunshadowmap", tr.sunShadowDepthImage[i]->width, tr.sunShadowDepthImage[i]->height); FBO_Bind(tr.sunShadowFbo[i]); @@ -654,9 +650,6 @@ void R_FBOList_f(void) ri.Printf(PRINT_ALL, " %i FBOs\n", tr.numFBOs); } -// FIXME -extern void RB_SetGL2D (void); - void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) { ivec4_t dstBox, srcBox; @@ -749,7 +742,7 @@ void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexS Mat4Ortho(0, width, height, 0, 0, 1, projection); - qglDisable( GL_CULL_FACE ); + GL_Cull( CT_TWO_SIDED ); GL_BindToTMU(src, TB_COLORMAP); diff --git a/code/renderergl2/tr_glsl.c b/code/renderergl2/tr_glsl.c index 58a00e6e..f526b8c6 100644 --- a/code/renderergl2/tr_glsl.c +++ b/code/renderergl2/tr_glsl.c @@ -79,16 +79,17 @@ static uniformInfo_t uniformsInfo[] = { "u_ShadowMap", GLSL_INT }, { "u_ShadowMap2", GLSL_INT }, { "u_ShadowMap3", GLSL_INT }, + { "u_ShadowMap4", GLSL_INT }, { "u_ShadowMvp", GLSL_MAT16 }, { "u_ShadowMvp2", GLSL_MAT16 }, { "u_ShadowMvp3", GLSL_MAT16 }, + { "u_ShadowMvp4", GLSL_MAT16 }, { "u_EnableTextures", GLSL_VEC4 }, { "u_DiffuseTexMatrix", GLSL_VEC4 }, { "u_DiffuseTexOffTurb", GLSL_VEC4 }, - { "u_Texture1Env", GLSL_INT }, { "u_TCGen0", GLSL_INT }, { "u_TCGen0Vector0", GLSL_VEC3 }, @@ -251,7 +252,7 @@ static void GLSL_GetShaderHeader( GLenum shaderType, const GLcharARB *extra, cha // va("#ifndef r_NormalScale\n#define r_NormalScale %f\n#endif\n", r_normalScale->value)); - Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846f\n#endif\n"); + Q_strcat(dest, size, "#ifndef M_PI\n#define M_PI 3.14159265358979323846\n#endif\n"); //Q_strcat(dest, size, va("#ifndef MAX_SHADOWMAPS\n#define MAX_SHADOWMAPS %i\n#endif\n", MAX_SHADOWMAPS)); @@ -400,24 +401,30 @@ static int GLSL_LoadGPUShaderText(const char *name, const char *fallback, Com_sprintf(filename, sizeof(filename), "glsl/%s_fp.glsl", name); } - ri.Printf(PRINT_DEVELOPER, "...loading '%s'\n", filename); - size = ri.FS_ReadFile(filename, (void **)&buffer); + if ( r_externalGLSL->integer ) { + size = ri.FS_ReadFile(filename, (void **)&buffer); + } else { + size = 0; + buffer = NULL; + } + if(!buffer) { if (fallback) { - ri.Printf(PRINT_DEVELOPER, "couldn't load, using fallback\n"); + ri.Printf(PRINT_DEVELOPER, "...loading built-in '%s'\n", filename); shaderText = fallback; size = strlen(shaderText); } else { - ri.Printf(PRINT_DEVELOPER, "couldn't load!\n"); + ri.Printf(PRINT_DEVELOPER, "couldn't load '%s'\n", filename); return 0; } } else { + ri.Printf(PRINT_DEVELOPER, "...loading '%s'\n", filename); shaderText = buffer; } @@ -529,10 +536,10 @@ static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int qglBindAttribLocationARB(program->program, ATTR_INDEX_POSITION, "attr_Position"); if(attribs & ATTR_TEXCOORD) - qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD0, "attr_TexCoord0"); + qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD, "attr_TexCoord0"); if(attribs & ATTR_LIGHTCOORD) - qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD1, "attr_TexCoord1"); + qglBindAttribLocationARB(program->program, ATTR_INDEX_LIGHTCOORD, "attr_TexCoord1"); // if(attribs & ATTR_TEXCOORD2) // qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD2, "attr_TexCoord2"); @@ -540,10 +547,8 @@ static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int // if(attribs & ATTR_TEXCOORD3) // qglBindAttribLocationARB(program->program, ATTR_INDEX_TEXCOORD3, "attr_TexCoord3"); -#ifdef USE_VERT_TANGENT_SPACE if(attribs & ATTR_TANGENT) qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT, "attr_Tangent"); -#endif if(attribs & ATTR_NORMAL) qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL, "attr_Normal"); @@ -563,10 +568,8 @@ static int GLSL_InitGPUShader2(shaderProgram_t * program, const char *name, int if(attribs & ATTR_NORMAL2) qglBindAttribLocationARB(program->program, ATTR_INDEX_NORMAL2, "attr_Normal2"); -#ifdef USE_VERT_TANGENT_SPACE if(attribs & ATTR_TANGENT2) qglBindAttribLocationARB(program->program, ATTR_INDEX_TANGENT2, "attr_Tangent2"); -#endif GLSL_LinkProgram(program->program); @@ -915,12 +918,6 @@ void GLSL_InitGPUShaders(void) if (i & GENERICDEF_USE_RGBAGEN) Q_strcat(extradefines, 1024, "#define USE_RGBAGEN\n"); - if (i & GENERICDEF_USE_LIGHTMAP) - Q_strcat(extradefines, 1024, "#define USE_LIGHTMAP\n"); - - if (r_hdr->integer && !glRefConfig.floatLightmap) - Q_strcat(extradefines, 1024, "#define RGBM_LIGHTMAP\n"); - if (!GLSL_InitGPUShader(&tr.genericShader[i], "generic", attribs, qtrue, extradefines, qtrue, fallbackShader_generic_vp, fallbackShader_generic_fp)) { ri.Error(ERR_FATAL, "Could not load generic shader!"); @@ -1082,7 +1079,11 @@ void GLSL_InitGPUShaders(void) #endif if ((i & LIGHTDEF_USE_PARALLAXMAP) && !(i & LIGHTDEF_ENTITY) && r_parallaxMapping->integer) + { Q_strcat(extradefines, 1024, "#define USE_PARALLAXMAP\n"); + if (r_parallaxMapping->integer > 1) + Q_strcat(extradefines, 1024, "#define USE_RELIEFMAP\n"); + } } if (r_specularMapping->integer) @@ -1168,7 +1169,7 @@ void GLSL_InitGPUShaders(void) numLightShaders++; } - + attribs = ATTR_POSITION | ATTR_POSITION2 | ATTR_NORMAL | ATTR_NORMAL2 | ATTR_TEXCOORD; extradefines[0] = '\0'; @@ -1296,9 +1297,10 @@ void GLSL_InitGPUShaders(void) if (r_shadowFilter->integer >= 2) Q_strcat(extradefines, 1024, "#define USE_SHADOW_FILTER2\n"); - Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n"); + if (r_shadowCascadeZFar->integer != 0) + Q_strcat(extradefines, 1024, "#define USE_SHADOW_CASCADE\n"); - Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %d\n", r_shadowMapSize->integer)); + Q_strcat(extradefines, 1024, va("#define r_shadowMapSize %f\n", r_shadowMapSize->value)); Q_strcat(extradefines, 1024, va("#define r_shadowCascadeZFar %f\n", r_shadowCascadeZFar->value)); @@ -1314,6 +1316,7 @@ void GLSL_InitGPUShaders(void) GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP, TB_SHADOWMAP); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP2, TB_SHADOWMAP2); GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP3, TB_SHADOWMAP3); + GLSL_SetUniformInt(&tr.shadowmaskShader, UNIFORM_SHADOWMAP4, TB_SHADOWMAP4); qglUseProgramObjectARB(0); GLSL_FinishGPUShader(&tr.shadowmaskShader); @@ -1402,20 +1405,9 @@ void GLSL_ShutdownGPUShaders(void) ri.Printf(PRINT_ALL, "------- GLSL_ShutdownGPUShaders -------\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2); - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL); -#ifdef USE_VERT_TANGENT_SPACE - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT); -#endif - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2); -#ifdef USE_VERT_TANGENT_SPACE - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2); -#endif - qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR); - qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION); + for (i = 0; i < ATTR_INDEX_COUNT; i++) + qglDisableVertexAttribArrayARB(i); + GLSL_BindNullProgram(); for ( i = 0; i < GENERICDEF_COUNT; i++) @@ -1490,275 +1482,6 @@ void GLSL_BindNullProgram(void) } -void GLSL_VertexAttribsState(uint32_t stateBits) -{ - uint32_t diff; - - GLSL_VertexAttribPointers(stateBits); - - diff = stateBits ^ glState.vertexAttribsState; - if(!diff) - { - return; - } - - if(diff & ATTR_POSITION) - { - if(stateBits & ATTR_POSITION) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION); - } - } - - if(diff & ATTR_TEXCOORD) - { - if(stateBits & ATTR_TEXCOORD) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TEXCOORD )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD0); - } - } - - if(diff & ATTR_LIGHTCOORD) - { - if(stateBits & ATTR_LIGHTCOORD) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTCOORD )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TEXCOORD1); - } - } - - if(diff & ATTR_NORMAL) - { - if(stateBits & ATTR_NORMAL) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL); - } - } - -#ifdef USE_VERT_TANGENT_SPACE - if(diff & ATTR_TANGENT) - { - if(stateBits & ATTR_TANGENT) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT); - } - } -#endif - - if(diff & ATTR_COLOR) - { - if(stateBits & ATTR_COLOR) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_COLOR); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_COLOR )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_COLOR); - } - } - - if(diff & ATTR_LIGHTDIRECTION) - { - if(stateBits & ATTR_LIGHTDIRECTION) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_LIGHTDIRECTION )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_LIGHTDIRECTION); - } - } - - if(diff & ATTR_POSITION2) - { - if(stateBits & ATTR_POSITION2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_POSITION2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_POSITION2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_POSITION2); - } - } - - if(diff & ATTR_NORMAL2) - { - if(stateBits & ATTR_NORMAL2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_NORMAL2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_NORMAL2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_NORMAL2); - } - } - -#ifdef USE_VERT_TANGENT_SPACE - if(diff & ATTR_TANGENT2) - { - if(stateBits & ATTR_TANGENT2) - { - GLimp_LogComment("qglEnableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n"); - qglEnableVertexAttribArrayARB(ATTR_INDEX_TANGENT2); - } - else - { - GLimp_LogComment("qglDisableVertexAttribArrayARB( ATTR_INDEX_TANGENT2 )\n"); - qglDisableVertexAttribArrayARB(ATTR_INDEX_TANGENT2); - } - } -#endif - - glState.vertexAttribsState = stateBits; -} - -void GLSL_VertexAttribPointers(uint32_t attribBits) -{ - qboolean animated; - int newFrame, oldFrame; - VBO_t *vbo = glState.currentVBO; - - if(!vbo) - { - ri.Error(ERR_FATAL, "GL_VertexAttribPointers: no VBO bound"); - return; - } - - // don't just call LogComment, or we will get a call to va() every frame! - if(r_logFile->integer) - { - GLimp_LogComment(va("--- GL_VertexAttribPointers( %s ) ---\n", vbo->name)); - } - - // position/normal/tangent are always set in case of animation - oldFrame = glState.vertexAttribsOldFrame; - newFrame = glState.vertexAttribsNewFrame; - animated = glState.vertexAnimation; - - if((attribBits & ATTR_POSITION) && (!(glState.vertexAttribPointersSet & ATTR_POSITION) || animated)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_POSITION, 3, GL_FLOAT, 0, vbo->stride_xyz, BUFFER_OFFSET(vbo->ofs_xyz + newFrame * vbo->size_xyz)); - glState.vertexAttribPointersSet |= ATTR_POSITION; - } - - if((attribBits & ATTR_TEXCOORD) && !(glState.vertexAttribPointersSet & ATTR_TEXCOORD)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TEXCOORD )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD0, 2, GL_FLOAT, 0, vbo->stride_st, BUFFER_OFFSET(vbo->ofs_st)); - glState.vertexAttribPointersSet |= ATTR_TEXCOORD; - } - - if((attribBits & ATTR_LIGHTCOORD) && !(glState.vertexAttribPointersSet & ATTR_LIGHTCOORD)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTCOORD )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TEXCOORD1, 2, GL_FLOAT, 0, vbo->stride_lightmap, BUFFER_OFFSET(vbo->ofs_lightmap)); - glState.vertexAttribPointersSet |= ATTR_LIGHTCOORD; - } - - if((attribBits & ATTR_NORMAL) && (!(glState.vertexAttribPointersSet & ATTR_NORMAL) || animated)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_NORMAL, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_normal, BUFFER_OFFSET(vbo->ofs_normal + newFrame * vbo->size_normal)); - glState.vertexAttribPointersSet |= ATTR_NORMAL; - } - -#ifdef USE_VERT_TANGENT_SPACE - if((attribBits & ATTR_TANGENT) && (!(glState.vertexAttribPointersSet & ATTR_TANGENT) || animated)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TANGENT, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_tangent, BUFFER_OFFSET(vbo->ofs_tangent + newFrame * vbo->size_normal)); // FIXME - glState.vertexAttribPointersSet |= ATTR_TANGENT; - } -#endif - - if((attribBits & ATTR_COLOR) && !(glState.vertexAttribPointersSet & ATTR_COLOR)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_COLOR )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_COLOR, 4, GL_FLOAT, 0, vbo->stride_vertexcolor, BUFFER_OFFSET(vbo->ofs_vertexcolor)); - glState.vertexAttribPointersSet |= ATTR_COLOR; - } - - if((attribBits & ATTR_LIGHTDIRECTION) && !(glState.vertexAttribPointersSet & ATTR_LIGHTDIRECTION)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_LIGHTDIRECTION )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_LIGHTDIRECTION, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_lightdir, BUFFER_OFFSET(vbo->ofs_lightdir)); - glState.vertexAttribPointersSet |= ATTR_LIGHTDIRECTION; - } - - if((attribBits & ATTR_POSITION2) && (!(glState.vertexAttribPointersSet & ATTR_POSITION2) || animated)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_POSITION2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_POSITION2, 3, GL_FLOAT, 0, vbo->stride_xyz, BUFFER_OFFSET(vbo->ofs_xyz + oldFrame * vbo->size_xyz)); - glState.vertexAttribPointersSet |= ATTR_POSITION2; - } - - if((attribBits & ATTR_NORMAL2) && (!(glState.vertexAttribPointersSet & ATTR_NORMAL2) || animated)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_NORMAL2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_NORMAL2, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_normal, BUFFER_OFFSET(vbo->ofs_normal + oldFrame * vbo->size_normal)); - glState.vertexAttribPointersSet |= ATTR_NORMAL2; - } - -#ifdef USE_VERT_TANGENT_SPACE - if((attribBits & ATTR_TANGENT2) && (!(glState.vertexAttribPointersSet & ATTR_TANGENT2) || animated)) - { - GLimp_LogComment("qglVertexAttribPointerARB( ATTR_INDEX_TANGENT2 )\n"); - - qglVertexAttribPointerARB(ATTR_INDEX_TANGENT2, 4, glRefConfig.packedNormalDataType, GL_TRUE, vbo->stride_tangent, BUFFER_OFFSET(vbo->ofs_tangent + oldFrame * vbo->size_normal)); // FIXME - glState.vertexAttribPointersSet |= ATTR_TANGENT2; - } -#endif - -} - - shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) { shaderStage_t *pStage = tess.xstages[stage]; @@ -1769,11 +1492,6 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) shaderAttribs |= GENERICDEF_USE_FOG; } - if (pStage->bundle[1].image[0] && tess.shader->multitextureEnv) - { - shaderAttribs |= GENERICDEF_USE_LIGHTMAP; - } - switch (pStage->rgbGen) { case CGEN_LIGHTING_DIFFUSE: diff --git a/code/renderergl2/tr_image.c b/code/renderergl2/tr_image.c index ffee673d..bb5759ee 100644 --- a/code/renderergl2/tr_image.c +++ b/code/renderergl2/tr_image.c @@ -1275,145 +1275,57 @@ void R_LightScaleTexture (byte *in, int inwidth, int inheight, qboolean only_gam /* ================ -R_MipMap2 +R_MipMapsRGB Operates in place, quartering the size of the texture -Proper linear filter +Colors are gamma correct ================ */ -static void R_MipMap2( byte *in, int inWidth, int inHeight ) { - int i, j, k; - byte *outpix; - int inWidthMask, inHeightMask; - int total; - int outWidth, outHeight; - unsigned *temp; - - outWidth = inWidth >> 1; - outHeight = inHeight >> 1; - temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); - - inWidthMask = inWidth - 1; - inHeightMask = inHeight - 1; - - for ( i = 0 ; i < outHeight ; i++ ) { - for ( j = 0 ; j < outWidth ; j++ ) { - outpix = (byte *) ( temp + i * outWidth + j ); - for ( k = 0 ; k < 4 ; k++ ) { - total = - 1 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 1 * (&in[ 4*(((i*2-1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] + - - 2 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2 )&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] + - - 2 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 4 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2+1)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k] + - - 1 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2-1)&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2 )&inWidthMask)) ])[k] + - 2 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2+1)&inWidthMask)) ])[k] + - 1 * (&in[ 4*(((i*2+2)&inHeightMask)*inWidth + ((j*2+2)&inWidthMask)) ])[k]; - outpix[k] = total / 36; - } - } - } - - Com_Memcpy( in, temp, outWidth * outHeight * 4 ); - ri.Hunk_FreeTempMemory( temp ); -} - - static void R_MipMapsRGB( byte *in, int inWidth, int inHeight) { - int i, j, k; - int outWidth, outHeight; - byte *temp; + int x, y, c, stride; + const byte *in2; + float total; + static float downmipSrgbLookup[256]; + static int downmipSrgbLookupSet = 0; + byte *out = in; - outWidth = inWidth >> 1; - outHeight = inHeight >> 1; - temp = ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); + if (!downmipSrgbLookupSet) { + for (x = 0; x < 256; x++) + downmipSrgbLookup[x] = powf(x / 255.0f, 2.2f) * 0.25f; + downmipSrgbLookupSet = 1; + } - for ( i = 0 ; i < outHeight ; i++ ) { - byte *outbyte = temp + ( i * outWidth ) * 4; - byte *inbyte1 = in + ( i * 2 * inWidth ) * 4; - byte *inbyte2 = in + ( (i * 2 + 1) * inWidth ) * 4; - for ( j = 0 ; j < outWidth ; j++ ) { - for ( k = 0 ; k < 3 ; k++ ) { - float total, current; + if (inWidth == 1 && inHeight == 1) + return; - current = ByteToFloat(inbyte1[0]); total = sRGBtoRGB(current); - current = ByteToFloat(inbyte1[4]); total += sRGBtoRGB(current); - current = ByteToFloat(inbyte2[0]); total += sRGBtoRGB(current); - current = ByteToFloat(inbyte2[4]); total += sRGBtoRGB(current); + if (inWidth == 1 || inHeight == 1) { + for (x = (inWidth * inHeight) >> 1; x; x--) { + for (c = 3; c; c--, in++) { + total = (downmipSrgbLookup[*(in)] + downmipSrgbLookup[*(in + 4)]) * 2.0f; - total *= 0.25f; - - inbyte1++; - inbyte2++; - - current = RGBtosRGB(total); - *outbyte++ = FloatToByte(current); + *out++ = (byte)(powf(total, 1.0f / 2.2f) * 255.0f); } - *outbyte++ = (inbyte1[0] + inbyte1[4] + inbyte2[0] + inbyte2[4]) >> 2; - inbyte1 += 5; - inbyte2 += 5; + *out++ = (*(in) + *(in + 4)) >> 1; in += 5; } - } - - Com_Memcpy( in, temp, outWidth * outHeight * 4 ); - ri.Hunk_FreeTempMemory( temp ); -} - -/* -================ -R_MipMap - -Operates in place, quartering the size of the texture -================ -*/ -static void R_MipMap (byte *in, int width, int height) { - int i, j; - byte *out; - int row; - - if ( !r_simpleMipMaps->integer ) { - R_MipMap2( in, width, height ); + return; } - if ( width == 1 && height == 1 ) { - return; - } + stride = inWidth * 4; + inWidth >>= 1; inHeight >>= 1; - row = width * 4; - out = in; - width >>= 1; - height >>= 1; + in2 = in + stride; + for (y = inHeight; y; y--, in += stride, in2 += stride) { + for (x = inWidth; x; x--) { + for (c = 3; c; c--, in++, in2++) { + total = downmipSrgbLookup[*(in)] + downmipSrgbLookup[*(in + 4)] + + downmipSrgbLookup[*(in2)] + downmipSrgbLookup[*(in2 + 4)]; - if ( width == 0 || height == 0 ) { - width += height; // get largest - for (i=0 ; i>1; - out[1] = ( in[1] + in[5] )>>1; - out[2] = ( in[2] + in[6] )>>1; - out[3] = ( in[3] + in[7] )>>1; - } - return; - } + *out++ = (byte)(powf(total, 1.0f / 2.2f) * 255.0f); + } - for (i=0 ; i>2; - out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2; - out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2; - out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2; + *out++ = (*(in) + *(in + 4) + *(in2) + *(in2 + 4)) >> 2; in += 5, in2 += 5; } } } @@ -2212,14 +2124,14 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + if (image->flags & IMGFLAG_MIPMAP) { - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { - qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } @@ -2729,7 +2641,6 @@ static void R_CreateFogImage( void ) { int x,y; byte *data; float d; - float borderColor[4]; data = ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 ); @@ -2744,18 +2655,8 @@ static void R_CreateFogImage( void ) { data[(y*FOG_S+x)*4+3] = 255*d; } } - // standard openGL clamping doesn't really do what we want -- it includes - // the border color at the edges. OpenGL 1.2 has clamp-to-edge, which does - // what we want. tr.fogImage = R_CreateImage("*fog", (byte *)data, FOG_S, FOG_T, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE, 0 ); ri.Hunk_FreeTempMemory( data ); - - borderColor[0] = 1.0; - borderColor[1] = 1.0; - borderColor[2] = 1.0; - borderColor[3] = 1; - - qglTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor ); } /* @@ -2813,7 +2714,7 @@ void R_CreateBuiltinImages( void ) { { for( x = 0; x < MAX_DLIGHTS; x++) { - tr.shadowCubemaps[x] = R_CreateImage(va("*shadowcubemap%i", x), (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE | IMGFLAG_CUBEMAP, 0); + tr.shadowCubemaps[x] = R_CreateImage(va("*shadowcubemap%i", x), NULL, PSHADOW_MAP_SIZE, PSHADOW_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_CLAMPTOEDGE | IMGFLAG_CUBEMAP, 0); } } @@ -2922,9 +2823,14 @@ void R_CreateBuiltinImages( void ) { if (r_sunlightMode->integer) { - for ( x = 0; x < 3; x++) + for ( x = 0; x < 4; x++) { tr.sunShadowDepthImage[x] = R_CreateImage(va("*sunshadowdepth%i", x), NULL, r_shadowMapSize->integer, r_shadowMapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_DEPTH_COMPONENT24_ARB); + GL_Bind(tr.sunShadowDepthImage[x]); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); } tr.screenShadowImage = R_CreateImage("*screenShadow", NULL, width, height, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE, GL_RGBA8); @@ -3090,12 +2996,15 @@ static char *CommaParse( char **data_p ) { // skip double slash comments if ( c == '/' && data[1] == '/' ) { - while (*data && *data != '\n') + data += 2; + while (*data && *data != '\n') { data++; + } } // skip /* */ comments else if ( c=='/' && data[1] == '*' ) { + data += 2; while ( *data && ( *data != '*' || data[1] != '/' ) ) { data++; @@ -3128,7 +3037,7 @@ static char *CommaParse( char **data_p ) { *data_p = ( char * ) data; return com_token; } - if (len < MAX_TOKEN_CHARS) + if (len < MAX_TOKEN_CHARS - 1) { com_token[len] = c; len++; @@ -3139,7 +3048,7 @@ static char *CommaParse( char **data_p ) { // parse a regular word do { - if (len < MAX_TOKEN_CHARS) + if (len < MAX_TOKEN_CHARS - 1) { com_token[len] = c; len++; @@ -3148,11 +3057,6 @@ static char *CommaParse( char **data_p ) { c = *data; } while (c>32 && c != ',' ); - if (len == MAX_TOKEN_CHARS) - { -// ri.Printf (PRINT_DEVELOPER, "Token exceeded %i chars, discarded.\n", MAX_TOKEN_CHARS); - len = 0; - } com_token[len] = 0; *data_p = ( char * ) data; @@ -3216,7 +3120,7 @@ qhandle_t RE_RegisterSkin( const char *name ) { // If not a .skin file, load as a single shader if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue ); return hSkin; } @@ -3287,7 +3191,7 @@ void R_InitSkins( void ) { skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces ), h_low ); + skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } diff --git a/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index b7dc64fe..525dfba0 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -101,15 +101,19 @@ cvar_t *r_ext_multi_draw_arrays; cvar_t *r_ext_framebuffer_object; cvar_t *r_ext_texture_float; cvar_t *r_arb_half_float_pixel; +cvar_t *r_arb_half_float_vertex; cvar_t *r_ext_framebuffer_multisample; cvar_t *r_arb_seamless_cube_map; cvar_t *r_arb_vertex_type_2_10_10_10_rev; +cvar_t *r_arb_vertex_array_object; cvar_t *r_mergeMultidraws; cvar_t *r_mergeLeafSurfaces; cvar_t *r_cameraExposure; +cvar_t *r_externalGLSL; + cvar_t *r_hdr; cvar_t *r_floatLightmap; cvar_t *r_postProcess; @@ -145,7 +149,6 @@ cvar_t *r_baseNormalY; cvar_t *r_baseParallax; cvar_t *r_baseSpecular; cvar_t *r_baseGloss; -cvar_t *r_recalcMD3Normals; cvar_t *r_mergeLightmaps; cvar_t *r_dlightMode; cvar_t *r_pshadowDist; @@ -942,16 +945,20 @@ void GL_SetDefaultState( void ) // make sure our GL state vector is set correctly // glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; + glState.storedGlState = 0; + glState.faceCulling = CT_TWO_SIDED; + glState.faceCullFront = qtrue; - glState.vertexAttribsState = 0; - glState.vertexAttribPointersSet = 0; glState.currentProgram = 0; qglUseProgramObjectARB(0); + if (glRefConfig.vertexArrayObject) + qglBindVertexArrayARB(0); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - glState.currentVBO = NULL; - glState.currentIBO = NULL; + glState.currentVao = NULL; + glState.vertexAttribsEnabled = 0; qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); qglDepthMask( GL_TRUE ); @@ -962,6 +969,11 @@ void GL_SetDefaultState( void ) if (glRefConfig.seamlessCubeMap) qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + // GL_POLYGON_OFFSET_FILL will be glEnable()d when this is used + qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); + + qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky } /* @@ -1132,9 +1144,11 @@ void R_Register( void ) r_ext_framebuffer_object = ri.Cvar_Get( "r_ext_framebuffer_object", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_float = ri.Cvar_Get( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH); r_arb_half_float_pixel = ri.Cvar_Get( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH); + r_arb_half_float_vertex = ri.Cvar_Get( "r_arb_half_float_vertex", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_framebuffer_multisample = ri.Cvar_Get( "r_ext_framebuffer_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH); r_arb_seamless_cube_map = ri.Cvar_Get( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH); r_arb_vertex_type_2_10_10_10_rev = ri.Cvar_Get( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH); + r_arb_vertex_array_object = ri.Cvar_Get( "r_arb_vertex_array_object", "1", CVAR_ARCHIVE | CVAR_LATCH); r_ext_texture_filter_anisotropic = ri.Cvar_Get( "r_ext_texture_filter_anisotropic", "0", CVAR_ARCHIVE | CVAR_LATCH ); @@ -1167,6 +1181,8 @@ void R_Register( void ) r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH); ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse); + r_externalGLSL = ri.Cvar_Get( "r_externalGLSL", "0", CVAR_LATCH ); + r_hdr = ri.Cvar_Get( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_floatLightmap = ri.Cvar_Get( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_postProcess = ri.Cvar_Get( "r_postProcess", "1", CVAR_ARCHIVE ); @@ -1206,7 +1222,6 @@ void R_Register( void ) r_baseGloss = ri.Cvar_Get( "r_baseGloss", "0.3", CVAR_ARCHIVE | CVAR_LATCH ); r_dlightMode = ri.Cvar_Get( "r_dlightMode", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_pshadowDist = ri.Cvar_Get( "r_pshadowDist", "128", CVAR_ARCHIVE ); - r_recalcMD3Normals = ri.Cvar_Get( "r_recalcMD3Normals", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_mergeLightmaps = ri.Cvar_Get( "r_mergeLightmaps", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_imageUpsample = ri.Cvar_Get( "r_imageUpsample", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_imageUpsampleMaxSize = ri.Cvar_Get( "r_imageUpsampleMaxSize", "1024", CVAR_ARCHIVE | CVAR_LATCH ); @@ -1223,9 +1238,9 @@ void R_Register( void ) r_sunShadows = ri.Cvar_Get( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_shadowFilter = ri.Cvar_Get( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_shadowMapSize = ri.Cvar_Get( "r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "4", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "3072", CVAR_ARCHIVE | CVAR_LATCH ); - r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "-320", CVAR_ARCHIVE | CVAR_LATCH ); + r_shadowCascadeZNear = ri.Cvar_Get( "r_shadowCascadeZNear", "8", CVAR_ARCHIVE | CVAR_LATCH ); + r_shadowCascadeZFar = ri.Cvar_Get( "r_shadowCascadeZFar", "1024", CVAR_ARCHIVE | CVAR_LATCH ); + r_shadowCascadeZBias = ri.Cvar_Get( "r_shadowCascadeZBias", "0", CVAR_ARCHIVE | CVAR_LATCH ); r_ignoreDstAlpha = ri.Cvar_Get( "r_ignoreDstAlpha", "1", CVAR_ARCHIVE | CVAR_LATCH ); // @@ -1440,7 +1455,7 @@ void R_Init( void ) { GLSL_InitGPUShaders(); - R_InitVBOs(); + R_InitVaos(); R_InitShaders(); @@ -1490,7 +1505,7 @@ void RE_Shutdown( qboolean destroyWindow ) { if (glRefConfig.framebufferObject) FBO_Shutdown(); R_DeleteTextures(); - R_ShutdownVBOs(); + R_ShutdownVaos(); GLSL_ShutdownGPUShaders(); } diff --git a/code/renderergl2/tr_light.c b/code/renderergl2/tr_light.c index 3d1d1f24..7d3ed2a5 100644 --- a/code/renderergl2/tr_light.c +++ b/code/renderergl2/tr_light.c @@ -99,7 +99,7 @@ void R_DlightBmodel( bmodel_t *bmodel ) { case SF_FACE: case SF_GRID: case SF_TRIANGLES: - case SF_VBO_MESH: + case SF_VAO_MESH: ((srfBspSurface_t *)surf->data)->dlightBits = mask; break; @@ -156,7 +156,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { frac[i] = v - pos[i]; if ( pos[i] < 0 ) { pos[i] = 0; - } else if ( pos[i] >= world->lightGridBounds[i] - 1 ) { + } else if ( pos[i] > world->lightGridBounds[i] - 1 ) { pos[i] = world->lightGridBounds[i] - 1; } } @@ -180,18 +180,15 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { byte *data; int lat, lng; vec3_t normal; - qboolean ignore; #if idppc float d0, d1, d2, d3, d4, d5; #endif factor = 1.0; data = gridData; - ignore = qfalse; for ( j = 0 ; j < 3 ; j++ ) { if ( i & (1<= world->lightGridBounds[j] - 1) - { - ignore = qtrue; // ignore values outside lightgrid + if ( pos[j] + 1 > world->lightGridBounds[j] - 1 ) { + break; // ignore values outside lightgrid } factor *= frac[j]; data += gridStep[j]; @@ -200,8 +197,9 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { } } - if ( ignore ) + if ( j != 3 ) { continue; + } if (world->hdrLightGrid) { diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index a0e9b5ec..21b572f5 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -49,8 +49,7 @@ typedef unsigned int glIndex_t; #define MAX_FBOS 64 #define MAX_VISCOUNTS 5 -#define MAX_VBOS 4096 -#define MAX_IBOS 4096 +#define MAX_VAOS 4096 #define MAX_CALC_PSHADOWS 64 #define MAX_DRAWN_PSHADOWS 16 // do not increase past 32, because bit flags are used on surfaces @@ -96,50 +95,41 @@ typedef struct { float transformMatrix[16]; } orientationr_t; +// Ensure this is >= the ATTR_INDEX_COUNT enum below +#define VAO_MAX_ATTRIBS 16 + typedef enum { - VBO_USAGE_STATIC, - VBO_USAGE_DYNAMIC -} vboUsage_t; + VAO_USAGE_STATIC, + VAO_USAGE_DYNAMIC +} vaoUsage_t; -typedef struct VBO_s +typedef struct vaoAttrib_s +{ + uint32_t enabled; + uint32_t count; + uint32_t type; + uint32_t normalized; + uint32_t stride; + uint32_t offset; +} +vaoAttrib_t; + +typedef struct vao_s { char name[MAX_QPATH]; + uint32_t vao; + uint32_t vertexesVBO; int vertexesSize; // amount of memory data allocated for all vertices in bytes - uint32_t ofs_xyz; - uint32_t ofs_normal; - uint32_t ofs_st; - uint32_t ofs_lightmap; - uint32_t ofs_vertexcolor; - uint32_t ofs_lightdir; -#ifdef USE_VERT_TANGENT_SPACE - uint32_t ofs_tangent; -#endif - uint32_t stride_xyz; - uint32_t stride_normal; - uint32_t stride_st; - uint32_t stride_lightmap; - uint32_t stride_vertexcolor; - uint32_t stride_lightdir; -#ifdef USE_VERT_TANGENT_SPACE - uint32_t stride_tangent; -#endif - uint32_t size_xyz; - uint32_t size_normal; + vaoAttrib_t attribs[VAO_MAX_ATTRIBS]; - int attribs; -} VBO_t; + uint32_t frameSize; // bytes to skip per frame when doing vertex animation -typedef struct IBO_s -{ - char name[MAX_QPATH]; - - uint32_t indexesVBO; + uint32_t indexesIBO; int indexesSize; // amount of memory data allocated for all triangles in bytes -// uint32_t ofsIndexes; -} IBO_t; +} vao_t; //=============================================================================== @@ -364,6 +354,7 @@ enum TB_SPECULARMAP = 4, TB_SHADOWMAP = 5, TB_CUBEMAP = 6, + TB_SHADOWMAP4 = 6, NUM_TEXTURE_BUNDLES = 7 }; @@ -460,8 +451,6 @@ typedef struct shader_s { float portalRange; // distance to fog out at qboolean isPortal; - int multitextureEnv; // 0, GL_MODULATE, GL_ADD (FIXME: put in stage) - cullType_t cullType; // CT_FRONT_SIDED, CT_BACK_SIDED, or CT_TWO_SIDED qboolean polygonOffset; // set for decals and other items that must be offset qboolean noMipMaps; // for console fonts, 2D elements, etc. @@ -513,8 +502,8 @@ static ID_INLINE qboolean ShaderRequiresCPUDeforms(const shader_t * shader) enum { ATTR_INDEX_POSITION = 0, - ATTR_INDEX_TEXCOORD0 = 1, - ATTR_INDEX_TEXCOORD1 = 2, + ATTR_INDEX_TEXCOORD = 1, + ATTR_INDEX_LIGHTCOORD = 2, ATTR_INDEX_TANGENT = 3, ATTR_INDEX_NORMAL = 4, ATTR_INDEX_COLOR = 5, @@ -526,26 +515,28 @@ enum // GPU vertex animations ATTR_INDEX_POSITION2 = 10, ATTR_INDEX_TANGENT2 = 11, - ATTR_INDEX_NORMAL2 = 12 + ATTR_INDEX_NORMAL2 = 12, + + ATTR_INDEX_COUNT = 13 }; enum { - ATTR_POSITION = 0x0001, - ATTR_TEXCOORD = 0x0002, - ATTR_LIGHTCOORD = 0x0004, - ATTR_TANGENT = 0x0008, - ATTR_NORMAL = 0x0010, - ATTR_COLOR = 0x0020, - ATTR_PAINTCOLOR = 0x0040, - ATTR_LIGHTDIRECTION = 0x0080, - ATTR_BONE_INDEXES = 0x0100, - ATTR_BONE_WEIGHTS = 0x0200, + ATTR_POSITION = 1 << ATTR_INDEX_POSITION, + ATTR_TEXCOORD = 1 << ATTR_INDEX_TEXCOORD, + ATTR_LIGHTCOORD = 1 << ATTR_INDEX_LIGHTCOORD, + ATTR_TANGENT = 1 << ATTR_INDEX_TANGENT, + ATTR_NORMAL = 1 << ATTR_INDEX_NORMAL, + ATTR_COLOR = 1 << ATTR_INDEX_COLOR, + ATTR_PAINTCOLOR = 1 << ATTR_INDEX_PAINTCOLOR, + ATTR_LIGHTDIRECTION = 1 << ATTR_INDEX_LIGHTDIRECTION, + ATTR_BONE_INDEXES = 1 << ATTR_INDEX_BONE_INDEXES, + ATTR_BONE_WEIGHTS = 1 << ATTR_INDEX_BONE_WEIGHTS, // for .md3 interpolation - ATTR_POSITION2 = 0x0400, - ATTR_TANGENT2 = 0x0800, - ATTR_NORMAL2 = 0x1000, + ATTR_POSITION2 = 1 << ATTR_INDEX_POSITION2, + ATTR_TANGENT2 = 1 << ATTR_INDEX_TANGENT2, + ATTR_NORMAL2 = 1 << ATTR_INDEX_NORMAL2, ATTR_DEFAULT = ATTR_POSITION, ATTR_BITS = ATTR_POSITION | @@ -570,9 +561,8 @@ enum GENERICDEF_USE_VERTEX_ANIMATION = 0x0004, GENERICDEF_USE_FOG = 0x0008, GENERICDEF_USE_RGBAGEN = 0x0010, - GENERICDEF_USE_LIGHTMAP = 0x0020, - GENERICDEF_ALL = 0x003F, - GENERICDEF_COUNT = 0x0040, + GENERICDEF_ALL = 0x001F, + GENERICDEF_COUNT = 0x0020, }; enum @@ -633,16 +623,17 @@ typedef enum UNIFORM_SHADOWMAP, UNIFORM_SHADOWMAP2, UNIFORM_SHADOWMAP3, + UNIFORM_SHADOWMAP4, UNIFORM_SHADOWMVP, UNIFORM_SHADOWMVP2, UNIFORM_SHADOWMVP3, + UNIFORM_SHADOWMVP4, UNIFORM_ENABLETEXTURES, UNIFORM_DIFFUSETEXMATRIX, UNIFORM_DIFFUSETEXOFFTURB, - UNIFORM_TEXTURE1ENV, UNIFORM_TCGEN0, UNIFORM_TCGEN0VECTOR0, @@ -760,7 +751,7 @@ typedef struct { int num_pshadows; struct pshadow_s *pshadows; - float sunShadowMvp[3][16]; + float sunShadowMvp[4][16]; float sunDir[4]; float sunCol[4]; float sunAmbCol[4]; @@ -857,9 +848,8 @@ typedef enum { SF_IQM, SF_FLARE, SF_ENTITY, // beams, rails, lightning, etc that can be determined by entity - SF_DISPLAY_LIST, - SF_VBO_MESH, - SF_VBO_MDVMESH, + SF_VAO_MESH, + SF_VAO_MDVMESH, SF_NUM_SURFACE_TYPES, SF_MAX = 0x7fffffff // ensures that sizeof( surfaceType_t ) == sizeof( int ) @@ -886,11 +876,6 @@ typedef struct srfPoly_s { polyVert_t *verts; } srfPoly_t; -typedef struct srfDisplayList_s { - surfaceType_t surfaceType; - int listNum; -} srfDisplayList_t; - typedef struct srfFlare_s { surfaceType_t surfaceType; @@ -922,7 +907,7 @@ typedef struct #define srfVert_t_cleared(x) srfVert_t (x) = {{0, 0, 0}, {0, 0}, {0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0, 0}} #endif -// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VBO_MESH +// srfBspSurface_t covers SF_GRID, SF_TRIANGLES, SF_POLY, and SF_VAO_MESH typedef struct srfBspSurface_s { surfaceType_t surfaceType; @@ -952,8 +937,7 @@ typedef struct srfBspSurface_s glIndex_t maxIndex; // static render data - VBO_t *vbo; - IBO_t *ibo; + vao_t *vao; // SF_GRID specific variables after here @@ -1015,7 +999,7 @@ typedef struct srfIQModel_s { int first_triangle, num_triangles; } srfIQModel_t; -typedef struct srfVBOMDVMesh_s +typedef struct srfVaoMdvMesh_s { surfaceType_t surfaceType; @@ -1029,9 +1013,8 @@ typedef struct srfVBOMDVMesh_s glIndex_t maxIndex; // static render data - VBO_t *vbo; - IBO_t *ibo; -} srfVBOMDVMesh_t; + vao_t *vao; +} srfVaoMdvMesh_t; extern void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])(void *); @@ -1255,8 +1238,8 @@ typedef struct mdvModel_s int numSurfaces; mdvSurface_t *surfaces; - int numVBOSurfaces; - srfVBOMDVMesh_t *vboSurfaces; + int numVaoSurfaces; + srfVaoMdvMesh_t *vaoSurfaces; int numSkins; } mdvModel_t; @@ -1368,17 +1351,15 @@ typedef struct { qboolean finishCalled; int texEnv[2]; int faceCulling; - unsigned long glStateBits; - uint32_t vertexAttribsState; - uint32_t vertexAttribPointersSet; - uint32_t vertexAttribsNewFrame; - uint32_t vertexAttribsOldFrame; + int faceCullFront; + uint32_t glStateBits; + uint32_t storedGlState; float vertexAttribsInterpolation; qboolean vertexAnimation; + uint32_t vertexAttribsEnabled; // global if no VAOs, tess only otherwise shaderProgram_t *currentProgram; FBO_t *currentFBO; - VBO_t *currentVBO; - IBO_t *currentIBO; + vao_t *currentVao; mat4_t modelview; mat4_t projection; mat4_t modelviewProjection; @@ -1425,8 +1406,13 @@ typedef struct { qboolean seamlessCubeMap; GLenum packedNormalDataType; + GLenum packedTexcoordDataType; + GLenum packedColorDataType; + int packedTexcoordDataSize; + int packedColorDataSize; qboolean floatLightmap; + qboolean vertexArrayObject; } glRefConfig_t; @@ -1435,13 +1421,12 @@ typedef struct { int c_surfBatches; float c_overDraw; - int c_vboVertexBuffers; - int c_vboIndexBuffers; - int c_vboVertexes; - int c_vboIndexes; + int c_vaoBinds; + int c_vaoVertexes; + int c_vaoIndexes; - int c_staticVboDraws; - int c_dynamicVboDraws; + int c_staticVaoDraws; + int c_dynamicVaoDraws; int c_multidraws; int c_multidrawsMerged; @@ -1534,7 +1519,7 @@ typedef struct { image_t *calcLevelsImage; image_t *targetLevelsImage; image_t *fixedLevelsImage; - image_t *sunShadowDepthImage[3]; + image_t *sunShadowDepthImage[4]; image_t *screenShadowImage; image_t *screenSsaoImage; image_t *hdrDepthImage; @@ -1551,7 +1536,7 @@ typedef struct { FBO_t *quarterFbo[2]; FBO_t *calcLevelsFbo; FBO_t *targetLevelsFbo; - FBO_t *sunShadowFbo[3]; + FBO_t *sunShadowFbo[4]; FBO_t *screenShadowFbo; FBO_t *screenSsaoFbo; FBO_t *hdrDepthFbo; @@ -1623,6 +1608,8 @@ typedef struct { qboolean sunShadows; vec3_t sunLight; // from the sky shader for this level vec3_t sunDirection; + vec3_t lastCascadeSunDirection; + float lastCascadeSunMvp[16]; frontEndCounters_t pc; int frontEndMsec; // not in pc due to clearing issue @@ -1640,11 +1627,8 @@ typedef struct { int numFBOs; FBO_t *fbos[MAX_FBOS]; - int numVBOs; - VBO_t *vbos[MAX_VBOS]; - - int numIBOs; - IBO_t *ibos[MAX_IBOS]; + int numVaos; + vao_t *vaos[MAX_VAOS]; // shader indexes from other modules will be looked up in tr.shaders[] // shader indexes from drawsurfs will be looked up in sortedShaders[] @@ -1723,9 +1707,11 @@ extern cvar_t *r_ext_multi_draw_arrays; extern cvar_t *r_ext_framebuffer_object; extern cvar_t *r_ext_texture_float; extern cvar_t *r_arb_half_float_pixel; +extern cvar_t *r_arb_half_float_vertex; extern cvar_t *r_ext_framebuffer_multisample; extern cvar_t *r_arb_seamless_cube_map; extern cvar_t *r_arb_vertex_type_2_10_10_10_rev; +extern cvar_t *r_arb_vertex_array_object; extern cvar_t *r_nobind; // turns off binding to appropriate textures extern cvar_t *r_singleShader; // make most world faces use default shader @@ -1766,6 +1752,8 @@ extern cvar_t *r_anaglyphMode; extern cvar_t *r_mergeMultidraws; extern cvar_t *r_mergeLeafSurfaces; +extern cvar_t *r_externalGLSL; + extern cvar_t *r_hdr; extern cvar_t *r_floatLightmap; extern cvar_t *r_postProcess; @@ -1805,7 +1793,6 @@ extern cvar_t *r_baseSpecular; extern cvar_t *r_baseGloss; extern cvar_t *r_dlightMode; extern cvar_t *r_pshadowDist; -extern cvar_t *r_recalcMD3Normals; extern cvar_t *r_mergeLightmaps; extern cvar_t *r_imageUpsample; extern cvar_t *r_imageUpsampleMaxSize; @@ -1866,8 +1853,9 @@ void R_DecomposeSort( unsigned sort, int *entityNum, shader_t **shader, void R_AddDrawSurf( surfaceType_t *surface, shader_t *shader, int fogIndex, int dlightMap, int pshadowMap, int cubemap ); -void R_CalcTangentSpace(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v0, const vec3_t v1, const vec3_t v2, const vec2_t t0, const vec2_t t1, const vec2_t t2); +void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2, + const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3); +void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t normal, vec3_t sdir, vec3_t tdir); qboolean R_CalcTangentVectors(srfVert_t * dv[3]); #define CULL_IN 0 // completely unclipped @@ -2011,7 +1999,7 @@ typedef struct stageVars vec2_t texcoords[NUM_TEXTURE_BUNDLES][SHADER_MAX_VERTEXES]; } stageVars_t; -#define MAX_MULTIDRAW_PRIMITIVES 16384 +#define MAX_MULTIDRAW_PRIMITIVES 256 typedef struct shaderCommands_s { @@ -2026,9 +2014,9 @@ typedef struct shaderCommands_s uint32_t lightdir[SHADER_MAX_VERTEXES] QALIGN(16); //int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16); - VBO_t *vbo; - IBO_t *ibo; - qboolean useInternalVBO; + void *attribPointers[ATTR_INDEX_COUNT]; + vao_t *vao; + qboolean useInternalVao; stageVars_t svars QALIGN(16); @@ -2051,7 +2039,6 @@ typedef struct shaderCommands_s int multiDrawPrimitives; GLsizei multiDrawNumIndexes[MAX_MULTIDRAW_PRIMITIVES]; glIndex_t *multiDrawFirstIndex[MAX_MULTIDRAW_PRIMITIVES]; - glIndex_t *multiDrawLastIndex[MAX_MULTIDRAW_PRIMITIVES]; glIndex_t multiDrawMinIndex[MAX_MULTIDRAW_PRIMITIVES]; glIndex_t multiDrawMaxIndex[MAX_MULTIDRAW_PRIMITIVES]; @@ -2068,7 +2055,7 @@ void RB_EndSurface(void); void RB_CheckOverflow( int verts, int indexes ); #define RB_CHECKOVERFLOW(v,i) if (tess.numVertexes + (v) >= SHADER_MAX_VERTEXES || tess.numIndexes + (i) >= SHADER_MAX_INDEXES ) {RB_CheckOverflow(v,i);} -void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex ); +void R_DrawElementsVao( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex ); void RB_StageIteratorGeneric( void ); void RB_StageIteratorSky( void ); void RB_StageIteratorVertexLitTexture( void ); @@ -2188,28 +2175,26 @@ VERTEX BUFFER OBJECTS ============================================================ */ -uint32_t R_VboPackTangent(vec4_t v); -uint32_t R_VboPackNormal(vec3_t v); -void R_VboUnpackTangent(vec4_t v, uint32_t b); -void R_VboUnpackNormal(vec3_t v, uint32_t b); +int R_VaoPackTangent(byte *out, vec4_t v); +int R_VaoPackNormal(byte *out, vec3_t v); +int R_VaoPackTexCoord(byte *out, vec2_t st); +int R_VaoPackColors(byte *out, vec4_t color); +void R_VaoUnpackTangent(vec4_t v, uint32_t b); +void R_VaoUnpackNormal(vec3_t v, uint32_t b); -VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage); -VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * vertexes, uint32_t stateBits, vboUsage_t usage); +vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage); +vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *inIndexes); -IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage); -IBO_t *R_CreateIBO2(const char *name, int numIndexes, glIndex_t * inIndexes, vboUsage_t usage); +void R_BindVao(vao_t *vao); +void R_BindNullVao(void); -void R_BindVBO(VBO_t * vbo); -void R_BindNullVBO(void); +void Vao_SetVertexPointers(vao_t *vao); -void R_BindIBO(IBO_t * ibo); -void R_BindNullIBO(void); +void R_InitVaos(void); +void R_ShutdownVaos(void); +void R_VaoList_f(void); -void R_InitVBOs(void); -void R_ShutdownVBOs(void); -void R_VBOList_f(void); - -void RB_UpdateVBOs(unsigned int attribBits); +void RB_UpdateTessVao(unsigned int attribBits); /* @@ -2222,7 +2207,6 @@ GLSL void GLSL_InitGPUShaders(void); void GLSL_ShutdownGPUShaders(void); -void GLSL_VertexAttribsState(uint32_t stateBits); void GLSL_VertexAttribPointers(uint32_t attribBits); void GLSL_BindProgram(shaderProgram_t * program); void GLSL_BindNullProgram(void); @@ -2292,20 +2276,6 @@ int R_IQMLerpTag( orientation_t *tag, iqmData_t *data, int startFrame, int endFrame, float frac, const char *tagName ); -/* -============================================================= - -IMAGE LOADERS - -============================================================= -*/ - -void R_LoadBMP( const char *name, byte **pic, int *width, int *height ); -void R_LoadJPG( const char *name, byte **pic, int *width, int *height ); -void R_LoadPCX( const char *name, byte **pic, int *width, int *height ); -void R_LoadPNG( const char *name, byte **pic, int *width, int *height ); -void R_LoadTGA( const char *name, byte **pic, int *width, int *height ); - /* ============================================================= ============================================================= diff --git a/code/renderergl2/tr_main.c b/code/renderergl2/tr_main.c index 3e614394..6d397c4a 100644 --- a/code/renderergl2/tr_main.c +++ b/code/renderergl2/tr_main.c @@ -294,13 +294,11 @@ void R_CalcTangentSpaceFast(vec3_t tangent, vec3_t bitangent, vec3_t normal, /* http://www.terathon.com/code/tangent.html */ -void R_CalcTBN(vec3_t tangent, vec3_t bitangent, vec3_t normal, - const vec3_t v1, const vec3_t v2, const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3) +void R_CalcTexDirs(vec3_t sdir, vec3_t tdir, const vec3_t v1, const vec3_t v2, + const vec3_t v3, const vec2_t w1, const vec2_t w2, const vec2_t w3) { - vec3_t u, v; float x1, x2, y1, y2, z1, z2; - float s1, s2, t1, t2; - float r, dot; + float s1, s2, t1, t2, r; x1 = v2[0] - v1[0]; x2 = v3[0] - v1[0]; @@ -316,24 +314,27 @@ void R_CalcTBN(vec3_t tangent, vec3_t bitangent, vec3_t normal, r = 1.0f / (s1 * t2 - s2 * t1); - VectorSet(tangent, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); - VectorSet(bitangent, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); + VectorSet(sdir, (t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); + VectorSet(tdir, (s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); +} - // compute the face normal based on vertex points - VectorSubtract(v3, v1, u); - VectorSubtract(v2, v1, v); - CrossProduct(u, v, normal); - - VectorNormalize(normal); +void R_CalcTbnFromNormalAndTexDirs(vec3_t tangent, vec3_t bitangent, vec3_t normal, vec3_t sdir, vec3_t tdir) +{ + vec3_t n_cross_t; + vec_t n_dot_t, handedness; // Gram-Schmidt orthogonalize - //tangent[a] = (t - n * Dot(n, t)).Normalize(); - dot = DotProduct(normal, tangent); - VectorMA(tangent, -dot, normal, tangent); + n_dot_t = DotProduct(normal, sdir); + VectorMA(sdir, -n_dot_t, normal, tangent); VectorNormalize(tangent); - // B=NxT - //CrossProduct(normal, tangent, bitangent); + // Calculate handedness + CrossProduct(normal, sdir, n_cross_t); + handedness = (DotProduct(n_cross_t, tdir) < 0.0f) ? -1.0f : 1.0f; + + // Calculate bitangent + CrossProduct(normal, tangent, bitangent); + VectorScale(bitangent, handedness, bitangent); } void R_CalcTBN2(vec3_t tangent, vec3_t bitangent, vec3_t normal, @@ -1574,7 +1575,7 @@ static qboolean SurfIsOffscreen( const drawSurf_t *drawSurf, vec4_t clipDest[128 shortest = len; } - R_VboUnpackNormal(tNormal, tess.normal[tess.indexes[i]]); + R_VaoUnpackNormal(tNormal, tess.normal[tess.indexes[i]]); if ( DotProduct( normal, tNormal ) >= 0 ) { @@ -1678,6 +1679,10 @@ int R_SpriteFogNum( trRefEntity_t *ent ) { return 0; } + if ( ent->e.renderfx & RF_CROSSHAIR ) { + return 0; + } + for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { @@ -2571,14 +2576,16 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) //splitZFar = 3072; break; } - - VectorCopy(fd->vieworg, lightOrigin); - + + if (level != 3) + VectorCopy(fd->vieworg, lightOrigin); + else + VectorCopy(tr.world->lightGridOrigin, lightOrigin); // Make up a projection VectorScale(lightDir, -1.0f, lightViewAxis[0]); - if (lightViewIndependentOfCameraView) + if (level == 3 || lightViewIndependentOfCameraView) { // Use world up as light view up VectorSet(lightViewAxis[2], 0, 0, 1); @@ -2598,7 +2605,7 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) // Check if too close to parallel to light direction if (abs(DotProduct(lightViewAxis[2], lightViewAxis[0])) > 0.9f) { - if (lightViewIndependentOfCameraView) + if (level == 3 || lightViewIndependentOfCameraView) { // Use world left as light view up VectorSet(lightViewAxis[2], 0, 1, 0); @@ -2635,56 +2642,117 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) ClearBounds(lightviewBounds[0], lightviewBounds[1]); - // add view near plane - lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f); - ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f); - VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base); + if (level != 3) + { + // add view near plane + lx = splitZNear * tan(fd->fov_x * M_PI / 360.0f); + ly = splitZNear * tan(fd->fov_y * M_PI / 360.0f); + VectorMA(fd->vieworg, splitZNear, fd->viewaxis[0], base); - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, lx, fd->viewaxis[1], point); + VectorMA(point, ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, -lx, fd->viewaxis[1], point); + VectorMA(point, ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, lx, fd->viewaxis[1], point); + VectorMA(point, -ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - + VectorMA(base, -lx, fd->viewaxis[1], point); + VectorMA(point, -ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + - // add view far plane - lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f); - ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f); - VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base); + // add view far plane + lx = splitZFar * tan(fd->fov_x * M_PI / 360.0f); + ly = splitZFar * tan(fd->fov_y * M_PI / 360.0f); + VectorMA(fd->vieworg, splitZFar, fd->viewaxis[0], base); - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, lx, fd->viewaxis[1], point); + VectorMA(point, ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, -lx, fd->viewaxis[1], point); + VectorMA(point, ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - VectorMA(base, lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, lx, fd->viewaxis[1], point); + VectorMA(point, -ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); - VectorMA(base, -lx, fd->viewaxis[1], point); - VectorMA(point, -ly, fd->viewaxis[2], point); - Mat4Transform(lightViewMatrix, point, lightViewPoint); - AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + VectorMA(base, -lx, fd->viewaxis[1], point); + VectorMA(point, -ly, fd->viewaxis[2], point); + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + } + else + { + // use light grid size as level size + // FIXME: could be tighter + vec3_t bounds; + + bounds[0] = tr.world->lightGridSize[0] * tr.world->lightGridBounds[0]; + bounds[1] = tr.world->lightGridSize[1] * tr.world->lightGridBounds[1]; + bounds[2] = tr.world->lightGridSize[2] * tr.world->lightGridBounds[2]; + + point[0] = tr.world->lightGridOrigin[0]; + point[1] = tr.world->lightGridOrigin[1]; + point[2] = tr.world->lightGridOrigin[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0] + bounds[0]; + point[1] = tr.world->lightGridOrigin[1]; + point[2] = tr.world->lightGridOrigin[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0]; + point[1] = tr.world->lightGridOrigin[1] + bounds[1]; + point[2] = tr.world->lightGridOrigin[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0] + bounds[0]; + point[1] = tr.world->lightGridOrigin[1] + bounds[1]; + point[2] = tr.world->lightGridOrigin[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0]; + point[1] = tr.world->lightGridOrigin[1]; + point[2] = tr.world->lightGridOrigin[2] + bounds[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0] + bounds[0]; + point[1] = tr.world->lightGridOrigin[1]; + point[2] = tr.world->lightGridOrigin[2] + bounds[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0]; + point[1] = tr.world->lightGridOrigin[1] + bounds[1]; + point[2] = tr.world->lightGridOrigin[2] + bounds[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + + point[0] = tr.world->lightGridOrigin[0] + bounds[0]; + point[1] = tr.world->lightGridOrigin[1] + bounds[1]; + point[2] = tr.world->lightGridOrigin[2] + bounds[2]; + Mat4Transform(lightViewMatrix, point, lightViewPoint); + AddPointToBounds(lightViewPoint, lightviewBounds[0], lightviewBounds[1]); + } if (!glRefConfig.depthClamp) lightviewBounds[0][0] = lightviewBounds[1][0] - 8192; @@ -2714,11 +2782,10 @@ void R_RenderSunShadowMaps(const refdef_t *fd, int level) VectorScale(lightviewBounds[1], worldUnitsPerTexel, lightviewBounds[1]); } - //ri.Printf(PRINT_ALL, "znear %f zfar %f\n", lightviewBounds[0][0], lightviewBounds[1][0]); - //ri.Printf(PRINT_ALL, "fovx %f fovy %f xmin %f xmax %f ymin %f ymax %f\n", fd->fov_x, fd->fov_y, xmin, xmax, ymin, ymax); + //ri.Printf(PRINT_ALL, "level %d znear %f zfar %f\n", level, lightviewBounds[0][0], lightviewBounds[1][0]); + //ri.Printf(PRINT_ALL, "xmin %f xmax %f ymin %f ymax %f\n", lightviewBounds[0][1], lightviewBounds[1][1], -lightviewBounds[1][2], -lightviewBounds[0][2]); } - { int firstDrawSurf; @@ -2856,6 +2923,7 @@ void R_RenderCubemapSide( int cubemapIndex, int cubemapSide, qboolean subscene ) R_RenderSunShadowMaps(&refdef, 0); R_RenderSunShadowMaps(&refdef, 1); R_RenderSunShadowMaps(&refdef, 2); + R_RenderSunShadowMaps(&refdef, 3); } } diff --git a/code/renderergl2/tr_mesh.c b/code/renderergl2/tr_mesh.c index 618958be..0d6844a4 100644 --- a/code/renderergl2/tr_mesh.c +++ b/code/renderergl2/tr_mesh.c @@ -388,9 +388,9 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) { // don't add third_person objects if not viewing through a portal if(!personalModel) { - srfVBOMDVMesh_t *vboSurface = &model->vboSurfaces[i]; + srfVaoMdvMesh_t *vaoSurface = &model->vaoSurfaces[i]; - R_AddDrawSurf((void *)vboSurface, shader, fogNum, qfalse, qfalse, cubemapIndex ); + R_AddDrawSurf((void *)vaoSurface, shader, fogNum, qfalse, qfalse, cubemapIndex ); } surface++; diff --git a/code/renderergl2/tr_model.c b/code/renderergl2/tr_model.c index f2f55425..897e202e 100644 --- a/code/renderergl2/tr_model.c +++ b/code/renderergl2/tr_model.c @@ -372,7 +372,7 @@ R_LoadMD3 */ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, const char *modName) { - int f, i, j, k; + int f, i, j; md3Header_t *md3Model; md3Frame_t *md3Frame; @@ -598,70 +598,54 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, #ifdef USE_VERT_TANGENT_SPACE // calc tangent spaces { - // Valgrind complaints: Conditional jump or move depends on uninitialised value(s) - // So lets Initialize them. - const float *v0 = NULL, *v1 = NULL, *v2 = NULL; - const float *t0 = NULL, *t1 = NULL, *t2 = NULL; - vec3_t tangent = { 0, 0, 0 }; - vec3_t bitangent = { 0, 0, 0 }; - vec3_t normal = { 0, 0, 0 }; - for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++) { VectorClear(v->tangent); VectorClear(v->bitangent); - if (r_recalcMD3Normals->integer) - VectorClear(v->normal); } for(f = 0; f < mdvModel->numFrames; f++) { for(j = 0, tri = surf->indexes; j < surf->numIndexes; j += 3, tri += 3) { - v0 = surf->verts[surf->numVerts * f + tri[0]].xyz; - v1 = surf->verts[surf->numVerts * f + tri[1]].xyz; - v2 = surf->verts[surf->numVerts * f + tri[2]].xyz; + vec3_t sdir, tdir; + const float *v0, *v1, *v2, *t0, *t1, *t2; + glIndex_t index0, index1, index2; + + index0 = surf->numVerts * f + tri[0]; + index1 = surf->numVerts * f + tri[1]; + index2 = surf->numVerts * f + tri[2]; + + v0 = surf->verts[index0].xyz; + v1 = surf->verts[index1].xyz; + v2 = surf->verts[index2].xyz; t0 = surf->st[tri[0]].st; t1 = surf->st[tri[1]].st; t2 = surf->st[tri[2]].st; - if (!r_recalcMD3Normals->integer) - VectorCopy(v->normal, normal); - else - VectorClear(normal); + R_CalcTexDirs(sdir, tdir, v0, v1, v2, t0, t1, t2); - #if 1 - R_CalcTangentSpace(tangent, bitangent, normal, v0, v1, v2, t0, t1, t2); - #else - R_CalcNormalForTriangle(normal, v0, v1, v2); - R_CalcTangentsForTriangle(tangent, bitangent, v0, v1, v2, t0, t1, t2); - #endif - - for(k = 0; k < 3; k++) - { - float *v; - - v = surf->verts[surf->numVerts * f + tri[k]].tangent; - VectorAdd(v, tangent, v); - - v = surf->verts[surf->numVerts * f + tri[k]].bitangent; - VectorAdd(v, bitangent, v); - - if (r_recalcMD3Normals->integer) - { - v = surf->verts[surf->numVerts * f + tri[k]].normal; - VectorAdd(v, normal, v); - } - } + VectorAdd(sdir, surf->verts[index0].tangent, surf->verts[index0].tangent); + VectorAdd(sdir, surf->verts[index1].tangent, surf->verts[index1].tangent); + VectorAdd(sdir, surf->verts[index2].tangent, surf->verts[index2].tangent); + VectorAdd(tdir, surf->verts[index0].bitangent, surf->verts[index0].bitangent); + VectorAdd(tdir, surf->verts[index1].bitangent, surf->verts[index1].bitangent); + VectorAdd(tdir, surf->verts[index2].bitangent, surf->verts[index2].bitangent); } } for(j = 0, v = surf->verts; j < (surf->numVerts * mdvModel->numFrames); j++, v++) { - VectorNormalize(v->tangent); - VectorNormalize(v->bitangent); - VectorNormalize(v->normal); + vec3_t sdir, tdir; + + VectorCopy(v->tangent, sdir); + VectorCopy(v->bitangent, tdir); + + VectorNormalize(sdir); + VectorNormalize(tdir); + + R_CalcTbnFromNormalAndTexDirs(v->tangent, v->bitangent, v->normal, sdir, tdir); } } #endif @@ -672,110 +656,174 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, int bufferSize, } { - srfVBOMDVMesh_t *vboSurf; + srfVaoMdvMesh_t *vaoSurf; - mdvModel->numVBOSurfaces = mdvModel->numSurfaces; - mdvModel->vboSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low); + mdvModel->numVaoSurfaces = mdvModel->numSurfaces; + mdvModel->vaoSurfaces = ri.Hunk_Alloc(sizeof(*mdvModel->vaoSurfaces) * mdvModel->numSurfaces, h_low); - vboSurf = mdvModel->vboSurfaces; + vaoSurf = mdvModel->vaoSurfaces; surf = mdvModel->surfaces; - for (i = 0; i < mdvModel->numSurfaces; i++, vboSurf++, surf++) + for (i = 0; i < mdvModel->numSurfaces; i++, vaoSurf++, surf++) { - vec3_t *verts; - vec2_t *texcoords; - uint32_t *normals; + uint32_t offset_xyz, offset_st, offset_normal, offset_tangent; + uint32_t stride_xyz, stride_st, stride_normal, stride_tangent; + uint32_t dataSize, dataOfs; + uint8_t *data; + + if (mdvModel->numFrames > 1) + { + // vertex animation, store texcoords first, then position/normal/tangents + offset_st = 0; + offset_xyz = surf->numVerts * glRefConfig.packedTexcoordDataSize; + offset_normal = offset_xyz + sizeof(vec3_t); + offset_tangent = offset_normal + sizeof(uint32_t); + stride_st = glRefConfig.packedTexcoordDataSize; + stride_xyz = sizeof(vec3_t) + sizeof(uint32_t); #ifdef USE_VERT_TANGENT_SPACE - uint32_t *tangents; + stride_xyz += sizeof(uint32_t); #endif + stride_normal = stride_tangent = stride_xyz; - byte *data; - int dataSize; - - int ofs_xyz, ofs_normal, ofs_st; + dataSize = offset_xyz + surf->numVerts * mdvModel->numFrames * stride_xyz; + } + else + { + // no animation, interleave everything + offset_xyz = 0; + offset_st = offset_xyz + sizeof(vec3_t); + offset_normal = offset_st + glRefConfig.packedTexcoordDataSize; + offset_tangent = offset_normal + sizeof(uint32_t); #ifdef USE_VERT_TANGENT_SPACE - int ofs_tangent; + stride_xyz = offset_tangent + sizeof(uint32_t); +#else + stride_xyz = offset_normal + sizeof(uint32_t); #endif + stride_st = stride_normal = stride_tangent = stride_xyz; - dataSize = 0; + dataSize = surf->numVerts * stride_xyz; + } - ofs_xyz = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*verts); - - ofs_normal = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*normals); - -#ifdef USE_VERT_TANGENT_SPACE - ofs_tangent = dataSize; - dataSize += surf->numVerts * mdvModel->numFrames * sizeof(*tangents); -#endif - - ofs_st = dataSize; - dataSize += surf->numVerts * sizeof(*texcoords); data = ri.Malloc(dataSize); + dataOfs = 0; - verts = (void *)(data + ofs_xyz); - normals = (void *)(data + ofs_normal); -#ifdef USE_VERT_TANGENT_SPACE - tangents = (void *)(data + ofs_tangent); -#endif - texcoords = (void *)(data + ofs_st); - - v = surf->verts; - for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ ) + if (mdvModel->numFrames > 1) { - vec3_t nxt; - vec4_t tangent; + st = surf->st; + for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { + dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st); + } - VectorCopy(v->xyz, verts[j]); - - normals[j] = R_VboPackNormal(v->normal); + v = surf->verts; + for ( j = 0; j < surf->numVerts * mdvModel->numFrames ; j++, v++ ) + { #ifdef USE_VERT_TANGENT_SPACE - CrossProduct(v->normal, v->tangent, nxt); - VectorCopy(v->tangent, tangent); - tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f; - - tangents[j] = R_VboPackTangent(tangent); + vec3_t nxt; + vec4_t tangent; #endif + // xyz + memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t)); + dataOfs += sizeof(vec3_t); + + // normal + dataOfs += R_VaoPackNormal(data + dataOfs, v->normal); + +#ifdef USE_VERT_TANGENT_SPACE + CrossProduct(v->normal, v->tangent, nxt); + VectorCopy(v->tangent, tangent); + tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f; + + // tangent + dataOfs += R_VaoPackTangent(data + dataOfs, tangent); +#endif + } + } + else + { + v = surf->verts; + st = surf->st; + for ( j = 0; j < surf->numVerts; j++, v++, st++ ) + { +#ifdef USE_VERT_TANGENT_SPACE + vec3_t nxt; + vec4_t tangent; +#endif + // xyz + memcpy(data + dataOfs, &v->xyz, sizeof(vec3_t)); + dataOfs += sizeof(v->xyz); + + // st + dataOfs += R_VaoPackTexCoord(data + dataOfs, st->st); + + // normal + dataOfs += R_VaoPackNormal(data + dataOfs, v->normal); + +#ifdef USE_VERT_TANGENT_SPACE + CrossProduct(v->normal, v->tangent, nxt); + VectorCopy(v->tangent, tangent); + tangent[3] = (DotProduct(nxt, v->bitangent) < 0.0f) ? -1.0f : 1.0f; + + // tangent + dataOfs += R_VaoPackTangent(data + dataOfs, tangent); +#endif + } } - st = surf->st; - for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { - texcoords[j][0] = st->st[0]; - texcoords[j][1] = st->st[1]; - } - - vboSurf->surfaceType = SF_VBO_MDVMESH; - vboSurf->mdvModel = mdvModel; - vboSurf->mdvSurface = surf; - vboSurf->numIndexes = surf->numIndexes; - vboSurf->numVerts = surf->numVerts; + vaoSurf->surfaceType = SF_VAO_MDVMESH; + vaoSurf->mdvModel = mdvModel; + vaoSurf->mdvSurface = surf; + vaoSurf->numIndexes = surf->numIndexes; + vaoSurf->numVerts = surf->numVerts; - vboSurf->minIndex = 0; - vboSurf->maxIndex = surf->numVerts; + vaoSurf->minIndex = 0; + vaoSurf->maxIndex = surf->numVerts - 1; - vboSurf->vbo = R_CreateVBO(va("staticMD3Mesh_VBO '%s'", surf->name), data, dataSize, VBO_USAGE_STATIC); + vaoSurf->vao = R_CreateVao(va("staticMD3Mesh_VAO '%s'", surf->name), data, dataSize, (byte *)surf->indexes, surf->numIndexes * sizeof(*surf->indexes), VAO_USAGE_STATIC); - vboSurf->vbo->ofs_xyz = ofs_xyz; - vboSurf->vbo->ofs_normal = ofs_normal; + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].enabled = 1; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].enabled = 1; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1; #ifdef USE_VERT_TANGENT_SPACE - vboSurf->vbo->ofs_tangent = ofs_tangent; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1; #endif - vboSurf->vbo->ofs_st = ofs_st; - vboSurf->vbo->stride_xyz = sizeof(*verts); - vboSurf->vbo->stride_normal = sizeof(*normals); -#ifdef USE_VERT_TANGENT_SPACE - vboSurf->vbo->stride_tangent = sizeof(*tangents); -#endif - vboSurf->vbo->stride_st = sizeof(*st); + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].count = 3; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].count = 2; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].count = 4; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].count = 4; - vboSurf->vbo->size_xyz = sizeof(*verts) * surf->numVerts; - vboSurf->vbo->size_normal = sizeof(*normals) * surf->numVerts; + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].type = GL_FLOAT; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].type = glRefConfig.packedTexcoordDataType; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; + + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].normalized = GL_FALSE; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].normalized = GL_FALSE; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; + + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].offset = offset_xyz; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].offset = offset_st; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].offset = offset_normal; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].offset = offset_tangent; + + vaoSurf->vao->attribs[ATTR_INDEX_POSITION].stride = stride_xyz; + vaoSurf->vao->attribs[ATTR_INDEX_TEXCOORD].stride = stride_st; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ].stride = stride_normal; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ].stride = stride_tangent; + + if (mdvModel->numFrames > 1) + { + vaoSurf->vao->attribs[ATTR_INDEX_POSITION2] = vaoSurf->vao->attribs[ATTR_INDEX_POSITION]; + vaoSurf->vao->attribs[ATTR_INDEX_NORMAL2 ] = vaoSurf->vao->attribs[ATTR_INDEX_NORMAL ]; + vaoSurf->vao->attribs[ATTR_INDEX_TANGENT2 ] = vaoSurf->vao->attribs[ATTR_INDEX_TANGENT ]; + + vaoSurf->vao->frameSize = stride_xyz * surf->numVerts; + } + + Vao_SetVertexPointers(vaoSurf->vao); ri.Free(data); - - vboSurf->ibo = R_CreateIBO2(va("staticMD3Mesh_IBO %s", surf->name), surf->numIndexes, surf->indexes, VBO_USAGE_STATIC); } } @@ -1132,6 +1180,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char ** RE_BeginRegistration */ void RE_BeginRegistration( glconfig_t *glconfigOut ) { + int i; R_Init(); @@ -1140,7 +1189,10 @@ void RE_BeginRegistration( glconfig_t *glconfigOut ) { R_IssuePendingRenderCommands(); tr.visIndex = 0; - memset(tr.visClusters, -2, sizeof(tr.visClusters)); // force markleafs to regenerate + // force markleafs to regenerate + for(i = 0; i < MAX_VISCOUNTS; i++) { + tr.visClusters[i] = -2; + } R_ClearFlares(); RE_ClearScene(); diff --git a/code/renderergl2/tr_model_iqm.c b/code/renderergl2/tr_model_iqm.c index b3843c5d..3cabca00 100644 --- a/code/renderergl2/tr_model_iqm.c +++ b/code/renderergl2/tr_model_iqm.c @@ -144,7 +144,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na unsigned short *framedata; char *str; int i, j; - float jointInvMats[IQM_MAX_JOINTS * 12]; + float jointInvMats[IQM_MAX_JOINTS * 12] = {0.0f}; float *mat, *matInv; size_t size, joint_names; iqmData_t *iqmData; @@ -1130,7 +1130,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { normal[1] = DotProduct(&nrmMat[3], &data->normals[3*vtx]); normal[2] = DotProduct(&nrmMat[6], &data->normals[3*vtx]); - *outNormal = R_VboPackNormal(normal); + R_VaoPackNormal((byte *)outNormal, normal); #ifdef USE_VERT_TANGENT_SPACE tangent[0] = DotProduct(&nrmMat[0], &data->tangents[4*vtx]); @@ -1138,7 +1138,7 @@ void RB_IQMSurfaceAnim( surfaceType_t *surface ) { tangent[2] = DotProduct(&nrmMat[6], &data->tangents[4*vtx]); tangent[3] = data->tangents[4*vtx+3]; - *outTangent++ = R_VboPackTangent(tangent); + R_VaoPackTangent((byte *)outTangent++, tangent); #endif } diff --git a/code/renderergl2/tr_scene.c b/code/renderergl2/tr_scene.c index db2d1386..88eda479 100644 --- a/code/renderergl2/tr_scene.c +++ b/code/renderergl2/tr_scene.c @@ -498,9 +498,30 @@ void RE_RenderScene( const refdef_t *fd ) { // playing with even more shadows if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows)) { - R_RenderSunShadowMaps(fd, 0); - R_RenderSunShadowMaps(fd, 1); - R_RenderSunShadowMaps(fd, 2); + if (r_shadowCascadeZFar != 0) + { + R_RenderSunShadowMaps(fd, 0); + R_RenderSunShadowMaps(fd, 1); + R_RenderSunShadowMaps(fd, 2); + } + else + { + Mat4Zero(tr.refdef.sunShadowMvp[0]); + Mat4Zero(tr.refdef.sunShadowMvp[1]); + Mat4Zero(tr.refdef.sunShadowMvp[2]); + } + + // only rerender last cascade if sun has changed position + if (r_forceSun->integer == 2 || !VectorCompare(tr.refdef.sunDir, tr.lastCascadeSunDirection)) + { + VectorCopy(tr.refdef.sunDir, tr.lastCascadeSunDirection); + R_RenderSunShadowMaps(fd, 3); + Mat4Copy(tr.refdef.sunShadowMvp[3], tr.lastCascadeSunMvp); + } + else + { + Mat4Copy(tr.lastCascadeSunMvp, tr.refdef.sunShadowMvp[3]); + } } // playing with cube maps diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c index 5285e28e..0a652fbb 100644 --- a/code/renderergl2/tr_shade.c +++ b/code/renderergl2/tr_shade.c @@ -41,7 +41,7 @@ R_DrawElements ================== */ -void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex ) +void R_DrawElementsVao( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex, glIndex_t maxIndex ) { if (glRefConfig.drawRangeElements) qglDrawRangeElementsEXT(GL_TRIANGLES, minIndex, maxIndex, numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(firstIndex * sizeof(glIndex_t))); @@ -51,10 +51,10 @@ void R_DrawElementsVBO( int numIndexes, glIndex_t firstIndex, glIndex_t minIndex } -static void R_DrawMultiElementsVBO( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex, +static void R_DrawMultiElementsVao( int multiDrawPrimitives, glIndex_t *multiDrawMinIndex, glIndex_t *multiDrawMaxIndex, GLsizei *multiDrawNumIndexes, glIndex_t **multiDrawFirstIndex) { - if (glRefConfig.multiDrawArrays) + if (glRefConfig.multiDrawArrays && multiDrawPrimitives > 1) { qglMultiDrawElementsEXT(GL_TRIANGLES, multiDrawNumIndexes, GL_INDEX_TYPE, (const GLvoid **)multiDrawFirstIndex, multiDrawPrimitives); } @@ -145,7 +145,6 @@ static void DrawTris (shaderCommands_t *input) { shaderProgram_t *sp = &tr.textureColorShader; vec4_t color; - GLSL_VertexAttribsState(ATTR_POSITION); GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); @@ -154,11 +153,11 @@ static void DrawTris (shaderCommands_t *input) { if (input->multiDrawPrimitives) { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); + R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } } @@ -202,7 +201,7 @@ void RB_BeginSurface( shader_t *shader, int fogNum, int cubemapIndex ) { tess.xstages = state->stages; tess.numPasses = state->numUnfoggedPasses; tess.currentStageIteratorFunc = state->optimalStageIteratorFunc; - tess.useInternalVBO = qtrue; + tess.useInternalVao = qtrue; tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset; if (tess.shader->clampTime && tess.shaderTime >= tess.shader->clampTime) { @@ -429,11 +428,11 @@ static void ProjectDlightTexture( void ) { if (tess.multiDrawPrimitives) { shaderCommands_t *input = &tess; - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); + R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; @@ -873,11 +872,11 @@ static void ForwardDlight( void ) { if (input->multiDrawPrimitives) { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); + R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; @@ -949,11 +948,11 @@ static void ProjectPshadowVBOGLSL( void ) { if (input->multiDrawPrimitives) { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); + R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; @@ -1032,11 +1031,11 @@ static void RB_FogPass( void ) { if (tess.multiDrawPrimitives) { shaderCommands_t *input = &tess; - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); + R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); } } @@ -1352,16 +1351,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) else if ( pStage->bundle[1].image[0] != 0 ) { R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); - - // - // lightmap/secondary pass - // - if ( r_lightmap->integer ) { - GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, GL_REPLACE); - } else { - GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, tess.shader->multitextureEnv); - } - R_BindAnimatedImageToTMU( &pStage->bundle[1], 1 ); } else @@ -1370,8 +1359,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) // set state // R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); - - GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, 0); } // @@ -1398,11 +1385,11 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input ) // if (input->multiDrawPrimitives) { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); + R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } // allow skipping out to show just lightmaps during development @@ -1462,11 +1449,11 @@ static void RB_RenderShadowmap( shaderCommands_t *input ) if (input->multiDrawPrimitives) { - R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); + R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { - R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); + R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } } } @@ -1489,20 +1476,20 @@ void RB_StageIteratorGeneric( void ) return; } - if (tess.useInternalVBO) + if (tess.useInternalVao) { RB_DeformTessGeometry(); } vertexAttribs = RB_CalcShaderVertexAttribs( input ); - if (tess.useInternalVBO) + if (tess.useInternalVao) { - RB_UpdateVBOs(vertexAttribs); + RB_UpdateTessVao(vertexAttribs); } else { - backEnd.pc.c_staticVboDraws++; + backEnd.pc.c_staticVaoDraws++; } // @@ -1518,33 +1505,35 @@ void RB_StageIteratorGeneric( void ) // // set face culling appropriately // - if ((backEnd.viewParms.flags & VPF_DEPTHSHADOW)) + if (input->shader->cullType == CT_TWO_SIDED) { - //GL_Cull( CT_TWO_SIDED ); - - if (input->shader->cullType == CT_TWO_SIDED) - GL_Cull( CT_TWO_SIDED ); - else if (input->shader->cullType == CT_FRONT_SIDED) - GL_Cull( CT_BACK_SIDED ); - else - GL_Cull( CT_FRONT_SIDED ); - + GL_Cull( CT_TWO_SIDED ); } else - GL_Cull( input->shader->cullType ); + { + qboolean cullFront = (input->shader->cullType == CT_FRONT_SIDED); + + if ( backEnd.viewParms.flags & VPF_DEPTHSHADOW ) + cullFront = !cullFront; + + if ( backEnd.viewParms.isMirror ) + cullFront = !cullFront; + + if ( backEnd.currentEntity && backEnd.currentEntity->mirrored ) + cullFront = !cullFront; + + if (cullFront) + GL_Cull( CT_FRONT_SIDED ); + else + GL_Cull( CT_BACK_SIDED ); + } // set polygon offset if necessary if ( input->shader->polygonOffset ) { qglEnable( GL_POLYGON_OFFSET_FILL ); - qglPolygonOffset( r_offsetFactor->value, r_offsetUnits->value ); } - // - // Set vertex attribs and pointers - // - GLSL_VertexAttribsState(vertexAttribs); - // // render depth if in depthfill mode // diff --git a/code/renderergl2/tr_shade_calc.c b/code/renderergl2/tr_shade_calc.c index c9816fa8..bb16bb0d 100644 --- a/code/renderergl2/tr_shade_calc.c +++ b/code/renderergl2/tr_shade_calc.c @@ -125,7 +125,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds ) for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) { - R_VboUnpackNormal(offset, *normal); + R_VaoUnpackNormal(offset, *normal); xyz[0] += offset[0] * scale; xyz[1] += offset[1] * scale; @@ -145,7 +145,7 @@ void RB_CalcDeformVertexes( deformStage_t *ds ) ds->deformationWave.phase + off, ds->deformationWave.frequency ); - R_VboUnpackNormal(offset, *normal); + R_VaoUnpackNormal(offset, *normal); xyz[0] += offset[0] * scale; xyz[1] += offset[1] * scale; @@ -170,7 +170,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) { for ( i = 0; i < tess.numVertexes; i++, xyz += 4, normal++ ) { vec3_t fNormal; - R_VboUnpackNormal(fNormal, *normal); + R_VaoUnpackNormal(fNormal, *normal); scale = 0.98f; scale = R_NoiseGet4f( xyz[0] * scale, xyz[1] * scale, xyz[2] * scale, @@ -189,7 +189,7 @@ void RB_CalcDeformNormals( deformStage_t *ds ) { VectorNormalizeFast( fNormal ); - *normal = R_VboPackNormal(fNormal); + R_VaoPackNormal((byte *)normal, fNormal); } } @@ -213,7 +213,7 @@ void RB_CalcBulgeVertexes( deformStage_t *ds ) { float scale; vec3_t fNormal; - R_VboUnpackNormal(fNormal, *normal); + R_VaoUnpackNormal(fNormal, *normal); off = (float)( FUNCTABLE_SIZE / (M_PI*2) ) * ( st[0] * ds->bulgeWidth + now ); @@ -277,7 +277,7 @@ void DeformText( const char *text ) { height[1] = 0; height[2] = -1; - R_VboUnpackNormal(fNormal, tess.normal[0]); + R_VaoUnpackNormal(fNormal, tess.normal[0]); CrossProduct( fNormal, height, width ); // find the midpoint of the box @@ -640,7 +640,7 @@ float RB_CalcWaveAlphaSingle( const waveForm_t *wf ) */ void RB_CalcModulateColorsByFog( unsigned char *colors ) { int i; - float texCoords[SHADER_MAX_VERTEXES][2]; + float texCoords[SHADER_MAX_VERTEXES][2] = {{0.0f}}; // calculate texcoords so we can derive density // this is not wasted, because it would only have diff --git a/code/renderergl2/tr_shader.c b/code/renderergl2/tr_shader.c index 295dad7b..9bf2ec20 100644 --- a/code/renderergl2/tr_shader.c +++ b/code/renderergl2/tr_shader.c @@ -639,7 +639,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) else if ( !Q_stricmp( token, "$lightmap" ) ) { stage->bundle[0].isLightmap = qtrue; - if ( shader.lightmapIndex < 0 ) { + if ( shader.lightmapIndex < 0 || !tr.lightmaps ) { stage->bundle[0].image[0] = tr.whiteImage; } else { stage->bundle[0].image[0] = tr.lightmaps[shader.lightmapIndex]; @@ -1091,6 +1091,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) { vec3_t color; + VectorClear( color ); + ParseVector( text, 3, color ); stage->constantColor[0] = 255 * color[0]; stage->constantColor[1] = 255 * color[1]; @@ -1265,8 +1267,8 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) token = COM_ParseExt( text, qfalse ); if ( token[0] == 0 ) break; - strcat( buffer, token ); - strcat( buffer, " " ); + Q_strcat( buffer, sizeof (buffer), token ); + Q_strcat( buffer, sizeof (buffer), " " ); } ParseTexMod( buffer, stage ); @@ -1712,7 +1714,7 @@ static qboolean ParseShader( char **text ) else if ( token[0] == '{' ) { if ( s >= MAX_SHADER_STAGES ) { - ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s\n", shader.name ); + ri.Printf( PRINT_WARNING, "WARNING: too many stages in shader %s (max is %i)\n", shader.name, MAX_SHADER_STAGES ); return qfalse; } @@ -1854,6 +1856,23 @@ static qboolean ParseShader( char **text ) return qfalse; } + if ( r_greyscale->integer ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + VectorSet( shader.fogParms.color, luminance, luminance, luminance ); + } + else if ( r_greyscale->value ) + { + float luminance; + + luminance = LUMA( shader.fogParms.color[0], shader.fogParms.color[1], shader.fogParms.color[2] ); + shader.fogParms.color[0] = LERP( shader.fogParms.color[0], luminance, r_greyscale->value ); + shader.fogParms.color[1] = LERP( shader.fogParms.color[1], luminance, r_greyscale->value ); + shader.fogParms.color[2] = LERP( shader.fogParms.color[2], luminance, r_greyscale->value ); + } + token = COM_ParseExt( text, qfalse ); if ( !token[0] ) { @@ -2120,161 +2139,6 @@ static void ComputeVertexAttribs(void) } } -typedef struct { - int blendA; - int blendB; - - int multitextureEnv; - int multitextureBlend; -} collapse_t; - -static collapse_t collapse[] = { - { 0, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, - GL_MODULATE, 0 }, - - { 0, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, - GL_MODULATE, 0 }, - - { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO, - GL_MODULATE, GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR }, - - { 0, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, - GL_ADD, 0 }, - - { GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE, - GL_ADD, GLS_DSTBLEND_ONE | GLS_SRCBLEND_ONE }, -#if 0 - { 0, GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_SRCBLEND_SRC_ALPHA, - GL_DECAL, 0 }, -#endif - { -1 } -}; - -/* -================ -CollapseMultitexture - -Attempt to combine two stages into a single multitexture stage -FIXME: I think modulated add + modulated add collapses incorrectly -================= -*/ -static qboolean CollapseMultitexture( void ) { - int abits, bbits; - int i; - textureBundle_t tmpBundle; - - if ( !qglActiveTextureARB ) { - return qfalse; - } - - // make sure both stages are active - if ( !stages[0].active || !stages[1].active ) { - return qfalse; - } - - // on voodoo2, don't combine different tmus - if ( glConfig.driverType == GLDRV_VOODOO ) { - if ( stages[0].bundle[0].image[0]->TMU == - stages[1].bundle[0].image[0]->TMU ) { - return qfalse; - } - } - - abits = stages[0].stateBits; - bbits = stages[1].stateBits; - - // make sure that both stages have identical state other than blend modes - if ( ( abits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) != - ( bbits & ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS | GLS_DEPTHMASK_TRUE ) ) ) { - return qfalse; - } - - abits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - bbits &= ( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - - // search for a valid multitexture blend function - for ( i = 0; collapse[i].blendA != -1 ; i++ ) { - if ( abits == collapse[i].blendA - && bbits == collapse[i].blendB ) { - break; - } - } - - // nothing found - if ( collapse[i].blendA == -1 ) { - return qfalse; - } - - // GL_ADD is a separate extension - if ( collapse[i].multitextureEnv == GL_ADD && !glConfig.textureEnvAddAvailable ) { - return qfalse; - } - - // make sure waveforms have identical parameters - if ( ( stages[0].rgbGen != stages[1].rgbGen ) || - ( stages[0].alphaGen != stages[1].alphaGen ) ) { - return qfalse; - } - - // an add collapse can only have identity colors - if ( collapse[i].multitextureEnv == GL_ADD && stages[0].rgbGen != CGEN_IDENTITY ) { - return qfalse; - } - - if ( stages[0].rgbGen == CGEN_WAVEFORM ) - { - if ( memcmp( &stages[0].rgbWave, - &stages[1].rgbWave, - sizeof( stages[0].rgbWave ) ) ) - { - return qfalse; - } - } - if ( stages[0].alphaGen == AGEN_WAVEFORM ) - { - if ( memcmp( &stages[0].alphaWave, - &stages[1].alphaWave, - sizeof( stages[0].alphaWave ) ) ) - { - return qfalse; - } - } - - - // make sure that lightmaps are in bundle 1 for 3dfx - if ( stages[0].bundle[0].isLightmap ) - { - tmpBundle = stages[0].bundle[0]; - stages[0].bundle[0] = stages[1].bundle[0]; - stages[0].bundle[1] = tmpBundle; - } - else - { - stages[0].bundle[1] = stages[1].bundle[0]; - } - - // set the new blend state bits - shader.multitextureEnv = collapse[i].multitextureEnv; - stages[0].stateBits &= ~( GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS ); - stages[0].stateBits |= collapse[i].multitextureBlend; - - // - // move down subsequent shaders - // - memmove( &stages[1], &stages[2], sizeof( stages[0] ) * ( MAX_SHADER_STAGES - 2 ) ); - Com_Memset( &stages[MAX_SHADER_STAGES-1], 0, sizeof( stages[0] ) ); - - return qtrue; -} static void CollapseStagesToLightall(shaderStage_t *diffuse, shaderStage_t *normal, shaderStage_t *specular, shaderStage_t *lightmap, @@ -2368,7 +2232,7 @@ static void CollapseStagesToLightall(shaderStage_t *diffuse, } -static qboolean CollapseStagesToGLSL(void) +static int CollapseStagesToGLSL(void) { int i, j, numStages; qboolean skip = qfalse; @@ -2605,9 +2469,6 @@ static qboolean CollapseStagesToGLSL(void) numStages++; } - if (numStages == i && i >= 2 && CollapseMultitexture()) - numStages--; - // convert any remaining lightmap stages to a lighting pass with a white texture // only do this with r_sunlightMode non-zero, as it's only for correct shadows. if (r_sunlightMode->integer && shader.numDeforms == 0) @@ -2918,6 +2779,33 @@ static void VertexLightingCollapse( void ) { } } +/* +=============== +InitShader +=============== +*/ +static void InitShader( const char *name, int lightmapIndex ) { + int i; + + // clear the global shader + Com_Memset( &shader, 0, sizeof( shader ) ); + Com_Memset( &stages, 0, sizeof( stages ) ); + + Q_strncpyz( shader.name, name, sizeof( shader.name ) ); + shader.lightmapIndex = lightmapIndex; + + for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { + stages[i].bundle[0].texMods = texMods[i]; + + // default normal/specular + VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f); + stages[i].specularScale[0] = + stages[i].specularScale[1] = + stages[i].specularScale[2] = r_baseSpecular->value; + stages[i].specularScale[3] = r_baseGloss->value; + } +} + /* ========================= FinishShader @@ -3078,7 +2966,9 @@ static shader_t *FinishShader( void ) { // // look for multitexture potential // - stage = CollapseStagesToGLSL(); + if ( qglActiveTextureARB ) { + stage = CollapseStagesToGLSL(); + } if ( shader.lightmapIndex >= 0 && !hasLightmapStage ) { if (vertexLightmap) { @@ -3238,7 +3128,7 @@ most world construction surfaces. */ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImage ) { char strippedName[MAX_QPATH]; - int i, hash; + int hash; char *shaderText; image_t *image; shader_t *sh; @@ -3276,21 +3166,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag } } - // clear the global shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - Q_strncpyz(shader.name, strippedName, sizeof(shader.name)); - shader.lightmapIndex = lightmapIndex; - for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { - stages[i].bundle[0].texMods = texMods[i]; - - // default normal/specular - VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f); - stages[i].specularScale[0] = - stages[i].specularScale[1] = - stages[i].specularScale[2] = r_baseSpecular->value; - stages[i].specularScale[3] = r_baseGloss->value; - } + InitShader( strippedName, lightmapIndex ); // // attempt to define shader from an explicit parameter file @@ -3397,7 +3273,7 @@ shader_t *R_FindShader( const char *name, int lightmapIndex, qboolean mipRawImag qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_t *image, qboolean mipRawImage) { - int i, hash; + int hash; shader_t *sh; hash = generateHashValue(name, FILE_HASH_SIZE); @@ -3425,21 +3301,7 @@ qhandle_t RE_RegisterShaderFromImage(const char *name, int lightmapIndex, image_ } } - // clear the global shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - Q_strncpyz(shader.name, name, sizeof(shader.name)); - shader.lightmapIndex = lightmapIndex; - for ( i = 0 ; i < MAX_SHADER_STAGES ; i++ ) { - stages[i].bundle[0].texMods = texMods[i]; - - // default normal/specular - VectorSet4(stages[i].normalScale, 0.0f, 0.0f, 0.0f, 0.0f); - stages[i].specularScale[0] = - stages[i].specularScale[1] = - stages[i].specularScale[2] = r_baseSpecular->value; - stages[i].specularScale[3] = r_baseGloss->value; - } + InitShader( name, lightmapIndex ); // // create the default shading commands @@ -3644,15 +3506,6 @@ void R_ShaderList_f (void) { } else { ri.Printf (PRINT_ALL, " "); } - if ( shader->multitextureEnv == GL_ADD ) { - ri.Printf( PRINT_ALL, "MT(a) " ); - } else if ( shader->multitextureEnv == GL_MODULATE ) { - ri.Printf( PRINT_ALL, "MT(m) " ); - } else if ( shader->multitextureEnv == GL_DECAL ) { - ri.Printf( PRINT_ALL, "MT(d) " ); - } else { - ri.Printf( PRINT_ALL, " " ); - } if ( shader->explicitlyDefined ) { ri.Printf( PRINT_ALL, "E " ); } else { @@ -3690,7 +3543,7 @@ a single large text block that can be scanned for shader names static void ScanAndLoadShaderFiles( void ) { char **shaderFiles; - char *buffers[MAX_SHADER_FILES]; + char *buffers[MAX_SHADER_FILES] = {NULL}; char *p; int numShaderFiles; int i; @@ -3861,12 +3714,7 @@ static void CreateInternalShaders( void ) { tr.numShaders = 0; // init the default shader - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - - Q_strncpyz( shader.name, "", sizeof( shader.name ) ); - - shader.lightmapIndex = LIGHTMAP_NONE; + InitShader( "", LIGHTMAP_NONE ); stages[0].bundle[0].image[0] = tr.defaultImage; stages[0].active = qtrue; stages[0].stateBits = GLS_DEFAULT; @@ -3909,12 +3757,7 @@ static void CreateExternalShaders( void ) { else image = tr.dlightImage; - Com_Memset( &shader, 0, sizeof( shader ) ); - Com_Memset( &stages, 0, sizeof( stages ) ); - - Q_strncpyz( shader.name, "gfx/2d/sunflare", sizeof( shader.name ) ); - - shader.lightmapIndex = LIGHTMAP_NONE; + InitShader( "gfx/2d/sunflare", LIGHTMAP_NONE ); stages[0].bundle[0].image[0] = image; stages[0].active = qtrue; stages[0].stateBits = GLS_DEFAULT; diff --git a/code/renderergl2/tr_shadows.c b/code/renderergl2/tr_shadows.c index f412b00d..13fbfdf7 100644 --- a/code/renderergl2/tr_shadows.c +++ b/code/renderergl2/tr_shadows.c @@ -44,6 +44,7 @@ typedef struct { static edgeDef_t edgeDefs[SHADER_MAX_VERTEXES][MAX_EDGE_DEFS]; static int numEdgeDefs[SHADER_MAX_VERTEXES]; static int facing[SHADER_MAX_INDEXES/3]; +static vec3_t shadowXyz[SHADER_MAX_VERTEXES]; void R_AddEdgeDef( int i1, int i2, int facing ) { int c; @@ -80,13 +81,13 @@ void R_RenderShadowEdges( void ) { qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i1 ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i2 ] ); qglVertex3fv( tess.xyz[ i3 ] ); - qglVertex3fv( tess.xyz[ i3 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i3 ] ); qglVertex3fv( tess.xyz[ i1 ] ); - qglVertex3fv( tess.xyz[ i1 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i1 ] ); qglEnd(); } #else @@ -126,9 +127,9 @@ void R_RenderShadowEdges( void ) { if ( hit[ 1 ] == 0 ) { qglBegin( GL_TRIANGLE_STRIP ); qglVertex3fv( tess.xyz[ i ] ); - qglVertex3fv( tess.xyz[ i + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i ] ); qglVertex3fv( tess.xyz[ i2 ] ); - qglVertex3fv( tess.xyz[ i2 + tess.numVertexes ] ); + qglVertex3fv( shadowXyz[ i2 ] ); qglEnd(); c_edges++; } else { @@ -157,11 +158,6 @@ void RB_ShadowTessEnd( void ) { vec3_t lightDir; GLboolean rgba[4]; - // we can only do this if we have enough space in the vertex buffers - if ( tess.numVertexes >= SHADER_MAX_VERTEXES / 2 ) { - return; - } - if ( glConfig.stencilBits < 4 ) { return; } @@ -170,7 +166,7 @@ void RB_ShadowTessEnd( void ) { // project vertexes away from light direction for ( i = 0 ; i < tess.numVertexes ; i++ ) { - VectorMA( tess.xyz[i], -512, lightDir, tess.xyz[i+tess.numVertexes] ); + VectorMA( tess.xyz[i], -512, lightDir, shadowXyz[i] ); } // decide which triangles face the light @@ -211,7 +207,6 @@ void RB_ShadowTessEnd( void ) { // draw the silhouette edges GL_Bind( tr.whiteImage ); - qglEnable( GL_CULL_FACE ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor3f( 0.2f, 0.2f, 0.2f ); @@ -222,28 +217,15 @@ void RB_ShadowTessEnd( void ) { qglEnable( GL_STENCIL_TEST ); qglStencilFunc( GL_ALWAYS, 1, 255 ); - // mirrors have the culling order reversed - if ( backEnd.viewParms.isMirror ) { - qglCullFace( GL_FRONT ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); + GL_Cull( CT_BACK_SIDED ); + qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - R_RenderShadowEdges(); + R_RenderShadowEdges(); - qglCullFace( GL_BACK ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); + GL_Cull( CT_FRONT_SIDED ); + qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - R_RenderShadowEdges(); - } else { - qglCullFace( GL_BACK ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR ); - - R_RenderShadowEdges(); - - qglCullFace( GL_FRONT ); - qglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); - - R_RenderShadowEdges(); - } + R_RenderShadowEdges(); // reenable writing to the color buffer @@ -272,7 +254,7 @@ void RB_ShadowFinish( void ) { qglStencilFunc( GL_NOTEQUAL, 0, 255 ); qglDisable (GL_CLIP_PLANE0); - qglDisable (GL_CULL_FACE); + GL_Cull( CT_TWO_SIDED ); GL_Bind( tr.whiteImage ); diff --git a/code/renderergl2/tr_sky.c b/code/renderergl2/tr_sky.c index 3b739df0..05ff8f94 100644 --- a/code/renderergl2/tr_sky.c +++ b/code/renderergl2/tr_sky.c @@ -421,7 +421,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max tess.maxIndex = tess.numVertexes; // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function - RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD); + RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD); /* { shaderProgram_t *sp = &tr.textureColorShader; @@ -442,7 +442,6 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max shaderProgram_t *sp = &tr.lightallShader[0]; vec4_t vector; - GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); @@ -466,7 +465,7 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); } - R_DrawElementsVBO(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex); + R_DrawElementsVao(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex); //qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t))); diff --git a/code/renderergl2/tr_surface.c b/code/renderergl2/tr_surface.c index 825582bd..c5b1b0f8 100644 --- a/code/renderergl2/tr_surface.c +++ b/code/renderergl2/tr_surface.c @@ -66,19 +66,18 @@ void RB_CheckOverflow( int verts, int indexes ) { RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex ); } -void RB_CheckVBOandIBO(VBO_t *vbo, IBO_t *ibo) +void RB_CheckVao(vao_t *vao) { - if (!(vbo == glState.currentVBO && ibo == glState.currentIBO) || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES) + if (vao != glState.currentVao || tess.multiDrawPrimitives >= MAX_MULTIDRAW_PRIMITIVES) { RB_EndSurface(); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); - R_BindVBO(vbo); - R_BindIBO(ibo); + R_BindVao(vao); } - if (vbo != tess.vbo && ibo != tess.ibo) - tess.useInternalVBO = qfalse; + if (vao != tess.vao) + tess.useInternalVao = qfalse; } @@ -89,8 +88,11 @@ RB_AddQuadStampExt */ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], float s1, float t1, float s2, float t2 ) { vec3_t normal; + uint32_t pNormal; int ndx; + RB_CheckVao(tess.vao); + RB_CHECKOVERFLOW( 4, 6 ); ndx = tess.numVertexes; @@ -124,10 +126,11 @@ void RB_AddQuadStampExt( vec3_t origin, vec3_t left, vec3_t up, float color[4], // constant normal all the way around VectorSubtract( vec3_origin, backEnd.viewParms.or.axis[0], normal ); + R_VaoPackNormal((byte *)&pNormal, normal); tess.normal[ndx] = tess.normal[ndx+1] = tess.normal[ndx+2] = - tess.normal[ndx+3] = R_VboPackNormal(normal); + tess.normal[ndx+3] = pNormal; // standard square texture coordinates VectorSet2(tess.texCoords[ndx ][0], s1, t1); @@ -203,11 +206,9 @@ void RB_InstantQuad2(vec4_t quadVerts[4], vec2_t texCoords[4]) tess.minIndex = 0; tess.maxIndex = 3; - RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD); + RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD); - GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); - - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); + R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); tess.numIndexes = 0; tess.numVertexes = 0; @@ -284,6 +285,8 @@ static void RB_SurfacePolychain( srfPoly_t *p ) { int i; int numv; + RB_CheckVao(tess.vao); + RB_CHECKOVERFLOW( p->numVerts, 3*(p->numVerts - 2) ); // fan triangles into the tess array @@ -325,7 +328,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn glIndex_t *outIndex; float *color; - RB_CheckVBOandIBO(tess.vbo, tess.ibo); + RB_CheckVao(tess.vao); RB_CHECKOVERFLOW( numVerts, numIndexes ); @@ -349,7 +352,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn dv = verts; normal = &tess.normal[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, normal++ ) - *normal = R_VboPackNormal(dv->normal); + R_VaoPackNormal((byte *)normal, dv->normal); } #ifdef USE_VERT_TANGENT_SPACE @@ -358,7 +361,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn dv = verts; tangent = &tess.tangent[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, tangent++ ) - *tangent = R_VboPackTangent(dv->tangent); + R_VaoPackTangent((byte *)tangent, dv->tangent); } #endif @@ -391,7 +394,7 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn dv = verts; lightdir = &tess.lightdir[ tess.numVertexes ]; for ( i = 0 ; i < numVerts ; i++, dv++, lightdir++ ) - *lightdir = R_VboPackNormal(dv->lightdir); + R_VaoPackNormal((byte *)lightdir, dv->lightdir); } #if 0 // nothing even uses vertex dlightbits @@ -406,12 +409,12 @@ static void RB_SurfaceVertsAndIndexes( int numVerts, srfVert_t *verts, int numIn tess.numVertexes += numVerts; } -static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndexes, int firstIndex, int minIndex, int maxIndex, int dlightBits, int pshadowBits, qboolean shaderCheck) +static qboolean RB_SurfaceVao(vao_t *vao, int numVerts, int numIndexes, int firstIndex, int minIndex, int maxIndex, int dlightBits, int pshadowBits, qboolean shaderCheck) { int i, mergeForward, mergeBack; GLvoid *firstIndexOffset, *lastIndexOffset; - if (!vbo || !ibo) + if (!vao) { return qfalse; } @@ -421,7 +424,7 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex return qfalse; } - RB_CheckVBOandIBO(vbo, ibo); + RB_CheckVao(vao); tess.dlightBits |= dlightBits; tess.pshadowBits |= pshadowBits; @@ -432,29 +435,32 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex firstIndexOffset = BUFFER_OFFSET(firstIndex * sizeof(glIndex_t)); lastIndexOffset = BUFFER_OFFSET((firstIndex + numIndexes) * sizeof(glIndex_t)); - if (r_mergeMultidraws->integer) + if (tess.multiDrawPrimitives && r_mergeMultidraws->integer) { i = 0; if (r_mergeMultidraws->integer == 1) { // lazy merge, only check the last primitive - if (tess.multiDrawPrimitives) - { - i = tess.multiDrawPrimitives - 1; - } + i = tess.multiDrawPrimitives - 1; } for (; i < tess.multiDrawPrimitives; i++) { - if (tess.multiDrawLastIndex[i] == firstIndexOffset) + if (firstIndexOffset == tess.multiDrawFirstIndex[i] + tess.multiDrawNumIndexes[i]) { mergeBack = i; + + if (mergeForward != -1) + break; } if (lastIndexOffset == tess.multiDrawFirstIndex[i]) { mergeForward = i; + + if (mergeBack != -1) + break; } } } @@ -462,7 +468,6 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex if (mergeBack != -1 && mergeForward == -1) { tess.multiDrawNumIndexes[mergeBack] += numIndexes; - tess.multiDrawLastIndex[mergeBack] = tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack]; tess.multiDrawMinIndex[mergeBack] = MIN(tess.multiDrawMinIndex[mergeBack], minIndex); tess.multiDrawMaxIndex[mergeBack] = MAX(tess.multiDrawMaxIndex[mergeBack], maxIndex); backEnd.pc.c_multidrawsMerged++; @@ -471,7 +476,6 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex { tess.multiDrawNumIndexes[mergeForward] += numIndexes; tess.multiDrawFirstIndex[mergeForward] = firstIndexOffset; - tess.multiDrawLastIndex[mergeForward] = tess.multiDrawFirstIndex[mergeForward] + tess.multiDrawNumIndexes[mergeForward]; tess.multiDrawMinIndex[mergeForward] = MIN(tess.multiDrawMinIndex[mergeForward], minIndex); tess.multiDrawMaxIndex[mergeForward] = MAX(tess.multiDrawMaxIndex[mergeForward], maxIndex); backEnd.pc.c_multidrawsMerged++; @@ -479,7 +483,6 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex else if (mergeBack != -1 && mergeForward != -1) { tess.multiDrawNumIndexes[mergeBack] += numIndexes + tess.multiDrawNumIndexes[mergeForward]; - tess.multiDrawLastIndex[mergeBack] = tess.multiDrawFirstIndex[mergeBack] + tess.multiDrawNumIndexes[mergeBack]; tess.multiDrawMinIndex[mergeBack] = MIN(tess.multiDrawMinIndex[mergeBack], MIN(tess.multiDrawMinIndex[mergeForward], minIndex)); tess.multiDrawMaxIndex[mergeBack] = MAX(tess.multiDrawMaxIndex[mergeBack], MAX(tess.multiDrawMaxIndex[mergeForward], maxIndex)); tess.multiDrawPrimitives--; @@ -488,14 +491,15 @@ static qboolean RB_SurfaceVbo(VBO_t *vbo, IBO_t *ibo, int numVerts, int numIndex { tess.multiDrawNumIndexes[mergeForward] = tess.multiDrawNumIndexes[tess.multiDrawPrimitives]; tess.multiDrawFirstIndex[mergeForward] = tess.multiDrawFirstIndex[tess.multiDrawPrimitives]; + tess.multiDrawMinIndex[mergeForward] = tess.multiDrawMinIndex[tess.multiDrawPrimitives]; + tess.multiDrawMaxIndex[mergeForward] = tess.multiDrawMaxIndex[tess.multiDrawPrimitives]; } backEnd.pc.c_multidrawsMerged += 2; } - else if (mergeBack == -1 && mergeForward == -1) + else //if (mergeBack == -1 && mergeForward == -1) { tess.multiDrawNumIndexes[tess.multiDrawPrimitives] = numIndexes; tess.multiDrawFirstIndex[tess.multiDrawPrimitives] = firstIndexOffset; - tess.multiDrawLastIndex[tess.multiDrawPrimitives] = lastIndexOffset; tess.multiDrawMinIndex[tess.multiDrawPrimitives] = minIndex; tess.multiDrawMaxIndex[tess.multiDrawPrimitives] = maxIndex; tess.multiDrawPrimitives++; @@ -515,7 +519,7 @@ RB_SurfaceTriangles ============= */ static void RB_SurfaceTriangles( srfBspSurface_t *srf ) { - if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, + if( RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) { return; @@ -601,16 +605,15 @@ static void RB_SurfaceBeam( void ) tess.maxIndex = tess.numVertexes; // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function - RB_UpdateVBOs(ATTR_POSITION); + RB_UpdateTessVao(ATTR_POSITION); - GLSL_VertexAttribsState(ATTR_POSITION); GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed); - R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); + R_DrawElementsVao(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); tess.numIndexes = 0; tess.numVertexes = 0; @@ -627,6 +630,8 @@ static void DoRailCore( const vec3_t start, const vec3_t end, const vec3_t up, f int vbase; float t = len / 256.0f; + RB_CheckVao(tess.vao); + RB_CHECKOVERFLOW( 4, 6 ); vbase = tess.numVertexes; @@ -708,6 +713,8 @@ static void DoRailDiscs( int numSegs, const vec3_t start, const vec3_t dir, cons } } + RB_CheckVao(tess.vao); + for ( i = 0; i < numSegs; i++ ) { int j; @@ -1150,7 +1157,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp) VectorCopy(newVerts->xyz, outXyz); VectorCopy(newVerts->normal, normal); - *outNormal = R_VboPackNormal(normal); + R_VaoPackNormal((byte *)outNormal, normal); newVerts++; outXyz += 4; @@ -1175,7 +1182,7 @@ static void LerpMeshVertexes_scalar(mdvSurface_t *surf, float backlerp) VectorLerp(newVerts->normal, oldVerts->normal, backlerp, normal); VectorNormalize(normal); - *outNormal = R_VboPackNormal(normal); + R_VaoPackNormal((byte *)outNormal, normal); newVerts++; oldVerts++; @@ -1219,6 +1226,8 @@ static void RB_SurfaceMesh(mdvSurface_t *surface) { backlerp = backEnd.currentEntity->e.backlerp; } + RB_CheckVao(tess.vao); + RB_CHECKOVERFLOW( surface->numVerts, surface->numIndexes ); LerpMeshVertexes (surface, backlerp); @@ -1250,7 +1259,7 @@ RB_SurfaceFace ============== */ static void RB_SurfaceFace( srfBspSurface_t *srf ) { - if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, + if( RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) { return; @@ -1320,12 +1329,14 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) { int pshadowBits; //int *vDlightBits; - if( RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, + if( RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qtrue ) ) { return; } + RB_CheckVao(tess.vao); + dlightBits = srf->dlightBits; tess.dlightBits |= dlightBits; @@ -1413,13 +1424,13 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) { if ( tess.shader->vertexAttribs & ATTR_NORMAL ) { - *normal++ = R_VboPackNormal(dv->normal); + R_VaoPackNormal((byte *)normal++, dv->normal); } #ifdef USE_VERT_TANGENT_SPACE if ( tess.shader->vertexAttribs & ATTR_TANGENT ) { - *tangent++ = R_VboPackTangent(dv->tangent); + R_VaoPackTangent((byte *)tangent++, dv->tangent); } #endif if ( tess.shader->vertexAttribs & ATTR_TEXCOORD ) @@ -1442,7 +1453,7 @@ static void RB_SurfaceGrid( srfBspSurface_t *srf ) { if ( tess.shader->vertexAttribs & ATTR_LIGHTDIRECTION ) { - *lightdir++ = R_VboPackNormal(dv->lightdir); + R_VaoPackNormal((byte *)lightdir++, dv->lightdir); } //*vDlightBits++ = dlightBits; @@ -1567,34 +1578,33 @@ static void RB_SurfaceFlare(srfFlare_t *surf) RB_AddFlare(surf, tess.fogNum, surf->origin, surf->color, surf->normal); } -static void RB_SurfaceVBOMesh(srfBspSurface_t * srf) +static void RB_SurfaceVaoMesh(srfBspSurface_t * srf) { - RB_SurfaceVbo (srf->vbo, srf->ibo, srf->numVerts, srf->numIndexes, srf->firstIndex, + RB_SurfaceVao (srf->vao, srf->numVerts, srf->numIndexes, srf->firstIndex, srf->minIndex, srf->maxIndex, srf->dlightBits, srf->pshadowBits, qfalse ); } -void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) +void RB_SurfaceVaoMdvMesh(srfVaoMdvMesh_t * surface) { //mdvModel_t *mdvModel; //mdvSurface_t *mdvSurface; refEntity_t *refEnt; - GLimp_LogComment("--- RB_SurfaceVBOMDVMesh ---\n"); + GLimp_LogComment("--- RB_SurfaceVaoMdvMesh ---\n"); - if(!surface->vbo || !surface->ibo) + if(!surface->vao) return; - //RB_CheckVBOandIBO(surface->vbo, surface->ibo); + //RB_CheckVao(surface->vao); RB_EndSurface(); RB_BeginSurface(tess.shader, tess.fogNum, tess.cubemapIndex); - R_BindVBO(surface->vbo); - R_BindIBO(surface->ibo); + R_BindVao(surface->vao); - tess.useInternalVBO = qfalse; + tess.useInternalVao = qfalse; - tess.numIndexes += surface->numIndexes; - tess.numVertexes += surface->numVerts; + tess.numIndexes = surface->numIndexes; + tess.numVertexes = surface->numVerts; tess.minIndex = surface->minIndex; tess.maxIndex = surface->maxIndex; @@ -1603,18 +1613,56 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) refEnt = &backEnd.currentEntity->e; - if(refEnt->oldframe == refEnt->frame) - { - glState.vertexAttribsInterpolation = 0; - } - else - { - glState.vertexAttribsInterpolation = refEnt->backlerp; - } + glState.vertexAttribsInterpolation = (refEnt->oldframe == refEnt->frame) ? 0.0f : refEnt->backlerp; - glState.vertexAttribsOldFrame = refEnt->oldframe; - glState.vertexAttribsNewFrame = refEnt->frame; - glState.vertexAnimation = qtrue; + if (surface->mdvModel->numFrames > 1) + { + int frameOffset, attribIndex; + vaoAttrib_t *vAtb; + + glState.vertexAnimation = qtrue; + + if (glRefConfig.vertexArrayObject) + { + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, surface->vao->vertexesVBO); + } + + frameOffset = refEnt->frame * surface->vao->frameSize; + + attribIndex = ATTR_INDEX_POSITION; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_NORMAL; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_TANGENT; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + frameOffset = refEnt->oldframe * surface->vao->frameSize; + + attribIndex = ATTR_INDEX_POSITION2; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_NORMAL2; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + attribIndex = ATTR_INDEX_TANGENT2; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset + frameOffset)); + + + if (!glRefConfig.vertexArrayObject) + { + attribIndex = ATTR_INDEX_TEXCOORD; + vAtb = &surface->vao->attribs[attribIndex]; + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); + } + } RB_EndSurface(); @@ -1622,12 +1670,6 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) glState.vertexAnimation = qfalse; } -static void RB_SurfaceDisplayList( srfDisplayList_t *surf ) { - // all apropriate state must be set in RB_BeginSurface - // this isn't implemented yet... - qglCallList( surf->listNum ); -} - static void RB_SurfaceSkip( void *surf ) { } @@ -1644,7 +1686,6 @@ void (*rb_surfaceTable[SF_NUM_SURFACE_TYPES])( void *) = { (void(*)(void*))RB_IQMSurfaceAnim, // SF_IQM, (void(*)(void*))RB_SurfaceFlare, // SF_FLARE, (void(*)(void*))RB_SurfaceEntity, // SF_ENTITY - (void(*)(void*))RB_SurfaceDisplayList, // SF_DISPLAY_LIST - (void(*)(void*))RB_SurfaceVBOMesh, // SF_VBO_MESH, - (void(*)(void*))RB_SurfaceVBOMDVMesh, // SF_VBO_MDVMESH + (void(*)(void*))RB_SurfaceVaoMesh, // SF_VAO_MESH, + (void(*)(void*))RB_SurfaceVaoMdvMesh, // SF_VAO_MDVMESH }; diff --git a/code/renderergl2/tr_vbo.c b/code/renderergl2/tr_vbo.c index dc0f33be..8f9ba66f 100644 --- a/code/renderergl2/tr_vbo.c +++ b/code/renderergl2/tr_vbo.c @@ -23,858 +23,691 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" -uint32_t R_VboPackTangent(vec4_t v) +union pack10_u { + struct { + signed int x:10; + signed int y:10; + signed int z:10; + signed int w:2; + } pack; + uint32_t i; +}; + +union pack8_u { + struct { + signed int x:8; + signed int y:8; + signed int z:8; + signed int w:8; + } pack; + uint32_t i; +}; + + +int R_VaoPackTangent(byte *out, vec4_t v) { - if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) + if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV) { - return (((uint32_t)(v[3] * 1.5f + 2.0f )) << 30) - | (((uint32_t)(v[2] * 511.5f + 512.0f)) << 20) - | (((uint32_t)(v[1] * 511.5f + 512.0f)) << 10) - | (((uint32_t)(v[0] * 511.5f + 512.0f))); + union pack10_u *num = (union pack10_u *)out; + + num->pack.x = v[0] * 511.0f; + num->pack.y = v[1] * 511.0f; + num->pack.z = v[2] * 511.0f; + num->pack.w = v[3]; } else { - return (((uint32_t)(v[3] * 127.5f + 128.0f)) << 24) - | (((uint32_t)(v[2] * 127.5f + 128.0f)) << 16) - | (((uint32_t)(v[1] * 127.5f + 128.0f)) << 8) - | (((uint32_t)(v[0] * 127.5f + 128.0f))); + union pack8_u *num = (union pack8_u *)out; + + num->pack.x = v[0] * 127.0f; + num->pack.y = v[1] * 127.0f; + num->pack.z = v[2] * 127.0f; + num->pack.w = v[3] * 127.0f; + } + + return 4; +} + +int R_VaoPackNormal(byte *out, vec3_t v) +{ + if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV) + { + union pack10_u *num = (union pack10_u *)out; + + num->pack.x = v[0] * 511.0f; + num->pack.y = v[1] * 511.0f; + num->pack.z = v[2] * 511.0f; + num->pack.w = 0; + } + else + { + union pack8_u *num = (union pack8_u *)out; + + num->pack.x = v[0] * 127.0f; + num->pack.y = v[1] * 127.0f; + num->pack.z = v[2] * 127.0f; + num->pack.w = 0; + } + + return 4; +} + +int R_VaoPackTexCoord(byte *out, vec2_t st) +{ + if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT) + { + uint16_t *num = (uint16_t *)out; + + *num++ = FloatToHalf(st[0]); + *num++ = FloatToHalf(st[1]); + + return sizeof(*num) * 2; + } + else + { + float *num = (float *)out; + + *num++ = st[0]; + *num++ = st[1]; + + return sizeof(*num) * 2; } } -uint32_t R_VboPackNormal(vec3_t v) +int R_VaoPackColors(byte *out, vec4_t color) { - if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) + if (glRefConfig.packedTexcoordDataType == GL_HALF_FLOAT) { - return (((uint32_t)(v[2] * 511.5f + 512.0f)) << 20) - | (((uint32_t)(v[1] * 511.5f + 512.0f)) << 10) - | (((uint32_t)(v[0] * 511.5f + 512.0f))); + uint16_t *num = (uint16_t *)out; + + *num++ = FloatToHalf(color[0]); + *num++ = FloatToHalf(color[1]); + *num++ = FloatToHalf(color[2]); + *num++ = FloatToHalf(color[3]); + + return sizeof(*num) * 4; } else { - return (((uint32_t)(v[2] * 127.5f + 128.0f)) << 16) - | (((uint32_t)(v[1] * 127.5f + 128.0f)) << 8) - | (((uint32_t)(v[0] * 127.5f + 128.0f))); + float *num = (float *)out; + + *num++ = color[0]; + *num++ = color[1]; + *num++ = color[2]; + *num++ = color[3]; + + return sizeof(*num) * 4; } } -void R_VboUnpackTangent(vec4_t v, uint32_t b) + +void R_VaoUnpackTangent(vec4_t v, uint32_t b) { - if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) + if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV) { - v[0] = ((b) & 0x3ff) * 1.0f/511.5f - 1.0f; - v[1] = ((b >> 10) & 0x3ff) * 1.0f/511.5f - 1.0f; - v[2] = ((b >> 20) & 0x3ff) * 1.0f/511.5f - 1.0f; - v[3] = ((b >> 30) & 0x3) * 1.0f/1.5f - 1.0f; + union pack10_u *num = (union pack10_u *)&b; + + v[0] = num->pack.x / 511.0f; + v[1] = num->pack.y / 511.0f; + v[2] = num->pack.z / 511.0f; + v[3] = num->pack.w; } else { - v[0] = ((b) & 0xff) * 1.0f/127.5f - 1.0f; - v[1] = ((b >> 8) & 0xff) * 1.0f/127.5f - 1.0f; - v[2] = ((b >> 16) & 0xff) * 1.0f/127.5f - 1.0f; - v[3] = ((b >> 24) & 0xff) * 1.0f/127.5f - 1.0f; + union pack8_u *num = (union pack8_u *)&b; + + v[0] = num->pack.x / 127.0f; + v[1] = num->pack.y / 127.0f; + v[2] = num->pack.z / 127.0f; + v[3] = num->pack.w / 127.0f; } } -void R_VboUnpackNormal(vec3_t v, uint32_t b) +void R_VaoUnpackNormal(vec3_t v, uint32_t b) { - if (glRefConfig.packedNormalDataType == GL_UNSIGNED_INT_2_10_10_10_REV) + if (glRefConfig.packedNormalDataType == GL_INT_2_10_10_10_REV) { - v[0] = ((b) & 0x3ff) * 1.0f/511.5f - 1.0f; - v[1] = ((b >> 10) & 0x3ff) * 1.0f/511.5f - 1.0f; - v[2] = ((b >> 20) & 0x3ff) * 1.0f/511.5f - 1.0f; + union pack10_u *num = (union pack10_u *)&b; + + v[0] = num->pack.x / 511.0f; + v[1] = num->pack.y / 511.0f; + v[2] = num->pack.z / 511.0f; } else { - v[0] = ((b) & 0xff) * 1.0f/127.5f - 1.0f; - v[1] = ((b >> 8) & 0xff) * 1.0f/127.5f - 1.0f; - v[2] = ((b >> 16) & 0xff) * 1.0f/127.5f - 1.0f; + union pack8_u *num = (union pack8_u *)&b; + + v[0] = num->pack.x / 127.0f; + v[1] = num->pack.y / 127.0f; + v[2] = num->pack.z / 127.0f; + } +} + + +void Vao_SetVertexPointers(vao_t *vao) +{ + int attribIndex; + + // set vertex pointers + for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) + { + uint32_t attribBit = 1 << attribIndex; + vaoAttrib_t *vAtb = &vao->attribs[attribIndex]; + + if (vAtb->enabled) + { + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); + if (glRefConfig.vertexArrayObject || !(glState.vertexAttribsEnabled & attribBit)) + qglEnableVertexAttribArrayARB(attribIndex); + + if (!glRefConfig.vertexArrayObject || vao == tess.vao) + glState.vertexAttribsEnabled |= attribBit; + } + else + { + // don't disable vertex attribs when using vertex array objects + // Vao_SetVertexPointers is only called during init when using VAOs, and vertex attribs start disabled anyway + if (!glRefConfig.vertexArrayObject && (glState.vertexAttribsEnabled & attribBit)) + qglDisableVertexAttribArrayARB(attribIndex); + + if (!glRefConfig.vertexArrayObject || vao == tess.vao) + glState.vertexAttribsEnabled &= ~attribBit; + } } } /* ============ -R_CreateVBO +R_CreateVao ============ */ -VBO_t *R_CreateVBO(const char *name, byte * vertexes, int vertexesSize, vboUsage_t usage) +vao_t *R_CreateVao(const char *name, byte *vertexes, int vertexesSize, byte *indexes, int indexesSize, vaoUsage_t usage) { - VBO_t *vbo; + vao_t *vao; int glUsage; switch (usage) { - case VBO_USAGE_STATIC: + case VAO_USAGE_STATIC: glUsage = GL_STATIC_DRAW_ARB; break; - case VBO_USAGE_DYNAMIC: + case VAO_USAGE_DYNAMIC: glUsage = GL_DYNAMIC_DRAW_ARB; break; default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); + Com_Error(ERR_FATAL, "bad vaoUsage_t given: %i", usage); return NULL; } if(strlen(name) >= MAX_QPATH) { - ri.Error(ERR_DROP, "R_CreateVBO: \"%s\" is too long", name); + ri.Error(ERR_DROP, "R_CreateVao: \"%s\" is too long", name); } - if ( tr.numVBOs == MAX_VBOS ) { - ri.Error( ERR_DROP, "R_CreateVBO: MAX_VBOS hit"); + if ( tr.numVaos == MAX_VAOS ) { + ri.Error( ERR_DROP, "R_CreateVao: MAX_VAOS hit"); } R_IssuePendingRenderCommands(); - vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); - tr.numVBOs++; + vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low); + tr.numVaos++; - memset(vbo, 0, sizeof(*vbo)); + memset(vao, 0, sizeof(*vao)); - Q_strncpyz(vbo->name, name, sizeof(vbo->name)); + Q_strncpyz(vao->name, name, sizeof(vao->name)); - vbo->vertexesSize = vertexesSize; - qglGenBuffersARB(1, &vbo->vertexesVBO); + if (glRefConfig.vertexArrayObject) + { + qglGenVertexArraysARB(1, &vao->vao); + qglBindVertexArrayARB(vao->vao); + } - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); + + vao->vertexesSize = vertexesSize; + + qglGenBuffersARB(1, &vao->vertexesVBO); + + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO); qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vertexesSize, vertexes, glUsage); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - glState.currentVBO = NULL; + vao->indexesSize = indexesSize; + + qglGenBuffersARB(1, &vao->indexesIBO); + + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO); + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); + + + glState.currentVao = vao; GL_CheckErrors(); - return vbo; + return vao; } /* ============ -R_CreateVBO2 +R_CreateVao2 ============ */ -VBO_t *R_CreateVBO2(const char *name, int numVertexes, srfVert_t * verts, unsigned int stateBits, vboUsage_t usage) +vao_t *R_CreateVao2(const char *name, int numVertexes, srfVert_t *verts, int numIndexes, glIndex_t *indexes) { - VBO_t *vbo; + vao_t *vao; int i; byte *data; int dataSize; int dataOfs; - int glUsage; + int glUsage = GL_STATIC_DRAW_ARB; - switch (usage) - { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(!numVertexes) + if(!numVertexes || !numIndexes) return NULL; if(strlen(name) >= MAX_QPATH) { - ri.Error(ERR_DROP, "R_CreateVBO2: \"%s\" is too long", name); + ri.Error(ERR_DROP, "R_CreateVao2: \"%s\" is too long", name); } - if ( tr.numVBOs == MAX_VBOS ) { - ri.Error( ERR_DROP, "R_CreateVBO2: MAX_VBOS hit"); + if ( tr.numVaos == MAX_VAOS ) { + ri.Error( ERR_DROP, "R_CreateVao2: MAX_VAOS hit"); } R_IssuePendingRenderCommands(); - vbo = tr.vbos[tr.numVBOs] = ri.Hunk_Alloc(sizeof(*vbo), h_low); - tr.numVBOs++; + vao = tr.vaos[tr.numVaos] = ri.Hunk_Alloc(sizeof(*vao), h_low); + tr.numVaos++; - memset(vbo, 0, sizeof(*vbo)); + memset(vao, 0, sizeof(*vao)); - Q_strncpyz(vbo->name, name, sizeof(vbo->name)); + Q_strncpyz(vao->name, name, sizeof(vao->name)); - if (usage == VBO_USAGE_STATIC) + // since these vertex attributes are never altered, interleave them + vao->attribs[ATTR_INDEX_POSITION ].enabled = 1; + vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1; +#ifdef USE_VERT_TANGENT_SPACE + vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1; +#endif + vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1; + vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1; + vao->attribs[ATTR_INDEX_COLOR ].enabled = 1; + vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1; + + vao->attribs[ATTR_INDEX_POSITION ].count = 3; + vao->attribs[ATTR_INDEX_NORMAL ].count = 4; + vao->attribs[ATTR_INDEX_TANGENT ].count = 4; + vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2; + vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2; + vao->attribs[ATTR_INDEX_COLOR ].count = 4; + vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4; + + vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT; + vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; + vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; + vao->attribs[ATTR_INDEX_TEXCOORD ].type = glRefConfig.packedTexcoordDataType; + vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = glRefConfig.packedTexcoordDataType; + vao->attribs[ATTR_INDEX_COLOR ].type = glRefConfig.packedColorDataType; + vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType; + + vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE; + vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; + vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; + vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE; + vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE; + vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE; + vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE; + + vao->attribs[ATTR_INDEX_POSITION ].offset = 0; dataSize = sizeof(verts[0].xyz); + vao->attribs[ATTR_INDEX_NORMAL ].offset = dataSize; dataSize += sizeof(uint32_t); +#ifdef USE_VERT_TANGENT_SPACE + vao->attribs[ATTR_INDEX_TANGENT ].offset = dataSize; dataSize += sizeof(uint32_t); +#endif + vao->attribs[ATTR_INDEX_TEXCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize; + vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = dataSize; dataSize += glRefConfig.packedTexcoordDataSize; + vao->attribs[ATTR_INDEX_COLOR ].offset = dataSize; dataSize += glRefConfig.packedColorDataSize; + vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = dataSize; dataSize += sizeof(uint32_t); + + vao->attribs[ATTR_INDEX_POSITION ].stride = dataSize; + vao->attribs[ATTR_INDEX_NORMAL ].stride = dataSize; + vao->attribs[ATTR_INDEX_TANGENT ].stride = dataSize; + vao->attribs[ATTR_INDEX_TEXCOORD ].stride = dataSize; + vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = dataSize; + vao->attribs[ATTR_INDEX_COLOR ].stride = dataSize; + vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = dataSize; + + + if (glRefConfig.vertexArrayObject) { - // since these vertex attributes are never altered, interleave them - vbo->ofs_xyz = 0; - dataSize = sizeof(verts[0].xyz); - - if(stateBits & ATTR_NORMAL) - { - vbo->ofs_normal = dataSize; - dataSize += sizeof(uint32_t); - } - -#ifdef USE_VERT_TANGENT_SPACE - if(stateBits & ATTR_TANGENT) - { - vbo->ofs_tangent = dataSize; - dataSize += sizeof(uint32_t); - } -#endif - - if(stateBits & ATTR_TEXCOORD) - { - vbo->ofs_st = dataSize; - dataSize += sizeof(verts[0].st); - } - - if(stateBits & ATTR_LIGHTCOORD) - { - vbo->ofs_lightmap = dataSize; - dataSize += sizeof(verts[0].lightmap); - } - - if(stateBits & ATTR_COLOR) - { - vbo->ofs_vertexcolor = dataSize; - dataSize += sizeof(verts[0].vertexColors); - } - - if(stateBits & ATTR_LIGHTDIRECTION) - { - vbo->ofs_lightdir = dataSize; - dataSize += sizeof(uint32_t); - } - - vbo->stride_xyz = dataSize; - vbo->stride_normal = dataSize; -#ifdef USE_VERT_TANGENT_SPACE - vbo->stride_tangent = dataSize; -#endif - vbo->stride_st = dataSize; - vbo->stride_lightmap = dataSize; - vbo->stride_vertexcolor = dataSize; - vbo->stride_lightdir = dataSize; - - // create VBO - dataSize *= numVertexes; - data = ri.Hunk_AllocateTempMemory(dataSize); - dataOfs = 0; - - //ri.Printf(PRINT_ALL, "CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, - //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); - - for (i = 0; i < numVertexes; i++) - { - // xyz - memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); - dataOfs += sizeof(verts[i].xyz); - - // normal - if(stateBits & ATTR_NORMAL) - { - uint32_t *p = (uint32_t *)(data + dataOfs); - - *p = R_VboPackNormal(verts[i].normal); - - dataOfs += sizeof(uint32_t); - } - -#ifdef USE_VERT_TANGENT_SPACE - // tangent - if(stateBits & ATTR_TANGENT) - { - uint32_t *p = (uint32_t *)(data + dataOfs); - - *p = R_VboPackTangent(verts[i].tangent); - - dataOfs += sizeof(uint32_t); - } -#endif - - // vertex texcoords - if(stateBits & ATTR_TEXCOORD) - { - memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); - dataOfs += sizeof(verts[i].st); - } - - // feed vertex lightmap texcoords - if(stateBits & ATTR_LIGHTCOORD) - { - memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); - dataOfs += sizeof(verts[i].lightmap); - } - - // feed vertex colors - if(stateBits & ATTR_COLOR) - { - memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); - dataOfs += sizeof(verts[i].vertexColors); - } - - // feed vertex light directions - if(stateBits & ATTR_LIGHTDIRECTION) - { - uint32_t *p = (uint32_t *)(data + dataOfs); - - *p = R_VboPackNormal(verts[i].lightdir); - - dataOfs += sizeof(uint32_t); - } - } + qglGenVertexArraysARB(1, &vao->vao); + qglBindVertexArrayARB(vao->vao); } - else + + + // create VBO + dataSize *= numVertexes; + data = ri.Hunk_AllocateTempMemory(dataSize); + dataOfs = 0; + + for (i = 0; i < numVertexes; i++) { - // since these vertex attributes may be changed, put them in flat arrays - dataSize = sizeof(verts[0].xyz); - - if(stateBits & ATTR_NORMAL) - { - dataSize += sizeof(uint32_t); - } - -#ifdef USE_VERT_TANGENT_SPACE - if(stateBits & ATTR_TANGENT) - { - dataSize += sizeof(uint32_t); - } -#endif - - if(stateBits & ATTR_TEXCOORD) - { - dataSize += sizeof(verts[0].st); - } - - if(stateBits & ATTR_LIGHTCOORD) - { - dataSize += sizeof(verts[0].lightmap); - } - - if(stateBits & ATTR_COLOR) - { - dataSize += sizeof(verts[0].vertexColors); - } - - if(stateBits & ATTR_LIGHTDIRECTION) - { - dataSize += sizeof(uint32_t); - } - - // create VBO - dataSize *= numVertexes; - data = ri.Hunk_AllocateTempMemory(dataSize); - dataOfs = 0; - - vbo->ofs_xyz = 0; - vbo->ofs_normal = 0; -#ifdef USE_VERT_TANGENT_SPACE - vbo->ofs_tangent = 0; -#endif - vbo->ofs_st = 0; - vbo->ofs_lightmap = 0; - vbo->ofs_vertexcolor = 0; - vbo->ofs_lightdir = 0; - - vbo->stride_xyz = sizeof(verts[0].xyz); - vbo->stride_normal = sizeof(uint32_t); -#ifdef USE_VERT_TANGENT_SPACE - vbo->stride_tangent = sizeof(uint32_t); -#endif - vbo->stride_vertexcolor = sizeof(verts[0].vertexColors); - vbo->stride_st = sizeof(verts[0].st); - vbo->stride_lightmap = sizeof(verts[0].lightmap); - vbo->stride_lightdir = sizeof(uint32_t); - - //ri.Printf(PRINT_ALL, "2CreateVBO: %d, %d %d %d %d %d, %d %d %d %d %d\n", dataSize, vbo->ofs_xyz, vbo->ofs_normal, vbo->ofs_st, vbo->ofs_lightmap, vbo->ofs_vertexcolor, - //vbo->stride_xyz, vbo->stride_normal, vbo->stride_st, vbo->stride_lightmap, vbo->stride_vertexcolor); - // xyz - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); - dataOfs += sizeof(verts[i].xyz); - } + memcpy(data + dataOfs, &verts[i].xyz, sizeof(verts[i].xyz)); + dataOfs += sizeof(verts[i].xyz); // normal - if(stateBits & ATTR_NORMAL) - { - vbo->ofs_normal = dataOfs; - for (i = 0; i < numVertexes; i++) - { - uint32_t *p = (uint32_t *)(data + dataOfs); - - *p = R_VboPackNormal(verts[i].normal); - - dataOfs += sizeof(uint32_t); - } - } + dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].normal); #ifdef USE_VERT_TANGENT_SPACE // tangent - if(stateBits & ATTR_TANGENT) - { - vbo->ofs_tangent = dataOfs; - for (i = 0; i < numVertexes; i++) - { - uint32_t *p = (uint32_t *)(data + dataOfs); - - *p = R_VboPackTangent(verts[i].tangent); - - dataOfs += sizeof(uint32_t); - } - } + dataOfs += R_VaoPackTangent(data + dataOfs, verts[i].tangent); #endif - // vertex texcoords - if(stateBits & ATTR_TEXCOORD) - { - vbo->ofs_st = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].st, sizeof(verts[i].st)); - dataOfs += sizeof(verts[i].st); - } - } + // texcoords + dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].st); - // feed vertex lightmap texcoords - if(stateBits & ATTR_LIGHTCOORD) - { - vbo->ofs_lightmap = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].lightmap, sizeof(verts[i].lightmap)); - dataOfs += sizeof(verts[i].lightmap); - } - } + // lightmap texcoords + dataOfs += R_VaoPackTexCoord(data + dataOfs, verts[i].lightmap); - // feed vertex colors - if(stateBits & ATTR_COLOR) - { - vbo->ofs_vertexcolor = dataOfs; - for (i = 0; i < numVertexes; i++) - { - memcpy(data + dataOfs, &verts[i].vertexColors, sizeof(verts[i].vertexColors)); - dataOfs += sizeof(verts[i].vertexColors); - } - } + // colors + dataOfs += R_VaoPackColors(data + dataOfs, verts[i].vertexColors); - // feed vertex lightdirs - if(stateBits & ATTR_LIGHTDIRECTION) - { - vbo->ofs_lightdir = dataOfs; - for (i = 0; i < numVertexes; i++) - { - uint32_t *p = (uint32_t *)(data + dataOfs); - - *p = R_VboPackNormal(verts[i].lightdir); - - dataOfs += sizeof(uint32_t); - } - } + // light directions + dataOfs += R_VaoPackNormal(data + dataOfs, verts[i].lightdir); } + vao->vertexesSize = dataSize; - vbo->vertexesSize = dataSize; + qglGenBuffersARB(1, &vao->vertexesVBO); - qglGenBuffersARB(1, &vbo->vertexesVBO); + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO); + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vao->vertexesSize, data, glUsage); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); - qglBufferDataARB(GL_ARRAY_BUFFER_ARB, dataSize, data, glUsage); - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + // create IBO + vao->indexesSize = numIndexes * sizeof(glIndex_t); - glState.currentVBO = NULL; + qglGenBuffersARB(1, &vao->indexesIBO); + + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO); + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesSize, indexes, glUsage); + + + Vao_SetVertexPointers(vao); + + + glState.currentVao = vao; GL_CheckErrors(); ri.Hunk_FreeTempMemory(data); - return vbo; + return vao; } /* ============ -R_CreateIBO +R_BindVao ============ */ -IBO_t *R_CreateIBO(const char *name, byte * indexes, int indexesSize, vboUsage_t usage) +void R_BindVao(vao_t * vao) { - IBO_t *ibo; - int glUsage; - - switch (usage) + if(!vao) { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "R_CreateIBO: \"%s\" is too long", name); - } - - if ( tr.numIBOs == MAX_IBOS ) { - ri.Error( ERR_DROP, "R_CreateIBO: MAX_IBOS hit"); - } - - R_IssuePendingRenderCommands(); - - ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); - tr.numIBOs++; - - Q_strncpyz(ibo->name, name, sizeof(ibo->name)); - - ibo->indexesSize = indexesSize; - - qglGenBuffersARB(1, &ibo->indexesVBO); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - - glState.currentIBO = NULL; - - GL_CheckErrors(); - - return ibo; -} - -/* -============ -R_CreateIBO2 -============ -*/ -IBO_t *R_CreateIBO2(const char *name, int numIndexes, glIndex_t * inIndexes, vboUsage_t usage) -{ - IBO_t *ibo; - int i; - - glIndex_t *indexes; - int indexesSize; - - int glUsage; - - switch (usage) - { - case VBO_USAGE_STATIC: - glUsage = GL_STATIC_DRAW_ARB; - break; - - case VBO_USAGE_DYNAMIC: - glUsage = GL_DYNAMIC_DRAW_ARB; - break; - - default: - Com_Error(ERR_FATAL, "bad vboUsage_t given: %i", usage); - return NULL; - } - - if(!numIndexes) - return NULL; - - if(strlen(name) >= MAX_QPATH) - { - ri.Error(ERR_DROP, "R_CreateIBO2: \"%s\" is too long", name); - } - - if ( tr.numIBOs == MAX_IBOS ) { - ri.Error( ERR_DROP, "R_CreateIBO2: MAX_IBOS hit"); - } - - R_IssuePendingRenderCommands(); - - ibo = tr.ibos[tr.numIBOs] = ri.Hunk_Alloc(sizeof(*ibo), h_low); - tr.numIBOs++; - - Q_strncpyz(ibo->name, name, sizeof(ibo->name)); - - indexesSize = numIndexes * sizeof(glIndex_t); - indexes = ri.Hunk_AllocateTempMemory(indexesSize); - - for(i = 0; i < numIndexes; i++) - { - indexes[i] = inIndexes[i]; - } - - ibo->indexesSize = indexesSize; - - qglGenBuffersARB(1, &ibo->indexesVBO); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, indexesSize, indexes, glUsage); - - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - - glState.currentIBO = NULL; - - GL_CheckErrors(); - - ri.Hunk_FreeTempMemory(indexes); - - return ibo; -} - -/* -============ -R_BindVBO -============ -*/ -void R_BindVBO(VBO_t * vbo) -{ - if(!vbo) - { - //R_BindNullVBO(); - ri.Error(ERR_DROP, "R_BindNullVBO: NULL vbo"); + //R_BindNullVao(); + ri.Error(ERR_DROP, "R_BindVao: NULL vao"); return; } if(r_logFile->integer) { // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- R_BindVBO( %s ) ---\n", vbo->name)); + GLimp_LogComment(va("--- R_BindVao( %s ) ---\n", vao->name)); } - if(glState.currentVBO != vbo) + if(glState.currentVao != vao) { - glState.currentVBO = vbo; - glState.vertexAttribPointersSet = 0; + glState.currentVao = vao; glState.vertexAttribsInterpolation = 0; - glState.vertexAttribsOldFrame = 0; - glState.vertexAttribsNewFrame = 0; glState.vertexAnimation = qfalse; + backEnd.pc.c_vaoBinds++; - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo->vertexesVBO); + if (glRefConfig.vertexArrayObject) + { + qglBindVertexArrayARB(vao->vao); - backEnd.pc.c_vboVertexBuffers++; + // why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel? + if (1) + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, vao->indexesIBO); + + // tess VAO always has buffers bound + if (vao == tess.vao) + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO); + } + else + { + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, vao->vertexesVBO); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, vao->indexesIBO); + + // tess VAO doesn't have vertex pointers set until data is uploaded + if (vao != tess.vao) + Vao_SetVertexPointers(vao); + } } } /* ============ -R_BindNullVBO +R_BindNullVao ============ */ -void R_BindNullVBO(void) +void R_BindNullVao(void) { - GLimp_LogComment("--- R_BindNullVBO ---\n"); + GLimp_LogComment("--- R_BindNullVao ---\n"); - if(glState.currentVBO) + if(glState.currentVao) { - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - glState.currentVBO = NULL; + if (glRefConfig.vertexArrayObject) + { + qglBindVertexArrayARB(0); + + // why you no save GL_ELEMENT_ARRAY_BUFFER binding, Intel? + if (1) qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + else + { + qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + glState.currentVao = NULL; } GL_CheckErrors(); } -/* -============ -R_BindIBO -============ -*/ -void R_BindIBO(IBO_t * ibo) -{ - if(!ibo) - { - //R_BindNullIBO(); - ri.Error(ERR_DROP, "R_BindIBO: NULL ibo"); - return; - } - - if(r_logFile->integer) - { - // don't just call LogComment, or we will get a call to va() every frame! - GLimp_LogComment(va("--- R_BindIBO( %s ) ---\n", ibo->name)); - } - - if(glState.currentIBO != ibo) - { - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo->indexesVBO); - - glState.currentIBO = ibo; - - backEnd.pc.c_vboIndexBuffers++; - } -} /* ============ -R_BindNullIBO +R_InitVaos ============ */ -void R_BindNullIBO(void) +void R_InitVaos(void) { - GLimp_LogComment("--- R_BindNullIBO ---\n"); - - if(glState.currentIBO) - { - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); - glState.currentIBO = NULL; - glState.vertexAttribPointersSet = 0; - } -} - -/* -============ -R_InitVBOs -============ -*/ -void R_InitVBOs(void) -{ - int dataSize; + int vertexesSize, indexesSize; int offset; - ri.Printf(PRINT_ALL, "------- R_InitVBOs -------\n"); + ri.Printf(PRINT_ALL, "------- R_InitVaos -------\n"); - tr.numVBOs = 0; - tr.numIBOs = 0; + tr.numVaos = 0; - dataSize = sizeof(tess.xyz[0]); - dataSize += sizeof(tess.normal[0]); + vertexesSize = sizeof(tess.xyz[0]); + vertexesSize += sizeof(tess.normal[0]); #ifdef USE_VERT_TANGENT_SPACE - dataSize += sizeof(tess.tangent[0]); + vertexesSize += sizeof(tess.tangent[0]); #endif - dataSize += sizeof(tess.vertexColors[0]); - dataSize += sizeof(tess.texCoords[0][0]) * 2; - dataSize += sizeof(tess.lightdir[0]); - dataSize *= SHADER_MAX_VERTEXES; + vertexesSize += sizeof(tess.vertexColors[0]); + vertexesSize += sizeof(tess.texCoords[0][0]) * 2; + vertexesSize += sizeof(tess.lightdir[0]); + vertexesSize *= SHADER_MAX_VERTEXES; - tess.vbo = R_CreateVBO("tessVertexArray_VBO", NULL, dataSize, VBO_USAGE_DYNAMIC); + indexesSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES; + + tess.vao = R_CreateVao("tessVertexArray_VAO", NULL, vertexesSize, NULL, indexesSize, VAO_USAGE_DYNAMIC); offset = 0; - tess.vbo->ofs_xyz = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES; - tess.vbo->ofs_normal = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES; + tess.vao->attribs[ATTR_INDEX_POSITION ].enabled = 1; + tess.vao->attribs[ATTR_INDEX_NORMAL ].enabled = 1; #ifdef USE_VERT_TANGENT_SPACE - tess.vbo->ofs_tangent = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES; + tess.vao->attribs[ATTR_INDEX_TANGENT ].enabled = 1; +#endif + tess.vao->attribs[ATTR_INDEX_TEXCOORD ].enabled = 1; + tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].enabled = 1; + tess.vao->attribs[ATTR_INDEX_COLOR ].enabled = 1; + tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].enabled = 1; + + tess.vao->attribs[ATTR_INDEX_POSITION ].count = 3; + tess.vao->attribs[ATTR_INDEX_NORMAL ].count = 4; + tess.vao->attribs[ATTR_INDEX_TANGENT ].count = 4; + tess.vao->attribs[ATTR_INDEX_TEXCOORD ].count = 2; + tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].count = 2; + tess.vao->attribs[ATTR_INDEX_COLOR ].count = 4; + tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].count = 4; + + tess.vao->attribs[ATTR_INDEX_POSITION ].type = GL_FLOAT; + tess.vao->attribs[ATTR_INDEX_NORMAL ].type = glRefConfig.packedNormalDataType; + tess.vao->attribs[ATTR_INDEX_TANGENT ].type = glRefConfig.packedNormalDataType; + tess.vao->attribs[ATTR_INDEX_TEXCOORD ].type = GL_FLOAT; + tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].type = GL_FLOAT; + tess.vao->attribs[ATTR_INDEX_COLOR ].type = GL_FLOAT; + tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].type = glRefConfig.packedNormalDataType; + + tess.vao->attribs[ATTR_INDEX_POSITION ].normalized = GL_FALSE; + tess.vao->attribs[ATTR_INDEX_NORMAL ].normalized = GL_TRUE; + tess.vao->attribs[ATTR_INDEX_TANGENT ].normalized = GL_TRUE; + tess.vao->attribs[ATTR_INDEX_TEXCOORD ].normalized = GL_FALSE; + tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].normalized = GL_FALSE; + tess.vao->attribs[ATTR_INDEX_COLOR ].normalized = GL_FALSE; + tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].normalized = GL_TRUE; + + tess.vao->attribs[ATTR_INDEX_POSITION ].offset = offset; offset += sizeof(tess.xyz[0]) * SHADER_MAX_VERTEXES; + tess.vao->attribs[ATTR_INDEX_NORMAL ].offset = offset; offset += sizeof(tess.normal[0]) * SHADER_MAX_VERTEXES; +#ifdef USE_VERT_TANGENT_SPACE + tess.vao->attribs[ATTR_INDEX_TANGENT ].offset = offset; offset += sizeof(tess.tangent[0]) * SHADER_MAX_VERTEXES; #endif // these next two are actually interleaved - tess.vbo->ofs_st = offset; - tess.vbo->ofs_lightmap = offset + sizeof(tess.texCoords[0][0]); - offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES; + tess.vao->attribs[ATTR_INDEX_TEXCOORD ].offset = offset; + tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].offset = offset + sizeof(tess.texCoords[0][0]); + offset += sizeof(tess.texCoords[0][0]) * 2 * SHADER_MAX_VERTEXES; - tess.vbo->ofs_vertexcolor = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES; - tess.vbo->ofs_lightdir = offset; + tess.vao->attribs[ATTR_INDEX_COLOR ].offset = offset; offset += sizeof(tess.vertexColors[0]) * SHADER_MAX_VERTEXES; + tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].offset = offset; - tess.vbo->stride_xyz = sizeof(tess.xyz[0]); - tess.vbo->stride_normal = sizeof(tess.normal[0]); + tess.vao->attribs[ATTR_INDEX_POSITION ].stride = sizeof(tess.xyz[0]); + tess.vao->attribs[ATTR_INDEX_NORMAL ].stride = sizeof(tess.normal[0]); #ifdef USE_VERT_TANGENT_SPACE - tess.vbo->stride_tangent = sizeof(tess.tangent[0]); + tess.vao->attribs[ATTR_INDEX_TANGENT ].stride = sizeof(tess.tangent[0]); #endif - tess.vbo->stride_vertexcolor = sizeof(tess.vertexColors[0]); - tess.vbo->stride_st = sizeof(tess.texCoords[0][0]) * 2; - tess.vbo->stride_lightmap = sizeof(tess.texCoords[0][0]) * 2; - tess.vbo->stride_lightdir = sizeof(tess.lightdir[0]); + tess.vao->attribs[ATTR_INDEX_COLOR ].stride = sizeof(tess.vertexColors[0]); + tess.vao->attribs[ATTR_INDEX_TEXCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2; + tess.vao->attribs[ATTR_INDEX_LIGHTCOORD ].stride = sizeof(tess.texCoords[0][0]) * 2; + tess.vao->attribs[ATTR_INDEX_LIGHTDIRECTION].stride = sizeof(tess.lightdir[0]); - dataSize = sizeof(tess.indexes[0]) * SHADER_MAX_INDEXES; + tess.attribPointers[ATTR_INDEX_POSITION] = tess.xyz; + tess.attribPointers[ATTR_INDEX_TEXCOORD] = tess.texCoords; + tess.attribPointers[ATTR_INDEX_NORMAL] = tess.normal; +#ifdef USE_VERT_TANGENT_SPACE + tess.attribPointers[ATTR_INDEX_TANGENT] = tess.tangent; +#endif + tess.attribPointers[ATTR_INDEX_COLOR] = tess.vertexColors; + tess.attribPointers[ATTR_INDEX_LIGHTDIRECTION] = tess.lightdir; - tess.ibo = R_CreateIBO("tessVertexArray_IBO", NULL, dataSize, VBO_USAGE_DYNAMIC); + Vao_SetVertexPointers(tess.vao); - R_BindNullVBO(); - R_BindNullIBO(); + R_BindNullVao(); GL_CheckErrors(); } /* ============ -R_ShutdownVBOs +R_ShutdownVaos ============ */ -void R_ShutdownVBOs(void) +void R_ShutdownVaos(void) { int i; - VBO_t *vbo; - IBO_t *ibo; + vao_t *vao; - ri.Printf(PRINT_ALL, "------- R_ShutdownVBOs -------\n"); + ri.Printf(PRINT_ALL, "------- R_ShutdownVaos -------\n"); - R_BindNullVBO(); - R_BindNullIBO(); + R_BindNullVao(); - - for(i = 0; i < tr.numVBOs; i++) + for(i = 0; i < tr.numVaos; i++) { - vbo = tr.vbos[i]; + vao = tr.vaos[i]; - if(vbo->vertexesVBO) + if(vao->vao) + qglDeleteVertexArraysARB(1, &vao->vao); + + if(vao->vertexesVBO) { - qglDeleteBuffersARB(1, &vbo->vertexesVBO); + qglDeleteBuffersARB(1, &vao->vertexesVBO); } - //ri.Free(vbo); - } - - for(i = 0; i < tr.numIBOs; i++) - { - ibo = tr.ibos[i]; - - if(ibo->indexesVBO) + if(vao->indexesIBO) { - qglDeleteBuffersARB(1, &ibo->indexesVBO); + qglDeleteBuffersARB(1, &vao->indexesIBO); } - - //ri.Free(ibo); } - tr.numVBOs = 0; - tr.numIBOs = 0; + tr.numVaos = 0; } /* ============ -R_VBOList_f +R_VaoList_f ============ */ -void R_VBOList_f(void) +void R_VaoList_f(void) { int i; - VBO_t *vbo; - IBO_t *ibo; + vao_t *vao; int vertexesSize = 0; int indexesSize = 0; ri.Printf(PRINT_ALL, " size name\n"); ri.Printf(PRINT_ALL, "----------------------------------------------------------\n"); - for(i = 0; i < tr.numVBOs; i++) + for(i = 0; i < tr.numVaos; i++) { - vbo = tr.vbos[i]; + vao = tr.vaos[i]; - ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vbo->vertexesSize / (1024 * 1024), - (vbo->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vbo->name); + ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vao->vertexesSize / (1024 * 1024), + (vao->vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vao->name); - vertexesSize += vbo->vertexesSize; + vertexesSize += vao->vertexesSize; } - for(i = 0; i < tr.numIBOs; i++) + for(i = 0; i < tr.numVaos; i++) { - ibo = tr.ibos[i]; + vao = tr.vaos[i]; - ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", ibo->indexesSize / (1024 * 1024), - (ibo->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), ibo->name); + ri.Printf(PRINT_ALL, "%d.%02d MB %s\n", vao->indexesSize / (1024 * 1024), + (vao->indexesSize % (1024 * 1024)) * 100 / (1024 * 1024), vao->name); - indexesSize += ibo->indexesSize; + indexesSize += vao->indexesSize; } - ri.Printf(PRINT_ALL, " %i total VBOs\n", tr.numVBOs); + ri.Printf(PRINT_ALL, " %i total VAOs\n", tr.numVaos); ri.Printf(PRINT_ALL, " %d.%02d MB total vertices memory\n", vertexesSize / (1024 * 1024), (vertexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); - - ri.Printf(PRINT_ALL, " %i total IBOs\n", tr.numIBOs); ri.Printf(PRINT_ALL, " %d.%02d MB total triangle indices memory\n", indexesSize / (1024 * 1024), (indexesSize % (1024 * 1024)) * 100 / (1024 * 1024)); } @@ -882,89 +715,78 @@ void R_VBOList_f(void) /* ============== -RB_UpdateVBOs +RB_UpdateTessVao Adapted from Tess_UpdateVBOs from xreal -Update the default VBO to replace the client side vertex arrays +Update the default VAO to replace the client side vertex arrays ============== */ -void RB_UpdateVBOs(unsigned int attribBits) +void RB_UpdateTessVao(unsigned int attribBits) { - GLimp_LogComment("--- RB_UpdateVBOs ---\n"); + GLimp_LogComment("--- RB_UpdateTessVao ---\n"); - backEnd.pc.c_dynamicVboDraws++; + backEnd.pc.c_dynamicVaoDraws++; - // update the default VBO - if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES) + // update the default VAO + if(tess.numVertexes > 0 && tess.numVertexes <= SHADER_MAX_VERTEXES && tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES) { - R_BindVBO(tess.vbo); + int attribIndex; + int attribUpload; - // orphan old buffer so we don't stall on it - qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB); + R_BindVao(tess.vao); - if(attribBits & ATTR_BITS) + // orphan old vertex buffer so we don't stall on it + qglBufferDataARB(GL_ARRAY_BUFFER_ARB, tess.vao->vertexesSize, NULL, GL_DYNAMIC_DRAW_ARB); + + // if nothing to set, set everything + if(!(attribBits & ATTR_BITS)) + attribBits = ATTR_BITS; + + attribUpload = attribBits; + + if((attribUpload & ATTR_TEXCOORD) || (attribUpload & ATTR_LIGHTCOORD)) { - if(attribBits & ATTR_POSITION) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz); - } - - if(attribBits & ATTR_TEXCOORD || attribBits & ATTR_LIGHTCOORD) - { - // these are interleaved, so we update both if either need it - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords); - } - - if(attribBits & ATTR_NORMAL) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal); - } - -#ifdef USE_VERT_TANGENT_SPACE - if(attribBits & ATTR_TANGENT) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent); - } -#endif - - if(attribBits & ATTR_COLOR) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors); - } - - if(attribBits & ATTR_LIGHTDIRECTION) - { - //ri.Printf(PRINT_ALL, "offset %d, size %d\n", tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0])); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir); - } - } - else - { - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_xyz, tess.numVertexes * sizeof(tess.xyz[0]), tess.xyz); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_st, tess.numVertexes * sizeof(tess.texCoords[0][0]) * 2, tess.texCoords); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_normal, tess.numVertexes * sizeof(tess.normal[0]), tess.normal); -#ifdef USE_VERT_TANGENT_SPACE - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_tangent, tess.numVertexes * sizeof(tess.tangent[0]), tess.tangent); -#endif - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_vertexcolor, tess.numVertexes * sizeof(tess.vertexColors[0]), tess.vertexColors); - qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, tess.vbo->ofs_lightdir, tess.numVertexes * sizeof(tess.lightdir[0]), tess.lightdir); + // these are interleaved, so we update both if either need it + // this translates to updating ATTR_TEXCOORD twice as large as it needs + attribUpload &= ~ATTR_LIGHTCOORD; + attribUpload |= ATTR_TEXCOORD; } - } + for (attribIndex = 0; attribIndex < ATTR_INDEX_COUNT; attribIndex++) + { + uint32_t attribBit = 1 << attribIndex; + vaoAttrib_t *vAtb = &tess.vao->attribs[attribIndex]; - // update the default IBO - if(tess.numIndexes > 0 && tess.numIndexes <= SHADER_MAX_INDEXES) - { - R_BindIBO(tess.ibo); + if (attribUpload & attribBit) + { + // note: tess has a VBO where stride == size + qglBufferSubDataARB(GL_ARRAY_BUFFER_ARB, vAtb->offset, tess.numVertexes * vAtb->stride, tess.attribPointers[attribIndex]); + } - // orphan old buffer so we don't stall on it - qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.ibo->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB); + if (attribBits & attribBit) + { + if (!glRefConfig.vertexArrayObject) + qglVertexAttribPointerARB(attribIndex, vAtb->count, vAtb->type, vAtb->normalized, vAtb->stride, BUFFER_OFFSET(vAtb->offset)); + + if (!(glState.vertexAttribsEnabled & attribBit)) + { + qglEnableVertexAttribArrayARB(attribIndex); + glState.vertexAttribsEnabled |= attribBit; + } + } + else + { + if ((glState.vertexAttribsEnabled & attribBit)) + { + qglDisableVertexAttribArrayARB(attribIndex); + glState.vertexAttribsEnabled &= ~attribBit; + } + } + } + + // orphan old index buffer so we don't stall on it + qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, tess.vao->indexesSize, NULL, GL_DYNAMIC_DRAW_ARB); qglBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, tess.numIndexes * sizeof(tess.indexes[0]), tess.indexes); } diff --git a/code/renderergl2/tr_world.c b/code/renderergl2/tr_world.c index f4edbb03..98b1c811 100644 --- a/code/renderergl2/tr_world.c +++ b/code/renderergl2/tr_world.c @@ -213,7 +213,7 @@ static int R_DlightSurface( msurface_t *surf, int dlightBits ) { case SF_FACE: case SF_GRID: case SF_TRIANGLES: - case SF_VBO_MESH: + case SF_VAO_MESH: ((srfBspSurface_t *)surf->data)->dlightBits = dlightBits; break; @@ -299,7 +299,7 @@ static int R_PshadowSurface( msurface_t *surf, int pshadowBits ) { case SF_FACE: case SF_GRID: case SF_TRIANGLES: - case SF_VBO_MESH: + case SF_VAO_MESH: ((srfBspSurface_t *)surf->data)->pshadowBits = pshadowBits; break; @@ -330,7 +330,7 @@ static void R_AddWorldSurface( msurface_t *surf, int dlightBits, int pshadowBits } // check for dlighting - if ( dlightBits ) { + /*if ( dlightBits ) */{ dlightBits = R_DlightSurface( surf, dlightBits ); dlightBits = ( dlightBits != 0 ); } diff --git a/code/sdl/sdl_gamma.c b/code/sdl/sdl_gamma.c index b1af55ab..a1e0cb5b 100644 --- a/code/sdl/sdl_gamma.c +++ b/code/sdl/sdl_gamma.c @@ -88,6 +88,9 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned } } - SDL_SetWindowGammaRamp(SDL_window, table[0], table[1], table[2]); + if (SDL_SetWindowGammaRamp(SDL_window, table[0], table[1], table[2]) < 0) + { + ri.Printf( PRINT_DEVELOPER, "SDL_SetWindowGammaRamp() failed: %s\n", SDL_GetError() ); + } } diff --git a/code/sdl/sdl_glimp.c b/code/sdl/sdl_glimp.c index 9b36b71b..7ac87893 100644 --- a/code/sdl/sdl_glimp.c +++ b/code/sdl/sdl_glimp.c @@ -128,21 +128,34 @@ GLimp_DetectAvailableModes */ static void GLimp_DetectAvailableModes(void) { - int i; + int i, j; char buf[ MAX_STRING_CHARS ] = { 0 }; - SDL_Rect modes[ 128 ]; + int numSDLModes; + SDL_Rect *modes; int numModes = 0; - int display = SDL_GetWindowDisplayIndex( SDL_window ); SDL_DisplayMode windowMode; - - if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 ) + int display = SDL_GetWindowDisplayIndex( SDL_window ); + if( display < 0 ) { - ri.Printf( PRINT_WARNING, "Couldn't get window display mode, no resolutions detected\n" ); + ri.Printf( PRINT_WARNING, "Couldn't get window display index, no resolutions detected: %s\n", SDL_GetError() ); + return; + } + numSDLModes = SDL_GetNumDisplayModes( display ); + + if( SDL_GetWindowDisplayMode( SDL_window, &windowMode ) < 0 || numSDLModes <= 0 ) + { + ri.Printf( PRINT_WARNING, "Couldn't get window display mode, no resolutions detected: %s\n", SDL_GetError() ); return; } - for( i = 0; i < SDL_GetNumDisplayModes( display ); i++ ) + modes = SDL_calloc( (size_t)numSDLModes, sizeof( SDL_Rect ) ); + if ( !modes ) + { + ri.Error( ERR_FATAL, "Out of memory" ); + } + + for( i = 0; i < numSDLModes; i++ ) { SDL_DisplayMode mode; @@ -152,12 +165,24 @@ static void GLimp_DetectAvailableModes(void) if( !mode.w || !mode.h ) { ri.Printf( PRINT_ALL, "Display supports any resolution\n" ); + SDL_free( modes ); return; } if( windowMode.format != mode.format ) continue; + // SDL can give the same resolution with different refresh rates. + // Only list resolution once. + for( j = 0; j < numModes; j++ ) + { + if( mode.w == modes[ j ].w && mode.h == modes[ j ].h ) + break; + } + + if( j != numModes ) + continue; + modes[ numModes ].w = mode.w; modes[ numModes ].h = mode.h; numModes++; @@ -173,7 +198,7 @@ static void GLimp_DetectAvailableModes(void) if( strlen( newModeString ) < (int)sizeof( buf ) - strlen( buf ) ) Q_strcat( buf, sizeof( buf ), newModeString ); else - ri.Printf( PRINT_WARNING, "Skipping mode %ux%x, buffer too small\n", modes[ i ].w, modes[ i ].h ); + ri.Printf( PRINT_WARNING, "Skipping mode %ux%u, buffer too small\n", modes[ i ].w, modes[ i ].h ); } if( *buf ) @@ -182,6 +207,7 @@ static void GLimp_DetectAvailableModes(void) ri.Printf( PRINT_ALL, "Available modes: '%s'\n", buf ); ri.Cvar_Set( "r_availableModes", buf ); } + SDL_free( modes ); } /* @@ -224,9 +250,15 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) // If a window exists, note its display index if( SDL_window != NULL ) + { display = SDL_GetWindowDisplayIndex( SDL_window ); + if( display < 0 ) + { + ri.Printf( PRINT_DEVELOPER, "SDL_GetWindowDisplayIndex() failed: %s\n", SDL_GetError() ); + } + } - if( SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) + if( display >= 0 && SDL_GetDesktopDisplayMode( display, &desktopMode ) == 0 ) { displayAspect = (float)desktopMode.w / (float)desktopMode.h; @@ -414,7 +446,7 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) #endif if( ( SDL_window = SDL_CreateWindow( CLIENT_WINDOW_TITLE, x, y, - glConfig.vidWidth, glConfig.vidHeight, flags ) ) == 0 ) + glConfig.vidWidth, glConfig.vidHeight, flags ) ) == NULL ) { ri.Printf( PRINT_DEVELOPER, "SDL_CreateWindow failed: %s\n", SDL_GetError( ) ); continue; @@ -451,7 +483,14 @@ static int GLimp_SetMode(int mode, qboolean fullscreen, qboolean noborder) continue; } - SDL_GL_SetSwapInterval( r_swapInterval->integer ); + qglClearColor( 0, 0, 0, 1 ); + qglClear( GL_COLOR_BUFFER_BIT ); + SDL_GL_SwapWindow( SDL_window ); + + if( SDL_GL_SetSwapInterval( r_swapInterval->integer ) == -1 ) + { + ri.Printf( PRINT_DEVELOPER, "SDL_GL_SetSwapInterval failed: %s\n", SDL_GetError( ) ); + } glConfig.colorBits = testColorBits; glConfig.depthBits = testDepthBits; @@ -491,7 +530,7 @@ static qboolean GLimp_StartDriverAndSetMode(int mode, qboolean fullscreen, qbool { const char *driverName; - if (SDL_Init(SDL_INIT_VIDEO) == -1) + if (SDL_Init(SDL_INIT_VIDEO) != 0) { ri.Printf( PRINT_ALL, "SDL_Init( SDL_INIT_VIDEO ) FAILED (%s)\n", SDL_GetError()); return qfalse; diff --git a/code/sdl/sdl_input.c b/code/sdl/sdl_input.c index 22428d57..2afa2c16 100644 --- a/code/sdl/sdl_input.c +++ b/code/sdl/sdl_input.c @@ -44,7 +44,6 @@ static cvar_t *in_mouse = NULL; static cvar_t *in_nograb; static cvar_t *in_joystick = NULL; -static cvar_t *in_joystickDebug = NULL; static cvar_t *in_joystickThreshold = NULL; static cvar_t *in_joystickNo = NULL; static cvar_t *in_joystickUseAnalog = NULL; @@ -248,8 +247,13 @@ static keyNum_t IN_TranslateSDLToQ3Key( SDL_Keysym *keysym, qboolean down ) case SDLK_LCTRL: case SDLK_RCTRL: key = K_CTRL; break; +#ifdef MACOS_X case SDLK_RGUI: case SDLK_LGUI: key = K_COMMAND; break; +#else + case SDLK_RGUI: + case SDLK_LGUI: key = K_SUPER; break; +#endif case SDLK_RALT: case SDLK_LALT: key = K_ALT; break; @@ -267,9 +271,11 @@ static keyNum_t IN_TranslateSDLToQ3Key( SDL_Keysym *keysym, qboolean down ) case SDLK_PRINTSCREEN: key = K_PRINT; break; case SDLK_SYSREQ: key = K_SYSREQ; break; case SDLK_MENU: key = K_MENU; break; + case SDLK_APPLICATION: key = K_MENU; break; case SDLK_POWER: key = K_POWER; break; case SDLK_UNDO: key = K_UNDO; break; case SDLK_SCROLLLOCK: key = K_SCROLLOCK; break; + case SDLK_NUMLOCKCLEAR: key = K_KP_NUMLOCK; break; case SDLK_CAPSLOCK: key = K_CAPSLOCK; break; default: @@ -321,7 +327,7 @@ static void IN_ActivateMouse( void ) if( !mouseActive ) { SDL_SetRelativeMouseMode( SDL_TRUE ); - SDL_SetWindowGrab( SDL_window, 1 ); + SDL_SetWindowGrab( SDL_window, SDL_TRUE ); IN_GobbleMotionEvents( ); } @@ -332,9 +338,9 @@ static void IN_ActivateMouse( void ) if( in_nograb->modified || !mouseActive ) { if( in_nograb->integer ) - SDL_SetWindowGrab( SDL_window, 0 ); + SDL_SetWindowGrab( SDL_window, SDL_FALSE ); else - SDL_SetWindowGrab( SDL_window, 1 ); + SDL_SetWindowGrab( SDL_window, SDL_TRUE ); in_nograb->modified = qfalse; } @@ -365,7 +371,7 @@ static void IN_DeactivateMouse( void ) { IN_GobbleMotionEvents( ); - SDL_SetWindowGrab( SDL_window, 0 ); + SDL_SetWindowGrab( SDL_window, SDL_FALSE ); SDL_SetRelativeMouseMode( SDL_FALSE ); // Don't warp the mouse unless the cursor is within the window @@ -431,7 +437,7 @@ static void IN_InitJoystick( void ) if (!SDL_WasInit(SDL_INIT_JOYSTICK)) { Com_DPrintf("Calling SDL_Init(SDL_INIT_JOYSTICK)...\n"); - if (SDL_Init(SDL_INIT_JOYSTICK) == -1) + if (SDL_Init(SDL_INIT_JOYSTICK) != 0) { Com_DPrintf("SDL_Init(SDL_INIT_JOYSTICK) failed: %s\n", SDL_GetError()); return; @@ -507,7 +513,6 @@ IN_JoyMove */ static void IN_JoyMove( void ) { - qboolean joy_pressed[ARRAY_LEN(joy_keys)]; unsigned int axes = 0; unsigned int hats = 0; int total = 0; @@ -518,8 +523,6 @@ static void IN_JoyMove( void ) SDL_JoystickUpdate(); - memset(joy_pressed, '\0', sizeof (joy_pressed)); - // update the ball state. total = SDL_JoystickNumBalls(stick); if (total > 0) @@ -726,6 +729,9 @@ static void IN_ProcessEvents( void ) switch( e.type ) { case SDL_KEYDOWN: + if ( e.key.repeat && Key_GetCatcher( ) == 0 ) + break; + if( ( key = IN_TranslateSDLToQ3Key( &e.key.keysym, qtrue ) ) ) Com_QueueEvent( 0, SE_KEY, key, qtrue, 0, NULL ); @@ -770,7 +776,7 @@ static void IN_ProcessEvents( void ) else if( ( *c & 0xF8 ) == 0xF0 ) // 1111 0xxx { utf32 |= ( *c++ & 0x07 ) << 18; - utf32 |= ( *c++ & 0x3F ) << 6; + utf32 |= ( *c++ & 0x3F ) << 12; utf32 |= ( *c++ & 0x3F ) << 6; utf32 |= ( *c++ & 0x3F ); } @@ -796,7 +802,11 @@ static void IN_ProcessEvents( void ) case SDL_MOUSEMOTION: if( mouseActive ) + { + if( !e.motion.xrel && !e.motion.yrel ) + break; Com_QueueEvent( 0, SE_MOUSE, e.motion.xrel, e.motion.yrel, 0, NULL ); + } break; case SDL_MOUSEBUTTONDOWN: @@ -823,7 +833,7 @@ static void IN_ProcessEvents( void ) Com_QueueEvent( 0, SE_KEY, K_MWHEELUP, qtrue, 0, NULL ); Com_QueueEvent( 0, SE_KEY, K_MWHEELUP, qfalse, 0, NULL ); } - else + else if( e.wheel.y < 0 ) { Com_QueueEvent( 0, SE_KEY, K_MWHEELDOWN, qtrue, 0, NULL ); Com_QueueEvent( 0, SE_KEY, K_MWHEELDOWN, qfalse, 0, NULL ); @@ -839,11 +849,19 @@ static void IN_ProcessEvents( void ) { case SDL_WINDOWEVENT_RESIZED: { - char width[32], height[32]; - Com_sprintf( width, sizeof( width ), "%d", e.window.data1 ); - Com_sprintf( height, sizeof( height ), "%d", e.window.data2 ); - Cvar_Set( "r_customwidth", width ); - Cvar_Set( "r_customheight", height ); + int width, height; + + width = e.window.data1; + height = e.window.data2; + + // check if size actually changed + if( cls.glconfig.vidWidth == width && cls.glconfig.vidHeight == height ) + { + break; + } + + Cvar_SetValue( "r_customwidth", width ); + Cvar_SetValue( "r_customheight", height ); Cvar_Set( "r_mode", "-1" ); // Wait until user stops dragging for 1 second, so @@ -877,7 +895,6 @@ void IN_Frame( void ) qboolean loading; IN_JoyMove( ); - IN_ProcessEvents( ); // If not DISCONNECTED (main menu) or ACTIVE (in game), we're loading loading = ( clc.state != CA_DISCONNECTED && clc.state != CA_ACTIVE ); @@ -900,6 +917,8 @@ void IN_Frame( void ) else IN_ActivateMouse( ); + IN_ProcessEvents( ); + // In case we had to delay actual restart of video system if( ( vidRestartTime != 0 ) && ( vidRestartTime < Sys_Milliseconds( ) ) ) { @@ -908,20 +927,6 @@ void IN_Frame( void ) } } -/* -=============== -IN_InitKeyLockStates -=============== -*/ -void IN_InitKeyLockStates( void ) -{ - const unsigned char *keystate = SDL_GetKeyboardState(NULL); - - keys[K_SCROLLOCK].down = keystate[SDL_SCANCODE_SCROLLLOCK]; - keys[K_KP_NUMLOCK].down = keystate[SDL_SCANCODE_NUMLOCKCLEAR]; - keys[K_CAPSLOCK].down = keystate[SDL_SCANCODE_CAPSLOCK]; -} - /* =============== IN_Init @@ -948,7 +953,6 @@ void IN_Init( void *windowData ) in_nograb = Cvar_Get( "in_nograb", "0", CVAR_ARCHIVE ); in_joystick = Cvar_Get( "in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH ); - in_joystickDebug = Cvar_Get( "in_joystickDebug", "0", CVAR_TEMP ); in_joystickThreshold = Cvar_Get( "joy_threshold", "0.15", CVAR_ARCHIVE ); SDL_StartTextInput( ); @@ -960,8 +964,6 @@ void IN_Init( void *windowData ) Cvar_SetValue( "com_unfocused", !( appState & SDL_WINDOW_INPUT_FOCUS ) ); Cvar_SetValue( "com_minimized", appState & SDL_WINDOW_MINIMIZED ); - IN_InitKeyLockStates( ); - IN_InitJoystick( ); Com_DPrintf( "------------------------------------\n" ); } diff --git a/code/sdl/sdl_snd.c b/code/sdl/sdl_snd.c index 710c0362..609aed9e 100644 --- a/code/sdl/sdl_snd.c +++ b/code/sdl/sdl_snd.c @@ -156,7 +156,7 @@ qboolean SNDDMA_Init(void) if (!SDL_WasInit(SDL_INIT_AUDIO)) { - if (SDL_Init(SDL_INIT_AUDIO) == -1) + if (SDL_Init(SDL_INIT_AUDIO) != 0) { Com_Printf( "FAILED (%s)\n", SDL_GetError( ) ); return qfalse; diff --git a/code/server/sv_bot.c b/code/server/sv_bot.c index eb7089e1..d92dfcaf 100644 --- a/code/server/sv_bot.c +++ b/code/server/sv_bot.c @@ -188,7 +188,8 @@ static void BotImport_Trace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mins, ve VectorCopy(trace.plane.normal, bsptrace->plane.normal); bsptrace->plane.signbits = trace.plane.signbits; bsptrace->plane.type = trace.plane.type; - bsptrace->surface.value = trace.surfaceFlags; + bsptrace->surface.value = 0; + bsptrace->surface.flags = trace.surfaceFlags; bsptrace->ent = trace.entityNum; bsptrace->exp_dist = 0; bsptrace->sidenum = 0; @@ -213,7 +214,8 @@ static void BotImport_EntityTrace(bsp_trace_t *bsptrace, vec3_t start, vec3_t mi VectorCopy(trace.plane.normal, bsptrace->plane.normal); bsptrace->plane.signbits = trace.plane.signbits; bsptrace->plane.type = trace.plane.type; - bsptrace->surface.value = trace.surfaceFlags; + bsptrace->surface.value = 0; + bsptrace->surface.flags = trace.surfaceFlags; bsptrace->ent = trace.entityNum; bsptrace->exp_dist = 0; bsptrace->sidenum = 0; diff --git a/code/server/sv_ccmds.c b/code/server/sv_ccmds.c index ca73290a..1b723399 100644 --- a/code/server/sv_ccmds.c +++ b/code/server/sv_ccmds.c @@ -846,7 +846,7 @@ static void SV_AddBanToList(qboolean isexception) return; } - if(serverBansCount > ARRAY_LEN(serverBans)) + if(serverBansCount >= ARRAY_LEN(serverBans)) { Com_Printf ("Error: Maximum number of bans/exceptions exceeded.\n"); return; diff --git a/code/server/sv_main.c b/code/server/sv_main.c index ed50707e..4169fd2e 100644 --- a/code/server/sv_main.c +++ b/code/server/sv_main.c @@ -487,7 +487,7 @@ qboolean SVC_RateLimit( leakyBucket_t *bucket, int burst, int period ) { int expired = interval / period; int expiredRemainder = interval % period; - if ( expired > bucket->burst ) { + if ( expired > bucket->burst || interval < 0 ) { bucket->burst = 0; bucket->lastTime = now; } else { diff --git a/code/sys/con_win32.c b/code/sys/con_win32.c index ea64e013..e273ff05 100644 --- a/code/sys/con_win32.c +++ b/code/sys/con_win32.c @@ -44,6 +44,7 @@ static int qconsole_history_oldest = 0; static char qconsole_line[ MAX_EDIT_LINE ]; static int qconsole_linelen = 0; static qboolean qconsole_drawinput = qtrue; +static int qconsole_cursor; static HANDLE qconsole_hout; static HANDLE qconsole_hin; @@ -139,6 +140,7 @@ static void CON_HistPrev( void ) Q_strncpyz( qconsole_line, qconsole_history[ qconsole_history_pos ], sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); + qconsole_cursor = qconsole_linelen; } /* @@ -163,6 +165,7 @@ static void CON_HistNext( void ) qconsole_history_pos = pos; qconsole_line[ 0 ] = '\0'; qconsole_linelen = 0; + qconsole_cursor = qconsole_linelen; return; } @@ -170,6 +173,7 @@ static void CON_HistNext( void ) Q_strncpyz( qconsole_line, qconsole_history[ qconsole_history_pos ], sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); + qconsole_cursor = qconsole_linelen; } @@ -208,7 +212,7 @@ static void CON_Show( void ) { if( i < qconsole_linelen ) { - if( Q_IsColorString( qconsole_line + i ) ) + if( i + 1 < qconsole_linelen && Q_IsColorString( qconsole_line + i ) ) attrib = CON_ColorCharToAttrib( *( qconsole_line + i + 1 ) ); line[ i ].Char.AsciiChar = qconsole_line[ i ]; @@ -233,7 +237,11 @@ static void CON_Show( void ) // set curor position cursorPos.Y = binfo.dwCursorPosition.Y; - cursorPos.X = qconsole_linelen > binfo.srWindow.Right ? binfo.srWindow.Right : qconsole_linelen; + cursorPos.X = qconsole_cursor < qconsole_linelen + ? qconsole_cursor + : qconsole_linelen > binfo.srWindow.Right + ? binfo.srWindow.Right + : qconsole_linelen; SetConsoleCursorPosition( qconsole_hout, cursorPos ); } @@ -358,6 +366,7 @@ char *CON_Input( void ) if( key == VK_RETURN ) { newlinepos = i; + qconsole_cursor = 0; break; } else if( key == VK_UP ) @@ -370,6 +379,34 @@ char *CON_Input( void ) CON_HistNext(); break; } + else if( key == VK_LEFT ) + { + qconsole_cursor--; + if ( qconsole_cursor < 0 ) + { + qconsole_cursor = 0; + } + break; + } + else if( key == VK_RIGHT ) + { + qconsole_cursor++; + if ( qconsole_cursor > qconsole_linelen ) + { + qconsole_cursor = qconsole_linelen; + } + break; + } + else if( key == VK_HOME ) + { + qconsole_cursor = 0; + break; + } + else if( key == VK_END ) + { + qconsole_cursor = qconsole_linelen; + break; + } else if( key == VK_TAB ) { field_t f; @@ -380,6 +417,7 @@ char *CON_Input( void ) Q_strncpyz( qconsole_line, f.buffer, sizeof( qconsole_line ) ); qconsole_linelen = strlen( qconsole_line ); + qconsole_cursor = qconsole_linelen; break; } @@ -389,15 +427,33 @@ char *CON_Input( void ) if( key == VK_BACK ) { - int pos = ( qconsole_linelen > 0 ) ? - qconsole_linelen - 1 : 0; + if ( qconsole_cursor > 0 ) + { + int newlen = ( qconsole_linelen > 0 ) ? qconsole_linelen - 1 : 0; + if ( qconsole_cursor < qconsole_linelen ) + { + memmove( qconsole_line + qconsole_cursor - 1, + qconsole_line + qconsole_cursor, + qconsole_linelen - qconsole_cursor ); + } - qconsole_line[ pos ] = '\0'; - qconsole_linelen = pos; + qconsole_line[ newlen ] = '\0'; + qconsole_linelen = newlen; + qconsole_cursor--; + } } else if( c ) { - qconsole_line[ qconsole_linelen++ ] = c; + if ( qconsole_linelen > qconsole_cursor ) + { + memmove( qconsole_line + qconsole_cursor + 1, + qconsole_line + qconsole_cursor, + qconsole_linelen - qconsole_cursor ); + } + + qconsole_line[ qconsole_cursor++ ] = c; + + qconsole_linelen++; qconsole_line[ qconsole_linelen ] = '\0'; } } diff --git a/code/sys/sys_main.c b/code/sys/sys_main.c index 078011aa..46817c8a 100644 --- a/code/sys/sys_main.c +++ b/code/sys/sys_main.c @@ -127,6 +127,35 @@ char *Sys_ConsoleInput(void) return CON_Input( ); } +/* +================== +Sys_GetClipboardData +================== +*/ +char *Sys_GetClipboardData(void) +{ +#ifdef DEDICATED + return NULL; +#else + char *data = NULL; + char *cliptext; + + if ( ( cliptext = SDL_GetClipboardText() ) != NULL ) { + if ( cliptext[0] != '\0' ) { + size_t bufsize = strlen( cliptext ) + 1; + + data = Z_Malloc( bufsize ); + Q_strncpyz( data, cliptext, bufsize ); + + // find first listed char and set to '\0' + strtok( data, "\n\r\b" ); + } + SDL_free( cliptext ); + } + return data; +#endif +} + #ifdef DEDICATED # define PID_FILENAME PRODUCT_NAME "_server.pid" #else @@ -140,7 +169,7 @@ Sys_PIDFileName */ static char *Sys_PIDFileName( void ) { - const char *homePath = Sys_DefaultHomePath( ); + const char *homePath = Cvar_VariableString( "fs_homepath" ); if( *homePath != '\0' ) return va( "%s/%s", homePath, PID_FILENAME ); @@ -615,6 +644,12 @@ int main( int argc, char **argv ) // Set the initial time base Sys_Milliseconds( ); +#ifdef MACOS_X + // This is passed if we are launched by double-clicking + if ( argc >= 2 && Q_strncmp ( argv[1], "-psn", 4 ) == 0 ) + argc = 1; +#endif + #ifdef MACOS_X // This is passed if we are launched by double-clicking if ( argc >= 2 && Q_strncmp ( argv[1], "-psn", 4 ) == 0 ) diff --git a/code/sys/sys_unix.c b/code/sys/sys_unix.c index c2de336d..cf980eba 100644 --- a/code/sys/sys_unix.c +++ b/code/sys/sys_unix.c @@ -44,6 +44,9 @@ qboolean stdinIsATTY; // Used to determine where to store user-specific files static char homePath[ MAX_OSPATH ] = { 0 }; +// Used to store the Steam Quake 3 installation path +static char steamPath[ MAX_OSPATH ] = { 0 }; + /* ================== Sys_DefaultHomePath @@ -78,6 +81,31 @@ char *Sys_DefaultHomePath(void) return homePath; } +/* +================ +Sys_SteamPath +================ +*/ +char *Sys_SteamPath( void ) +{ + // Disabled since Steam doesn't let you install Quake 3 on Mac/Linux +#if 0 //#ifdef STEAMPATH_NAME + char *p; + + if( ( p = getenv( "HOME" ) ) != NULL ) + { +#ifdef MACOS_X + char *steamPathEnd = "/Library/Application Support/Steam/SteamApps/common/" STEAMPATH_NAME; +#else + char *steamPathEnd = "/.steam/steam/SteamApps/common/" STEAMPATH_NAME; +#endif + Com_sprintf(steamPath, sizeof(steamPath), "%s%s", p, steamPathEnd); + } +#endif + + return steamPath; +} + /* ================ Sys_Milliseconds @@ -123,6 +151,8 @@ qboolean Sys_RandomBytes( byte *string, int len ) if( !fp ) return qfalse; + setvbuf( fp, NULL, _IONBF, 0 ); // don't buffer reads from /dev/urandom + if( fread( string, sizeof( byte ), len, fp ) != len ) { fclose( fp ); @@ -148,16 +178,6 @@ char *Sys_GetCurrentUser( void ) return p->pw_name; } -/* -================== -Sys_GetClipboardData -================== -*/ -char *Sys_GetClipboardData(void) -{ - return NULL; -} - #define MEM_THRESHOLD 96*1024*1024 /* @@ -729,6 +749,7 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t qboolean tried[ NUM_DIALOG_PROGRAMS ] = { qfalse }; dialogCommandBuilder_t commands[ NUM_DIALOG_PROGRAMS ] = { NULL }; dialogCommandType_t preferredCommandType = NONE; + int i; commands[ ZENITY ] = &Sys_ZenityCommand; commands[ KDIALOG ] = &Sys_KdialogCommand; @@ -740,50 +761,37 @@ dialogResult_t Sys_Dialog( dialogType_t type, const char *message, const char *t else if( !Q_stricmp( session, "kde" ) ) preferredCommandType = KDIALOG; - while( 1 ) + for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ ) { - int i; + if( preferredCommandType != NONE && preferredCommandType != i ) + continue; - for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ ) + if( !tried[ i ] ) { - if( preferredCommandType != NONE && preferredCommandType != i ) - continue; + int exitCode; - if( !tried[ i ] ) + commands[ i ]( type, message, title ); + exitCode = Sys_Exec( ); + + if( exitCode >= 0 ) { - int exitCode; - - commands[ i ]( type, message, title ); - exitCode = Sys_Exec( ); - - if( exitCode >= 0 ) + switch( type ) { - switch( type ) - { - case DT_YES_NO: return exitCode ? DR_NO : DR_YES; - case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK; - default: return DR_OK; - } - } - - tried[ i ] = qtrue; - - // The preference failed, so start again in order - if( preferredCommandType != NONE ) - { - preferredCommandType = NONE; - break; + case DT_YES_NO: return exitCode ? DR_NO : DR_YES; + case DT_OK_CANCEL: return exitCode ? DR_CANCEL : DR_OK; + default: return DR_OK; } } - } - for( i = NONE + 1; i < NUM_DIALOG_PROGRAMS; i++ ) - { - if( !tried[ i ] ) - continue; - } + tried[ i ] = qtrue; - break; + // The preference failed, so start again in order + if( preferredCommandType != NONE ) + { + preferredCommandType = NONE; + i = NONE + 1; + } + } } Com_DPrintf( S_COLOR_YELLOW "WARNING: failed to show a dialog\n" ); @@ -835,9 +843,11 @@ void Sys_PlatformInit( void ) signal( SIGHUP, Sys_SigHandler ); signal( SIGQUIT, Sys_SigHandler ); signal( SIGTRAP, Sys_SigHandler ); - signal( SIGIOT, Sys_SigHandler ); + signal( SIGABRT, Sys_SigHandler ); signal( SIGBUS, Sys_SigHandler ); + Sys_SetFloatEnv(); + stdinIsATTY = isatty( STDIN_FILENO ) && !( term && ( !strcmp( term, "raw" ) || !strcmp( term, "dumb" ) ) ); } diff --git a/code/sys/sys_win32.c b/code/sys/sys_win32.c index 57c7ed56..24fe1cf5 100644 --- a/code/sys/sys_win32.c +++ b/code/sys/sys_win32.c @@ -42,6 +42,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Used to determine where to store user-specific files static char homePath[ MAX_OSPATH ] = { 0 }; +// Used to store the Steam Quake 3 installation path +static char steamPath[ MAX_OSPATH ] = { 0 }; + #ifndef DEDICATED static UINT timerResolution = 0; #endif @@ -126,6 +129,62 @@ char *Sys_DefaultHomePath( void ) return homePath; } +/* +================ +Sys_SteamPath +================ +*/ +char *Sys_SteamPath( void ) +{ +#if defined(STEAMPATH_NAME) || defined(STEAMPATH_APPID) + HKEY steamRegKey; + DWORD pathLen = MAX_OSPATH; + qboolean finishPath = qfalse; + +#ifdef STEAMPATH_APPID + if (!steamPath[0] && !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App " STEAMPATH_APPID, 0, KEY_QUERY_VALUE, &steamRegKey)) + { + pathLen = MAX_OSPATH; + if (RegQueryValueEx(steamRegKey, "InstallLocation", NULL, NULL, (LPBYTE)steamPath, &pathLen)) + steamPath[0] = '\0'; + } + + if (!steamPath[0] && !RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Steam App " STEAMPATH_APPID, 0, KEY_QUERY_VALUE, &steamRegKey)) + { + pathLen = MAX_OSPATH; + if (RegQueryValueEx(steamRegKey, "InstallLocation", NULL, NULL, (LPBYTE)steamPath, &pathLen)) + steamPath[0] = '\0'; + } +#endif + +#ifdef STEAMPATH_NAME + if (!steamPath[0] && !RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Valve\\Steam", 0, KEY_QUERY_VALUE, &steamRegKey)) + { + pathLen = MAX_OSPATH; + if (RegQueryValueEx(steamRegKey, "SteamPath", NULL, NULL, (LPBYTE)steamPath, &pathLen)) + if (RegQueryValueEx(steamRegKey, "InstallPath", NULL, NULL, (LPBYTE)steamPath, &pathLen)) + steamPath[0] = '\0'; + + if (steamPath[0]) + finishPath = qtrue; + } +#endif + + if (steamPath[0]) + { + if (pathLen == MAX_OSPATH) + pathLen--; + + steamPath[pathLen] = '\0'; + + if (finishPath) + Q_strcat(steamPath, MAX_OSPATH, "\\SteamApps\\common\\" STEAMPATH_NAME ); + } +#endif + + return steamPath; +} + /* ================ Sys_Milliseconds @@ -190,33 +249,6 @@ char *Sys_GetCurrentUser( void ) return s_userName; } -/* -================ -Sys_GetClipboardData -================ -*/ -char *Sys_GetClipboardData( void ) -{ - char *data = NULL; - char *cliptext; - - if ( OpenClipboard( NULL ) != 0 ) { - HANDLE hClipboardData; - - if ( ( hClipboardData = GetClipboardData( CF_TEXT ) ) != 0 ) { - if ( ( cliptext = GlobalLock( hClipboardData ) ) != 0 ) { - data = Z_Malloc( GlobalSize( hClipboardData ) + 1 ); - Q_strncpyz( data, cliptext, GlobalSize( hClipboardData ) ); - GlobalUnlock( hClipboardData ); - - strtok( data, "\n\r\b" ); - } - } - CloseClipboard(); - } - return data; -} - #define MEM_THRESHOLD 96*1024*1024 /* @@ -437,6 +469,7 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter intptr_t findhandle; int flag; int i; + int extLen; if (filter) { @@ -470,6 +503,8 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter flag = _A_SUBDIR; } + extLen = strlen( extension ); + Com_sprintf( search, sizeof(search), "%s\\*%s", directory, extension ); // search @@ -483,6 +518,14 @@ char **Sys_ListFiles( const char *directory, const char *extension, char *filter do { if ( (!wantsubs && flag ^ ( findinfo.attrib & _A_SUBDIR )) || (wantsubs && findinfo.attrib & _A_SUBDIR) ) { + if (*extension) { + if ( strlen( findinfo.name ) < extLen || + Q_stricmp( + findinfo.name + strlen( findinfo.name ) - extLen, + extension ) ) { + continue; // didn't match + } + } if ( nfiles == MAX_FOUND_FILES - 1 ) { break; } diff --git a/code/tools/lcc/cpp/cpp.c b/code/tools/lcc/cpp/cpp.c index b999d212..5c0cfd7b 100644 --- a/code/tools/lcc/cpp/cpp.c +++ b/code/tools/lcc/cpp/cpp.c @@ -9,7 +9,7 @@ char rcsid[] = "cpp.c - faked rcsid"; #define OUTS 16384 char outbuf[OUTS]; -char *outp = outbuf; +char *outbufp = outbuf; Source *cursource; int nerrs; struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" }; @@ -51,7 +51,7 @@ process(Tokenrow *trp) for (;;) { if (trp->tp >= trp->lp) { trp->tp = trp->lp = trp->bp; - outp = outbuf; + outbufp = outbuf; anymacros |= gettokens(trp, 1); trp->tp = trp->bp; } diff --git a/code/tools/lcc/cpp/cpp.h b/code/tools/lcc/cpp/cpp.h index 87871d9d..ddd7502d 100644 --- a/code/tools/lcc/cpp/cpp.h +++ b/code/tools/lcc/cpp/cpp.h @@ -143,7 +143,7 @@ void setobjname(char *); char *basepath( char *fname ); -extern char *outp; +extern char *outbufp; extern Token nltoken; extern Source *cursource; extern char *curtime; diff --git a/code/tools/lcc/cpp/include.c b/code/tools/lcc/cpp/include.c index 54c0b77a..5ecd8b30 100644 --- a/code/tools/lcc/cpp/include.c +++ b/code/tools/lcc/cpp/include.c @@ -120,7 +120,7 @@ genline(void) static Tokenrow tr = { &ta, &ta, &ta+1, 1 }; uchar *p; - ta.t = p = (uchar*)outp; + ta.t = p = (uchar*)outbufp; strcpy((char*)p, "#line "); p += sizeof("#line ")-1; p = (uchar*)outnum((char*)p, cursource->line); @@ -133,8 +133,8 @@ genline(void) strcpy((char*)p, cursource->filename); p += strlen((char*)p); *p++ = '"'; *p++ = '\n'; - ta.len = (char*)p-outp; - outp = (char*)p; + ta.len = (char*)p-outbufp; + outbufp = (char*)p; tr.tp = tr.bp; puttokens(&tr); } diff --git a/code/tools/lcc/cpp/macro.c b/code/tools/lcc/cpp/macro.c index 71102570..2972083e 100644 --- a/code/tools/lcc/cpp/macro.c +++ b/code/tools/lcc/cpp/macro.c @@ -470,10 +470,10 @@ builtin(Tokenrow *trp, int biname) /* most are strings */ tp->type = STRING; if (tp->wslen) { - *outp++ = ' '; + *outbufp++ = ' '; tp->wslen = 1; } - op = outp; + op = outbufp; *op++ = '"'; switch (biname) { @@ -508,7 +508,7 @@ builtin(Tokenrow *trp, int biname) } if (tp->type==STRING) *op++ = '"'; - tp->t = (uchar*)outp; - tp->len = op - outp; - outp = op; + tp->t = (uchar*)outbufp; + tp->len = op - outbufp; + outbufp = op; } diff --git a/code/tools/lcc/cpp/unix.c b/code/tools/lcc/cpp/unix.c index bd879448..75e5b6d3 100644 --- a/code/tools/lcc/cpp/unix.c +++ b/code/tools/lcc/cpp/unix.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "cpp.h" extern int lcc_getopt(int, char *const *, const char *); @@ -66,7 +67,12 @@ setup(int argc, char **argv) error(FATAL, "Can't open input file %s", fp); } if (optind+1 #include #include +#ifdef WIN32 +#include /* getpid() */ +#include /* access() */ +#else #include +#endif #ifndef TEMPDIR #define TEMPDIR "/tmp" diff --git a/code/tools/lcc/lburg/gram.c b/code/tools/lcc/lburg/gram.c index a7891031..94fd3b3d 100644 --- a/code/tools/lcc/lburg/gram.c +++ b/code/tools/lcc/lburg/gram.c @@ -1,246 +1,1545 @@ -#ifndef lint -static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; -#endif +/* A Bison parser, made by GNU Bison 3.0.2. */ -#define YYBYACC 1 -#define YYMAJOR 1 -#define YYMINOR 9 -#define YYPATCH 20130304 +/* Bison implementation for Yacc-like parsers in C -#define YYEMPTY (-1) -#define yyclearin (yychar = YYEMPTY) -#define yyerrok (yyerrflag = 0) -#define YYRECOVERING() (yyerrflag != 0) + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. -#define YYPREFIX "yy" + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.2" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ #define YYPURE 0 -#line 2 "code/tools/lcc/lburg/gram.y" +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* Copy the first part of user declarations. */ +#line 1 "code/tools/lcc/lburg/gram.y" /* yacc.c:339 */ + #include #include "lburg.h" -static char rcsid[] = "$Id: gram.y 145 2001-10-17 21:53:10Z timo $"; +//static char rcsid[] = "$Id: gram.y 145 2001-10-17 21:53:10Z timo $"; /*lint -e616 -e527 -e652 -esym(552,yynerrs) -esym(563,yynewstate,yyerrlab) */ static int yylineno = 0; -#line 8 "code/tools/lcc/lburg/gram.y" -#ifdef YYSTYPE -#undef YYSTYPE_IS_DECLARED -#define YYSTYPE_IS_DECLARED 1 + +#line 74 "y.tab.c" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 #endif -#ifndef YYSTYPE_IS_DECLARED -#define YYSTYPE_IS_DECLARED 1 -typedef union { + + +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + TERMINAL = 258, + START = 259, + PPERCENT = 260, + ID = 261, + TEMPLATE = 262, + CODE = 263, + INT = 264 + }; +#endif +/* Tokens. */ +#define TERMINAL 258 +#define START 259 +#define PPERCENT 260 +#define ID 261 +#define TEMPLATE 262 +#define CODE 263 +#define INT 264 + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE YYSTYPE; +union YYSTYPE +{ +#line 8 "code/tools/lcc/lburg/gram.y" /* yacc.c:355 */ + int n; char *string; Tree tree; -} YYSTYPE; -#endif /* !YYSTYPE_IS_DECLARED */ -#line 38 "y.tab.c" -/* compatibility with bison */ -#ifdef YYPARSE_PARAM -/* compatibility with FreeBSD */ -# ifdef YYPARSE_PARAM_TYPE -# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM) +#line 135 "y.tab.c" /* yacc.c:355 */ +}; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); +int yylex(void); + + + +/* Copy the second part of user declarations. */ + +#line 150 "y.tab.c" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t # else -# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM) +# define YYSIZE_T unsigned int # endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) #else -# define YYPARSE_DECL() yyparse(void) +# define YYUSE(E) /* empty */ #endif -/* Parameters sent to lex. */ -#ifdef YYLEX_PARAM -# define YYLEX_DECL() yylex(void *YYLEX_PARAM) -# define YYLEX yylex(YYLEX_PARAM) +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") #else -# define YYLEX_DECL() yylex(void) -# define YYLEX yylex() +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ #endif -/* Parameters sent to yyerror. */ -#ifndef YYERROR_DECL -#define YYERROR_DECL() yyerror(const char *s) -#endif -#ifndef YYERROR_CALL -#define YYERROR_CALL(msg) yyerror(msg) + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + #endif -extern int YYPARSE_DECL(); +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ -#define TERMINAL 257 -#define START 258 -#define PPERCENT 259 -#define ID 260 -#define TEMPLATE 261 -#define CODE 262 -#define INT 263 -#define YYERRCODE 256 -static const short yylhs[] = { -1, - 0, 0, 4, 4, 6, 6, 6, 6, 7, 7, - 5, 5, 5, 5, 1, 3, 3, 3, 2, +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 35 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 16 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 9 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 20 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 37 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 264 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 10, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 13, 14, 2, 2, 15, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 12, 2, + 2, 11, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9 }; -static const short yylen[] = { 2, - 3, 1, 0, 2, 3, 3, 1, 2, 0, 4, - 0, 7, 2, 3, 1, 1, 4, 6, 1, -}; -static const short yydefred[] = { 3, - 0, 0, 0, 9, 0, 11, 7, 4, 8, 0, - 15, 0, 0, 0, 5, 6, 0, 13, 0, 0, - 14, 0, 10, 0, 0, 0, 0, 0, 19, 0, - 17, 0, 12, 0, 18, -}; -static const short yydgoto[] = { 1, - 12, 30, 25, 2, 13, 8, 10, -}; -static const short yysindex[] = { 0, - 0, -4, -2, 0, -250, 0, 0, 0, 0, -9, - 0, 1, -10, -49, 0, 0, 3, 0, -44, -248, - 0, -244, 0, -22, -242, -244, -245, -37, 0, 10, - 0, -244, 0, -20, 0, -}; -static const short yyrindex[] = { 0, - 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, -39, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -}; -static const short yygindex[] = { 0, - 11, 0, -23, 0, 0, 0, 0, -}; -#define YYTABLESIZE 255 -static const short yytable[] = { 18, - 15, 16, 28, 31, 16, 7, 32, 9, 34, 11, - 16, 20, 21, 22, 23, 24, 29, 26, 27, 33, - 35, 2, 1, 19, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 17, 0, 0, 0, 11, - 14, 3, 4, 5, 6, -}; -static const short yycheck[] = { 10, - 10, 41, 26, 41, 44, 10, 44, 10, 32, 260, - 10, 61, 10, 58, 263, 260, 262, 40, 261, 10, - 41, 0, 0, 13, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 261, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 256, -1, -1, -1, 260, - 260, 256, 257, 258, 259, -}; -#define YYFINAL 1 -#ifndef YYDEBUG -#define YYDEBUG 0 -#endif -#define YYMAXTOKEN 263 + #if YYDEBUG -static const char *yyname[] = { - -"end-of-file",0,0,0,0,0,0,0,0,0,"'\\n'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,"'('","')'",0,0,"','",0,0,0,0,0,0,0,0,0,0,0,0,0,"':'",0,0, -"'='",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -"TERMINAL","START","PPERCENT","ID","TEMPLATE","CODE","INT", -}; -static const char *yyrule[] = { -"$accept : spec", -"spec : decls PPERCENT rules", -"spec : decls", -"decls :", -"decls : decls decl", -"decl : TERMINAL blist '\\n'", -"decl : START nonterm '\\n'", -"decl : '\\n'", -"decl : error '\\n'", -"blist :", -"blist : blist ID '=' INT", -"rules :", -"rules : rules nonterm ':' tree TEMPLATE cost '\\n'", -"rules : rules '\\n'", -"rules : rules error '\\n'", -"nonterm : ID", -"tree : ID", -"tree : ID '(' tree ')'", -"tree : ID '(' tree ',' tree ')'", -"cost : CODE", - + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint8 yyrline[] = +{ + 0, 22, 22, 23, 26, 27, 30, 31, 35, 36, + 39, 40, 43, 44, 45, 46, 49, 52, 53, 54, + 57 }; #endif -int yydebug; -int yynerrs; - -int yyerrflag; -int yychar; -YYSTYPE yyval; -YYSTYPE yylval; - -/* define the initial stack-sizes */ -#ifdef YYSTACKSIZE -#undef YYMAXDEPTH -#define YYMAXDEPTH YYSTACKSIZE -#else -#ifdef YYMAXDEPTH -#define YYSTACKSIZE YYMAXDEPTH -#else -#define YYSTACKSIZE 10000 -#define YYMAXDEPTH 500 -#endif +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TERMINAL", "START", "PPERCENT", "ID", + "TEMPLATE", "CODE", "INT", "'\\n'", "'='", "':'", "'('", "')'", "','", + "$accept", "spec", "decls", "decl", "blist", "rules", "nonterm", "tree", + "cost", YY_NULLPTR +}; #endif -#define YYINITSTACKSIZE 500 +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 10, 61, 58, 40, 41, 44 +}; +# endif + +#define YYPACT_NINF -26 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-26))) + +#define YYTABLE_NINF -4 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int8 yypact[] = +{ + -26, 11, 0, -26, 5, -26, 8, -26, -26, -26, + -26, 3, -26, 7, 6, 9, -26, -26, 12, -26, + 13, 14, -26, 15, -26, 16, 17, 15, 18, 4, + -26, 20, -26, 15, -26, 19, -26 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 4, 0, 0, 1, 0, 10, 0, 12, 8, 5, + 9, 0, 16, 0, 0, 0, 6, 7, 0, 14, + 0, 0, 15, 0, 11, 17, 0, 0, 0, 0, + 20, 0, 18, 0, 13, 0, 19 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -26, -26, -26, -26, -26, -26, 21, -25, -26 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 1, 2, 9, 11, 14, 13, 26, 31 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int8 yytable[] = +{ + -3, 4, 29, 5, 6, 7, -2, 18, 35, 15, + 8, 3, 12, 16, 12, 10, 19, 17, 32, 33, + 21, 25, 22, 24, 28, 23, 30, 0, 0, 27, + 34, 0, 0, 36, 0, 20 +}; + +static const yytype_int8 yycheck[] = +{ + 0, 1, 27, 3, 4, 5, 0, 1, 33, 6, + 10, 0, 6, 10, 6, 10, 10, 10, 14, 15, + 11, 6, 10, 9, 7, 12, 8, -1, -1, 13, + 10, -1, -1, 14, -1, 14 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 17, 18, 0, 1, 3, 4, 5, 10, 19, + 10, 20, 6, 22, 21, 6, 10, 10, 1, 10, + 22, 11, 10, 12, 9, 6, 23, 13, 7, 23, + 8, 24, 14, 15, 10, 23, 14 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 16, 17, 17, 18, 18, 19, 19, 19, 19, + 20, 20, 21, 21, 21, 21, 22, 23, 23, 23, + 24 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 3, 1, 0, 2, 3, 3, 1, 2, + 0, 4, 0, 7, 2, 3, 1, 1, 4, 6, + 1 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 22 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { yylineno = 0; } +#line 1240 "y.tab.c" /* yacc.c:1646 */ + break; + + case 3: +#line 23 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { yylineno = 0; } +#line 1246 "y.tab.c" /* yacc.c:1646 */ + break; + + case 7: +#line 31 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { + if (nonterm((yyvsp[-1].string))->number != 1) + yyerror("redeclaration of the start symbol\n"); + } +#line 1255 "y.tab.c" /* yacc.c:1646 */ + break; + + case 9: +#line 36 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { yyerrok; } +#line 1261 "y.tab.c" /* yacc.c:1646 */ + break; + + case 11: +#line 40 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { term((yyvsp[-2].string), (yyvsp[0].n)); } +#line 1267 "y.tab.c" /* yacc.c:1646 */ + break; + + case 13: +#line 44 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { rule((yyvsp[-5].string), (yyvsp[-3].tree), (yyvsp[-2].string), (yyvsp[-1].string)); } +#line 1273 "y.tab.c" /* yacc.c:1646 */ + break; + + case 15: +#line 46 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { yyerrok; } +#line 1279 "y.tab.c" /* yacc.c:1646 */ + break; + + case 16: +#line 49 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { nonterm((yyval.string) = (yyvsp[0].string)); } +#line 1285 "y.tab.c" /* yacc.c:1646 */ + break; + + case 17: +#line 52 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { (yyval.tree) = tree((yyvsp[0].string), 0, 0); } +#line 1291 "y.tab.c" /* yacc.c:1646 */ + break; + + case 18: +#line 53 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { (yyval.tree) = tree((yyvsp[-3].string), (yyvsp[-1].tree), 0); } +#line 1297 "y.tab.c" /* yacc.c:1646 */ + break; + + case 19: +#line 54 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { (yyval.tree) = tree((yyvsp[-5].string), (yyvsp[-3].tree), (yyvsp[-1].tree)); } +#line 1303 "y.tab.c" /* yacc.c:1646 */ + break; + + case 20: +#line 57 "code/tools/lcc/lburg/gram.y" /* yacc.c:1646 */ + { if (*(yyvsp[0].string) == 0) (yyval.string) = "0"; } +#line 1309 "y.tab.c" /* yacc.c:1646 */ + break; + + +#line 1313 "y.tab.c" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 59 "code/tools/lcc/lburg/gram.y" /* yacc.c:1906 */ -typedef struct { - unsigned stacksize; - short *s_base; - short *s_mark; - short *s_last; - YYSTYPE *l_base; - YYSTYPE *l_mark; -} YYSTACKDATA; -/* variables for the parser stack */ -static YYSTACKDATA yystack; -#line 60 "code/tools/lcc/lburg/gram.y" #include #include #include @@ -383,323 +1682,5 @@ void yywarn(char *fmt, ...) { fprintf(stderr, "line %d: ", yylineno); fprintf(stderr, "warning: "); vfprintf(stderr, fmt, ap); -} -#line 387 "y.tab.c" - -#if YYDEBUG -#include /* needed for printf */ -#endif - -#include /* needed for malloc, etc */ -#include /* needed for memset */ - -/* allocate initial stack or double stack size, up to YYMAXDEPTH */ -static int yygrowstack(YYSTACKDATA *data) -{ - int i; - unsigned newsize; - short *newss; - YYSTYPE *newvs; - - if ((newsize = data->stacksize) == 0) - newsize = YYINITSTACKSIZE; - else if (newsize >= YYMAXDEPTH) - return -1; - else if ((newsize *= 2) > YYMAXDEPTH) - newsize = YYMAXDEPTH; - - i = (int) (data->s_mark - data->s_base); - newss = (short *)realloc(data->s_base, newsize * sizeof(*newss)); - if (newss == 0) - return -1; - - data->s_base = newss; - data->s_mark = newss + i; - - newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs)); - if (newvs == 0) - return -1; - - data->l_base = newvs; - data->l_mark = newvs + i; - - data->stacksize = newsize; - data->s_last = data->s_base + newsize - 1; - return 0; -} - -#if YYPURE || defined(YY_NO_LEAKS) -static void yyfreestack(YYSTACKDATA *data) -{ - free(data->s_base); - free(data->l_base); - memset(data, 0, sizeof(*data)); -} -#else -#define yyfreestack(data) /* nothing */ -#endif - -#define YYABORT goto yyabort -#define YYREJECT goto yyabort -#define YYACCEPT goto yyaccept -#define YYERROR goto yyerrlab - -int -YYPARSE_DECL() -{ - int yym, yyn, yystate; -#if YYDEBUG - const char *yys; - - if ((yys = getenv("YYDEBUG")) != 0) - { - yyn = *yys; - if (yyn >= '0' && yyn <= '9') - yydebug = yyn - '0'; - } -#endif - - yynerrs = 0; - yyerrflag = 0; - yychar = YYEMPTY; - yystate = 0; - -#if YYPURE - memset(&yystack, 0, sizeof(yystack)); -#endif - - if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow; - yystack.s_mark = yystack.s_base; - yystack.l_mark = yystack.l_base; - yystate = 0; - *yystack.s_mark = 0; - -yyloop: - if ((yyn = yydefred[yystate]) != 0) goto yyreduce; - if (yychar < 0) - { - if ((yychar = YYLEX) < 0) yychar = 0; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, yystate, yychar, yys); - } -#endif - } - if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yychar) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, shifting to state %d\n", - YYPREFIX, yystate, yytable[yyn]); -#endif - if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) - { - goto yyoverflow; - } - yystate = yytable[yyn]; - *++yystack.s_mark = yytable[yyn]; - *++yystack.l_mark = yylval; - yychar = YYEMPTY; - if (yyerrflag > 0) --yyerrflag; - goto yyloop; - } - if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yychar) - { - yyn = yytable[yyn]; - goto yyreduce; - } - if (yyerrflag) goto yyinrecovery; - - yyerror("syntax error"); - - goto yyerrlab; - -yyerrlab: - ++yynerrs; - -yyinrecovery: - if (yyerrflag < 3) - { - yyerrflag = 3; - for (;;) - { - if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, error recovery shifting\ - to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]); -#endif - if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) - { - goto yyoverflow; - } - yystate = yytable[yyn]; - *++yystack.s_mark = yytable[yyn]; - *++yystack.l_mark = yylval; - goto yyloop; - } - else - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: error recovery discarding state %d\n", - YYPREFIX, *yystack.s_mark); -#endif - if (yystack.s_mark <= yystack.s_base) goto yyabort; - --yystack.s_mark; - --yystack.l_mark; - } - } - } - else - { - if (yychar == 0) goto yyabort; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, error recovery discards token %d (%s)\n", - YYPREFIX, yystate, yychar, yys); - } -#endif - yychar = YYEMPTY; - goto yyloop; - } - -yyreduce: -#if YYDEBUG - if (yydebug) - printf("%sdebug: state %d, reducing by rule %d (%s)\n", - YYPREFIX, yystate, yyn, yyrule[yyn]); -#endif - yym = yylen[yyn]; - if (yym) - yyval = yystack.l_mark[1-yym]; - else - memset(&yyval, 0, sizeof yyval); - switch (yyn) - { -case 1: -#line 22 "code/tools/lcc/lburg/gram.y" - { yylineno = 0; } -break; -case 2: -#line 23 "code/tools/lcc/lburg/gram.y" - { yylineno = 0; } -break; -case 6: -#line 31 "code/tools/lcc/lburg/gram.y" - { - if (nonterm(yystack.l_mark[-1].string)->number != 1) - yyerror("redeclaration of the start symbol\n"); - } -break; -case 8: -#line 36 "code/tools/lcc/lburg/gram.y" - { yyerrok; } -break; -case 10: -#line 40 "code/tools/lcc/lburg/gram.y" - { term(yystack.l_mark[-2].string, yystack.l_mark[0].n); } -break; -case 12: -#line 44 "code/tools/lcc/lburg/gram.y" - { rule(yystack.l_mark[-5].string, yystack.l_mark[-3].tree, yystack.l_mark[-2].string, yystack.l_mark[-1].string); } -break; -case 14: -#line 46 "code/tools/lcc/lburg/gram.y" - { yyerrok; } -break; -case 15: -#line 49 "code/tools/lcc/lburg/gram.y" - { nonterm(yyval.string = yystack.l_mark[0].string); } -break; -case 16: -#line 52 "code/tools/lcc/lburg/gram.y" - { yyval.tree = tree(yystack.l_mark[0].string, 0, 0); } -break; -case 17: -#line 53 "code/tools/lcc/lburg/gram.y" - { yyval.tree = tree(yystack.l_mark[-3].string, yystack.l_mark[-1].tree, 0); } -break; -case 18: -#line 54 "code/tools/lcc/lburg/gram.y" - { yyval.tree = tree(yystack.l_mark[-5].string, yystack.l_mark[-3].tree, yystack.l_mark[-1].tree); } -break; -case 19: -#line 57 "code/tools/lcc/lburg/gram.y" - { if (*yystack.l_mark[0].string == 0) yyval.string = "0"; } -break; -#line 644 "y.tab.c" - } - yystack.s_mark -= yym; - yystate = *yystack.s_mark; - yystack.l_mark -= yym; - yym = yylhs[yyn]; - if (yystate == 0 && yym == 0) - { -#if YYDEBUG - if (yydebug) - printf("%sdebug: after reduction, shifting from state 0 to\ - state %d\n", YYPREFIX, YYFINAL); -#endif - yystate = YYFINAL; - *++yystack.s_mark = YYFINAL; - *++yystack.l_mark = yyval; - if (yychar < 0) - { - if ((yychar = YYLEX) < 0) yychar = 0; -#if YYDEBUG - if (yydebug) - { - yys = 0; - if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; - if (!yys) yys = "illegal-symbol"; - printf("%sdebug: state %d, reading %d (%s)\n", - YYPREFIX, YYFINAL, yychar, yys); - } -#endif - } - if (yychar == 0) goto yyaccept; - goto yyloop; - } - if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && - yyn <= YYTABLESIZE && yycheck[yyn] == yystate) - yystate = yytable[yyn]; - else - yystate = yydgoto[yym]; -#if YYDEBUG - if (yydebug) - printf("%sdebug: after reduction, shifting from state %d \ -to state %d\n", YYPREFIX, *yystack.s_mark, yystate); -#endif - if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack)) - { - goto yyoverflow; - } - *++yystack.s_mark = (short) yystate; - *++yystack.l_mark = yyval; - goto yyloop; - -yyoverflow: - yyerror("yacc stack overflow"); - -yyabort: - yyfreestack(&yystack); - return (1); - -yyaccept: - yyfreestack(&yystack); - return (0); + va_end(ap); } diff --git a/code/tools/lcc/lburg/gram.y b/code/tools/lcc/lburg/gram.y index 1ecd8a9e..c0a9c942 100644 --- a/code/tools/lcc/lburg/gram.y +++ b/code/tools/lcc/lburg/gram.y @@ -199,4 +199,5 @@ void yywarn(char *fmt, ...) { fprintf(stderr, "line %d: ", yylineno); fprintf(stderr, "warning: "); vfprintf(stderr, fmt, ap); + va_end(ap); } diff --git a/code/tools/lcc/src/c.h b/code/tools/lcc/src/c.h index 68c8f629..43bec083 100644 --- a/code/tools/lcc/src/c.h +++ b/code/tools/lcc/src/c.h @@ -577,6 +577,7 @@ extern Tree cnsttree(Type, ...); extern Tree consttree(unsigned int, Type); extern Tree eqtree(int, Tree, Tree); extern int iscallb(Tree); +extern int isnullptr(Tree); extern Tree shtree(int, Tree, Tree); extern void typeerror(int, Tree, Tree); diff --git a/code/tools/lcc/src/enode.c b/code/tools/lcc/src/enode.c index 760096de..4a37618c 100644 --- a/code/tools/lcc/src/enode.c +++ b/code/tools/lcc/src/enode.c @@ -5,7 +5,6 @@ static Tree addtree(int, Tree, Tree); static Tree andtree(int, Tree, Tree); static Tree cmptree(int, Tree, Tree); static int compatible(Type, Type); -static int isnullptr(Tree e); static Tree multree(int, Tree, Tree); static Tree subtree(int, Tree, Tree); #define isvoidptr(ty) \ @@ -220,7 +219,7 @@ static int compatible(Type ty1, Type ty2) { && isptr(ty2) && !isfunc(ty2->type) && eqtype(unqual(ty1->type), unqual(ty2->type), 0); } -static int isnullptr(Tree e) { +int isnullptr(Tree e) { Type ty = unqual(e->type); return generic(e->op) == CNST diff --git a/code/tools/lcc/src/expr.c b/code/tools/lcc/src/expr.c index b8cb08b6..96eec217 100644 --- a/code/tools/lcc/src/expr.c +++ b/code/tools/lcc/src/expr.c @@ -621,7 +621,7 @@ Tree cast(Tree p, Type type) { p = simplify(CVP, dst, p, NULL); else { if ((isfunc(src->type) && !isfunc(dst->type)) - || (!isfunc(src->type) && isfunc(dst->type))) + || (!isnullptr(p) && !isfunc(src->type) && isfunc(dst->type))) warning("conversion from `%t' to `%t' is compiler dependent\n", p->type, type); if (src->size != dst->size) diff --git a/code/ui/ui_main.c b/code/ui/ui_main.c index cc75982e..68ff0c2e 100644 --- a/code/ui/ui_main.c +++ b/code/ui/ui_main.c @@ -783,7 +783,7 @@ int Text_Width(const char *text, float scale, int limit) s += 2; continue; } else { - glyph = &font->glyphs[(int) *s]; + glyph = &font->glyphs[*s & 255]; out += glyph->xSkip; //Makro - added if (maxPixels) @@ -824,7 +824,7 @@ int Text_Height(const char *text, float scale, int limit) s += 2; continue; } else { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; if (max < glyph->height) { max = glyph->height; } @@ -902,7 +902,7 @@ void Text_Paint(float x, float y, float scale, vec4_t color, const char *text, f count = 0; width = 0; while (s && *s && count < len) { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; //int yadj = Assets.textFont.glyphs[text[i]].bottom + Assets.textFont.glyphs[text[i]].top; //float yadj = scale * (Assets.textFont.glyphs[text[i]].imageHeight - Assets.textFont.glyphs[text[i]].height); if (Q_IsColorString(s)) { @@ -1110,7 +1110,7 @@ void Text_PaintAngled(float x, float y, const float *u, const float *v, float sc width = 0; count = 0; while (s && *s && count < len) { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; if (Q_IsColorString(s)) { //Makro - new tricks if (*(s+1) == '*') @@ -1201,9 +1201,9 @@ void Text_PaintWithCursor(float x, float y, float scale, vec4_t color, const cha len = limit; } count = 0; - glyph2 = &font->glyphs[(int) cursor]; // bk001206 - possible signed char + glyph2 = &font->glyphs[cursor & 255]; // bk001206 - possible signed char while (s && *s && count < len) { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; //int yadj = Assets.textFont.glyphs[text[i]].bottom + Assets.textFont.glyphs[text[i]].top; //float yadj = scale * (Assets.textFont.glyphs[text[i]].imageHeight - Assets.textFont.glyphs[text[i]].height); if (Q_IsColorString(s)) { @@ -1296,10 +1296,10 @@ void Text_PaintWithCursorAngled(float x, float y, const float *u, const float *v } width = 0; count = 0; - glyph2 = &font->glyphs[(int) cursor]; // bk001206 - possible signed char + glyph2 = &font->glyphs[cursor & 255]; // bk001206 - possible signed char while (s && *s && count < len) { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; if (Q_IsColorString(s)) { //Makro - new tricks if (*(s+1) == '*') @@ -1413,7 +1413,7 @@ static void Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t } count = 0; while (s && *s && count < len) { - glyph = &font->glyphs[(int) *s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build + glyph = &font->glyphs[*s & 255]; if (Q_IsColorString(s)) { memcpy(newColor, g_color_table[ColorIndex(*(s + 1))], sizeof(newColor)); newColor[3] = color[3]; @@ -1423,7 +1423,7 @@ static void Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t } else { float yadj = useScale * glyph->top; - if (Text_Width(s, useScale, 1) + x > max) { + if (Text_Width(s, scale, 1) + x > max) { *maxX = 0; break; } @@ -2045,7 +2045,7 @@ void UI_Load( void ) char *menuSet = UI_Cvar_VariableString("ui_menuFiles"); if (menu && menu->window.name) { - strcpy(lastName, menu->window.name); + Q_strncpyz(lastName, menu->window.name, sizeof(lastName)); } if (menuSet == NULL || menuSet[0] == '\0') { menuSet = "ui/menus.txt"; @@ -2516,8 +2516,8 @@ static void UI_DrawPlayerModel(rectDef_t * rect) vec3_t moveangles; if (trap_Cvar_VariableValue("ui_Q3Model")) { - strcpy(model, UI_Cvar_VariableString("model")); - strcpy(head, UI_Cvar_VariableString("headmodel")); + Q_strncpyz(model, UI_Cvar_VariableString("model"), sizeof(model)); + Q_strncpyz(head, UI_Cvar_VariableString("headmodel"), sizeof(head)); if (!q3Model) { q3Model = qtrue; updateModel = qtrue; @@ -2525,9 +2525,9 @@ static void UI_DrawPlayerModel(rectDef_t * rect) team[0] = '\0'; } else { - strcpy(team, UI_Cvar_VariableString("ui_teamName")); - strcpy(model, UI_Cvar_VariableString("model")); - strcpy(head, UI_Cvar_VariableString("headmodel")); + Q_strncpyz(team, UI_Cvar_VariableString("ui_teamName"), sizeof(team)); + Q_strncpyz(model, UI_Cvar_VariableString("model"), sizeof(model)); + Q_strncpyz(head, UI_Cvar_VariableString("headmodel"), sizeof(head)); if (q3Model) { q3Model = qfalse; updateModel = qtrue; @@ -2565,7 +2565,7 @@ static void UI_DrawPlayerModel(rectDef_t * rect) static void UI_DrawNetSource(rectDef_t * rect, float scale, vec4_t color, int textStyle) { const char* msg = netSources[ui_netSource.integer]; - if (ui_netSource.integer < 0 || ui_netSource.integer > numNetSources) { + if (ui_netSource.integer < 0 || ui_netSource.integer >= numNetSources) { ui_netSource.integer = 0; } if (rect->hasVectors) @@ -2604,7 +2604,7 @@ static void UI_DrawNetMapCinematic(rectDef_t * rect, float scale, vec4_t color) static void UI_DrawNetFilter(rectDef_t * rect, float scale, vec4_t color, int textStyle) { - if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) { + if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer >= numServerFilters) { ui_serverFilterType.integer = 0; } Text_Paint(rect->x, rect->y, scale, color, @@ -2662,7 +2662,7 @@ static void UI_DrawTierMapName(rectDef_t * rect, float scale, vec4_t color, int i = 0; } j = trap_Cvar_VariableValue("ui_currentMap"); - if (j < 0 || j > MAPS_PER_TIER) { + if (j < 0 || j >= MAPS_PER_TIER) { j = 0; } @@ -2679,7 +2679,7 @@ static void UI_DrawTierGameType(rectDef_t * rect, float scale, vec4_t color, int i = 0; } j = trap_Cvar_VariableValue("ui_currentMap"); - if (j < 0 || j > MAPS_PER_TIER) { + if (j < 0 || j >= MAPS_PER_TIER) { j = 0; } @@ -2769,8 +2769,8 @@ static void UI_DrawOpponent(rectDef_t * rect) updateOpponentModel = updateOpponentModel || trap_Cvar_VariableValue("ui_RQ3_modelCommand") != 0; if (updateOpponentModel) { - strcpy(model, UI_Cvar_VariableString("ui_opponentModel")); - strcpy(headmodel, UI_Cvar_VariableString("ui_opponentModel")); + Q_strncpyz(model, UI_Cvar_VariableString("ui_opponentModel"), sizeof(model)); + Q_strncpyz(headmodel, UI_Cvar_VariableString("ui_opponentModel"), sizeof(headmodel)); team[0] = '\0'; memset(&info2, 0, sizeof(playerInfo_t)); @@ -3055,14 +3055,14 @@ static int UI_OwnerDrawWidth(int ownerDraw, float scale) s = va("%i. %s", ownerDraw - UI_REDTEAM1 + 1, text); break; case UI_NETSOURCE: - if (ui_netSource.integer < 0 || ui_netSource.integer > uiInfo.numJoinGameTypes) { + if (ui_netSource.integer < 0 || ui_netSource.integer >= numNetSources) { ui_netSource.integer = 0; } s = va("Source: %s", netSources[ui_netSource.integer]); break; case UI_NETFILTER: - if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer > numServerFilters) { + if (ui_serverFilterType.integer < 0 || ui_serverFilterType.integer >= numServerFilters) { ui_serverFilterType.integer = 0; } s = va("Filter: %s", serverFilters[ui_serverFilterType.integer].description); @@ -5268,7 +5268,7 @@ static void UI_StartSinglePlayer() { i = 0; } j = trap_Cvar_VariableValue("ui_currentMap"); - if (j < 0 || j > MAPS_PER_TIER) { + if (j < 0 || j >= MAPS_PER_TIER) { j = 0; } @@ -6644,19 +6644,18 @@ static void UI_RunMenuScript(char **args) int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer"); if (selectedPlayer < uiInfo.myTeamCount) { - strcpy(buff, orders); - trap_Cmd_ExecuteText(EXEC_APPEND, - va(buff, uiInfo.teamClientNums[selectedPlayer])); + Com_sprintf( buff, sizeof( buff ), orders, uiInfo.teamClientNums[selectedPlayer] ); + trap_Cmd_ExecuteText( EXEC_APPEND, buff ); trap_Cmd_ExecuteText(EXEC_APPEND, "\n"); } else { int i; for (i = 0; i < uiInfo.myTeamCount; i++) { - if (Q_stricmp(UI_Cvar_VariableString("name"), uiInfo.teamNames[i]) == 0) { + if (uiInfo.playerNumber == uiInfo.teamClientNums[i]) { continue; } - strcpy(buff, orders); - trap_Cmd_ExecuteText(EXEC_APPEND, va(buff, uiInfo.teamNames[i])); + Com_sprintf( buff, sizeof( buff ), orders, uiInfo.teamClientNums[i] ); + trap_Cmd_ExecuteText( EXEC_APPEND, buff ); trap_Cmd_ExecuteText(EXEC_APPEND, "\n"); } } @@ -6687,9 +6686,8 @@ static void UI_RunMenuScript(char **args) int selectedPlayer = trap_Cvar_VariableValue("cg_selectedPlayer"); if (selectedPlayer < uiInfo.myTeamCount) { - strcpy(buff, orders); - trap_Cmd_ExecuteText(EXEC_APPEND, - va(buff, uiInfo.teamClientNums[selectedPlayer])); + Com_sprintf( buff, sizeof( buff ), orders, uiInfo.teamClientNums[selectedPlayer] ); + trap_Cmd_ExecuteText( EXEC_APPEND, buff ); trap_Cmd_ExecuteText(EXEC_APPEND, "\n"); } trap_Key_SetCatcher(trap_Key_GetCatcher() & ~KEYCATCH_UI); @@ -7239,8 +7237,6 @@ static int UI_GetServerStatusInfo(const char *serverAddress, serverStatusInfo_t while (p && *p) { if (*p == '\\') *p++ = '\0'; - if (!p) - break; score = p; p = strchr(p, ' '); if (!p) @@ -7932,6 +7928,11 @@ static qboolean Team_Parse(char **p) } if (token[0] == '{') { + if (uiInfo.teamCount == MAX_TEAMS) { + uiInfo.teamCount--; + Com_Printf("Too many teams, last team replaced!\n"); + } + // seven tokens per line, team name and icon, and 5 team member names if (!String_Parse(p, &uiInfo.teamList[uiInfo.teamCount].teamName) || !String_Parse(p, &tempStr)) { return qfalse; @@ -7956,11 +7957,8 @@ static qboolean Team_Parse(char **p) Com_Printf("Loaded team %s with team icon %s.\n", uiInfo.teamList[uiInfo.teamCount].teamName, tempStr); - if (uiInfo.teamCount < MAX_TEAMS) { - uiInfo.teamCount++; - } else { - Com_Printf("Too many teams, last team replaced!\n"); - } + uiInfo.teamCount++; + token = COM_ParseExt(p, qtrue); if (token[0] != '}') { return qfalse; @@ -7995,6 +7993,11 @@ static qboolean Character_Parse(char **p) } if (token[0] == '{') { + if (uiInfo.characterCount == MAX_HEADS) { + uiInfo.characterCount--; + Com_Printf("Too many characters, last character replaced!\n"); + } + // two tokens per line, character name and sex if (!String_Parse(p, &uiInfo.characterList[uiInfo.characterCount].name) || !String_Parse(p, &tempStr)) { @@ -8017,11 +8020,7 @@ static qboolean Character_Parse(char **p) Com_Printf("Loaded %s character %s.\n", uiInfo.characterList[uiInfo.characterCount].base, uiInfo.characterList[uiInfo.characterCount].name); - if (uiInfo.characterCount < MAX_HEADS) { - uiInfo.characterCount++; - } else { - Com_Printf("Too many characters, last character replaced!\n"); - } + uiInfo.characterCount++; token = COM_ParseExt(p, qtrue); if (token[0] != '}') { @@ -8056,6 +8055,11 @@ static qboolean Alias_Parse(char **p) } if (token[0] == '{') { + if (uiInfo.aliasCount == MAX_ALIASES) { + uiInfo.aliasCount--; + Com_Printf("Too many aliases, last alias replaced!\n"); + } + // three tokens per line, character name, bot alias, and preferred action a - all purpose, d - defense, o - offense if (!String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].name) || !String_Parse(p, &uiInfo.aliasList[uiInfo.aliasCount].ai) @@ -8065,11 +8069,7 @@ static qboolean Alias_Parse(char **p) Com_Printf("Loaded character alias %s using character ai %s.\n", uiInfo.aliasList[uiInfo.aliasCount].name, uiInfo.aliasList[uiInfo.aliasCount].ai); - if (uiInfo.aliasCount < MAX_ALIASES) { - uiInfo.aliasCount++; - } else { - Com_Printf("Too many aliases, last alias replaced!\n"); - } + uiInfo.aliasCount++; token = COM_ParseExt(p, qtrue); if (token[0] != '}') { @@ -9261,7 +9261,7 @@ void UI_DrawConnectScreen(qboolean overlay) ITEM_TEXTSTYLE_SHADOWEDMORE); //Q_strncpyz(uiInfo.startupText, "Starting up...", sizeof(uiInfo.startupText)); } else { - strcpy(text, va("Connecting to %s", cstate.servername)); + Com_sprintf(text, sizeof(text), "Connecting to %s", cstate.servername); Text_PaintCenter(centerPoint, yStart + 48, scale, colorWhite, text, ITEM_TEXTSTYLE_SHADOWEDMORE); //Q_strncpyz(uiInfo.startupText, va("Connecting to %s", cstate.servername), sizeof(uiInfo.startupText)); } diff --git a/code/ui/ui_players.c b/code/ui/ui_players.c index 8c0f3853..d0c98643 100644 --- a/code/ui/ui_players.c +++ b/code/ui/ui_players.c @@ -109,15 +109,13 @@ static void UI_PlayerInfo_SetWeapon(playerInfo_t * pi, weapon_t weaponNum) } //Blaze: none of our weapons have barrel models /*if ( weaponNum == WP_PISTOL || weaponNum == WP_GAUNTLET || weaponNum == WP_BFG ) { - strcpy( path, item->world_model[0] ); - COM_StripExtension( path, path ); - strcat( path, "_barrel.md3" ); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_barrel.md3" ); pi->barrelModel = trap_R_RegisterModel( path ); } */ - strcpy(path, item->world_model[0]); - COM_StripExtensionInPlace(path); - strcat(path, "_flash.md3"); + COM_StripExtension( item->world_model[0], path, sizeof(path) ); + Q_strcat( path, sizeof(path), "_flash.md3" ); pi->flashModel = trap_R_RegisterModel(path); //Blaze: I think this makes some funky colors or something, I dont really know ;) @@ -349,8 +347,8 @@ static void UI_PositionRotatedEntityOnTag(refEntity_t * entity, const refEntity_ } // cast away const because of compiler problems - MatrixMultiply(entity->axis, ((refEntity_t *) parent)->axis, tempAxis); - MatrixMultiply(lerped.axis, tempAxis, entity->axis); + MatrixMultiply( entity->axis, lerped.axis, tempAxis ); + MatrixMultiply( tempAxis, ((refEntity_t *)parent)->axis, entity->axis ); } /* @@ -700,14 +698,14 @@ UI_DrawPlayer void UI_DrawPlayer(float x, float y, float w, float h, playerInfo_t * pi, int time) { refdef_t refdef; - refEntity_t legs; - refEntity_t torso; - refEntity_t head; - refEntity_t gun; + refEntity_t legs = {0}; + refEntity_t torso = {0}; + refEntity_t head = {0}; + refEntity_t gun = {0}; //Makro - barrel is no longer used - //refEntity_t barrel; - refEntity_t flash; + //refEntity_t barrel = {0}; + refEntity_t flash = {0}; vec3_t origin; int renderfx; vec3_t mins = { -16, -16, -24 }; @@ -858,10 +856,6 @@ void UI_DrawPlayer(float x, float y, float w, float h, playerInfo_t * pi, int ti angles[YAW] = 0; angles[PITCH] = 0; angles[ROLL] = UI_MachinegunSpinAngle( pi ); - if( pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) { - angles[PITCH] = angles[ROLL]; - angles[ROLL] = 0; - } AnglesToAxis( angles, barrel.axis ); UI_PositionRotatedEntityOnTag( &barrel, &gun, pi->weaponModel, "tag_barrel"); diff --git a/code/ui/ui_shared.c b/code/ui/ui_shared.c index f78f1173..95a678a7 100644 --- a/code/ui/ui_shared.c +++ b/code/ui/ui_shared.c @@ -626,6 +626,8 @@ qboolean PC_Int_Parse(int handle, int *i) pc_token_t token; int negative = qfalse; + if (!i) + return qfalse; if (!trap_PC_ReadToken(handle, &token)) return qfalse; @@ -876,7 +878,11 @@ void Window_Paint(Window * w, float fadeAmount, float fadeClamp, float fadeCycle { //float bordersize = 0; vec4_t color = {1, 1, 1, 1}; - rectDef_t fillRect = w->rect; + rectDef_t fillRect; + + if (w == NULL) { + return; + } if (debugMode) { //color[0] = color[1] = color[2] = color[3] = 1; @@ -884,10 +890,6 @@ void Window_Paint(Window * w, float fadeAmount, float fadeClamp, float fadeCycle DC->drawRect(w->rect.x, w->rect.y, w->rect.w, w->rect.h, 1, color, DC->whiteShader); } - if (w == NULL) { - return; - } - //Makro - fade forecolor/backcolor if needed UI_RQ3_HandleFading(w); @@ -918,6 +920,8 @@ void Window_Paint(Window * w, float fadeAmount, float fadeClamp, float fadeCycle return; } + fillRect = w->rect; + if (w->border != 0) { fillRect.x += w->borderSize; fillRect.y += w->borderSize; @@ -2457,7 +2461,7 @@ Point Item_Slider_ThumbPosition(itemDef_t * item) p.y = item->window.rect.y - 2; } - if (editDef == NULL && item->cvar) { + if (!editDef || !item->cvar) { return p; } @@ -6513,6 +6517,10 @@ menuDef_t *Menus_ActivateByName(const char *p, qboolean special) void Item_Init(itemDef_t * item) { + if (item == NULL) { + return; + } + memset(item, 0, sizeof(itemDef_t)); item->textscale = 0.55f; Window_Init(&item->window); @@ -6590,7 +6598,7 @@ void Menu_HandleMouseMove(menuDef_t * menu, float x, float y) //Com_Printf("Listbox: %.1f %.1f %.1f %.1f / %.1f %.1f %.1f %.1f / %d %d %d IN\n", PRINT_RECT(menu->items[i]->window.rect), menu->items[i]->window.rectClient.u[0], menu->items[i]->window.rectClient.u[1], menu->items[i]->window.rectClient.v[0], menu->items[i]->window.rectClient.v[1], menu->items[i]->window.rectClient.hasVectors, DC->cursorx, DC->cursory); } } - } else if (menu->items[i]->window.flags & WINDOW_MOUSEOVER) { + } else if (menu->items[i] && menu->items[i]->window.flags & WINDOW_MOUSEOVER) { Item_MouseLeave(menu->items[i]); Item_SetMouseOver(menu->items[i], qfalse); if (menu->items[i]->type == ITEM_TYPE_LISTBOX) { @@ -8750,6 +8758,9 @@ qboolean MenuParse_itemDef( itemDef_t *item, int handle ) { menuDef_t *menu = (menuDef_t*)item; if (menu->itemCount < MAX_MENUITEMS) { menu->items[menu->itemCount] = UI_Alloc(sizeof(itemDef_t)); + if (!menu->items[menu->itemCount]) { + return qfalse; + } Item_Init(menu->items[menu->itemCount]); //was below menu->items[menu->itemCount]->parent = menu; diff --git a/jenkins-ci-build.sh b/jenkins-ci-build.sh index fb922f25..31bdd97f 100755 --- a/jenkins-ci-build.sh +++ b/jenkins-ci-build.sh @@ -6,10 +6,10 @@ BUILD_DEFAULT="release" cd ${MASTER_DIR} -if [ "$OPTIONS" = "all_options" ]; +if [ "${OPTIONS}" == "all_options" ]; then - export USE_CODEC_VORBIS=1 - export USE_FREETYPE=1 + export USE_CODEC_VORBIS=1 + export USE_FREETYPE=1 fi if [ "$UNAME" == "Darwin" ]; then @@ -27,6 +27,28 @@ else echo "build type : ${BUILD_TYPE}" fi -make -j${CORES} distclean ${BUILD_TYPE} +echo "environment :" +export + +if [ -n "${CPPCHECK}" ]; then + if [ ! -f "${CPPCHECK}" ]; then + command -v cppcheck >/dev/null + if [ "$?" != "0" ]; then + echo "cppcheck not installed" + exit 1 + fi + + cppcheck --enable=all --max-configs=1 --xml --xml-version=2 code 2> ${CPPCHECK} + fi + + ln -sf ${CPPCHECK} cppcheck.xml +fi + +# Bit of a hack; only run scan-build with clang and all options enabled +if [ "${CC}" == "clang" ] && [ "${OPTIONS}" == "all_options" ]; then + MAKE_PREFIX="scan-build" +fi + +${MAKE_PREFIX} make -j${CORES} distclean ${BUILD_TYPE} exit $? diff --git a/make-macosx-app.sh b/make-macosx-app.sh index 7e484dd4..82eb623a 100755 --- a/make-macosx-app.sh +++ b/make-macosx-app.sh @@ -42,7 +42,7 @@ if [ "$2" != "" ]; then elif [ "$2" == "ppc" ]; then CURRENT_ARCH="ppc" else - echo "Invalid architecture: $1" + echo "Invalid architecture: $2" echo "Valid architectures are:" echo " x86" echo " x86_64" @@ -137,12 +137,8 @@ IOQ3_RENDERER_GL2_ARCHS="" IOQ3_CGAME_ARCHS="" IOQ3_GAME_ARCHS="" IOQ3_UI_ARCHS="" -IOQ3_MP_CGAME_ARCHS="" -IOQ3_MP_GAME_ARCHS="" -IOQ3_MP_UI_ARCHS="" -BASEDIR="baseq3" -MISSIONPACKDIR="missionpack" +BASEDIR="Boomstick" CGAME="cgame" GAME="qagame" @@ -150,7 +146,7 @@ UI="ui" RENDERER_OPENGL="renderer_opengl" -DEDICATED_NAME="ioq3ded" +DEDICATED_NAME="Reactionded" CGAME_NAME="${CGAME}.dylib" GAME_NAME="${GAME}.dylib" @@ -160,12 +156,12 @@ RENDERER_OPENGL1_NAME="${RENDERER_OPENGL}1.dylib" RENDERER_OPENGL2_NAME="${RENDERER_OPENGL}2.dylib" ICNSDIR="misc" -ICNS="quake3_flat.icns" +ICNS="quake3.icns" PKGINFO="APPLIOQ3" OBJROOT="build" #BUILT_PRODUCTS_DIR="${OBJROOT}/${TARGET_NAME}-darwin-${CURRENT_ARCH}" -PRODUCT_NAME="ioquake3" +PRODUCT_NAME="Reaction" WRAPPER_EXTENSION="app" WRAPPER_NAME="${PRODUCT_NAME}.${WRAPPER_EXTENSION}" CONTENTS_FOLDER_PATH="${WRAPPER_NAME}/Contents" @@ -220,16 +216,6 @@ for ARCH in $SEARCH_ARCHS; do if [ -e ${BUILT_PRODUCTS_DIR}/${BASEDIR}/${IOQ3_UI} ]; then IOQ3_UI_ARCHS="${BUILT_PRODUCTS_DIR}/${BASEDIR}/${IOQ3_UI} ${IOQ3_UI_ARCHS}" fi - # missionpack - if [ -e ${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_CGAME} ]; then - IOQ3_MP_CGAME_ARCHS="${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_CGAME} ${IOQ3_MP_CGAME_ARCHS}" - fi - if [ -e ${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_GAME} ]; then - IOQ3_MP_GAME_ARCHS="${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_GAME} ${IOQ3_MP_GAME_ARCHS}" - fi - if [ -e ${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_UI} ]; then - IOQ3_MP_UI_ARCHS="${BUILT_PRODUCTS_DIR}/${MISSIONPACKDIR}/${IOQ3_UI} ${IOQ3_MP_UI_ARCHS}" - fi #echo "valid arch: ${ARCH}" done @@ -272,9 +258,6 @@ echo "" if [ ! -d ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}/$BASEDIR ]; then mkdir -p ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}/$BASEDIR || exit 1; fi -if [ ! -d ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}/$MISSIONPACKDIR ]; then - mkdir -p ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}/$MISSIONPACKDIR || exit 1; -fi if [ ! -d ${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH} ]; then mkdir -p ${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH} || exit 1; fi @@ -292,9 +275,9 @@ echo " CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile - quake3_flat + quake3 CFBundleIdentifier - org.ioquake.${PRODUCT_NAME} + com.rq3.${PRODUCT_NAME} CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -312,7 +295,7 @@ echo " LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright - QUAKE III ARENA Copyright © 1999-2000 id Software, Inc. All rights reserved. + Reaction Copyright © 2000-2012 Boomstick Studios. NSPrincipalClass NSApplication @@ -365,11 +348,3 @@ action ${BUNDLEBINDIR}/${BASEDIR}/${UI_NAME} "${IOQ3_UI_ARCHS}" symlinkArch "${CGAME}" "${CGAME}" "" "${BUNDLEBINDIR}/${BASEDIR}" symlinkArch "${GAME}" "${GAME}" "" "${BUNDLEBINDIR}/${BASEDIR}" symlinkArch "${UI}" "${UI}" "" "${BUNDLEBINDIR}/${BASEDIR}" - -# missionpack -action ${BUNDLEBINDIR}/${MISSIONPACKDIR}/${CGAME_NAME} "${IOQ3_MP_CGAME_ARCHS}" -action ${BUNDLEBINDIR}/${MISSIONPACKDIR}/${GAME_NAME} "${IOQ3_MP_GAME_ARCHS}" -action ${BUNDLEBINDIR}/${MISSIONPACKDIR}/${UI_NAME} "${IOQ3_MP_UI_ARCHS}" -symlinkArch "${CGAME}" "${CGAME}" "" "${BUNDLEBINDIR}/${MISSIONPACKDIR}" -symlinkArch "${GAME}" "${GAME}" "" "${BUNDLEBINDIR}/${MISSIONPACKDIR}" -symlinkArch "${UI}" "${UI}" "" "${BUNDLEBINDIR}/${MISSIONPACKDIR}" diff --git a/misc/msvc11/cgame.vcxproj b/misc/msvc11/cgame.vcxproj index 1ba9da22..50395b5c 100644 --- a/misc/msvc11/cgame.vcxproj +++ b/misc/msvc11/cgame.vcxproj @@ -42,41 +42,49 @@ DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 @@ -1122,6 +1130,7 @@ + diff --git a/misc/msvc11/cgame.vcxproj.filters b/misc/msvc11/cgame.vcxproj.filters index 44bfbbbc..d2425d51 100644 --- a/misc/msvc11/cgame.vcxproj.filters +++ b/misc/msvc11/cgame.vcxproj.filters @@ -115,5 +115,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/misc/msvc11/game.vcxproj b/misc/msvc11/game.vcxproj index 0bb8f32f..649fd539 100644 --- a/misc/msvc11/game.vcxproj +++ b/misc/msvc11/game.vcxproj @@ -41,41 +41,49 @@ DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 DynamicLibrary false + NotSet v110 @@ -1251,17 +1259,17 @@ - - - - - - - - + + + + + + + + - + diff --git a/misc/msvc11/game.vcxproj.filters b/misc/msvc11/game.vcxproj.filters index 1e7135c6..d12945cc 100644 --- a/misc/msvc11/game.vcxproj.filters +++ b/misc/msvc11/game.vcxproj.filters @@ -139,39 +139,12 @@ Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - - - Header Files - Header Files Header Files - - Header Files - Header Files @@ -199,5 +172,32 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/misc/msvc11/q3_ui.vcxproj b/misc/msvc11/q3_ui.vcxproj index 97c32685..c3f6865d 100644 --- a/misc/msvc11/q3_ui.vcxproj +++ b/misc/msvc11/q3_ui.vcxproj @@ -41,49 +41,49 @@ DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 @@ -1809,20 +1809,31 @@ - + true true true true - + + true + true + true + true + + + true + true + true + true + true true true true - + true true true diff --git a/misc/msvc11/q3_ui.vcxproj.filters b/misc/msvc11/q3_ui.vcxproj.filters index 66153a2d..89c347a3 100644 --- a/misc/msvc11/q3_ui.vcxproj.filters +++ b/misc/msvc11/q3_ui.vcxproj.filters @@ -151,15 +151,18 @@ Header Files + + Header Files + - - Header Files - Header Files - + + Header Files + + Header Files diff --git a/misc/msvc11/quake3.vcxproj b/misc/msvc11/quake3.vcxproj index 7050463d..40f84c8a 100644 --- a/misc/msvc11/quake3.vcxproj +++ b/misc/msvc11/quake3.vcxproj @@ -41,41 +41,49 @@ Application false + NotSet v110 Application false + NotSet v110 Application - Static + false + NotSet v110 Application - Static + false + NotSet v110 Application false + NotSet v110 Application false + NotSet v110 Application - Static + false + NotSet v110 Application - Static + false + NotSet v110 @@ -149,18 +157,6 @@ ioquake3.$(PlatformShortName) ioquake3.$(PlatformShortName) - - ..\..\code\libcurl-7.35.0;$(IncludePath) - - - ..\..\code\libcurl-7.35.0;$(IncludePath) - - - ..\..\code\libcurl-7.35.0;$(IncludePath) - - - ..\..\code\libcurl-7.35.0;$(IncludePath) - NDEBUG;%(PreprocessorDefinitions) @@ -174,7 +170,7 @@ MaxSpeed AnySuitable - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;MISSIONPACK;%(PreprocessorDefinitions) true MultiThreaded @@ -188,20 +184,21 @@ Level4 true CompileAsC + Fast NDEBUG;%(PreprocessorDefinitions) 0x0409 - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true false $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false @@ -209,10 +206,11 @@ MachineX86 libcmt.lib false + ..\..\code\libs\win32;%(AdditionalLibraryDirectories) - Post build processing.. - rem bash -c "perl ./unix/cons -- release-TA" + copy SDL2.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win32\SDL2.dll" "$(TargetDir)" @@ -227,7 +225,7 @@ MaxSpeed AnySuitable - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;_WIN64;__WIN64__;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;MISSIONPACK;%(PreprocessorDefinitions) true MultiThreaded @@ -241,30 +239,32 @@ Level4 true CompileAsC + Fast NDEBUG;%(PreprocessorDefinitions) 0x0409 - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true false $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false libcmt.lib false + ..\..\code\libs\win64;%(AdditionalLibraryDirectories) - Post build processing.. - rem bash -c "perl ./unix/cons -- release-TA" + copy SDL264.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win64\SDL264.dll" "$(TargetDir)" @@ -279,7 +279,7 @@ Disabled - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;%(PreprocessorDefinitions) MultiThreadedDebugDLL @@ -294,6 +294,7 @@ true EditAndContinue CompileAsC + Fast _DEBUG;%(PreprocessorDefinitions) @@ -301,7 +302,7 @@ ..\winquake.res - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true @@ -310,17 +311,18 @@ $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false MachineX86 false + ..\..\code\libs\win32;%(AdditionalLibraryDirectories) - Post build processing.. - rem bash -c "perl ./unix/cons -- debug" + copy SDL2.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win32\SDL2.dll" "$(TargetDir)" @@ -334,7 +336,7 @@ Disabled - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;_WIN64;__WIN64__;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;%(PreprocessorDefinitions) MultiThreadedDebugDLL @@ -349,6 +351,7 @@ true ProgramDatabase CompileAsC + Fast FastCall @@ -357,7 +360,7 @@ ..\winquake.res - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true @@ -366,15 +369,16 @@ $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false + ..\..\code\libs\win64;%(AdditionalLibraryDirectories) - Post build processing.. - rem bash -c "perl ./unix/cons -- debug" + copy SDL264.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win64\SDL264.dll" "$(TargetDir)" @@ -390,7 +394,7 @@ MaxSpeed AnySuitable - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;%(PreprocessorDefinitions) true MultiThreaded @@ -404,20 +408,21 @@ Level4 true CompileAsC + Fast NDEBUG;%(PreprocessorDefinitions) 0x0409 - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true false $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false @@ -425,7 +430,12 @@ MachineX86 libcmt.lib false + ..\..\code\libs\win32;%(AdditionalLibraryDirectories) + + copy SDL2.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win32\SDL2.dll" "$(TargetDir)" + @@ -439,10 +449,10 @@ MaxSpeed AnySuitable - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;_WIN64;__WIN64__;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;%(PreprocessorDefinitions) true - MultiThreaded + MultiThreadedDLL true @@ -453,26 +463,32 @@ Level4 true CompileAsC + Fast NDEBUG;%(PreprocessorDefinitions) 0x0409 - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true false $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false libcmt.lib + ..\..\code\libs\win64;%(AdditionalLibraryDirectories) + + copy SDL264.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win64\SDL264.dll" "$(TargetDir)" + @@ -486,7 +502,7 @@ Disabled - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;MISSIONPACK;%(PreprocessorDefinitions) MultiThreadedDebugDLL @@ -501,6 +517,7 @@ true EditAndContinue CompileAsC + Fast _DEBUG;%(PreprocessorDefinitions) @@ -508,14 +525,14 @@ ..\winquake.res - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true true $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false @@ -524,10 +541,11 @@ false + ..\..\code\libs\win32;%(AdditionalLibraryDirectories) - Post build processing.. - rem bash -c "perl ./unix/cons -- debug-TA" + copy SDL2.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win32\SDL2.dll" "$(TargetDir)" @@ -541,7 +559,7 @@ Disabled - ..\..\code\SDL12\include;..\..\code\libcurl;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) + ..\..\code\SDL2\include;..\..\code\libcurl-7.35.0;..\..\code\AL;..\..\code\libspeex\include;..\..\code\zlib;..\..\code\jpeg-8c;%(AdditionalIncludeDirectories) _WIN32;WIN32;_WIN64;__WIN64__;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;BOTLIB;USE_ICON;USE_CURL;USE_CURL_DLOPEN;USE_OPENAL;USE_OPENAL_DLOPEN;USE_VOIP;USE_INTERNAL_JPEG;HAVE_CONFIG_H;MISSIONPACK;%(PreprocessorDefinitions) MultiThreadedDebugDLL @@ -556,6 +574,7 @@ true ProgramDatabase CompileAsC + Fast _DEBUG;%(PreprocessorDefinitions) @@ -563,22 +582,23 @@ ..\winquake.res - user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDLmain.lib;SDL.lib;OpenGL32.lib;%(AdditionalDependencies) + user32.lib;gdi32.lib;advapi32.lib;winmm.lib;psapi.lib;wsock32.lib;ws2_32.lib;dxguid.lib;SDL2main.lib;SDL2.lib;OpenGL32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) true true $(IntDir)quake3.pdb true $(IntDir)quake3.map - Windows + Console 8388608 false + ..\..\code\libs\win64;%(AdditionalLibraryDirectories) - Post build processing.. - rem bash -c "perl ./unix/cons -- debug-TA" + copy SDL264.dll + xcopy /Y /S "$(SolutionDir)..\..\code\libs\win64\SDL264.dll" "$(TargetDir)" @@ -1804,43 +1824,34 @@ - - - + - - - - - + - - - - - - - - - - - - - + + + + + + + + + + diff --git a/misc/msvc11/quake3.vcxproj.filters b/misc/msvc11/quake3.vcxproj.filters index e1789455..d7afa0c6 100644 --- a/misc/msvc11/quake3.vcxproj.filters +++ b/misc/msvc11/quake3.vcxproj.filters @@ -713,9 +713,6 @@ Header Files - - Header Files - Header Files @@ -734,12 +731,6 @@ Header Files - - Header Files - - - Header Files - Header Files @@ -752,15 +743,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - Header Files @@ -770,45 +752,9 @@ Header Files - - Header Files - Resource Files - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - - - jpeg\Header Files - botlib\Header Files @@ -905,6 +851,39 @@ renderergl1 + + Header Files + + + Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + + + jpeg\Header Files + diff --git a/misc/msvc11/ui.vcxproj b/misc/msvc11/ui.vcxproj index 0df23449..ccf108be 100644 --- a/misc/msvc11/ui.vcxproj +++ b/misc/msvc11/ui.vcxproj @@ -41,49 +41,49 @@ DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 DynamicLibrary false - MultiByte + NotSet v110 @@ -793,7 +793,7 @@ true true - + true true true @@ -805,19 +805,13 @@ true true - + true true true true - - true - true - true - true - - + true true true diff --git a/misc/msvc11/ui.vcxproj.filters b/misc/msvc11/ui.vcxproj.filters index 875ff0ef..65a24684 100644 --- a/misc/msvc11/ui.vcxproj.filters +++ b/misc/msvc11/ui.vcxproj.filters @@ -49,21 +49,9 @@ Header Files - - Header Files - Header Files - - Header Files - - - Header Files - - - Header Files - Header Files @@ -73,5 +61,14 @@ Header Files + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/opengl2-readme.txt b/opengl2-readme.md similarity index 83% rename from opengl2-readme.txt rename to opengl2-readme.md index 77721832..ccf89751 100644 --- a/opengl2-readme.txt +++ b/opengl2-readme.md @@ -52,7 +52,9 @@ For Win32: 1. Start ioquake3. (ioquake3.x86.exe on Win32) -2. Open the console (default key ~) and type '/cl_renderer opengl2; vid_restart' +2. Open the console (the default key is tilde ~) and type +`/cl_renderer opengl2` and press enter +`/vid_restart` then press enter again. 3. Enjoy. @@ -62,100 +64,94 @@ For Win32: ------------------------------------------------------------------------------- Cvars for simple rendering features: - r_ext_compressed_textures - Automatically compress textures. + +* `r_ext_compressed_textures` - Automatically compress textures. 0 - No texture compression. (default) 1 - DXT/LATC texture compression if supported. 2 - BPTC texture compression if supported. - r_ext_framebuffer_multisample - Multisample Anti-aliasing. +* `r_ext_framebuffer_multisample` - Multisample Anti-aliasing. 0 - None. (default) 1-16 - Some. 17+ - Too much! - r_ssao - Enable screen-space ambient occlusion. +* `r_ssao` - Enable screen-space ambient occlusion. Currently eats framerate and has some visible artifacts. 0 - No. (default) 1 - Yes. - r_softOverbright - Enable software overbrighting. This enables - overbrighting even in a window. Is disabled - when r_toneMap 1 and r_hdr 1. - 0 - No. - 1 - Yes. (default) - Cvars for HDR and tonemapping: - r_hdr - Do scene rendering in a framebuffer with + + * `r_hdr` - Do scene rendering in a framebuffer with high dynamic range. (Less banding, and exposure changes look much better) 0 - No. 1 - Yes. (default) - r_cameraExposure - Cheat. Alter brightness, in powers of two. +* `r_cameraExposure` - Cheat. Alter brightness, in powers of two. -2 - 4x as dark. 0 - Normal. (default) 0.5 - Sqrt(2)x as bright. 2 - 4x as bright. - r_postProcess - Enable post-processing. +* `r_postProcess` - Enable post-processing. 0 - No. 1 - Yes. (default) - r_toneMap - Enable tone mapping. Requires +* `r_toneMap` - Enable tone mapping. Requires r_hdr and r_postProcess. 0 - No. 1 - Yes. (default) - r_forceToneMap - Cheat. Override built-in and map tonemap - settings and use cvars r_forceToneMapAvg, - r_forceToneMapMin, and r_forceToneMapMax. +* `r_forceToneMap` - Cheat. Override built-in and map tonemap settings and use cvars r_forceToneMapAvg, r_forceToneMapMin, and r_forceToneMapMax. 0 - No. (default) 1 - Yes. - r_forceToneMapAvg - Cheat. Map average scene luminance to this +* `r_forceToneMapAvg` - Cheat. Map average scene luminance to this value, in powers of two. Requires r_forceToneMap. -2.0 - Dark. -1.0 - Kinda dark. (default). 2.0 - Too bright. - r_forceToneMapMin - Cheat. After mapping average, luminance +* `r_forceToneMapMin` - Cheat. After mapping average, luminance below this level is mapped to black. Requires r_forceToneMap. -5 - Not noticeable. -3.25 - Normal. (default) 0.0 - Too dark. - r_forceToneMapMin - Cheat. After mapping average, luminance +* `r_forceToneMapMin` - Cheat. After mapping average, luminance above this level is mapped to white. Requires r_forceToneMap. 0.0 - Too bright. 1.0 - Normal. (default). 2.0 - Washed out. - r_autoExposure - Do automatic exposure based on scene +* `r_autoExposure` - Do automatic exposure based on scene brightness. Hardcoded to -2 to 2 on maps that don't specify otherwise. Requires r_hdr, r_postprocess, and r_toneMap. 0 - No. 1 - Yes. (default) - r_forceAutoExposure - Cheat. Override built-in and map auto +* `r_forceAutoExposure` - Cheat. Override built-in and map auto exposure settings and use cvars r_forceAutoExposureMin and r_forceAutoExposureMax. 0 - No. (default) 1 - Yes. - r_forceAutoExposureMin - Cheat. Set minimum exposure to this value, +* `r_forceAutoExposureMin` - Cheat. Set minimum exposure to this value, in powers of two. Requires r_forceAutoExpsure. -3.0 - Dimmer. -2.0 - Normal. (default) -1.0 - Brighter. - r_forceAutoExposureMax - Cheat. Set maximum exposure to this value, +* `r_forceAutoExposureMax` - Cheat. Set maximum exposure to this value, in powers of two. Requires r_forceAutoExpsure. 1.0 - Dimmer. @@ -163,7 +159,8 @@ Cvars for HDR and tonemapping: 3.0 - Brighter. Cvars for advanced material usage: - r_normalMapping - Enable normal mapping for materials that + +* `r_normalMapping` - Enable normal mapping for materials that support it, and also specify advanced shading techniques. 0 - No. @@ -173,7 +170,7 @@ Cvars for advanced material usage: 3 - Yes, and use tri-Ace's Oren-Nayar reflectance model. - r_specularMapping - Enable specular mapping for materials that +* `r_specularMapping` - Enable specular mapping for materials that support it, and also specify advanced specular techniques. 0 - No. @@ -182,7 +179,7 @@ Cvars for advanced material usage: 3 - Yes, and use Cook-Torrance. 4 - Yes, and use Torrance-Sparrow. - r_deluxeMapping - Enable deluxe mapping. (Map is compiled +* `r_deluxeMapping` - Enable deluxe mapping. (Map is compiled with light directions.) Even if the map doesn't have deluxe mapping compiled in, an approximation based on the lightgrid @@ -190,26 +187,27 @@ Cvars for advanced material usage: 0 - No. 1 - Yes. (default) - r_parallaxMapping - Enable parallax mapping for materials that +* `r_parallaxMapping` - Enable parallax mapping for materials that support it. 0 - No. (default) - 1 - Yes. + 1 - Use parallax occlusion mapping. + 2 - Use relief mapping. (slower) - r_baseSpecular - Set the specular reflectance of materials +* `r_baseSpecular` - Set the specular reflectance of materials which don't include a specular map or use the specularReflectance keyword. 0 - No. 0.04 - Realistic. (default) 1.0 - Ack. - r_baseGloss - Set the glossiness of materials which don't +* `r_baseGloss` - Set the glossiness of materials which don't include a specular map or use the specularExponent keyword. 0 - Rough. 0.3 - Default. 1.0 - Shiny. - r_baseNormalX - Set the scale of the X values from normal +* `r_baseNormalX` - Set the scale of the X values from normal maps when the normalScale keyword is not used. -1 - Flip X. @@ -217,7 +215,7 @@ Cvars for advanced material usage: 1 - Normal X. (default) 2 - Double X. - r_baseNormalY - Set the scale of the Y values from normal +* `r_baseNormalY` - Set the scale of the Y values from normal maps when the normalScale keyword is not used. -1 - Flip Y. @@ -225,7 +223,7 @@ Cvars for advanced material usage: 1 - Normal Y. (default) 2 - Double Y. - r_baseParallax - Sets the scale of the parallax effect for +* `r_baseParallax` - Sets the scale of the parallax effect for materials when the parallaxDepth keyword is not used. 0 - No depth. @@ -234,7 +232,8 @@ Cvars for advanced material usage: 0.1 - Looks broken. Cvars for image interpolation and generation: - r_imageUpsample - Use interpolation to artifically increase + +* `r_imageUpsample` - Use interpolation to artifically increase the resolution of all textures. Looks good in certain circumstances. 0 - No. (default) @@ -242,50 +241,48 @@ Cvars for image interpolation and generation: 2 - 4x size. 3 - 8x size, etc - r_imageUpsampleMaxSize - Maximum texture size when upsampling +* `r_imageUpsampleMaxSize` - Maximum texture size when upsampling textures. 1024 - Default. 2048 - Really nice. 4096 - Really slow. 8192 - Crash. - r_imageUpsampleType - Type of interpolation when upsampling +* `r_imageUpsampleType` - Type of interpolation when upsampling textures. 0 - None. (probably broken) 1 - Bad but fast (default, FCBI without second derivatives) 2 - Okay but slow (normal FCBI) - r_genNormalMaps - Naively generate normal maps for all +* `r_genNormalMaps* - Naively generate normal maps for all textures. 0 - Don't. (default) 1 - Do. Cvars for the sunlight and cascaded shadow maps: - r_forceSun - Cheat. Force sunlight and shadows, using sun - position from sky material. + +* `r_forceSun` - Cheat. Force sunlight and shadows, using sun position from sky material. 0 - Don't. (default) 1 - Do. 2 - Sunrise, sunset. - r_forceSunMapLightScale - Cheat. Scale map brightness by this factor +* `r_forceSunMapLightScale` - Cheat. Scale map brightness by this factor when r_forceSun 1. 1.0 - Default - r_forceSunLightScale - Cheat. Scale sun brightness by this factor +* `r_forceSunLightScale` - Cheat. Scale sun brightness by this factor when r_forceSun 1. 1.0 - Default - - r_forceSunAmbientScale - Cheat. Scale sun ambient brightness by this - factor when r_forceSun 1. - 0.5 - Default - r_sunShadows - Enable sunlight and cascaded shadow maps for +* `r_forceSunAmbientScale` - Cheat. Scale sun ambient brightness by this factor when r_forceSun 1. 0.5 - Default + +* `r_sunShadows` - Enable sunlight and cascaded shadow maps for it on maps that support it. 0 - No. 1 - Yes. (default) - r_sunlightMode - Specify the method used to add sunlight to +* `r_sunlightMode` - Specify the method used to add sunlight to the scene. 0 - No. 1 - Multiply lit areas by light scale, and @@ -295,13 +292,13 @@ Cvars for the sunlight and cascaded shadow maps: and doesn't integrate well with existing maps. - r_shadowFilter - Enable filtering shadows for a smoother +* `r_shadowFilter` - Enable filtering shadows for a smoother look. 0 - No. 1 - Some. (default) 2 - Much. - r_shadowMapSize - Size of each cascaded shadow map. +* `r_shadowMapSize` - Size of each cascaded shadow map. 256 - 256x256, ugly, probably shouldn't go below this. 512 - 512x512, passable. @@ -311,77 +308,78 @@ Cvars for the sunlight and cascaded shadow maps: 2048. Cvars that you probably don't care about or shouldn't mess with: - r_mergeMultidraws - Optimize number of calls to + +* `r_mergeMultidraws` - Optimize number of calls to glMultiDrawElements(). 0 - Don't. 1 - Do some. (default) 2 - Do more than necessary (eats CPU). - r_mergeLeafSurfaces - Merge surfaces that share common materials +* `r_mergeLeafSurfaces` - Merge surfaces that share common materials and a common leaf. Speeds up rendering. 0 - Don't. 1 - Do. (default) - r_recalcMD3Normals - Recalculate the normals when loading an MD3. +* `r_recalcMD3Normals` - Recalculate the normals when loading an MD3. Fixes normal maps in some cases but looks ugly in others. 0 - Don't. (default) 1 - Do. - r_depthPrepass - Do a depth-only pass before rendering. +* `r_depthPrepass` - Do a depth-only pass before rendering. Speeds up rendering in cases where advanced features are used. Required for r_sunShadows. 0 - No. 1 - Yes. (default) - r_normalAmbient - Split map light into ambient and directed +* `r_normalAmbient` - Split map light into ambient and directed portions when doing deluxe mapping. Not very useful. 0 - Don't. (default). 0.3 - 30% ambient, 70% directed. 1.0 - 100% ambient. - r_mergeLightmaps - Merge the small (128x128) lightmaps into +* `r_mergeLightmaps` - Merge the small (128x128) lightmaps into 2 or fewer giant (4096x4096) lightmaps. Easy speedup. 0 - Don't. 1 - Do. (default) - r_shadowCascadeZNear - Near plane for shadow cascade frustums. +* `r_shadowCascadeZNear` - Near plane for shadow cascade frustums. 4 - Default. - r_shadowCascadeZFar - Far plane for shadow cascade frustums. +* `r_shadowCascadeZFar` - Far plane for shadow cascade frustums. 3072 - Default. - r_shadowCascadeZBias - Z-bias for shadow cascade frustums. +* `r_shadowCascadeZBias` - Z-bias for shadow cascade frustums. -256 - Default. - r_materialGamma - Gamma level for material textures. +* `r_materialGamma` - Gamma level for material textures. (diffuse, specular) 1.0 - Quake 3, fastest. (default) - r_lightGamma - Gamma level for light. +* `r_lightGamma` - Gamma level for light. (lightmap, lightgrid, vertex lights) 1.0 - Quake 3, fastest. (default) - r_framebufferGamma - Gamma level for framebuffers. +* `r_framebufferGamma` - Gamma level for framebuffers. 1.0 - Quake 3, fastest. (default) - r_tonemapGamma - Gamma applied after tonemapping. +* `r_tonemapGamma` - Gamma applied after tonemapping. 1.0 - Quake 3, fastest. (default) Cvars that have broken bits: - r_dlightMode - Change how dynamic lights look. + +* `r_dlightMode` - Change how dynamic lights look. 0 - Quake 3 style dlights, fake brightening. (default) 1 - Actual lighting, no shadows. 2 - Light and shadows. (broken) - r_pshadowDist - Virtual camera distance when creating shadow - maps for projected shadows. Deprecated. - - cg_shadows - Old shadow code. Deprecated. +* `r_pshadowDist` - Virtual camera distance when creating shadowmaps for projected shadows. Deprecated. + +* `cg_shadows` - Old shadow code. Deprecated. ------------------------------------------------------------------------------- @@ -554,7 +552,7 @@ There are currently two ways to use this in your own (and other people's) maps. surfaceparm nolightmap surfaceparm sky q3map_sunExt 240 238 200 100 195 35 3 16 - q3gl2_sun 240 238 200 50 195 35 3 1.0 0.2 + q3gl2_sun 240 238 200 50 195 35 1.0 0.2 q3map_skylight 50 16 q3map_lightimage $whiteimage @@ -577,7 +575,7 @@ There are currently two ways to use this in your own (and other people's) maps. surfaceparm noimpact surfaceparm nolightmap surfaceparm sky - q3gl2_sun 240 238 200 50 195 35 3 0.5 0.2 + q3gl2_sun 240 238 200 50 195 35 0.5 0.2 q3map_skylight 50 16 q3map_lightimage $whiteimage