added cmake file.

reduced input latency.
reworked how internal texture formats work,.
added support for LIGHTING_E5BGR9 bspx lump for HDR lighting.
updated support for srgb, no longer looks quite so weird. works on glx
vid_srgb 3 attempts to use half-float swapchains, where possible.
gl: use glTextureStorage where available.
d3d11: gave up on using dxgi for fullscreen, was just too buggy.
glx: updated gl context creation on linux.
server: fix svc_updatefrags not being passed though (fixes frikbot scores)
fs: spanned pk3s now work (fragmented files/directory will fail to open, so this needs a custom tool to be fully useful).
fixed restart_ents command (restarts the map, but preserving the players as they are)
tw: removed 'QWSKINS' featureset from tw config

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5217 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2018-03-04 14:41:16 +00:00
parent b1855b5268
commit 685404250f
122 changed files with 9613 additions and 2835 deletions

473
CMakeLists.txt Normal file
View File

@ -0,0 +1,473 @@
#Note: this file was made primarily to support msvc and its project file incompatibilities nightmare.
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
PROJECT(fteqw)
INCLUDE_DIRECTORIES(
engine/common
engine/client
engine/qclib
engine/gl
engine/server
engine
)
EXECUTE_PROCESS(COMMAND
"echo" hello world
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
OUTPUT_VARIABLE FTE_REVISON
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
IF (NOT "${FTE_REVISON}" STREQUAL "")
SET(FTE_REVISON SVNREVISION=${FTE_REVISON})
ENDIF()
#plugins need visibility hidden in order to avoid conflicts with function names that match the engine.
#this is consistent with how windows works so no great loss.
#plus it means that gcc can inline more (with LTO), including optimising args.
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_C_VISIBILITY_PRESET hidden)
#use LTO where possible. reportedly requires cmake 3.9 to actually work
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
IF(${WIN32})
INCLUDE_DIRECTORIES(engine/libs engine/libs/freetype2/include)
# LINK_DIRECTORIES(engine/libs/mingw64-libs)
# engine/server/sv_sys_win.c
SET(FTE_LIBS z ole32 gdi32 wsock32 winmm)
SET(FTE_DEFINES GLQUAKE;VKQUAKE;D3D9QUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG) #D3D11QUAKE not included.
SET(FTE_ARCH_FILES
engine/client/winquake.rc
engine/common/sys_win_threads.c
engine/common/net_ssl_winsspi.c
engine/common/fs_win32.c
engine/client/cd_win.c
engine/client/in_win.c
engine/client/snd_al.c
engine/client/snd_directx.c
engine/client/snd_wasapi.c
engine/client/snd_win.c
engine/client/snd_xaudio.c
engine/client/sys_win.c
engine/gl/gl_vidnt.c
engine/d3d/d3d_backend.c
engine/d3d/d3d_image.c
engine/d3d/d3d_shader.c
engine/d3d/d3d11_backend.c
engine/d3d/d3d11_image.c
engine/d3d/d3d11_shader.c
engine/d3d/d3d8_backend.c
engine/d3d/d3d8_image.c
engine/d3d/vid_d3d.c
engine/d3d/vid_d3d11.c
engine/d3d/vid_d3d8.c
)
SET(FTESV_LIBS z wsock32 winmm)
SET(FTESV_ARCH_FILES
engine/client/winquake.rc
engine/common/sys_win_threads.c
engine/common/net_ssl_winsspi.c
engine/common/fs_win32.c
engine/server/sv_sys_win.c
)
ELSEIF(${UNIX}) #linux(ish)
FIND_PACKAGE(Freetype REQUIRED)
INCLUDE_DIRECTORIES( ${FREETYPE_INCLUDE_DIRS} )
SET(FTE_DEFINES GLQUAKE;VKQUAKE;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;DYNAMIC_SDL;MULTITHREAD;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS z m dl pthread ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES
engine/client/sys_linux.c
engine/common/sys_linux_threads.c
engine/common/net_ssl_gnutls.c
engine/client/snd_al.c
engine/client/snd_alsa.c
engine/client/snd_linux.c
engine/client/snd_sdl.c #we use SDL audio even without sys_sdl, because of pulseaudio fucking over alsa, alsa fucking over oss3, and oss4 not being used. Either way, openal should be the default anyway.
engine/client/cd_linux.c
engine/gl/gl_vidlinuxglx.c
engine/gl/gl_videgl.c
# engine/gl/gl_vidrpi.c
# engine/gl/gl_vidwayland.c
)
SET(FTESV_DEFINES stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTESV_ARCH_FILES
engine/server/sv_sys_unix.c
engine/common/sys_linux_threads.c
engine/common/net_ssl_gnutls.c
)
SET(FTESV_LIBS z m dl)
ELSEIF(1) #SDL
FIND_PACKAGE(Freetype REQUIRED)
# INCLUDE_DIRECTORIES(engine/libs engine/libs/freetype2/include)
FIND_PACKAGE(PkgConfig REQUIRED)
PKG_SEARCH_MODULE(sdl2 REQUIRED sdl2)
# FIND_PACKAGE(SDL2 REQUIRED)
INCLUDE_DIRECTORIES(${FREETYPE_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS})
#SDL2.0.7 supports vulkan, so lets use it.
SET(FTE_DEFINES GLQUAKE;VKQUAKE;FTE_SDL;DYNAMIC_LIBPNG;DYNAMIC_LIBJPEG;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTE_LIBS z m dl ${SDL2_LIBRARIES})
SET(FTE_ARCH_FILES
engine/client/sys_sdl.c
engine/client/snd_al.c
engine/client/snd_sdl.c
engine/client/in_sdl.c
engine/client/cd_sdl.c
engine/gl/gl_vidsdl.c
)
SET(FTESV_DEFINES FTE_SDL;stricmp=strcasecmp;strnicmp=strncasecmp)
SET(FTESV_LIBS z m dl ${SDL2_LIBRARIES})
IF(WIN32)
SET(FTE_LIBS ${FTE_LIBS} wsock32 gdi32 ole32)
SET(FTE_DEFINES ${FTE_DEFINES};NO_DIRECTX)
SET(FTE_ARCH_FILES ${FTE_ARCH_FILES}
engine/client/winquake.rc
engine/common/net_ssl_winsspi.c
)
SET(FTESV_ARCH_FILES ${FTESV_ARCH_FILES}
engine/client/winquake.rc
engine/common/net_ssl_winsspi.c
engine/server/sv_sys_win.c
)
ELSE()
SET(FTE_ARCH_FILES ${FTE_ARCH_FILES}
engine/common/net_ssl_gnutls.c
)
SET(FTESV_ARCH_FILES ${FTESV_ARCH_FILES}
engine/common/net_ssl_gnutls.c
engine/common/sys_linux_threads.c
engine/server/sv_sys_unix.c
)
ENDIF()
ELSE()
# engine/common/sys_linux_threads.c
# engine/common/net_ssl_gnutls.c
# engine/server/sv_sys_unix.c
# engine/client/snd_alsa.c
# engine/client/snd_droid.c
# engine/client/snd_linux.c
# engine/client/snd_macos.c
# engine/client/snd_morphos.c
# engine/client/snd_sblaster.c
# engine/client/snd_sdl.c
# engine/client/snd_sndio.c
# engine/client/sys_dos.c
# engine/client/sys_droid.c
# engine/client/sys_linux.c
# engine/client/sys_morphos.c
# engine/client/sys_npfte.c
# engine/client/sys_plugfte.c
# engine/client/sys_sdl.c
# engine/client/sys_xdk.c
# engine/client/cd_linux.c
# engine/client/cd_null.c
# engine/client/cd_sdl.c
# engine/client/in_morphos.c
# engine/client/in_sdl.c
# engine/gl/gl_viddroid.c
# engine/gl/gl_videgl.c
# engine/gl/gl_vidlinuxglx.c
# engine/gl/gl_vidmacos.c
# engine/gl/gl_vidmorphos.c
# engine/gl/gl_vidnull.c
# engine/gl/gl_vidrpi.c
# engine/gl/gl_vidsdl.c
# engine/gl/gl_vidtinyglstubs.c
# engine/gl/gl_vidwayland.c
ENDIF()
SET(FTE_COMMON_FILES
#these files are common to both server-only and client+server builds.
engine/common/cmd.c
engine/common/com_mesh.c
engine/common/common.c
engine/common/crc.c
engine/common/cvar.c
engine/common/fs.c
engine/common/fs_dzip.c
engine/common/fs_pak.c
engine/common/fs_stdio.c
engine/common/fs_xz.c
engine/common/fs_zip.c
engine/common/gl_q2bsp.c
engine/common/huff.c
engine/common/log.c
engine/common/mathlib.c
engine/common/md4.c
engine/common/net_chan.c
engine/common/net_ice.c
engine/common/net_wins.c
engine/common/plugin.c
engine/common/pmove.c
engine/common/pmovetst.c
engine/common/pr_bgcmd.c
engine/common/q1bsp.c
engine/common/q2pmove.c
engine/common/q3common.c
engine/common/qvm.c
engine/common/sha1.c
engine/common/translate.c
engine/common/zone.c
#sigh
engine/client/pr_skelobj.c
engine/client/m_download.c
engine/client/net_master.c
#these are here because of hitmodel etc
engine/gl/gl_heightmap.c
engine/gl/gl_hlmdl.c
engine/gl/gl_model.c
engine/server/net_preparse.c
engine/server/pr_cmds.c
engine/server/pr_lua.c
engine/server/pr_q1qvm.c
engine/server/savegame.c
engine/server/sv_ccmds.c
engine/server/sv_chat.c
engine/server/sv_cluster.c
engine/server/sv_demo.c
engine/server/sv_ents.c
engine/server/sv_init.c
engine/server/sv_main.c
engine/server/sv_master.c
engine/server/sv_move.c
engine/server/sv_mvd.c
engine/server/sv_nchan.c
engine/server/sv_phys.c
engine/server/sv_rankin.c
engine/server/sv_send.c
engine/server/sv_sql.c
engine/server/sv_user.c
# engine/server/svhl_game.c
# engine/server/svhl_phys.c
# engine/server/svhl_world.c
engine/server/svq2_ents.c
engine/server/svq2_game.c
engine/server/svq3_game.c
engine/server/world.c
engine/qclib/comprout.c
engine/qclib/hash.c
engine/qclib/initlib.c
engine/qclib/pr_edict.c
engine/qclib/pr_exec.c
engine/qclib/pr_multi.c
engine/qclib/qcc_cmdlib.c
engine/qclib/qcc_pr_comp.c
engine/qclib/qcc_pr_lex.c
# engine/qclib/decomp.c
# engine/qclib/packager.c
# engine/qclib/pr_x86.c
# engine/qclib/qccgui.c
# engine/qclib/qccguistuff.c
# engine/qclib/qcctui.c
engine/qclib/qccmain.c
engine/qclib/qcd_main.c
engine/qclib/qcdecomp.c
engine/http/httpclient.c
)
ADD_EXECUTABLE(fteqw WIN32
${FTE_ARCH_FILES}
${FTE_COMMON_FILES}
engine/client/cl_cam.c
engine/client/cl_cg.c
engine/client/cl_demo.c
engine/client/cl_ents.c
engine/client/cl_ignore.c
engine/client/cl_input.c
engine/client/cl_main.c
engine/client/cl_parse.c
engine/client/cl_pred.c
engine/client/cl_screen.c
engine/client/cl_tent.c
engine/client/cl_ui.c
# engine/client/clhl_game.c
engine/client/clq2_cin.c
engine/client/clq2_ents.c
engine/client/clq3_parse.c
engine/client/console.c
engine/client/fragstats.c
engine/client/image.c
engine/client/in_generic.c
engine/client/keys.c
engine/client/m_items.c
engine/client/m_master.c
engine/client/m_mp3.c
engine/client/m_multi.c
engine/client/m_options.c
engine/client/m_script.c
engine/client/m_single.c
engine/client/menu.c
engine/client/p_classic.c
engine/client/p_null.c
engine/client/p_script.c
engine/client/pr_clcmd.c
engine/client/pr_csqc.c
engine/client/pr_menu.c
engine/client/r_2d.c
engine/client/r_d3.c
engine/client/r_part.c
engine/client/r_partset.c
engine/client/r_surf.c
engine/client/renderer.c
engine/client/renderque.c
engine/client/roq_read.c
engine/client/sbar.c
engine/client/skin.c
engine/client/snd_dma.c
engine/client/snd_mem.c
engine/client/snd_mix.c
engine/client/snd_mp3.c
engine/client/snd_ov.c
engine/client/textedit.c
engine/client/valid.c
engine/client/vid_headless.c
engine/client/view.c
engine/client/wad.c
engine/client/zqtp.c
#These are generic renderer files
engine/gl/gl_alias.c
engine/gl/gl_font.c
engine/gl/gl_ngraph.c
engine/gl/gl_rlight.c
engine/gl/gl_shader.c
engine/gl/gl_shadow.c
engine/gl/gl_warp.c
engine/gl/ltface.c
#These are GL-specific
engine/gl/gl_backend.c
engine/gl/gl_bloom.c
engine/gl/gl_draw.c
engine/gl/gl_rmain.c
engine/gl/gl_rmisc.c
engine/gl/gl_rsurf.c
engine/gl/gl_screen.c
engine/gl/gl_vidcommon.c
engine/gl/glmod_doom.c
engine/vk/vk_backend.c
engine/vk/vk_init.c
)
SET_TARGET_PROPERTIES(fteqw PROPERTIES COMPILE_DEFINITIONS "${FTE_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw ${FTE_LIBS} )
ADD_EXECUTABLE(fteqw-sv
${FTESV_ARCH_FILES}
${FTE_COMMON_FILES}
)
SET_TARGET_PROPERTIES(fteqw-sv PROPERTIES COMPILE_DEFINITIONS "SERVERONLY;${FTESV_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(fteqw-sv ${FTESV_LIBS})
ADD_EXECUTABLE(fteqcc
engine/qclib/qcctui.c
engine/qclib/comprout.c
engine/qclib/hash.c
engine/qclib/qcc_cmdlib.c
engine/qclib/qcc_pr_comp.c
engine/qclib/qcc_pr_lex.c
engine/qclib/qccmain.c
engine/qclib/qcd_main.c
)
TARGET_LINK_LIBRARIES(fteqcc z m)
IF(${WIN32})
ADD_EXECUTABLE(fteqccgui WIN32
engine/qclib/qccgui.c
engine/qclib/qccguistuff.c
engine/qclib/comprout.c
engine/qclib/hash.c
engine/qclib/qcc_cmdlib.c
engine/qclib/qcc_pr_comp.c
engine/qclib/qcc_pr_lex.c
engine/qclib/qccmain.c
engine/qclib/decomp.c
engine/qclib/packager.c
engine/qclib/qcd_main.c
)
TARGET_LINK_LIBRARIES(fteqccgui z shlwapi ole32 comctl32 comdlg32)
ENDIF()
#Quake Injector Alike plugin
ADD_LIBRARY(qi MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/qi/qi.c
plugins/emailnot/md5.c
plugins/jabber/xml.c
)
SET_TARGET_PROPERTIES(qi PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN")
SET_TARGET_PROPERTIES(qi PROPERTIES PREFIX "fteplug_")
#EzQuake Hud port plugin
ADD_LIBRARY(ezhud MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/ezhud/ezquakeisms.c
plugins/ezhud/hud.c
plugins/ezhud/hud_common.c
plugins/ezhud/hud_editor.c
)
SET_TARGET_PROPERTIES(ezhud PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN")
SET_TARGET_PROPERTIES(ezhud PROPERTIES PREFIX "fteplug_")
#IRC client plugin
ADD_LIBRARY(irc MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/irc/ircclient.c
)
SET_TARGET_PROPERTIES(irc PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN")
SET_TARGET_PROPERTIES(irc PROPERTIES PREFIX "fteplug_")
#XMPP/jabber client plugin
ADD_LIBRARY(xmpp MODULE
plugins/qvm_api.c
plugins/plugin.c
plugins/jabber/jabberclient.c
plugins/jabber/xml.c
plugins/jabber/jingle.c
plugins/jabber/sift.c
engine/common/sha1.c
plugins/emailnot/md5.c
)
SET_TARGET_PROPERTIES(xmpp PROPERTIES COMPILE_DEFINITIONS "FTEPLUGIN")
SET_TARGET_PROPERTIES(xmpp PROPERTIES PREFIX "fteplug_")
#ffmpeg plugin
#cef plugin
#bullet plugin

View File

@ -611,7 +611,6 @@ endif
CLIENT_OBJS = \
textedit.o \
fragstats.o \
teamplay.o \
zqtp.o \
cl_demo.o \
cl_ents.o \

View File

@ -559,8 +559,6 @@ void Cam_Unlock(playerview_t *pv)
void Cam_Lock(playerview_t *pv, int playernum)
{
int i;
pv->cam_lastviewtime = -1000; //allow the wallcam to re-snap as soon as it can
CL_SendClientCommand(true, "ptrack %i", playernum);
@ -592,8 +590,13 @@ void Cam_Lock(playerview_t *pv, int playernum)
Sbar_Changed();
for (i = 0; i < cl.allocated_client_slots; i++)
CL_NewTranslation(i);
#ifdef QWSKINS
{
int i;
for (i = 0; i < cl.allocated_client_slots; i++)
CL_NewTranslation(i);
}
#endif
}
trace_t Cam_DoTrace(vec3_t vec1, vec3_t vec2)

View File

@ -2012,8 +2012,8 @@ void CL_RotateAroundTag(entity_t *ent, int entnum, int parenttagent, int parentt
if ((ent->flags & RF_WEAPONMODEL) && ent->playerindex == -1 && ps->colormap > 0 && ps->colormap <= cl.allocated_client_slots)
{
ent->playerindex = ps->colormap-1;
ent->topcolour = cl.players[ent->playerindex].ttopcolor;
ent->bottomcolour = cl.players[ent->playerindex].tbottomcolor;
ent->topcolour = cl.players[ent->playerindex].dtopcolor;
ent->bottomcolour = cl.players[ent->playerindex].dbottomcolor;
}
}
else
@ -4057,8 +4057,8 @@ void CL_LinkPacketEntities (void)
#ifdef HEXEN2
ent->h2playerclass = cl.players[ent->playerindex].h2playerclass;
#endif
ent->topcolour = cl.players[ent->playerindex].ttopcolor;
ent->bottomcolour = cl.players[ent->playerindex].tbottomcolor;
ent->topcolour = cl.players[ent->playerindex].dtopcolor;
ent->bottomcolour = cl.players[ent->playerindex].dbottomcolor;
}
// set skin
@ -5109,8 +5109,8 @@ void CL_LinkPlayers (void)
// set colormap
ent->playerindex = j;
ent->topcolour = info->ttopcolor;
ent->bottomcolour = info->tbottomcolor;
ent->topcolour = info->dtopcolor;
ent->bottomcolour = info->dbottomcolor;
#ifdef HEXEN2
ent->h2playerclass = info->h2playerclass;
#endif

View File

@ -1924,7 +1924,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
}
#ifdef HLCLIENT
if (!CLHL_BuildUserInput(msecstouse, &independantphysics[0]))
if (!CLHL_BuildUserInput(msecstouse, &cl_pendingcmd[0]))
#endif
for (plnum = 0; plnum < (cl.splitclients?cl.splitclients:1); plnum++)
{
@ -1952,13 +1952,7 @@ void CL_SendCmd (double frametime, qboolean mainloop)
// if (cl.spectator)
Cam_Track(&cl.playerview[plnum], &cl_pendingcmd[plnum]);
Cam_FinishMove(&cl.playerview[plnum], &cl_pendingcmd[plnum]);
//HACK: 1000/77 = 12.98. nudge it just under so we never appear to be using 83fps at 77fps (which can trip cheat detection in mods that expect 72 fps when many servers are configured for 77)
//so lets just never use 12.
if (fullsend && (cl_pendingcmd[plnum].msec > 12.9 && cl_pendingcmd[plnum].msec < 13) && cls.maxfps == 77)
cl_pendingcmd[plnum].msec = 13;
}
// msecstouse = cl_pendingcmd[0].msec;
//the main loop isn't allowed to send
if (runningindepphys && mainloop)
@ -1973,6 +1967,13 @@ void CL_SendCmd (double frametime, qboolean mainloop)
// if (msecstouse > 127)
// Con_Printf("%i\n", msecstouse, msecs);
//HACK: 1000/77 = 12.98. nudge it just under so we never appear to be using 83fps at 77fps (which can trip cheat detection in mods that expect 72 fps when many servers are configured for 77)
//so lets just never use 12.
if (fullsend && cls.maxfps == 77)
for (plnum = 0; plnum < (cl.splitclients?cl.splitclients:1); plnum++)
if (cl_pendingcmd[plnum].msec > 12.9 && cl_pendingcmd[plnum].msec < 13)
cl_pendingcmd[plnum].msec = 13;
#ifdef NQPROT
if (cls.protocol != CP_NETQUAKE || cls.netchan.nqreliable_allowed)
#endif

View File

@ -4116,8 +4116,10 @@ void CL_Init (void)
extern void CL_Say_f (void);
extern void CL_SayMe_f (void);
extern void CL_SayTeam_f (void);
#ifdef QWSKINS
extern cvar_t baseskin;
extern cvar_t noskins;
#endif
char *ver;
cls.state = ca_disconnected;
@ -4204,8 +4206,10 @@ void CL_Init (void)
Cvar_Register (&cl_muzzleflash, cl_controlgroup);
#ifdef QWSKINS
Cvar_Register (&baseskin, "Teamplay");
Cvar_Register (&noskins, "Teamplay");
#endif
Cvar_Register (&cl_noblink, "Console controls"); //for lack of a better group
Cvar_Register (&cl_item_bobbing, "Item effects");
@ -4335,7 +4339,9 @@ void CL_Init (void)
Cmd_AddCommand ("stopdemo", CL_Stopdemo_f);
Cmd_AddCommand ("skins", Skin_Skins_f);
#ifdef QWSKINS
Cmd_AddCommand ("allskins", Skin_AllSkins_f);
#endif
Cmd_AddCommand ("cl_status", CL_Status_f);
Cmd_AddCommandD ("quit", CL_Quit_f, "Use this command when you get angry. Does not save any cvars. Use cfg_save to save settings, or use the menu for a prompt.");
@ -5518,12 +5524,13 @@ double Host_Frame (double time)
// host_frametime = 0.2;
// get new key events
Sys_SendKeyEvents ();
Sys_SendKeyEvents (); //from windowing system
INS_Move(); //from things that need special polling
// allow mice or other external controllers to add commands
// check what we got, and handle any click/button events
IN_Commands ();
// process console commands
// process console commands from said click/button events
Cbuf_Execute ();
#ifndef CLIENTONLY
@ -5543,6 +5550,8 @@ double Host_Frame (double time)
// fetch results from server
CL_ReadPackets ();
CL_RequestNextDownload();
// send intentions now
// resend a connection request if necessary
if (cls.state == ca_disconnected)
@ -5669,12 +5678,10 @@ double Host_Frame (double time)
}
IN_Commands ();
// IN_Commands ();
// process console commands
Cbuf_Execute ();
CL_RequestNextDownload();
// Cbuf_Execute ();
CL_QTVPoll();

View File

@ -840,8 +840,10 @@ void CL_DownloadFinished(qdownload_t *dl)
}
S_ResetFailedLoad(); //okay, so this can still get a little spammy in bad places...
#ifdef QWSKINS
//this'll do the magic for us
Skin_FlushSkin(filename);
#endif
}
}
@ -4892,6 +4894,7 @@ void CL_ParseClientdata (void)
CL_AckedInputFrame(cls.netchan.incoming_sequence, cl.parsecount, false);
}
#ifdef QWSKINS
static qboolean CLQ2_PlayerSkinIsOkay(skinid_t id)
{
skinfile_t *sk = Mod_LookupSkin(id);
@ -5025,6 +5028,7 @@ void CL_NewTranslation (int slot)
player->ttopcolor = top;
player->tbottomcolor = bottom;
}
#endif
/*
==============
@ -5064,7 +5068,6 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
if (player->rbottomcolor > 13)
player->rbottomcolor = 13;
*/
player->model = NULL;
#ifdef HEXEN2
/*if we're running hexen2, they have to be some class...*/
@ -5075,7 +5078,10 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
player->h2playerclass = 1;
#endif
#ifdef QWSKINS
player->model = NULL;
player->colourised = TP_FindColours(player->name);
#endif
// If it's us
for (i = 0; i < cl.splitclients; i++)
@ -5098,13 +5104,15 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
Skin_FlushPlayers();
}
#ifdef QWSKINS
else if (cl.teamplay && cl.playerview[0].spectator && slot == Cam_TrackNum(&cl.playerview[0])) //skin forcing cares about the team of the guy we're tracking.
Skin_FlushPlayers();
else if (cls.state == ca_active)
Skin_Find (player);
Sbar_Changed ();
CL_NewTranslation (slot);
#endif
Sbar_Changed ();
}
/*
@ -7863,13 +7871,14 @@ void CLNQ_ParseServerMessage (void)
// CLNQ_CheckPlayerIsSpectator(i);
#ifdef QWSKINS
if (cls.state == ca_active)
Skin_Find (&cl.players[i]);
if (i == cl.playerview[destsplit].playernum)
Skin_FlushPlayers();
Sbar_Changed ();
CL_NewTranslation (i);
#endif
Sbar_Changed ();
}
}
break;

View File

@ -2538,6 +2538,18 @@ qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer,
}
else if (!Q_strcasecmp(ext, "tga")) //tga
return WriteTGA(filename, fsroot, buffer[0], bytestride, width, height, fmt);
/*else if (!Q_strcasecmp(ext, "ktx")) //ktx
{
struct pendingtextureinfo out = {PTI_2D};
out.encoding = fmt;
out.mipcount = 1;
out.mip[0].data = buffer[0];
out.mip[0].datasize = bytestride*height;
out.mip[0].width = width;
out.mip[0].height = height;
out.mip[0].depth = 1;
return Image_WriteKTXFile(filename, fsroot, &out);
}*/
else //extension / type not recognised.
return false;
return true;

View File

@ -3103,9 +3103,9 @@ void CL_UpdateExplosions (void)
if (ex->flags & Q2RF_BEAM)
{
ent->rtype = RT_BEAM;
ent->shaderRGBAf[0] = ((d_8to24rgbtable[ex->skinnum & 0xFF] >> 0) & 0xFF)/255.0;
ent->shaderRGBAf[1] = ((d_8to24rgbtable[ex->skinnum & 0xFF] >> 8) & 0xFF)/255.0;
ent->shaderRGBAf[2] = ((d_8to24rgbtable[ex->skinnum & 0xFF] >> 16) & 0xFF)/255.0;
ent->shaderRGBAf[0] = ((d_8to24srgbtable[ex->skinnum & 0xFF] >> 0) & 0xFF)/255.0;
ent->shaderRGBAf[1] = ((d_8to24srgbtable[ex->skinnum & 0xFF] >> 8) & 0xFF)/255.0;
ent->shaderRGBAf[2] = ((d_8to24srgbtable[ex->skinnum & 0xFF] >> 16) & 0xFF)/255.0;
}
else if (ex->skinnum < 0)
{

View File

@ -163,6 +163,7 @@ typedef struct player_info_s
float teamstatustime;
// scoreboard information
int spectator;
char name[MAX_SCOREBOARDNAME];
char team[MAX_INFO_KEY];
float realentertime; //pegged against realtime, to cope with potentially not knowing the server's time when we first receive this message
@ -185,21 +186,27 @@ typedef struct player_info_s
qboolean ignored;
qboolean vignored;
colourised_t *colourised;
// skin information
unsigned int rtopcolor; //real, according to their userinfo
unsigned int rbottomcolor;
#ifdef QWSKINS
colourised_t *colourised;
qwskin_t *qwskin;
qwskin_t *lastskin; //last-known-good skin
unsigned int ttopcolor; //team, according to colour forcing
unsigned int tbottomcolor;
int spectator;
qwskin_t *qwskin;
qwskin_t *lastskin; //last-known-good skin
skinid_t skinid;
struct model_s *model;
#define dtopcolor ttopcolor
#define dbottomcolor tbottomcolor
#else
#define dtopcolor rtopcolor
#define dbottomcolor rbottomcolor
#endif
skinid_t skinid;
// unsigned short vweapindex;
#ifdef HEXEN2

View File

@ -1884,9 +1884,9 @@ static void CLQ2_AddPacketEntities (q2frame_t *frame)
if ( renderfx & Q2RF_BEAM )
{ // the four beam colors are encoded in 32 bits of skinnum (hack)
ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff;
ent.shaderRGBAf[0] = ((d_8to24rgbtable[ent.skinnum & 0xFF] >> 0) & 0xFF)/255.0;
ent.shaderRGBAf[1] = ((d_8to24rgbtable[ent.skinnum & 0xFF] >> 8) & 0xFF)/255.0;
ent.shaderRGBAf[2] = ((d_8to24rgbtable[ent.skinnum & 0xFF] >> 16) & 0xFF)/255.0;
ent.shaderRGBAf[0] = ((d_8to24srgbtable[ent.skinnum & 0xFF] >> 0) & 0xFF)/255.0;
ent.shaderRGBAf[1] = ((d_8to24srgbtable[ent.skinnum & 0xFF] >> 8) & 0xFF)/255.0;
ent.shaderRGBAf[2] = ((d_8to24srgbtable[ent.skinnum & 0xFF] >> 16) & 0xFF)/255.0;
ent.shaderRGBAf[3] = 0.30;
ent.model = NULL;
ent.framestate.g[FS_REG].lerpweight[0] = 0;

View File

@ -2120,12 +2120,12 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
if (l->flags & CONL_EXECUTION)
{
if (l->flags & CONL_BREAKPOINT)
R2D_ImageColours(0.3,0.15,0.0, alphaval);
R2D_ImageColours(SRGBA(0.3,0.15,0.0, alphaval));
else
R2D_ImageColours(0.3,0.3,0.0, alphaval);
R2D_ImageColours(SRGBA(0.3,0.3,0.0, alphaval));
}
else //if (l->flags & CONL_BREAKPOINT)
R2D_ImageColours(0.3,0.0,0.0, alphaval);
R2D_ImageColours(SRGBA(0.3,0.0,0.0, alphaval));
R2D_FillBlock((sx*(float)vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((ex - sx)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
R2D_Flush();
}
@ -2174,7 +2174,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
sstart += center;
send += center;
R2D_ImageColours(0.1,0.1,0.3, alphaval);
R2D_ImageColours(SRGBA(0.1,0.1,0.3, alphaval));
if (send < sstart)
R2D_FillBlock((send*(float)vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((sstart - send)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
else
@ -2258,7 +2258,7 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in
if (selactive == 1)
{
R2D_ImageColours(0.1,0.1,0.3, alphaval);
R2D_ImageColours(SRGBA(0.1,0.1,0.3, alphaval));
if (send < sstart)
R2D_FillBlock((send*vid.width)/(float)vid.rotpixelwidth, (y*vid.height)/(float)vid.rotpixelheight, ((sstart - send)*vid.width)/(float)vid.rotpixelwidth, (Font_CharHeight()*vid.height)/(float)vid.rotpixelheight);
else
@ -2374,9 +2374,9 @@ void Con_DrawConsole (int lines, qboolean noback)
{
int top = 8; //padding at the top
if (con_curwindow==w)
R2D_ImageColours(0.0, 0.05, 0.1, 0.8);
R2D_ImageColours(SRGBA(0.0, 0.05, 0.1, 0.8));
else
R2D_ImageColours(0.0, 0.05, 0.1, 0.5);
R2D_ImageColours(SRGBA(0.0, 0.05, 0.1, 0.5));
R2D_FillBlock(w->wnd_x, w->wnd_y, w->wnd_w, w->wnd_h);
R2D_ImageColours(1, 1, 1, 1);
@ -2495,7 +2495,7 @@ void Con_DrawConsole (int lines, qboolean noback)
{
if (!fadetime)
{
R2D_ImageColours(0, 0.1, 0.2, 1.0);
R2D_ImageColours(SRGBA(0, 0.1, 0.2, 1.0));
if ((w->buttonsdown & CB_SIZELEFT) || (con_curwindow==w && w->mousecursor[0] >= -8 && w->mousecursor[0] < 0 && w->mousecursor[1] >= 8 && w->mousecursor[1] < w->wnd_h))
R2D_FillBlock(w->wnd_x, w->wnd_y+8, 8, w->wnd_h-8);
if ((w->buttonsdown & CB_SIZERIGHT) || (con_curwindow==w && w->mousecursor[0] >= w->wnd_w-16 && w->mousecursor[0] < w->wnd_w-8 && w->mousecursor[1] >= 8 && w->mousecursor[1] < w->wnd_h))

File diff suppressed because it is too large Load Diff

View File

@ -976,7 +976,6 @@ void IN_MoveJoystick(struct joy_s *joy, float *movements, int pnum, float framet
void IN_Move (float *movements, int pnum, float frametime)
{
int i;
INS_Move(movements, pnum);
for (i = 0; i < MAXPOINTERS; i++)
IN_MoveMouse(&ptr[i], movements, pnum, frametime);

View File

@ -216,7 +216,7 @@ void INS_Commands(void)
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}
void INS_Move (float *movements, int pnum)
void INS_Move (void)
{
}

View File

@ -1011,7 +1011,7 @@ void INS_ReInit (void)
}
//stubs, all the work is done in Sys_SendKeyEvents
void INS_Move(float *movements, int pnum)
void INS_Move(void)
{
}
void INS_Init (void)

View File

@ -305,7 +305,7 @@ void INS_RawInput_DeInit(void);
// forward-referenced functions
void INS_StartupJoystick (void);
void INS_JoyMove (float *movements, int pnum);
void INS_JoyMove (void);
/*
===========
@ -1333,7 +1333,7 @@ void INS_MouseEvent (int mstate)
INS_MouseMove
===========
*/
void INS_MouseMove (float *movements, int pnum)
void INS_MouseMove (void)
{
#ifdef AVAIL_DINPUT
if (dinput && mouseactive)
@ -1426,12 +1426,12 @@ void INS_MouseMove (float *movements, int pnum)
INS_Move
===========
*/
void INS_Move (float *movements, int pnum)
void INS_Move (void)
{
if (vid.activeapp && !Minimized)
{
INS_MouseMove (movements, pnum);
INS_JoyMove (movements, pnum);
INS_MouseMove ();
INS_JoyMove ();
}
else
INS_Accumulate();
@ -2132,39 +2132,17 @@ static qboolean INS_ReadJoystick (struct wjoy_s *joy)
return false;
}
static void INS_JoyMovePtr (struct wjoy_s *joy, float *movements, int pnum)
{
int wpnum;
/*each device will be processed when its player comes to be processed*/
wpnum = cl.splitclients;
if (wpnum < 1)
wpnum = 1;
if (cl_forceseat.ival)
wpnum = (cl_forceseat.ival-1) % wpnum;
else
wpnum = joy->devid % wpnum;
if (wpnum != pnum)
return;
// collect the joystick data, if possible
if (INS_ReadJoystick (joy) != true)
{
return;
}
}
/*
===========
INS_JoyMove
===========
*/
void INS_JoyMove (float *movements, int pnum)
void INS_JoyMove (void)
{
unsigned int idx;
for (idx = 0; idx < joy_count; idx++)
{
INS_JoyMovePtr(&wjoy[idx], movements, pnum);
INS_ReadJoystick(&wjoy[idx]);
}
}

View File

@ -53,7 +53,7 @@ void IN_Accelerometer(unsigned int devid, float x, float y, float z);
void IN_Gyroscope(unsigned int devid, float pitch, float yaw, float roll);
//system-specific functions
void INS_Move (float *movements, int pnum);
void INS_Move (void);
void INS_Accumulate (void);
void INS_ClearStates (void);
void INS_ReInit (void);

View File

@ -373,11 +373,11 @@ void PM_ValidatePackage(package_t *p)
searchpathfuncs_t *archive;
if (!Q_strcasecmp(COM_FileExtension(n, buf, sizeof(buf)), "pak"))
archive = FSPAK_LoadArchive(pf, n, NULL);
archive = FSPAK_LoadArchive(pf, NULL, n, n, NULL);
else
{
#ifdef AVAIL_ZLIB //assume zip/pk3/pk4/apk/etc
archive = FSZIP_LoadArchive(pf, n, NULL);
archive = FSZIP_LoadArchive(pf, NULL, n, n, NULL);
#else
archive = NULL;
#endif
@ -1956,7 +1956,7 @@ static void PM_Download_Got(struct dl_download *dl)
vfsfile_t *f = FS_OpenVFS(tempname, "rb", p->fsroot);
if (f)
{
searchpathfuncs_t *archive = FSZIP_LoadArchive(f, tempname, NULL);
searchpathfuncs_t *archive = FSZIP_LoadArchive(f, NULL, tempname, tempname, NULL);
if (archive)
{
p->flags &= ~(DPF_NATIVE|DPF_CACHED|DPF_CORRUPT|DPF_ENABLED);

View File

@ -901,6 +901,7 @@ const char *presetexec[] =
"r_glsl_offsetmapping 1;"
"r_shadow_realtime_world 1;"
"gl_texture_anisotropic_filtering 16;"
"vid_hardwaregamma 6;" //scene gamma
};
typedef struct fpsmenuinfo_s
@ -1179,7 +1180,9 @@ void M_Menu_Render_f (void)
MB_SLIDER("Water Alpha", r_wateralpha, 0, 1, 0.1, NULL),
MB_SLIDER("Viewmodel Alpha", r_drawviewmodel, 0, 1, 0.1, NULL),
MB_CHECKBOXCVAR("Poly Blending", gl_cshiftenabled, 0),
#ifdef QWSKINS
MB_CHECKBOXCVAR("Disable Colormap", gl_nocolors, 0),
#endif
MB_COMBOCVAR("Log Centerprints", scr_logcenterprint, logcenteropts, logcentervalues, "Display centerprints in the console also."),
#ifdef GLQUAKE
MB_CHECKBOXCVAR("Bloom", r_bloom, 0),
@ -1380,7 +1383,7 @@ void M_Menu_Lighting_f (void)
#ifndef MINIMAL
extern cvar_t r_vertexlight;
#endif
extern cvar_t r_stains, r_shadows, r_loadlits;
extern cvar_t r_stains, r_shadows, r_loadlits, r_lightmap_format;
extern cvar_t r_lightstylesmooth, r_nolightdir;
#ifdef RTLIGHTS
extern cvar_t r_dynamic, r_shadow_realtime_world, r_shadow_realtime_dlight, r_shadow_realtime_dlight_shadows;
@ -1479,6 +1482,34 @@ void M_Menu_Lighting_f (void)
NULL
};
static const char *lightmapformatopts[] =
{
"Automatic",
"8bit (Greyscale)",
"8bit (Misaligned)",
"8bit (Aligned)",
"10bit",
"9bit (HDR)",
"Half-Float (HDR)",
"Float (HDR)",
NULL
};
static const char *lightmapformatvalues[] =
{
"",
"l8",
"rgb8",
"bgrx8",
"rgb10",
"rgb9e5",
"rgba16f",
"rgba32f",
// "rgb4",
// "rgb565",
// "rgba5551",
NULL
};
int y;
menu_t *menu = M_Options_Title(&y, sizeof(lightingmenuinfo_t));
@ -1535,6 +1566,7 @@ void M_Menu_Lighting_f (void)
MB_CMD("Apply Lighting", M_VideoApplyShadowLighting, "Applies set lighting modes and restarts video."),
MB_SPACING(4),
#endif
MB_COMBOCVAR("Lightmap Format", r_lightmap_format, lightmapformatopts, lightmapformatvalues, "Selects which format to use for lightmaps."),
MB_COMBOCVAR("LIT Loading", r_loadlits, loadlitopts, loadlitvalues, "Determines if the engine should use external colored lighting for maps. The generated setting will cause the engine to generate colored lighting for maps that don't have the associated data."),
MB_COMBOCVAR("Deluxmapping", r_deluxmapping_cvar, loadlitopts, loadlitvalues, "Controls whether static lighting should respond to lighting directions."),
MB_CHECKBOXCVAR("Lightstyle Lerp", r_lightstylesmooth, 0),
@ -2561,6 +2593,23 @@ void M_Menu_Video_f (void)
extern cvar_t vid_desktopsettings, vid_conautoscale;
extern cvar_t vid_bpp, vid_refreshrate, vid_multisample;
static const char *gammamodeopts[] = {
"Off",
"Auto",
"GLSL",
"Hardware",
"Scene-Only",
NULL
};
static const char *gammamodevalues[] = {
"0",
"1",
"2",
"3",
"4",
NULL
};
#ifdef ANDROID
extern cvar_t sys_orientation;
static const char *orientationopts[] = {
@ -2801,6 +2850,7 @@ void M_Menu_Video_f (void)
MB_CMD("Apply Settings", M_VideoApply, "Restart video and apply renderer, display, and 2D resolution options."),
MB_SPACING(4),
MB_SLIDER("View Size", scr_viewsize, 30, 120, 10, NULL),
MB_COMBOCVAR("Gamma Mode", v_gamma, gammamodeopts, gammamodevalues, "Controls how gamma is applied"),
MB_SLIDER("Gamma", v_gamma, 1.5, 0.25, -0.05, NULL),
MB_SLIDER("Contrast", v_contrast, 0.8, 3, 0.05, NULL),
MB_END()

View File

@ -225,6 +225,8 @@ typedef struct image_s
int regsequence;
int width; //this is the logical size. the physical size is not considered important (except for render targets, which should not be loaded from disk).
int height;
int depth;
uploadfmt_t format;
int status; //TEX_
unsigned int flags;
struct image_s *next;
@ -283,103 +285,12 @@ struct pendingtextureinfo
{
PTI_2D,
PTI_3D,
PTI_CUBEMAP //mips are packed (to make d3d11 happy)
PTI_CUBEMAP, //mips are packed (to make d3d11 happy)
PTI_2D_ARRAY, //looks like a 3d texture, but depth doesn't change.
PTI_CUBEMAP_ARRAY, //looks like PTI_2D_ARRAY, with depth*6
} type;
enum
{
//these formats are specified as direct byte access
PTI_RGBA8, //rgba byte ordering
PTI_RGBX8, //rgb pad byte ordering
PTI_BGRA8, //alpha channel
PTI_BGRX8, //no alpha channel
PTI_RGBA8_SRGB, //rgba byte ordering
PTI_RGBX8_SRGB, //rgb pad byte ordering
PTI_BGRA8_SRGB, //alpha channel
PTI_BGRX8_SRGB, //no alpha channel
//these formats are specified in native endian order
PTI_RGB565, //16bit alphaless format.
PTI_RGBA4444, //16bit format (gl)
PTI_ARGB4444, //16bit format (d3d)
PTI_RGBA5551, //16bit alpha format (gl).
PTI_ARGB1555, //16bit alpha format (d3d).
PTI_RGB8, //24bit packed format. generally not supported
PTI_LUMINANCE8_ALPHA8, //16bit format.
//floating point formats
PTI_RGBA16F,
PTI_RGBA32F,
//small formats.
PTI_R8,
PTI_RG8, //might be useful for normalmaps
PTI_R8_SIGNED,
PTI_RG8_SIGNED, //might be useful for normalmaps
//(desktop/tegra) compressed formats
PTI_BC1_RGB,
PTI_BC1_RGB_SRGB,
PTI_BC1_RGBA,
PTI_BC1_RGBA_SRGB,
PTI_BC2_RGBA,
PTI_BC2_RGBA_SRGB,
PTI_BC3_RGBA, //maybe add a bc3 normalmapswizzle type for d3d9?
PTI_BC3_RGBA_SRGB,
PTI_BC4_R8,
PTI_BC4_R8_SIGNED,
PTI_BC5_RG8, //useful for normalmaps
PTI_BC5_RG8_SIGNED, //useful for normalmaps
PTI_BC6_RGBF, //unsigned (half) floats!
PTI_BC6_RGBF_SIGNED, //signed (half) floats!
PTI_BC7_RGBA, //multimode compression, using as many bits as bc2/bc3
PTI_BC7_RGBA_SRGB,
//(mobile/intel) compressed formats
PTI_ETC1_RGB8, //limited form
PTI_ETC2_RGB8, //extended form
PTI_ETC2_RGB8A1,
PTI_ETC2_RGB8A8,
PTI_ETC2_RGB8_SRGB,
PTI_ETC2_RGB8A1_SRGB,
PTI_ETC2_RGB8A8_SRGB,
PTI_EAC_R11, //no idea what this might be used for, whatever
PTI_EAC_R11_SIGNED, //no idea what this might be used for, whatever
PTI_EAC_RG11, //useful for normalmaps (calculate blue)
PTI_EAC_RG11_SIGNED, //useful for normalmaps (calculate blue)
//astc... zomg
PTI_ASTC_4X4,
PTI_ASTC_4X4_SRGB,
PTI_ASTC_5X4,
PTI_ASTC_5X4_SRGB,
PTI_ASTC_5X5,
PTI_ASTC_5X5_SRGB,
PTI_ASTC_6X5,
PTI_ASTC_6X5_SRGB,
PTI_ASTC_6X6,
PTI_ASTC_6X6_SRGB,
PTI_ASTC_8X5,
PTI_ASTC_8X5_SRGB,
PTI_ASTC_8X6,
PTI_ASTC_8X6_SRGB,
PTI_ASTC_10X5,
PTI_ASTC_10X5_SRGB,
PTI_ASTC_10X6,
PTI_ASTC_10X6_SRGB,
PTI_ASTC_8X8,
PTI_ASTC_8X8_SRGB,
PTI_ASTC_10X8,
PTI_ASTC_10X8_SRGB,
PTI_ASTC_10X10,
PTI_ASTC_10X10_SRGB,
PTI_ASTC_12X10,
PTI_ASTC_12X10_SRGB,
PTI_ASTC_12X12,
PTI_ASTC_12X12_SRGB,
//weird specialcase mess to take advantage of webgl so we don't need redundant bloat where we're already strugging with potential heap limits
PTI_WHOLEFILE,
//depth formats
PTI_DEPTH16,
PTI_DEPTH24,
PTI_DEPTH32,
PTI_DEPTH24_8,
PTI_MAX,
} encoding; //0
uploadfmt_t encoding; //0
void *extrafree;
int mipcount;
struct
@ -388,6 +299,7 @@ struct pendingtextureinfo
size_t datasize;
int width;
int height;
int depth;
qboolean needfree;
} mip[72]; //enough for a 4096 cubemap. or a really smegging big 2d texture...
};

View File

@ -99,11 +99,9 @@ extern cvar_t r_part_density, r_part_classic_expgrav, r_part_classic_opaque;
static unsigned int particleframe;
extern qbyte default_quakepal[]; /*for ramps more than anything else*/
static int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
static int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
static int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3};
#define qpal(q) ((default_quakepal[(q)*3+0]<<0) | (default_quakepal[(q)*3+1]<<8) | (default_quakepal[(q)*3+2]<<16))
#ifndef POLYS
#define BUFFERVERTS 2048*3
@ -564,7 +562,7 @@ static void PClassic_DrawParticles(void)
if (p->ramp >= 6)
p->die = -1;
else
p->rgb = qpal(ramp3[(int) p->ramp]);
p->rgb = d_quaketo24srgbtable[ramp3[(int) p->ramp]];
p->vel[2] += grav;
break;
case pt_explode:
@ -572,7 +570,7 @@ static void PClassic_DrawParticles(void)
if (p->ramp >=8)
p->die = -1;
else
p->rgb = qpal(ramp1[(int) p->ramp]);
p->rgb = d_quaketo24srgbtable[ramp1[(int) p->ramp]];
for (i = 0; i < 3; i++)
p->vel[i] += p->vel[i] * dvel;
p->vel[2] -= grav*r_part_classic_expgrav.value;
@ -582,7 +580,7 @@ static void PClassic_DrawParticles(void)
if (p->ramp >=8)
p->die = -1;
else
p->rgb = qpal(ramp2[(int) p->ramp]);
p->rgb = d_quaketo24srgbtable[ramp2[(int) p->ramp]];
for (i = 0; i < 3; i++)
p->vel[i] -= p->vel[i] * frametime;
p->vel[2] -= grav*r_part_classic_expgrav.value;
@ -633,7 +631,7 @@ static void Classic_ParticleExplosion (vec3_t org)
active_particles = p;
p->die = cl.time + 5;
p->rgb = d_8to24rgbtable[ramp1[0]];
p->rgb = d_8to24srgbtable[ramp1[0]];
p->ramp = rand() & 3;
if (i & 1)
{
@ -672,7 +670,7 @@ static void Classic_ParticleExplosion2 (vec3_t org, int colorStart, int colorLen
active_particles = p;
p->die = cl.time + 0.3;
p->rgb = d_8to24rgbtable[(colorStart + (colorMod % colorLength)) & 255];
p->rgb = d_8to24srgbtable[(colorStart + (colorMod % colorLength)) & 255];
colorMod++;
p->type = pt_blob;
@ -706,7 +704,7 @@ static void Classic_BlobExplosion (vec3_t org)
if (i & 1)
{
p->type = pt_blob;
p->rgb = d_8to24rgbtable[66 + rand() % 6];
p->rgb = d_8to24srgbtable[66 + rand() % 6];
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + ((rand() % 32) - 16);
@ -716,7 +714,7 @@ static void Classic_BlobExplosion (vec3_t org)
else
{
p->type = pt_blob2;
p->rgb = d_8to24rgbtable[150 + rand() % 6];
p->rgb = d_8to24srgbtable[150 + rand() % 6];
for (j = 0; j < 3; j++)
{
p->org[j] = org[j] + ((rand() % 32) - 16);
@ -751,7 +749,7 @@ static void Classic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int co
active_particles = p;
p->die = cl.time + 0.1 * (rand() % 5);
p->rgb = d_8to24rgbtable[(color & ~7) + (rand() & 7)];
p->rgb = d_8to24srgbtable[(color & ~7) + (rand() & 7)];
if (qwstyle)
p->type = pt_grav; //QW
else
@ -785,7 +783,7 @@ static void Classic_LavaSplash (vec3_t org)
active_particles = p;
p->die = cl.time + 2 + (rand() & 31) * 0.02;
p->rgb = d_8to24rgbtable[224 + (rand() & 7)];
p->rgb = d_8to24srgbtable[224 + (rand() & 7)];
p->type = pt_grav;
dir[0] = j * 8 + (rand() & 7);
@ -829,7 +827,7 @@ static void Classic_TeleportSplash (vec3_t org)
active_particles = p;
p->die = cl.time + 0.2 + (rand() & 7) * 0.02;
p->rgb = d_8to24rgbtable[7 + (rand() & 7)];
p->rgb = d_8to24srgbtable[7 + (rand() & 7)];
p->type = pt_grav;
dir[0] = j * 8;
@ -903,7 +901,7 @@ static void Classic_BrightField (vec3_t org)
forward[2] = -sp;
p->die = cl.time;// + 0.01;
p->rgb = d_8to24rgbtable[0x6f];
p->rgb = d_8to24srgbtable[0x6f];
p->type = pt_oneframe;
p->org[0] = org[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength;
@ -1042,20 +1040,20 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef
{
case GRENADE_TRAIL:
p->ramp = (rand() & 3) + 2;
p->rgb = d_8to24rgbtable[ramp3[(int) p->ramp]];
p->rgb = d_8to24srgbtable[ramp3[(int) p->ramp]];
p->type = pt_fire;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
case BLOOD_TRAIL:
p->type = pt_slowgrav;
p->rgb = d_8to24rgbtable[67 + (rand() & 3)];
p->rgb = d_8to24srgbtable[67 + (rand() & 3)];
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
case BIG_BLOOD_TRAIL:
p->type = pt_slowgrav;
p->rgb = d_8to24rgbtable[67 + (rand() & 3)];
p->rgb = d_8to24srgbtable[67 + (rand() & 3)];
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
break;
@ -1064,9 +1062,9 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef
p->die = cl.time + 0.5;
p->type = pt_static;
if (type == TRACER1_TRAIL)
p->rgb = d_8to24rgbtable[52 + ((tracercount & 4) << 1)];
p->rgb = d_8to24srgbtable[52 + ((tracercount & 4) << 1)];
else
p->rgb = d_8to24rgbtable[230 + ((tracercount & 4) << 1)];
p->rgb = d_8to24srgbtable[230 + ((tracercount & 4) << 1)];
tracercount++;
@ -1083,7 +1081,7 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef
}
break;
case VOOR_TRAIL:
p->rgb = d_8to24rgbtable[9 * 16 + 8 + (rand() & 3)];
p->rgb = d_8to24srgbtable[9 * 16 + 8 + (rand() & 3)];
p->type = pt_static;
p->die = cl.time + 0.3;
for (j = 0; j < 3; j++)
@ -1091,7 +1089,7 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef
break;
case ALT_ROCKET_TRAIL:
p->ramp = (rand() & 3);
p->rgb = d_8to24rgbtable[ramp3[(int) p->ramp]];
p->rgb = d_8to24srgbtable[ramp3[(int) p->ramp]];
p->type = pt_fire;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
@ -1099,7 +1097,7 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef
case ROCKET_TRAIL:
default:
p->ramp = (rand() & 3);
p->rgb = d_8to24rgbtable[ramp3[(int) p->ramp]];
p->rgb = d_8to24srgbtable[ramp3[(int) p->ramp]];
p->type = pt_fire;
for (j = 0; j < 3; j++)
p->org[j] = point[j] + ((rand() % 6) - 3);
@ -1124,7 +1122,7 @@ int PClassic_PointFile(int c, vec3_t point)
VectorClear (p->vel);
p->die = 99999;
p->rgb = d_8to24rgbtable[(-c) & 0xff];
p->rgb = d_8to24srgbtable[(-c) & 0xff];
p->type = pt_static;
VectorCopy(point, p->org);

View File

@ -931,8 +931,8 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out)
if (ival > 0 && ival <= MAX_CLIENTS)
{
out->playerindex = ival - 1;
out->topcolour = cl.players[ival-1].ttopcolor;
out->bottomcolour = cl.players[ival-1].tbottomcolor;
out->topcolour = cl.players[ival-1].dtopcolor;
out->bottomcolour = cl.players[ival-1].dbottomcolor;
}
else if (ival /*>= 1024*/)
{
@ -3732,7 +3732,7 @@ static const char *PF_cs_getplayerkey_internal (unsigned int pnum, const char *k
// }
else if (!strcmp(keyname, "topcolor_rgb")) //packet loss
{
unsigned int col = cl.players[pnum].ttopcolor;
unsigned int col = cl.players[pnum].dtopcolor;
ret = buffer;
if (col < 16)
{
@ -3744,7 +3744,7 @@ static const char *PF_cs_getplayerkey_internal (unsigned int pnum, const char *k
}
else if (!strcmp(keyname, "bottomcolor_rgb")) //packet loss
{
unsigned int col = cl.players[pnum].tbottomcolor;
unsigned int col = cl.players[pnum].dbottomcolor;
ret = buffer;
if (col < 16)
{
@ -5289,10 +5289,10 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s *
AngleVectorsIndex(le->angles, ps->modelindex, NULL, NULL, G_VECTOR(OFS_RETURN));
break;
case GE_PANTSCOLOR:
G_FLOAT(OFS_RETURN) = cl.players[entnum-1].tbottomcolor;
G_FLOAT(OFS_RETURN) = cl.players[entnum-1].dbottomcolor;
break;
case GE_SHIRTCOLOR:
G_FLOAT(OFS_RETURN) = cl.players[entnum-1].ttopcolor;
G_FLOAT(OFS_RETURN) = cl.players[entnum-1].dtopcolor;
break;
case GE_LIGHT:
G_FLOAT(OFS_RETURN) = 0;
@ -5437,13 +5437,13 @@ static void QCBUILTIN PF_getentity(pubprogfuncs_t *prinst, struct globalvars_s *
break;
case GE_PANTSCOLOR:
if (es->colormap <= cl.allocated_client_slots && !(es->dpflags & RENDER_COLORMAPPED))
G_FLOAT(OFS_RETURN) = cl.players[es->colormap].tbottomcolor;
G_FLOAT(OFS_RETURN) = cl.players[es->colormap].dbottomcolor;
else
G_FLOAT(OFS_RETURN) = es->colormap & 15;
break;
case GE_SHIRTCOLOR:
if (es->colormap <= cl.allocated_client_slots && !(es->dpflags & RENDER_COLORMAPPED))
G_FLOAT(OFS_RETURN) = cl.players[es->colormap].ttopcolor;
G_FLOAT(OFS_RETURN) = cl.players[es->colormap].dtopcolor;
else
G_FLOAT(OFS_RETURN) = es->colormap>>4;
break;
@ -6137,6 +6137,7 @@ static struct {
{"skel_create", PF_skel_create, 263},//float(float modlindex) skel_create = #263; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_build", PF_skel_build, 264},//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone, optional float addition) skel_build = #264; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_build_ptr", PF_skel_build_ptr, 0},//float(float skel, int numblends, __variant *blends, int blendsize) skel_build_ptr = #0;
{"skel_get_numbones", PF_skel_get_numbones, 265},//float(float skel) skel_get_numbones = #265; // (FTE_CSQC_SKELETONOBJECTS)
{"skel_get_bonename", PF_skel_get_bonename, 266},//string(float skel, float bonenum) skel_get_bonename = #266; // (FTE_CSQC_SKELETONOBJECTS) (returns tempstring)
{"skel_get_boneparent", PF_skel_get_boneparent, 267},//float(float skel, float bonenum) skel_get_boneparent = #267; // (FTE_CSQC_SKELETONOBJECTS)

View File

@ -2812,7 +2812,6 @@ void MP_Draw(void)
qboolean MP_Keydown(int key, int unicode, unsigned int devid)
{
qboolean result = false;
extern qboolean keydown[K_MAX];
#ifdef TEXTEDITOR
if (editormodal)
@ -2822,9 +2821,10 @@ qboolean MP_Keydown(int key, int unicode, unsigned int devid)
if (setjmp(mp_abort))
return true;
#ifndef QUAKETC
#ifndef NOBUILTINMENUS
if (key == 'c')
{
extern qboolean keydown[K_MAX];
if (keydown[K_LCTRL] || keydown[K_RCTRL])
{
MP_Shutdown();

View File

@ -1946,6 +1946,167 @@ void QCBUILTIN PF_skel_build(pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1;
}
typedef struct
{
int sourcemodelindex;
int sourceskel;
int firstbone;
int lastbone;
float prescale; //0 destroys existing data, 1 retains it.
float scale[4];
int animation[4];
float animationtime[4];
//halflife models
float subblend[2];
float controllers[5];
} skelblend_t;
//float(float skel, int numblends, skelblend_t *blenddata, int structsize) skel_build_ptr
void QCBUILTIN PF_skel_build_ptr(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
world_t *w = prinst->parms->user;
int skelidx = G_FLOAT(OFS_PARM0);
int numblends = G_INT(OFS_PARM1);
int blends_qcptr = G_INT(OFS_PARM2);
int structsize = G_INT(OFS_PARM3);
skelblend_t *fte_restrict blends = (skelblend_t*)(prinst->stringtable+blends_qcptr);
int i, j;
framestate_t fstate;
skelobject_t *skelobj;
float relationsbuf[MAX_BONES*12];
float scale;
int numbones, firstbone, lastbone;
model_t *model;
qboolean noadd;
//default to failure
G_FLOAT(OFS_RETURN) = 0;
memset(&fstate, 0, sizeof(fstate));
skelobj = skel_get(w, skelidx);
if (!skelobj)
return; //couldn't get one, ran out of memory or something?
if (structsize < sizeof(skelblend_t))
return; //enforce a minimum size...
for(; numblends --> 0; blends = (skelblend_t*)((char*)blends + structsize))
{
noadd = blends->scale[0] == 0 && blends->scale[1] == 0 && blends->scale[2] == 0 && blends->scale[3] == 0;
if (blends->prescale == 1 && noadd)
continue; //does nothing to the model, skip it before wasting too much time.
if (blends->sourceskel)
{
skelobject_t *srcskel = skel_get(w, blends->sourceskel);
if (!srcskel)
continue;
model = srcskel->model;
if (!model)
continue; //invalid model, can't get a skeleton
fstate.bonecount = numbones = srcskel->numbones;
fstate.bonestate = srcskel->bonematrix;
fstate.skeltype = srcskel->type;
}
else
{
fstate.bonecount = 0;
fstate.bonestate = NULL;
fstate.skeltype = SKEL_RELATIVE;
if (blends->sourcemodelindex)
model = w->Get_CModel(w, blends->sourcemodelindex);
else
model = w->Get_CModel(w, skelobj->modelindex);
if (!model)
continue; //invalid model, can't get a skeleton
numbones = Mod_GetNumBones(model, false);
if (!numbones)
continue; //this isn't a skeletal model.
}
firstbone = blends->firstbone-1;
lastbone = blends->lastbone-1;
if (lastbone < 0)
lastbone = numbones;
if (lastbone > numbones)
lastbone = numbones;
if (firstbone < 0)
firstbone = 0;
if (lastbone < firstbone)
lastbone = firstbone;
fstate.g[FS_REG].endbone = 0x7fffffff;
for (i = 0; i < 4; i++)
{
fstate.g[FS_REG].frame[i] = blends->animation[i];
fstate.g[FS_REG].frametime[i] = blends->animationtime[i];
fstate.g[FS_REG].lerpweight[i] = blends->scale[i];
}
#ifdef HALFLIFEMODELS
fstate.g[FS_REG].subblendfrac = blends->subblend[0];
fstate.g[FS_REG].subblend2frac = blends->subblend[1];
fstate.bonecontrols[0] = blends->controllers[0];
fstate.bonecontrols[1] = blends->controllers[1];
fstate.bonecontrols[2] = blends->controllers[2];
fstate.bonecontrols[3] = blends->controllers[3];
fstate.bonecontrols[4] = blends->controllers[4];
#endif
if (skelobj->type != SKEL_RELATIVE)
{
if (firstbone > 0 || lastbone < skelobj->numbones || blends->prescale)
{
Con_Printf("skel_build on non-relative skeleton\n");
return;
}
skelobj->type = SKEL_RELATIVE; //entire model will get replaced, convert it.
}
if (noadd)
{
if (blends->prescale == 0)
memset(skelobj->bonematrix+firstbone*12, 0, sizeof(float)*12);
else
{ //just rescale the existing bones
scale = blends->prescale;
for (i = firstbone; i < lastbone; i++)
{
for (j = 0; j < 12; j++)
skelobj->bonematrix[i*12+j] *= scale;
}
}
}
else if (blends->prescale == 0) //new data only. directly replace the existing data
Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, skelobj->bonematrix);
else
{
if (blends->prescale != 1)
{ //rescale the existing bones
scale = blends->prescale;
for (i = firstbone; i < lastbone; i++)
{
for (j = 0; j < 12; j++)
skelobj->bonematrix[i*12+j] *= scale;
}
}
Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, relationsbuf);
for (i = firstbone; i < lastbone; i++)
{
for (j = 0; j < 12; j++)
skelobj->bonematrix[i*12+j] += relationsbuf[i*12+j];
}
}
}
G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1;
}
//float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS)
void QCBUILTIN PF_skel_get_numbones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{

View File

@ -202,6 +202,7 @@ extern "C" {
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#define max3(a,b,c) max(max(a,b),c)
//msvcrt lacks any and all c99 support.
#if defined(_WIN32)

View File

@ -355,7 +355,7 @@ void R2D_Init(void)
"{\n"
"map $whiteimage\n"
"blendfunc gl_dst_color gl_zero\n"
"rgbgen const $r_menutint\n"
"rgbgen srgb $r_menutint\n"
"}\n"
#else
"if gl_menutint_shader != 0\n"
@ -369,7 +369,7 @@ void R2D_Init(void)
"{\n"
"map $whiteimage\n"
"blendfunc gl_dst_color gl_zero\n"
"rgbgen const $r_menutint\n"
"rgbgen srgb $r_menutint\n"
"}\n"
"endif\n"
#endif
@ -1300,18 +1300,15 @@ void R2D_BrightenScreen (void)
if (v_contrast.value < 0.5)
v_contrast.value = 0.5;
if (r2d_canhwgamma)
if (r2d_canhwgamma || vid_hardwaregamma.ival == 4)
return;
TRACE(("R2D_BrightenScreen: brightening\n"));
if (v_gamma.value != 1 && shader_gammacb->prog)
if ((v_gamma.value != 1 || v_contrast.value > 3) && shader_gammacb->prog)
{
//this should really be done properly, with render-to-texture
R2D_ImageColours (v_gamma.value, v_contrast.value, v_brightness.value, 1);
if (qrenderer == QR_OPENGL)
R2D_Image(0, 0, vid.width, vid.height, 0, 1, 1, 0, shader_gammacb);
else
R2D_Image(0, 0, vid.width, vid.height, 0, 0, 1, 1, shader_gammacb);
R2D_Image(0, 0, vid.width, vid.height, 0, 0, 1, 1, shader_gammacb);
}
else
{

File diff suppressed because it is too large Load Diff

View File

@ -167,10 +167,12 @@ typedef struct
int nummappings;
int maxmappings;
qbyte geomset[MAX_GEOMSETS]; //allows selecting a single set of geometry from alternatives. this might be a can of worms.
#ifdef QWSKINS
char qwskinname[MAX_QPATH];
struct qwskin_s *qwskin;
unsigned int q1upper; //Q1UNSPECIFIED
unsigned int q1lower; //Q1UNSPECIFIED
#endif
struct
{
char surface[MAX_QPATH];
@ -414,7 +416,7 @@ enum imageflags
IF_NOGAMMA = 1<<9,
IF_3DMAP = 1<<10, /*waning - don't test directly*/
IF_CUBEMAP = 1<<11, /*waning - don't test directly*/
IF_TEXTYPE = (1<<10) | (1<<11), /*0=2d, 1=3d, 2=cubeface, 3=?*/
IF_TEXTYPE = (1<<10) | (1<<11), /*0=2d, 1=3d, 2=cubeface, 3=2d array texture*/
IF_TEXTYPESHIFT = 10, /*0=2d, 1=3d, 2-7=cubeface*/
IF_MIPCAP = 1<<12,
IF_PREMULTIPLYALPHA = 1<<13, //rgb *= alpha
@ -449,7 +451,8 @@ void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, in
void Image_Purge(void); //purge any textures which are not needed any more (releases memory, but doesn't give null pointers).
void Image_Init(void);
void Image_Shutdown(void);
void Image_BlockSizeForEncoding(unsigned int encoding, unsigned int *blockbytes, unsigned int *blockwidth, unsigned int *blockheight);
void Image_BlockSizeForEncoding(uploadfmt_t encoding, unsigned int *blockbytes, unsigned int *blockwidth, unsigned int *blockheight);
const char *Image_FormatName(uploadfmt_t encoding);
image_t *Image_LoadTexture (const char *identifier, int width, int height, uploadfmt_t fmt, void *data, unsigned int flags);
@ -645,7 +648,9 @@ extern cvar_t r_lightstylesmooth_limit;
extern cvar_t r_lightstylespeed;
extern cvar_t r_lightstylescale;
extern cvar_t r_lightmap_scale;
#ifdef QWSKINS
extern cvar_t gl_nocolors;
#endif
extern cvar_t gl_load24bit;
extern cvar_t gl_finish;

View File

@ -38,7 +38,9 @@ qboolean vid_isfullscreen;
#define VKRENDEREROPTIONS "Vulkan-Specific Renderer Options"
unsigned int d_8to24rgbtable[256];
unsigned int d_8to24srgbtable[256];
unsigned int d_8to24bgrtable[256];
unsigned int d_quaketo24srgbtable[256];
extern int gl_anisotropy_factor;
@ -76,8 +78,8 @@ cvar_t vid_vsync = CVARAF ("vid_vsync", "0",
"vid_wait", CVAR_ARCHIVE);
#endif
cvar_t _windowed_mouse = CVARF ("_windowed_mouse","1",
CVAR_ARCHIVE);
cvar_t _windowed_mouse = CVARF ("in_windowed_mouse","1",
CVAR_ARCHIVE); //renamed this, because of freecs users complaining that it doesn't work. I don't personally see why you'd want it set to 0, but that's winquake's default so boo hiss to that.
cvar_t con_ocranaleds = CVAR ("con_ocranaleds", "2");
@ -86,7 +88,9 @@ cvar_t cl_cursorscale = CVAR ("cl_cursor_scale", "1.0");
cvar_t cl_cursorbiasx = CVAR ("cl_cursor_bias_x", "0.0");
cvar_t cl_cursorbiasy = CVAR ("cl_cursor_bias_y", "0.0");
#ifdef QWSKINS
cvar_t gl_nocolors = CVARF ("gl_nocolors", "0", CVAR_ARCHIVE);
#endif
cvar_t gl_part_flame = CVARFD ("gl_part_flame", "1", CVAR_ARCHIVE, "Enable particle emitting from models. Mainly used for torch and flame effects.");
//opengl library, blank means try default.
@ -158,6 +162,7 @@ cvar_t r_lightstylesmooth_limit = CVAR ("r_lightstylesmooth_limit", "2");
cvar_t r_lightstylespeed = CVAR ("r_lightstylespeed", "10");
cvar_t r_lightstylescale = CVAR ("r_lightstylescale", "1");
cvar_t r_lightmap_scale = CVARFD ("r_shadow_realtime_nonworld_lightmaps", "1", 0, "Scaler for lightmaps used when not using realtime world lighting. Probably broken.");
cvar_t r_hdr_framebuffer = CVARFD("r_hdr_framebuffer", "0", CVAR_ARCHIVE, "If enabled, the map will be rendered into a high-precision image framebuffer. This avoids issues with shaders that contribute more than 1 in any single pass (like overbrights).");
cvar_t r_hdr_irisadaptation = CVARF ("r_hdr_irisadaptation", "0", CVAR_ARCHIVE);
cvar_t r_hdr_irisadaptation_multiplier = CVAR ("r_hdr_irisadaptation_multiplier", "2");
cvar_t r_hdr_irisadaptation_minvalue = CVAR ("r_hdr_irisadaptation_minvalue", "0.5");
@ -207,8 +212,9 @@ cvar_t r_waterwarp = CVARFD ("r_waterwarp", "1",
cvar_t r_replacemodels = CVARFD ("r_replacemodels", IFMINIMAL("","md3 md2"),
CVAR_ARCHIVE, "A list of filename extensions to attempt to use instead of mdl.");
cvar_t gl_lightmap_nearest = CVARFD ("gl_lightmap_nearest", "0", CVAR_ARCHIVE, "Use nearest sampling for lightmaps. This will give a more blocky look. Meaningless when gl_lightmap_average is enabled.");
cvar_t gl_lightmap_average = CVARFD ("gl_lightmap_average", "0", CVAR_ARCHIVE, "Determine lightmap values based upon the center of the polygon. This will give a more buggy look, quite probably.");
cvar_t r_lightmap_nearest = CVARFD ("gl_lightmap_nearest", "0", CVAR_ARCHIVE, "Use nearest sampling for lightmaps. This will give a more blocky look. Meaningless when gl_lightmap_average is enabled.");
cvar_t r_lightmap_average = CVARFD ("gl_lightmap_average", "0", CVAR_ARCHIVE, "Determine lightmap values based upon the center of the polygon. This will give a more buggy look, quite probably.");
cvar_t r_lightmap_format = CVARFD ("r_lightmap_format", "", CVAR_ARCHIVE|CVAR_RENDERERCALLBACK, "Overrides the default texture format used for lightmaps. rgb9e5 is a good choice for HDR.");
//otherwise it would defeat the point.
cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1",
@ -440,11 +446,12 @@ cvar_t r_vertexdlights = CVARD ("r_vertexdlights", "0", "Determine model li
cvar_t vid_preservegamma = CVARD ("vid_preservegamma", "0", "Restore initial hardware gamma ramps when quitting.");
cvar_t vid_hardwaregamma = CVARFD ("vid_hardwaregamma", "1",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Use hardware gamma ramps. 0=ugly texture-based gamma, 1=glsl(windowed) or hardware(fullscreen), 2=always glsl, 3=always hardware gamma (disabled if hardware doesn't support).");
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Use hardware gamma ramps. 0=ugly texture-based gamma, 1=glsl(windowed) or hardware(fullscreen), 2=always glsl, 3=always hardware gamma (disabled if hardware doesn't support), 4=scene-only gamma.");
cvar_t vid_desktopgamma = CVARFD ("vid_desktopgamma", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH, "Apply gamma ramps upon the desktop rather than the window.");
cvar_t r_fog_exp2 = CVARD ("r_fog_exp2", "1", "Expresses how fog fades with distance. 0 (matching DarkPlaces's default) is typically more realistic, while 1 (matching FitzQuake and others) is more common.");
cvar_t r_fog_permutation = CVARFD ("r_fog_permutation", "1", CVAR_SHADERSYSTEM, "Renders fog using a material permutation. 0 plays nicer with q3 shaders, but 1 is otherwise a better choice.");
extern cvar_t gl_dither;
cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
@ -487,7 +494,9 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_affinemodels, GLRENDEREROPTIONS);
Cvar_Register (&gl_nohwblend, GLRENDEREROPTIONS);
#ifdef QWSKINS
Cvar_Register (&gl_nocolors, GLRENDEREROPTIONS);
#endif
Cvar_Register (&gl_finish, GLRENDEREROPTIONS);
Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS);
Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS);
@ -524,6 +533,7 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_overbright_all, GRAPHICALNICETIES);
Cvar_Register (&gl_dither, GRAPHICALNICETIES);
Cvar_Register (&r_fog_exp2, GLRENDEREROPTIONS);
Cvar_Register (&r_fog_permutation, GLRENDEREROPTIONS);
Cvar_Register (&r_tessellation, GRAPHICALNICETIES);
Cvar_Register (&gl_ati_truform_type, GRAPHICALNICETIES);
@ -548,8 +558,9 @@ void GLRenderer_Init(void)
Cvar_Register (&gl_menutint_shader, GLRENDEREROPTIONS);
Cvar_Register (&gl_lightmap_nearest, GLRENDEREROPTIONS);
Cvar_Register (&gl_lightmap_average, GLRENDEREROPTIONS);
Cvar_Register (&r_lightmap_nearest, GLRENDEREROPTIONS);
Cvar_Register (&r_lightmap_average, GLRENDEREROPTIONS);
Cvar_Register (&r_lightmap_format, GLRENDEREROPTIONS);
}
#endif
@ -824,6 +835,7 @@ void Renderer_Init(void)
Cvar_Register(&r_lightstylescale, GRAPHICALNICETIES);
Cvar_Register(&r_lightmap_scale, GRAPHICALNICETIES);
Cvar_Register(&r_hdr_framebuffer, GRAPHICALNICETIES);
Cvar_Register(&r_hdr_irisadaptation, GRAPHICALNICETIES);
Cvar_Register(&r_hdr_irisadaptation_multiplier, GRAPHICALNICETIES);
Cvar_Register(&r_hdr_irisadaptation_minvalue, GRAPHICALNICETIES);
@ -1253,7 +1265,9 @@ void R_ShutdownRenderer(qboolean devicetoo)
CL_AllowIndependantSendCmd(false); //FIXME: figure out exactly which parts are going to affect the model loading.
#ifdef QWSKINS
Skin_FlushAll();
#endif
P_Shutdown();
Mod_Shutdown(false);
@ -1301,6 +1315,7 @@ void R_ShutdownRenderer(qboolean devicetoo)
void R_GenPaletteLookup(void)
{
extern qbyte default_quakepal[];
int r,g,b,i;
unsigned char *pal = host_basepal;
for (i=0 ; i<256 ; i++)
@ -1311,12 +1326,16 @@ void R_GenPaletteLookup(void)
pal += 3;
d_8to24rgbtable[i] = (255<<24) + (r<<0) + (g<<8) + (b<<16);
d_8to24srgbtable[i] = (255<<24) + (SRGBb(r)<<0) + (SRGBb(g)<<8) + (SRGBb(b)<<16);
d_8to24bgrtable[i] = (255<<24) + (b<<0) + (g<<8) + (r<<16);
}
d_8to24rgbtable[255] &= 0xffffff; // 255 is transparent
d_8to24srgbtable[255] &= 0xffffff; // 255 is transparent
d_8to24bgrtable[255] &= 0xffffff; // 255 is transparent
}
for (i=0 ; i<256 ; i++)
d_quaketo24srgbtable[i] = (255<<24) | (SRGBb(default_quakepal[(i)*3+0])<<0) | (SRGBb(default_quakepal[(i)*3+1])<<8) | (SRGBb(default_quakepal[(i)*3+2])<<16);
}
qboolean R_ApplyRenderer (rendererstate_t *newr)
{
double time;
@ -1384,7 +1403,7 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
#endif
if (newr)
if (!r_forceheadless || newr->renderer->rtype != QR_HEADLESS)
Con_TPrintf("Setting mode %i*%i*%i*%i %s\n", newr->width, newr->height, newr->bpp, newr->rate, newr->renderer->description);
Con_TPrintf("Setting mode %i*%i %ibpp %ihz %s%s\n", newr->width, newr->height, newr->bpp, newr->rate, newr->srgb?"SRGB ":"", newr->renderer->description);
vid.fullbright=0;
@ -1439,12 +1458,12 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr)
vid.fullbright = 0; //transparent colour doesn't count.
q2colormap:
R_GenPaletteLookup();
TRACE(("dbg: R_ApplyRenderer: Palette loaded\n"));
if (newr)
{
vid.flags = 0;
vid.gammarampsize = 256; //make a guess.
if (!VID_Init(newr, host_basepal))
{
@ -1453,6 +1472,9 @@ TRACE(("dbg: R_ApplyRenderer: Palette loaded\n"));
}
TRACE(("dbg: R_ApplyRenderer: vid applied\n"));
//update palettes now that we know whether srgb is to be used etc
R_GenPaletteLookup();
r_softwarebanding = false;
r_deluxmapping = false;
r_lightprepass = false;
@ -2025,7 +2047,7 @@ void R_SetRenderer_f (void)
}
if (newr.renderer->rtype != QR_HEADLESS && !strstr(param, "headless")) //don't save headless in the vid_renderer cvar via the setrenderer command. 'setrenderer headless;vid_restart' can then do what is most sane.
Cvar_Set(&vid_renderer, param);
Cvar_ForceSet(&vid_renderer, param);
if (!r_blockvidrestart)
R_RestartRenderer(&newr);

View File

@ -2224,8 +2224,10 @@ void Sbar_DrawScoreboard (playerview_t *pv)
if (Key_Dest_Has(~kdm_game))
return;
#ifdef CSQC_DAT
if (CSQC_DrawScores(pv))
return;
#endif
#ifndef CLIENTONLY
/*no scoreboard in single player (if you want bots, set deathmatch)*/
@ -2776,8 +2778,10 @@ void Sbar_Draw (playerview_t *pv)
qboolean minidmoverlay;
extern cvar_t scr_centersbar;
#ifdef CSQC_DAT
if (CSQC_DrawHud(pv))
return;
#endif
headsup = !(cl_sbar.value || (scr_viewsize.value<100));
if ((sb_updates >= vid.numpages) && !headsup)

View File

@ -85,42 +85,144 @@ enum fs_relative;
typedef enum uploadfmt
{
TF_INVALID,
TF_RGBA32, /*rgba byte order*/
TF_BGRA32, /*bgra byte order*/
TF_RGBX32, /*rgb byte order, with extra wasted byte after blue*/
TF_BGRX32, /*rgb byte order, with extra wasted byte after blue*/
TF_RGB24, /*rgb byte order, no alpha channel nor pad, and regular top down*/
TF_BGR24, /*bgr byte order, no alpha channel nor pad, and regular top down*/
TF_BGR24_FLIP, /*bgr byte order, no alpha channel nor pad, and bottom up*/
TF_LUM8, /*8bit greyscale image*/
TF_MIP4_LUM8, /*8bit 4-mip greyscale image*/
TF_MIP4_SOLID8, /*8bit 4-mip image in default palette*/
TF_MIP4_8PAL24, /*8bit 4-mip image with included palette*/
TF_MIP4_8PAL24_T255,/*8bit 4-mip image with included palette where index 255 is alpha 0*/
TF_SOLID8, /*8bit quake-palette image*/
TF_TRANS8, /*8bit quake-palette image, index 255=transparent*/
TF_TRANS8_FULLBRIGHT, /*fullbright 8 - fullbright texels have alpha 255, everything else 0*/
TF_HEIGHT8, /*image data is greyscale, convert to a normalmap and load that, uploaded alpha contains the original heights*/
TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap*/
TF_H2_T7G1, /*8bit data, odd indexes give greyscale transparence*/
TF_H2_TRANS8_0, /*8bit data, 0 is transparent, not 255*/
TF_H2_T4A4, /*8bit data, weird packing*/
PTI_INVALID,
/*this block requires a palette*/
TF_PALETTES,
TF_8PAL24,
TF_8PAL32,
//these formats are specified as direct byte access (listed in byte order, aka big-endian 0xrrggbbaa order)
PTI_RGBA8, //rgba byte ordering
PTI_RGBX8, //rgb pad byte ordering
PTI_BGRA8, //alpha channel
PTI_BGRX8, //no alpha channel
PTI_RGBA8_SRGB, //rgba byte ordering
PTI_RGBX8_SRGB, //rgb pad byte ordering
PTI_BGRA8_SRGB, //alpha channel
PTI_BGRX8_SRGB, //no alpha channel
PTI_RGB8, //24bit packed format. generally not supported
PTI_BGR8, //24bit packed format. generally not supported
PTI_L8, //8bit format (legacy more than anything else). luminance gets flooded to all RGB channels. might be supported using swizzles.
PTI_L8A8, //16bit format (legacy more than anything else). L=luminance
//small formats.
PTI_R8, //used for paletted data
PTI_RG8, //might be useful for normalmaps
PTI_R8_SNORM,
PTI_RG8_SNORM, //might be useful for normalmaps
//floating point formats
PTI_RGBA16F,
PTI_RGBA32F,
//packed/misaligned formats: these are specified in native endian order (high bits listed first because that's how things are represented in hex), so may need byte swapping...
PTI_A2BGR10, //mostly for rendertargets, might also be useful for overbight lightmaps.
PTI_E5BGR9, //mostly for fancy lightmaps
PTI_RGB565, //16bit alphaless format.
PTI_RGBA4444, //16bit format (gl)
PTI_ARGB4444, //16bit format (d3d)
PTI_RGBA5551, //16bit alpha format (gl).
PTI_ARGB1555, //16bit alpha format (d3d).
//(desktop/tegra) compressed formats
PTI_BC1_RGB,
PTI_BC1_RGB_SRGB,
PTI_BC1_RGBA,
PTI_BC1_RGBA_SRGB,
PTI_BC2_RGBA,
PTI_BC2_RGBA_SRGB,
PTI_BC3_RGBA, //maybe add a bc3 normalmapswizzle type for d3d9?
PTI_BC3_RGBA_SRGB,
PTI_BC4_R8,
PTI_BC4_R8_SNORM,
PTI_BC5_RG8, //useful for normalmaps
PTI_BC5_RG8_SNORM, //useful for normalmaps
PTI_BC6_RGB_UFLOAT, //unsigned (half) floats!
PTI_BC6_RGB_SFLOAT, //signed (half) floats!
PTI_BC7_RGBA, //multimode compression, using as many bits as bc2/bc3
PTI_BC7_RGBA_SRGB,
//(mobile/intel) compressed formats
PTI_ETC1_RGB8, //limited form
PTI_ETC2_RGB8, //extended form
PTI_ETC2_RGB8A1,
PTI_ETC2_RGB8A8,
PTI_ETC2_RGB8_SRGB,
PTI_ETC2_RGB8A1_SRGB,
PTI_ETC2_RGB8A8_SRGB,
PTI_EAC_R11, //no idea what this might be used for, whatever
PTI_EAC_R11_SNORM, //no idea what this might be used for, whatever
PTI_EAC_RG11, //useful for normalmaps (calculate blue)
PTI_EAC_RG11_SNORM, //useful for normalmaps (calculate blue)
//astc... zomg
PTI_ASTC_4X4,
PTI_ASTC_4X4_SRGB,
PTI_ASTC_5X4,
PTI_ASTC_5X4_SRGB,
PTI_ASTC_5X5,
PTI_ASTC_5X5_SRGB,
PTI_ASTC_6X5,
PTI_ASTC_6X5_SRGB,
PTI_ASTC_6X6,
PTI_ASTC_6X6_SRGB,
PTI_ASTC_8X5,
PTI_ASTC_8X5_SRGB,
PTI_ASTC_8X6,
PTI_ASTC_8X6_SRGB,
PTI_ASTC_10X5,
PTI_ASTC_10X5_SRGB,
PTI_ASTC_10X6,
PTI_ASTC_10X6_SRGB,
PTI_ASTC_8X8,
PTI_ASTC_8X8_SRGB,
PTI_ASTC_10X8,
PTI_ASTC_10X8_SRGB,
PTI_ASTC_10X10,
PTI_ASTC_10X10_SRGB,
PTI_ASTC_12X10,
PTI_ASTC_12X10_SRGB,
PTI_ASTC_12X12,
PTI_ASTC_12X12_SRGB,
/*for render targets*/
TF_DEPTH16,
TF_DEPTH24,
TF_DEPTH32,
TF_RGBA16F,
TF_RGBA32F,
//depth formats
PTI_DEPTH16,
PTI_DEPTH24,
PTI_DEPTH32,
PTI_DEPTH24_8,
/*for weird systems where the gl driver needs to do the decode (read: webgl)*/
TF_SYSTEMDECODE
TF_BGR24_FLIP, /*bgr byte order, no alpha channel nor pad, and bottom up*/
TF_MIP4_R8, /*8bit 4-mip greyscale image*/
TF_MIP4_SOLID8, /*8bit 4-mip image in default palette*/
TF_MIP4_8PAL24, /*8bit 4-mip image with included palette*/
TF_MIP4_8PAL24_T255,/*8bit 4-mip image with included palette where index 255 is alpha 0*/
TF_SOLID8, /*8bit quake-palette image*/
TF_TRANS8, /*8bit quake-palette image, index 255=transparent*/
TF_TRANS8_FULLBRIGHT, /*fullbright 8 - fullbright texels have alpha 255, everything else 0*/
TF_HEIGHT8, /*image data is greyscale, convert to a normalmap and load that, uploaded alpha contains the original heights*/
TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap*/
TF_H2_T7G1, /*8bit data, odd indexes give greyscale transparence*/
TF_H2_TRANS8_0, /*8bit data, 0 is transparent, not 255*/
TF_H2_T4A4, /*8bit data, weird packing*/
/*this block requires an explicit (separate) palette*/
TF_8PAL24,
TF_8PAL32,
#ifdef FTE_TARGET_WEB
//weird specialcase mess to take advantage of webgl so we don't need redundant bloat where we're already strugging with potential heap limits
PTI_WHOLEFILE,
#endif
PTI_MAX,
TF_INVALID = PTI_INVALID,
TF_DEPTH16 = PTI_DEPTH16,
TF_DEPTH24 = PTI_DEPTH24,
TF_DEPTH32 = PTI_DEPTH32,
TF_RGBA16F = PTI_RGBA16F,
TF_RGBA32F = PTI_RGBA32F,
TF_RGBA32 = PTI_RGBA8, /*rgba byte order*/
TF_BGRA32 = PTI_BGRA8, /*bgra byte order*/
TF_RGBX32 = PTI_RGBX8, /*rgb byte order, with extra wasted byte after blue*/
TF_BGRX32 = PTI_BGRX8, /*rgb byte order, with extra wasted byte after blue*/
TF_RGB24 = PTI_RGB8, /*rgb byte order, no alpha channel nor pad, and regular top down*/
TF_BGR24 = PTI_BGR8, /*bgr byte order, no alpha channel nor pad, and regular top down*/
TF_LUM8 = PTI_L8,
TF_R8 = PTI_R8
//these are emulated formats. this 'case' value allows drivers to easily ignore them
#define PTI_EMULATED TF_INVALID:case TF_BGR24_FLIP:case TF_MIP4_R8:case TF_MIP4_SOLID8:case TF_MIP4_8PAL24:case TF_MIP4_8PAL24_T255:case TF_SOLID8:case TF_TRANS8:case TF_TRANS8_FULLBRIGHT:case TF_HEIGHT8:case TF_HEIGHT8PAL:case TF_H2_T7G1:case TF_H2_TRANS8_0:case TF_H2_T4A4:case TF_8PAL24:case TF_8PAL32
} uploadfmt_t;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void **buffer, int numbuffers, int bytestride, int width, int height, enum uploadfmt fmt);
@ -185,6 +287,33 @@ void PR_ReleaseFonts(unsigned int purgeowner); //for menu/csqc
void PR_ReloadFonts(qboolean reload);
/*end fonts*/
//normally we're not srgb aware, which means that while the intensity may APPEAR linear, it actually isn't.
fte_inline float M_SRGBToLinear(float x, float mag)
{
x /= mag;
if (x <= 0.04045f)
x = x * (1.0f / 12.92f);
else
x = pow(( x + 0.055f) * (1.0f / 1.055f), 2.4f);
x *= mag;
return x;
}
fte_inline float M_LinearToSRGB(float x, float mag)
{
x /= mag;
if (x <= 0.00031308)
x = 12.92 * x;
else
x = 1.055*pow(x,(float)(1.0 / 2.4) ) - 0.055;
x *= mag;
return x;
}
//macros that are used to explicitly state that a value is srgb, and convert to linear as needed.
#define SRGBf(x) ((vid.flags&VID_SRGBAWARE)?M_SRGBToLinear(x,1):x)
#define SRGBb(x) ((vid.flags&VID_SRGBAWARE)?(unsigned char)M_SRGBToLinear(x,255):x)
#define SRGB3(x,y,z) SRGBf(x),SRGBf(y),SRGBf(z)
#define SRGBA(x,y,z,w) SRGBf(x),SRGBf(y),SRGBf(z),w
void R_NetgraphInit(void);
void R_NetGraph (void);
void R_FrameTimeGraph (int frametime);

View File

@ -19,8 +19,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "quakedef.h"
#include "glquake.h"
#ifdef QWSKINS
cvar_t baseskin = CVAR("baseskin", "");
cvar_t noskins = CVAR("noskins", "0");
@ -618,5 +618,27 @@ void Skin_FlushSkin(char *name)
}
}
}
#else
void Skin_FlushPlayers(void)
{
}
//required for the qw protocol (server stuffcmds 'skins' to get the client to send 'begin'. *sigh*
void Skin_Skins_f (void)
{
if (cls.state == ca_disconnected)
{
Con_Printf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
return;
}
R_GAliasFlushSkinCache(false);
// if (Cmd_FromServer())
{
SCR_SetLoadingStage(LS_NONE);
CL_SendClientCommand(true, "begin %i", cl.servercount);
}
}
#endif

View File

@ -84,7 +84,7 @@ JNIEXPORT jstring JNICALL Java_com_fteqw_FTEDroidEngine_getpreferedorientation(J
}
/*the java passes in all input directly via a 'UI' thread. we don't need to poll it at all*/
void INS_Move(float *movements, int pnum)
void INS_Move(void)
{
}
void INS_Commands(void)

View File

@ -64,7 +64,7 @@ void Sys_Init (void){} //safe, stub is fine. used to register system-speci
void Sys_Shutdown(void){} //safe
qboolean Sys_RandomBytes(qbyte *string, int len){return false;}
qboolean Sys_GetDesktopParameters(int *width, int *height, int *bpp, int *refreshrate){return false;}
void INS_Move(float *movements, int pnum){} //safe
void INS_Move(void){} //safe
void INS_Commands(void){} //safe
void INS_Init(void){} //safe. should be xinput2 I guess. nothing else is actually supported. touchscreens don't really count.
void INS_ReInit(void){} //safe

View File

@ -148,18 +148,18 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (QDECL *func)(
}
/*consoles don't tend to need system clipboards, so this is fully internal to our engine*/
#define SYS_CLIPBOARD_SIZE 256
static char clipboard_buffer[SYS_CLIPBOARD_SIZE] = {0};
char *Sys_GetClipboard(void)
{
return clipboard_buffer;
}
void Sys_CloseClipboard(char *bf)
{
}
void Sys_SaveClipboard(char *text)
{
Q_strncpyz(clipboard_buffer, text, SYS_CLIPBOARD_SIZE);
#define SYS_CLIPBOARD_SIZE 256
static char clipboard_buffer[SYS_CLIPBOARD_SIZE] = {0};
char *Sys_GetClipboard(void)
{
return clipboard_buffer;
}
void Sys_CloseClipboard(char *bf)
{
}
void Sys_SaveClipboard(char *text)
{
Q_strncpyz(clipboard_buffer, text, SYS_CLIPBOARD_SIZE);
}
/*dynamic library stubs*/
@ -225,7 +225,7 @@ void INS_Shutdown (void)
void INS_ReInit (void)
{
}
void INS_Move(float *movements, int pnum)
void INS_Move(void)
{
//accululates system-specific inputs on a per-seat basis.
}

View File

@ -1,384 +1,4 @@
/*
Teamplay.c
Contains various console stuff for improving the performance of a team...
Cheats I hear you say?...
Personally, I'd rather call it a hack job.
Most of it is dependant upon specific mod types - TF.
As far as split screen goes, this is all relative to player 0. We don't provide more than one say command.
replaced by zqtp.c (read: teamplay.c ported from zquake instead, with later fuhquake+ezquake additions, the ravages of time can be merciless)
*/
#include "quakedef.h"
#if 0 //ndef ZQUAKETEAMPLAY
cvar_t tp_name_armortype_ga = {"tp_name_armortype_ga", "g"};
cvar_t tp_name_armortype_ya = {"tp_name_armortype_ya", "y"};
cvar_t tp_name_armortype_ra = {"tp_name_armortype_ra", "r"};
cvar_t tp_name_none = {"tp_name_none", ""};
#define translatetext(i) #i
///////////////////////////////////////////////////////////////////
//Macros.
char *TP_ClassForTFSkin(void)
{
char *skin;
skin = Info_ValueForKey(cls.userinfo, "skin");
if (!*skin)
return "Classless";
if (skin[0] != 't' && skin[1] != 'f' && skin[2] != '_')
return skin;
if (!strcmp(skin, "tf_sold"))
return translatetext(TLTP_CLASS_SOLIDER);
if (!strcmp(skin, "tf_demo"))
return translatetext(TLTP_CLASS_DEMOGUY);
if (!strcmp(skin, "tf_eng"))
return translatetext(TLTP_CLASS_ENGINEER);
if (!strcmp(skin, "tf_snipe"))
return translatetext(TLTP_CLASS_SNIPER);
if (!strcmp(skin, "tf_hwguy"))
return translatetext(TLTP_CLASS_HWGUY);
if (!strcmp(skin, "tf_medic"))
return translatetext(TLTP_CLASS_MEDIC);
if (!strcmp(skin, "tf_pyro"))
return translatetext(TLTP_CLASS_PYRO);
if (!strcmp(skin, "tf_scout"))
return translatetext(TLTP_CLASS_SCOUT);
if (!strcmp(skin, "tf_spy"))
return translatetext(TLTP_CLASS_SPY);
return skin;
}
void *TP_ArmourType(void)
{
if (cl.stats[0][STAT_ITEMS] & IT_ARMOR1)
return tp_name_armortype_ga.string;
else if (cl.stats[0][STAT_ITEMS] & IT_ARMOR2)
return tp_name_armortype_ya.string;
else if (cl.stats[0][STAT_ITEMS] & IT_ARMOR3)
return tp_name_armortype_ra.string;
else
return tp_name_none.string;
}
///////////////////////////////////////////////////////////////////
//Locs
typedef struct location_s {
vec3_t pos;
struct location_s *next;
char name[0];
} location_t;
location_t *location;
char LocationLevel[64];
void CL_LoadLocs(void)
{
location_t *newloc;
vec3_t pos;
char *file;
char *end;
char name[MAX_QPATH];
// if (!strcmp(LocationLevel, cl.model_name[1]))
// return;
while(location)
{
newloc = location->next;
Z_Free(location);
location = newloc;
}
strcpy(LocationLevel, cl.model_name[1]);
COM_StripExtension(COM_SkipPath(LocationLevel), name);
file = COM_LoadTempFile(va("locs/%s.loc", name));
if (!file)
return;
for(;;)
{
file = COM_Parse(file);
pos[0] = atof(com_token)/8;
file = COM_Parse(file);
pos[1] = atof(com_token)/8;
file = COM_Parse(file);
pos[2] = atof(com_token)/8;
while(*file && *file <= '\0')
file++;
if (!file)
return;
end = strchr(file, '\n');
if (!end)
{
end = file + strlen(file);
}
newloc = Z_Malloc(sizeof(location_t) + end-file+1);
newloc->next = location;
location = newloc;
Q_strncpyz(newloc->name, file, end-file);
VectorCopy(pos, newloc->pos);
if (!*end)
return;
file = end+1;
}
}
char *CL_LocationName(float *pos)
{
location_t *loc;
vec3_t dir;
char *best;
float dist, bestdist;
CL_LoadLocs();
if (!location)
return "somewhere";
//get the initial one
best = location->name;
VectorSubtract(location->pos, pos, dir);
bestdist = VectorNormalize(dir);
//check for a closer one.
for (loc = location->next; loc; loc=loc->next)
{
VectorSubtract(loc->pos, pos, dir);
dist = VectorNormalize(dir);
if (dist < bestdist)
{
best = loc->name;
bestdist = dist;
}
}
return best;
}
//////////////////////////////////////////////////////////
//Commands
#define INVIS_CHAR1 12
#define INVIS_CHAR2 138
#define INVIS_CHAR3 160
/*
===============
CL_Say
Handles both say and say_team
===============
*/
void CL_Say_f (void)
{
char output[8192];
char string[256];
char *msg;
int c;
output[0] = '\0';
if (cls.state == ca_disconnected || cls.demoplayback)
{
#ifndef CLIENT_ONLY
if (sv.state)
SV_ConSay_f();
else
#endif
Con_TPrintf ("Can't \"%s\", not connected\n", Cmd_Argv(0));
return;
}
if (!strcmp("sayone", Cmd_Argv(0)))
{
if (strcmp(Info_ValueForKey(cl.serverinfo, "*distrib"), DISTRIBUTION) || atoi(Info_ValueForKey(cl.serverinfo, "*ver")) < PRE_SAYONE)
{
Con_Printf ("%s is only available with server support\n", Cmd_Argv(0));
return;
}
}
Q_strncpyz(output, Cmd_Argv(0), sizeof(string));
for (msg = output; *msg; msg++)
if (*msg >= 'A' && *msg <= 'Z')
*msg = *msg - 'A' + 'a';
msg = Cmd_Args();
if (Cmd_Argc() > 1)
{
Q_strncatz(output, " \"", sizeof(output));
while(*msg)
{
c = *msg;
if (c == '%')
{
char *message = NULL;
msg++;
if (message == NULL)
switch(*msg)
{
case 'n':
Q_strncatz(output, name.string, sizeof(output));
msg++;
continue;
case 'h':
Q_strncatz(output, va("%i", cl.stats[0][STAT_HEALTH]), sizeof(output));
msg++;
continue;
case 'a':
Q_strncatz(output, va("%i", cl.stats[0][STAT_ARMOR]), sizeof(output));
msg++;
continue;
case 'A':
Q_strncatz(output, TP_ArmourType(), sizeof(output));
msg++;
continue;
case 'l':
Q_strncatz(output, CL_LocationName(cl.simorg[0]), sizeof(output));
msg++;
continue;
case 'S':
Q_strncatz(output, TP_ClassForTFSkin(), sizeof(output));
msg++;
continue;
case '%':
c = '%';
break;
default:
c = '%';
msg--;
break;
}
}
else if (c == '$')
{
msg++;
switch(*msg)
{
case '\\': c = 0x0D; break;
case ':': c = 0x0A; break;
case '[': c = 0x10; break;
case ']': c = 0x11; break;
case 'G': c = 0x86; break;
case 'R': c = 0x87; break;
case 'Y': c = 0x88; break;
case 'B': c = 0x89; break;
case '(': c = 0x80; break;
case '=': c = 0x81; break;
case ')': c = 0x82; break;
case 'a': c = 0x83; break;
case '<': c = 0x1d; break;
case '-': c = 0x1e; break;
case '>': c = 0x1f; break;
case ',': c = 0x1c; break;
case '.': c = 0x9c; break;
case 'b': c = 0x8b; break;
case 'c':
case 'd': c = 0x8d; break;
case '$': c = '$'; break;
case '^': c = '^'; break;
case 'x':
c = INVIS_CHAR1;
break;
case 'y':
c = INVIS_CHAR2;
break;
case 'z':
c = INVIS_CHAR3;
break;
default:
msg--;
break;
}
}
Q_strncatz(output, va("%c", c), sizeof(output));
msg++;
}
Q_strncatz(output, "\"", sizeof(output));
}
CL_SendClientCommand("%s", output);
}
void TP_Init(void)
{
}
void TP_CheckPickupSound(char *s, vec3_t org)
{
}
#endif
qboolean TP_SoundTrigger(char *message) //if there is a trigger there, play it. Return true if we found one, stripping off the file (it's neater that way).
{
char *strip;
char *lineend = NULL;
char soundname[128];
int filter = 0;
for (strip = message+strlen(message)-1; *strip && strip >= message; strip--)
{
if (*strip == '#')
filter++;
if (*strip == ':')
break; //if someone says just one word, we can take any tidles in their name to be a voice command
if (*strip == '\n')
lineend = strip;
else if (*strip <= ' ')
{
if (filter == 0 || filter == 1) //allow one space in front of a filter.
{
filter++;
continue;
}
break;
}
else if (*strip == '~')
{
//looks like a trigger, whoopie!
if (lineend-strip > sizeof(soundname)-1)
{
Con_Printf("Sound trigger's file-name was too long\n");
return false;
}
Q_strncpyz(soundname, strip+1, lineend-strip);
memmove(strip, lineend, strlen(lineend)+1);
Cbuf_AddText(va("play %s\n", soundname), RESTRICT_LOCAL);
return true;
}
}
return false;
}

View File

@ -46,7 +46,7 @@ typedef struct {
int fullscreen; //0 = windowed. 1 = fullscreen (mode changes). 2 = borderless+maximized
qboolean stereo;
qboolean srgb;
int bpp;
int bpp; //16, 24(aka 32), 30, and 48 are meaningful
int rate;
int wait; //-1 = default, 0 = off, 1 = on, 2 = every other
int multisample; //for opengl antialiasing (which requires context stuff)
@ -72,6 +72,15 @@ typedef struct
int maxheight; //vid.pixelheight or so
} pxrect_t;
//srgb colourspace displays smoother visual gradients, but its more of an illusion than anything else.
//
#define VID_SRGBAWARE (1u<<0) //we need to convert input srgb values to actual linear values (requires vid_reload to change...)
#define VID_SRGB_FB_LINEAR (1u<<1) //framebuffer is linear (either the presentation engine is linear, or the blend unit is faking it)
#define VID_SRGB_FB_FAKED (1u<<2) //renderer is faking it with a linear texture
#define VID_SRGB_CAPABLE (1u<<3) //we can toggle VID_SRGB_FB_LINEARISED on or off.
#define VID_FP16 (1u<<4) //use 16bit currentrender etc to avoid banding
#define VID_SRGB_FB (VID_SRGB_FB_LINEAR|VID_SRGB_FB_FAKED)
typedef struct
{
qboolean activeapp;
@ -89,7 +98,7 @@ typedef struct
unsigned height; /*virtual 2d screen height*/
int numpages;
qboolean srgb; /*we're forcing linear fragment shaders, both inputs and outputs (and not using srgb as a gamma hack)*/
unsigned int flags; //VID_* flags
unsigned rotpixelwidth; /*width after rotation in pixels*/
unsigned rotpixelheight; /*pixel after rotation in pixels*/
@ -103,7 +112,9 @@ typedef struct
extern viddef_t vid; // global video state
extern unsigned int d_8to24rgbtable[256];
extern unsigned int d_8to24srgbtable[256];
extern unsigned int d_8to24bgrtable[256];
extern unsigned int d_quaketo24srgbtable[256];
#ifdef GLQUAKE
//called when gamma ramps need to be reapplied

View File

@ -1917,6 +1917,7 @@ char *TP_MapName (void)
return host_mapname.string;
}
#ifdef QWSKINS
/*
=============================================================================
TEAMCOLOR & ENEMYCOLOR
@ -2131,6 +2132,7 @@ static void TP_EnemyColor_f (void)
CL_NewTranslation(i);
}
}
#endif
//===================================================================
@ -3700,15 +3702,16 @@ void TP_Init (void)
Cmd_AddCommand ("loadloc", TP_LoadLocFile_f);
Cmd_AddCommand ("filter", TP_MsgFilter_f);
Cmd_AddCommand ("msg_trigger", TP_MsgTrigger_f);
#ifdef QWSKINS
Cmd_AddCommand ("teamcolor", TP_TeamColor_f);
Cmd_AddCommand ("enemycolor", TP_EnemyColor_f);
Cmd_AddCommand ("tp_took", TP_Took_f);
Cmd_AddCommand ("tp_pickup", TP_Pickup_f);
Cmd_AddCommand ("tp_point", TP_Point_f);
Cmd_AddCommand ("colourise", TP_Colourise_f); //uk
Cmd_AddCommand ("colorize", TP_Colourise_f); //us
//Cmd_AddCommand ("colorise", TP_Colourise_f); //piss off both.
#endif
Cmd_AddCommand ("tp_took", TP_Took_f);
Cmd_AddCommand ("tp_pickup", TP_Pickup_f);
Cmd_AddCommand ("tp_point", TP_Point_f);
TP_InitMacros();
}
@ -3888,5 +3891,44 @@ void CL_SayTeam_f (void)
CL_Say (true, NULL);
}
qboolean TP_SoundTrigger(char *message) //if there is a trigger there, play it. Return true if we found one, stripping off the file (it's neater that way).
{
char *strip;
char *lineend = NULL;
char soundname[128];
int filter = 0;
for (strip = message+strlen(message)-1; *strip && strip >= message; strip--)
{
if (*strip == '#')
filter++;
if (*strip == ':')
break; //if someone says just one word, we can take any tidles in their name to be a voice command
if (*strip == '\n')
lineend = strip;
else if (*strip <= ' ')
{
if (filter == 0 || filter == 1) //allow one space in front of a filter.
{
filter++;
continue;
}
break;
}
else if (*strip == '~')
{
//looks like a trigger, whoopie!
if (lineend-strip > sizeof(soundname)-1)
{
Con_Printf("Sound trigger's file-name was too long\n");
return false;
}
Q_strncpyz(soundname, strip+1, lineend-strip);
memmove(strip, lineend, strlen(lineend)+1);
Cbuf_AddText(va("play %s\n", soundname), RESTRICT_LOCAL);
return true;
}
}
return false;
}

View File

@ -81,6 +81,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define STRINGIFY2(s) #s
#define STRINGIFY(s) STRINGIFY2(s)
#define QWSKINS //disables qw .pcx skins, as well as enemy/team colour forcing.
#ifdef CONFIG_FILE_NAME
//yup, C89 allows this (doesn't like C's token concat though).
#include STRINGIFY(CONFIG_FILE_NAME)

View File

@ -3830,7 +3830,7 @@ void Cmd_WriteConfig_f(void)
return;
}
VFS_WRITE(f, "// FTE config file\n\n", 20);
VFS_PRINTF(f, "// %s config file\n\n", *fs_gamename.string?fs_gamename.string:FULLENGINENAME);
#ifndef SERVERONLY
Key_WriteBindings (f);
IN_WriteButtons(f, all);

View File

@ -1010,7 +1010,7 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion
int l = 0;
galiasanimation_t *g;
unsigned int b;
float totalweight = 0;
float totalweight = 0, dropweight = 0;
#ifndef SERVERONLY
extern cvar_t r_nolerp;
#endif
@ -1028,12 +1028,18 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion
if (inf->numanimations)
frame = 0;
else
{
dropweight += fs->lerpweight[b];
continue;//frame = (unsigned)frame%inf->groups;
}
}
g = &inf->ofsanimations[frame];
if (!g->numposes)
{
dropweight += fs->lerpweight[b];
continue; //err...
}
mlerp = time*g->rate;
frame1=mlerp;
@ -1053,7 +1059,10 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion
if (lerps->skeltype == SKEL_IDENTITY)
lerps->skeltype = g->skeltype;
else if (lerps->skeltype != g->skeltype)
{
dropweight += fs->lerpweight[b];
continue; //oops, can't cope with mixed blend types
}
if (frame1 == frame2)
mlerp = 0;
@ -1087,15 +1096,15 @@ static qboolean Alias_BuildSkelLerps(skellerps_t *lerps, struct framestateregion
mlerp = lerps->frac[b];
}
}
lerps->frac[0] = 1;
lerps->frac[0] = totalweight+dropweight;
lerps->pose[0] = lerps->pose[frame1];
l = 1;
}
else
#endif
if (l && totalweight != 1)
if (l && totalweight && dropweight)
{ //don't rescale if some animation got dropped.
totalweight = 1 / totalweight;
totalweight = (totalweight+dropweight) / totalweight;
for (b = 0; b < l; b++)
{
lerps->frac[b] *= totalweight;
@ -6948,7 +6957,7 @@ static void IQM_ImportArrayF(const qbyte *base, const struct iqmvertexarray *src
}
}
const void *IQM_FindExtension(const char *buffer, const char *extname, int index, size_t *extsize)
static const void *IQM_FindExtension(const char *buffer, size_t buffersize, const char *extname, int index, size_t *extsize)
{
struct iqmheader *h = (struct iqmheader *)buffer;
const char *strings = buffer + h->ofs_text;
@ -6956,6 +6965,8 @@ const void *IQM_FindExtension(const char *buffer, const char *extname, int index
int i;
for (i = 0, ext = (struct iqmextension*)(buffer + h->ofs_extensions); i < h->num_extensions; i++, ext = (struct iqmextension*)(buffer + ext->ofs_extensions))
{
if ((char*)ext > buffer+buffersize || ext->name > h->num_text || ext->ofs_data+ext->num_data>buffersize)
break;
if (!Q_strcasecmp(strings + ext->name, extname) && index-->=0)
{
*extsize = ext->num_data;
@ -6997,7 +7008,7 @@ static void Mod_CleanWeights(const char *modelname, size_t numverts, vec4_t *owe
}
}
if (problemfound)
Con_Printf(CON_ERROR"%s has invalid vertex weights. Verticies will probably be attached to the wrong bones\n", modelname);
Con_DPrintf(CON_ERROR"%s has invalid vertex weights. Verticies will probably be attached to the wrong bones\n", modelname);
}
galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsize)
@ -7360,7 +7371,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsi
extsize = 0;
}
else
fteevents = IQM_FindExtension(buffer, "FTE_EVENT", 0, &extsize);
fteevents = IQM_FindExtension(buffer, fsize, "FTE_EVENT", 0, &extsize);
if (fteevents && !(extsize % sizeof(*fteevents)))
{
galiasevent_t *oevent, **link;
@ -7400,7 +7411,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsi
else
AddPointToBounds(vec3_origin, mod->mins, mod->maxs);
ftemesh = IQM_FindExtension(buffer, "FTE_MESH", 0, &extsize);
ftemesh = IQM_FindExtension(buffer, fsize, "FTE_MESH", 0, &extsize);
if (!extsize || extsize != sizeof(*ftemesh)*h->num_meshes)
ftemesh = NULL; //erk.
@ -7496,7 +7507,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, size_t fsi
if (!noweights)
{
if (!IQM_ImportArray4B(buffer, &vbone, oindex, h->num_vertexes, h->num_joints))
Con_Printf(CON_WARNING "Invalid bone indexes detected inside %s\n", mod->name);
Con_DPrintf(CON_WARNING "Invalid bone indexes detected inside %s\n", mod->name);
IQM_ImportArrayF(buffer, &vweight, (float*)oweight, 4, h->num_vertexes, defaultweight);
Mod_CleanWeights(mod->name, h->num_vertexes, oweight, oindex);
}

View File

@ -27,6 +27,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//by adding 'extern' to one definition of a function in a translation unit, then the definition in that TU is NOT considered an inline definition. meaning non-inlined references in other TUs can link to it instead of their own if needed.
fte_inlinebody conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, unsigned int *codepoint);
fte_inlinebody float M_SRGBToLinear(float x, float mag);
fte_inlinebody float M_LinearToSRGB(float x, float mag);
// These 4 libraries required for the version command

View File

@ -67,8 +67,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define FTE_WORDSIZE 32
#else
#ifdef __LP64__
#define qintptr_t long
#define qint64_t long
#define qintptr_t long int
#define qint64_t long int
#define FTE_WORDSIZE 64
#elif __WORDSIZE == 64
#define qintptr_t long long

View File

@ -24,7 +24,7 @@
//#define D3D9QUAKE
//#define GLQUAKE
#undef D3D11QUAKE
#if defined(WIN32)
#if defined(WIN32) && !defined(D3D8QUAKE)
#define D3D8QUAKE
#endif
#undef VKQUAKE
@ -99,6 +99,7 @@
#undef USE_SQLITE //sql-database-as-file support
#undef QUAKESTATS //defines STAT_HEALTH etc. if omitted, you'll need to provide that functionality yourself.
#undef QUAKEHUD //support for drawing the vanilla hud.
#undef QWSKINS //disabling this means no qw .pcx skins nor enemy/team skin/colour forcing
#undef SVRANKING //legacy server-side ranking system.
#undef RAGDOLL //ragdoll support. requires RBE support.
#undef HUFFNETWORK //crappy network compression. probably needs reseeding.

View File

@ -51,11 +51,11 @@ struct
{
void *module;
const char *extension;
searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc, const char *prefix);
searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
qboolean loadscan;
} searchpathformats[64];
int FS_RegisterFileSystemType(void *module, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc, const char *prefix), qboolean loadscan)
int FS_RegisterFileSystemType(void *module, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix), qboolean loadscan)
{
unsigned int i;
for (i = 0; i < sizeof(searchpathformats)/sizeof(searchpathformats[0]); i++)
@ -2315,7 +2315,7 @@ searchpathfuncs_t *FS_GetOldPath(searchpath_t **oldpaths, const char *dir, unsig
}
typedef struct {
searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc, const char *prefix);
searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
searchpath_t **oldpaths;
const char *parentdesc;
const char *puredesc;
@ -2357,7 +2357,7 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_
if (!vfs)
return true;
}
newpak = param->OpenNew (vfs, pakfile, "");
newpak = param->OpenNew (vfs, funcs, descriptor, pakfile, "");
if (!newpak)
{
VFS_CLOSE(vfs);
@ -2375,7 +2375,7 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_
return true;
}
searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, const char *pakname)
searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname)
{
searchpathfuncs_t *pak;
int j;
@ -2387,7 +2387,7 @@ searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, const char *pakname)
continue;
if (!strcmp(ext, searchpathformats[j].extension))
{
pak = searchpathformats[j].OpenNew(f, pakname, "");
pak = searchpathformats[j].OpenNew(f, parent, filename, pakname, "");
if (pak)
return pak;
Con_Printf("Unable to open %s - corrupt?\n", pakname);
@ -2475,7 +2475,7 @@ void FS_AddHashedPackage(searchpath_t **oldpaths, const char *parentpath, const
}
if (vfs)
handle = searchpathformats[fmt].OpenNew (vfs, lname, pakprefix?pakprefix:"");
handle = searchpathformats[fmt].OpenNew (vfs, search?search->handle:NULL, pakpath, lname, pakprefix?pakprefix:"");
if (!handle && vfs)
VFS_CLOSE(vfs); //erk
}
@ -2538,6 +2538,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
char pakfile[MAX_OSPATH];
char logicalpaths[MAX_OSPATH]; //with a slash
char purefile[MAX_OSPATH];
char logicalfile[MAX_OSPATH];
unsigned int keptflags;
vfsfile_t *vfs;
flocation_t loc;
@ -2605,27 +2606,27 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
if (!search->handle->FindFile(search->handle, &loc, pakfile, NULL))
break; //not found..
snprintf (pakfile, sizeof(pakfile), "%spak%i.%s", logicalpaths, i, extension);
snprintf (logicalfile, sizeof(pakfile), "%spak%i.%s", logicalpaths, i, extension);
snprintf (purefile, sizeof(purefile), "%s/pak%i.%s", purepath, i, extension);
for (existing = com_searchpaths; existing; existing = existing->next)
{
if (!Q_strcasecmp(existing->logicalpath, pakfile)) //assumption: first member of structure is a char array
if (!Q_strcasecmp(existing->logicalpath, logicalfile)) //assumption: first member of structure is a char array
break; //already loaded (base paths?)
}
if (!existing)
{
handle = FS_GetOldPath(oldpaths, pakfile, &keptflags);
handle = FS_GetOldPath(oldpaths, logicalfile, &keptflags);
if (!handle)
{
vfs = search->handle->OpenVFS(search->handle, &loc, "rb");
if (!vfs)
break;
handle = searchpathformats[j].OpenNew (vfs, pakfile, "");
handle = searchpathformats[j].OpenNew (vfs, search->handle, pakfile, logicalfile, "");
if (!handle)
break;
}
FS_AddPathHandle(oldpaths, purefile, pakfile, handle, "", SPF_COPYPROTECTED|pflags|keptflags, (unsigned int)-1);
FS_AddPathHandle(oldpaths, purefile, logicalfile, handle, "", SPF_COPYPROTECTED|pflags|keptflags, (unsigned int)-1);
}
}
}
@ -2790,7 +2791,7 @@ void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, const ch
//
handle = FS_GetOldPath(oldpaths, dir, &keptflags);
if (!handle)
handle = VFSOS_OpenPath(NULL, dir, "");
handle = VFSOS_OpenPath(NULL, NULL, dir, dir, "");
FS_AddPathHandle(oldpaths, puredir, dir, handle, "", flags|keptflags, loadstuff);
}
@ -3332,7 +3333,7 @@ vfsfile_t *CL_OpenFileInPackage(searchpathfuncs_t *search, char *name)
f = (search?search:loc.search->handle)->OpenVFS(search?search:loc.search->handle, &loc, "rb");
if (f)
{
searchpathfuncs_t *newsearch = searchpathformats[i].OpenNew(f, name, "");
searchpathfuncs_t *newsearch = searchpathformats[i].OpenNew(f, search?search:loc.search->handle, name, name, "");
if (newsearch)
{
f = CL_OpenFileInPackage(newsearch, end+1);
@ -3429,7 +3430,7 @@ qboolean CL_ListFilesInPackage(searchpathfuncs_t *search, char *name, int (QDECL
f = (search?search:loc.search->handle)->OpenVFS(search?search:loc.search->handle, &loc, "rb");
if (f)
{
searchpathfuncs_t *newsearch = searchpathformats[i].OpenNew(f, name, "");
searchpathfuncs_t *newsearch = searchpathformats[i].OpenNew(f, search?search:loc.search->handle, name, name, "");
if (newsearch)
{
ret = CL_ListFilesInPackage(newsearch, end+1, func, parm, cb.nameprefix);
@ -3586,7 +3587,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
const char *pakname = com_argv[i+1];
searchpathfuncs_t *pak;
vfsfile_t *vfs = VFSOS_Open(pakname, "rb");
pak = FS_OpenPackByExtension(vfs, pakname);
pak = FS_OpenPackByExtension(vfs, NULL, pakname, pakname);
if (pak) //logically should have SPF_EXPLICIT set, but that would give it a worse gamedir depth
FS_AddPathHandle(&oldpaths, "", pakname, pak, "", SPF_COPYPROTECTED, reloadflags);
i = COM_CheckNextParm ("-basepack", i);
@ -3615,7 +3616,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
//paths equal to '*' actually result in loading packages without an actual gamedir. note that this does not imply that we can write anything.
if (!strcmp(dir, "*"))
{
searchpathfuncs_t *handle = VFSOS_OpenPath(NULL, com_gamepath, "");
searchpathfuncs_t *handle = VFSOS_OpenPath(NULL, NULL, com_gamepath, com_gamepath, "");
searchpath_t *search = (searchpath_t*)Z_Malloc (sizeof(searchpath_t));
search->flags = 0;
search->handle = handle;
@ -3814,7 +3815,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags)
continue;
if (!strcmp(ext, searchpathformats[i].extension))
{
handle = searchpathformats[i].OpenNew (vfs, local, "");
handle = searchpathformats[i].OpenNew (vfs, NULL, local, local, "");
if (!handle)
break;
sp = FS_AddPathHandle(&oldpaths, pname, local, handle, "", SPF_COPYPROTECTED|SPF_UNTRUSTED|SPF_TEMPORARY, (unsigned int)-1);
@ -4670,7 +4671,7 @@ static void FS_PackageDownloaded(struct dl_download *dl)
if (fspdl_extracttype == X_UNZIP || fspdl_extracttype == X_MULTIUNZIP) //if zip...
{ //archive
searchpathfuncs_t *archive = FSZIP_LoadArchive(VFSOS_Open(fspdl_temppath, "rb"), dl->url, "");
searchpathfuncs_t *archive = FSZIP_LoadArchive(VFSOS_Open(fspdl_temppath, "rb"), NULL, dl->url, dl->url, "");
if (archive)
{
flocation_t loc;
@ -5153,7 +5154,7 @@ ftemanifest_t *FS_ReadDefaultManifest(char *newbasedir, size_t newbasedirsize, q
const char *pakname = com_argv[i+1];
searchpathfuncs_t *pak;
vfsfile_t *vfs = VFSOS_Open(pakname, "rb");
pak = FS_OpenPackByExtension(vfs, pakname);
pak = FS_OpenPackByExtension(vfs, NULL, pakname, pakname);
if (pak)
{
flocation_t loc;
@ -5665,7 +5666,7 @@ int FS_EnumerateKnownGames(qboolean (*callback)(void *usr, ftemanifest_t *man),
const char *pakname = com_argv[i+1];
searchpathfuncs_t *pak;
vfsfile_t *vfs = VFSOS_Open(pakname, "rb");
pak = FS_OpenPackByExtension(vfs, pakname);
pak = FS_OpenPackByExtension(vfs, NULL, pakname, pakname);
if (pak)
{
pak->EnumerateFiles(pak, "*.fmf", FS_EnumerateFMFs, &e);
@ -6122,14 +6123,14 @@ void COM_InitFilesystem (void)
//this is at the bottom of the file to ensure these globals are not used elsewhere
extern searchpathfuncs_t *(QDECL VFSOS_OpenPath) (vfsfile_t *file, const char *desc, const char *prefix);
/*extern searchpathfuncs_t *(QDECL VFSOS_OpenPath) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
#if 1//def AVAIL_ZLIB
extern searchpathfuncs_t *(QDECL FSZIP_LoadArchive) (vfsfile_t *packhandle, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSZIP_LoadArchive) (vfsfile_t *packhandle, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
#endif
extern searchpathfuncs_t *(QDECL FSPAK_LoadArchive) (vfsfile_t *packhandle, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSPAK_LoadArchive) (vfsfile_t *packhandle, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
#ifdef PACKAGE_DOOMWAD
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *packhandle, const char *desc, const char *prefix);
#endif
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *packhandle, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
#endif*/
void FS_RegisterDefaultFileSystems(void)
{
#ifdef PACKAGE_DZIP

View File

@ -57,15 +57,15 @@ struct searchpathfuncs_s
//the stdio filesystem is special as that's the starting point of the entire filesystem
//warning: the handle is known to be a string pointer to the dir name
extern searchpathfuncs_t *(QDECL VFSOS_OpenPath) (vfsfile_t *file, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSZIP_LoadArchive) (vfsfile_t *packhandle, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSPAK_LoadArchive) (vfsfile_t *packhandle, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *packhandle, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSDZ_LoadArchive) (vfsfile_t *file, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL VFSOS_OpenPath) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSZIP_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSPAK_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSDWD_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
extern searchpathfuncs_t *(QDECL FSDZ_LoadArchive) (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix);
vfsfile_t *QDECL VFSOS_Open(const char *osname, const char *mode);
vfsfile_t *FS_DecompressGZip(vfsfile_t *infile, vfsfile_t *outfile);
int FS_RegisterFileSystemType(void *module, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc, const char *prefix), qboolean loadscan);
int FS_RegisterFileSystemType(void *module, const char *extension, searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix), qboolean loadscan);
void FS_UnRegisterFileSystemType(int idx);
void FS_UnRegisterFileSystemModule(void *module);

View File

@ -1352,7 +1352,7 @@ Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
searchpathfuncs_t *QDECL FSDZ_LoadArchive (vfsfile_t *file, const char *desc, const char *prefix)
searchpathfuncs_t *QDECL FSDZ_LoadArchive (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
{
dpackheader_t header;
int i;

View File

@ -309,7 +309,7 @@ Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, const char *desc, const char *prefix)
searchpathfuncs_t *QDECL FSPAK_LoadArchive (vfsfile_t *file, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
{
dpackheader_t header;
int i;

View File

@ -336,7 +336,7 @@ static qboolean QDECL FSSTDIO_FileStat (searchpathfuncs_t *handle, flocation_t *
}
searchpathfuncs_t *QDECL FSSTDIO_OpenPath(vfsfile_t *mustbenull, const char *desc, const char *prefix)
searchpathfuncs_t *QDECL FSSTDIO_OpenPath(vfsfile_t *mustbenull, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
{
stdiopath_t *np;
int dlen = strlen(desc);

View File

@ -226,6 +226,8 @@ static int QDECL VFSW32_ReadBytes (struct vfsfile_s *file, void *buffer, int byt
{
if (intfile->offset+bytestoread > intfile->length)
bytestoread = intfile->length-intfile->offset;
if (bytestoread < 0)
bytestoread = 0; //shouldn't happen...
memcpy(buffer, (char*)intfile->mmap + intfile->offset, bytestoread);
intfile->offset += bytestoread;
@ -327,6 +329,7 @@ static vfsfile_t *QDECL VFSW32_OpenInternal(vfsw32path_t *handle, const char *qu
qboolean write = !!strchr(mode, 'w');
qboolean append = !!strchr(mode, 'a');
qboolean text = !!strchr(mode, 't');
//qboolean persistent = !!strchr(mode, 'p'); //save to long-term storage
write |= append;
create = write;
if (strchr(mode, '+'))
@ -642,7 +645,7 @@ static qboolean QDECL VFSW32_MkDir(searchpathfuncs_t *handle, const char *filena
return true;
}
searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, const char *desc, const char *prefix)
searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
{
vfsw32path_t *np;
int dlen = strlen(desc);

View File

@ -513,6 +513,7 @@ typedef struct
{
fsbucket_t bucket;
char name[MAX_QPATH];
unsigned int disknum;
qofs_t localpos; //location of local header
qofs_t filelen; //uncompressed size
time_t mtime;
@ -522,7 +523,7 @@ typedef struct
#define ZFL_DEFLATED 1 //need to use zlib
#define ZFL_STORED 2 //direct access is okay
#define ZFL_SYMLINK 4 //file is a symlink
#define ZFL_CORRUPT 8 //file is corrupt or otherwise unreadable.
#define ZFL_CORRUPT 8 //file is corrupt or otherwise unreadable (usually just means we don't support reading it rather than actually corrupt, but hey).
#define ZFL_WEAKENCRYPT 16 //traditional zip encryption
@ -534,6 +535,12 @@ typedef struct zipfile_s
unsigned int numfiles;
zpackfile_t *files;
//spanned zips are weird.
//the starting zip is usually the last one, but should be null to simplify ref tracking.
unsigned int thisdisk;
unsigned int numspans;
struct zipfile_s **spans;
//info about the underlying file
void *mutex;
qofs_t curpos; //cache position to avoid excess seeks
@ -555,6 +562,7 @@ static void QDECL FSZIP_GetPathDetails(searchpathfuncs_t *handle, char *out, siz
}
static void QDECL FSZIP_ClosePath(searchpathfuncs_t *handle)
{
size_t s;
qboolean stillopen;
zipfile_t *zip = (void*)handle;
@ -566,6 +574,15 @@ static void QDECL FSZIP_ClosePath(searchpathfuncs_t *handle)
return; //not free yet
VFS_CLOSE(zip->raw);
for (s = 0; s < zip->numspans; s++)
{
if (zip->spans[s])
{
zip->spans[s]->pub.ClosePath(&zip->spans[s]->pub);
zip->spans[s] = NULL;
}
}
Z_Free(zip->spans);
Sys_DestroyMutex(zip->mutex);
if (zip->files)
Z_Free(zip->files);
@ -1074,6 +1091,22 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
if (flags & ZFL_CORRUPT)
return NULL;
if (zip->thisdisk != pf->disknum)
{
if (pf->disknum >= zip->numspans)
{
Con_Printf("file %s has oob disk number\n", pf->name);
return NULL;
}
zip = zip->spans[pf->disknum];
if (!zip)
{
zip = (void*)handle;
Con_Printf("spanned zip %s lacks segment %u for file %s\n", zip->filename, pf->disknum+1, pf->name);
return NULL;
}
}
vfsz = Z_Malloc(sizeof(vfszip_t));
vfsz->parent = zip;
@ -1093,6 +1126,7 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
if (!FSZIP_ValidateLocalHeader(zip, pf, &vfsz->startpos, &datasize))
{
Con_Printf("file %s:%s is incompatible or inconsistent with zip central directory\n", zip->filename, pf->name);
Z_Free(vfsz);
return NULL;
}
@ -1152,6 +1186,11 @@ static vfsfile_t *QDECL FSZIP_OpenVFS(searchpathfuncs_t *handle, flocation_t *lo
//infozip utf-8 name override.
//other 'extra' fields.
//split archives:
//central directory must be stored exclusively inside the initial zip.
//files on other parts will fail to load.
//individual files must not be split over files
struct zipinfo
{
unsigned int thisdisk; //this disk number
@ -1164,7 +1203,7 @@ struct zipinfo
unsigned int zip64_centraldirend_disk; //zip64 weirdness
qofs_t zip64_centraldirend_offset;
unsigned int zip64_diskcount;
unsigned int diskcount;
qofs_t zip64_eocdsize;
unsigned short zip64_version_madeby;
unsigned short zip64_version_needed;
@ -1315,7 +1354,7 @@ static qboolean FSZIP_ValidateLocalHeader(zipfile_t *zip, zpackfile_t *zfile, qo
}
localstart += local.extra_len;
*datastart = localstart; //this is the end of the local block, and the start of the data block (well, actually, should be encryption, but we don't support that).
*datasize = local.csize;
*datasize = local.csize; //FIXME: this is often masked. use the central directory's value instead.
if (local.gpflags & (1u<<3))
{
@ -1333,6 +1372,9 @@ static qboolean FSZIP_ValidateLocalHeader(zipfile_t *zip, zpackfile_t *zfile, qo
//FIXME: with pure paths, we still don't bother checking the crc (again, would require decompressing the entire file in advance).
if (localstart+local.csize > zip->rawsize)
return false; //FIXME: proper spanned zips fragment compressed data over multiple spans, but we don't support that
if (local.cmethod == 0)
return (zfile->flags & (ZFL_STORED|ZFL_CORRUPT|ZFL_DEFLATED)) == ZFL_STORED;
if (local.cmethod == 8)
@ -1342,6 +1384,7 @@ static qboolean FSZIP_ValidateLocalHeader(zipfile_t *zip, zpackfile_t *zfile, qo
static qboolean FSZIP_ReadCentralEntry(zipfile_t *zip, qbyte *data, struct zipcentralentry *entry)
{
struct tm t;
entry->flags = 0;
entry->fname = "";
entry->fnane_len = 0;
@ -1375,7 +1418,14 @@ static qboolean FSZIP_ReadCentralEntry(zipfile_t *zip, qbyte *data, struct zipce
entry->fname = data+entry->cesize;
entry->cesize += entry->fnane_len;
entry->mtime = 0;
memset(&t, 0, sizeof(t));
t.tm_mday = (entry->lastmodfiledate&0x001f)>>0;
t.tm_mon = (entry->lastmodfiledate&0x01e0)>>5;
t.tm_year = ((entry->lastmodfiledate&0xfe00)>>9) + (1980 - 1900);
t.tm_sec = ((entry->lastmodfiletime&0x001f)>>0)*2;
t.tm_min = (entry->lastmodfiletime&0x07e0)>>5;
t.tm_hour = (entry->lastmodfiletime&0xf800)>>11;
entry->mtime = mktime(&t);
//parse extra
if (entry->extra_len)
@ -1553,6 +1603,7 @@ static qboolean FSZIP_EnumerateCentralDirectory(zipfile_t *zip, struct zipinfo *
if (!FSZIP_ReadCentralEntry(zip, centraldir+ofs, &entry) || ofs + entry.cesize > info->centraldir_size)
break;
f->disknum = entry.disknum;
f->crc = entry.crc32;
//copy out the filename and lowercase it
@ -1662,6 +1713,8 @@ static qboolean FSZIP_FindEndCentralDirectory(zipfile_t *zip, struct zipinfo *in
info->centraldir_offset = LittleU4FromPtr(magic+16);
info->commentlength = LittleU2FromPtr(magic+20);
info->diskcount = info->thisdisk+1; //zips are normally opened via the last file.
result = true;
break;
}
@ -1685,13 +1738,7 @@ static qboolean FSZIP_FindEndCentralDirectory(zipfile_t *zip, struct zipinfo *in
info->zip64_centraldirend_disk = LittleU4FromPtr(magic+4);
info->zip64_centraldirend_offset = LittleU8FromPtr(magic+8);
info->zip64_diskcount = LittleU4FromPtr(magic+16);
if (info->zip64_diskcount != 1 || info->zip64_centraldirend_disk != 0)
{
Con_Printf("zip: archive is spanned\n");
return false;
}
info->diskcount = LittleU4FromPtr(magic+16);
VFS_SEEK(zip->raw, info->zip64_centraldirend_offset);
VFS_READ(zip->raw, z64eocd, sizeof(z64eocd));
@ -1730,11 +1777,17 @@ static qboolean FSZIP_FindEndCentralDirectory(zipfile_t *zip, struct zipinfo *in
result = false;
}
if (info->diskcount < 1 || info->zip64_centraldirend_disk != info->thisdisk)
{
Con_Printf("zip: archive is spanned\n");
return false;
}
break;
}
}
if (info->thisdisk || info->centraldir_startdisk || info->centraldir_numfiles_disk != info->centraldir_numfiles_all)
if (info->thisdisk != info->centraldir_startdisk || info->centraldir_numfiles_disk != info->centraldir_numfiles_all)
{
Con_Printf("zip: archive is spanned\n");
result = false;
@ -1758,7 +1811,7 @@ Loads the header and directory, adding the files at the beginning
of the list so they override previous pack files.
=================
*/
searchpathfuncs_t *QDECL FSZIP_LoadArchive (vfsfile_t *packhandle, const char *desc, const char *prefix)
searchpathfuncs_t *QDECL FSZIP_LoadArchive (vfsfile_t *packhandle, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
{
zipfile_t *zip;
struct zipinfo info;
@ -1788,7 +1841,7 @@ searchpathfuncs_t *QDECL FSZIP_LoadArchive (vfsfile_t *packhandle, const char *d
}
//now read it.
if (!FSZIP_EnumerateCentralDirectory(zip, &info, prefix) && !info.zip64_diskcount)
if (!FSZIP_EnumerateCentralDirectory(zip, &info, prefix))
{
//uh oh... the central directory wasn't where it was meant to be!
//assuming that the endofcentraldir is packed at the true end of the centraldir (and that we're not zip64 and thus don't have an extra block), then we can guess based upon the offset difference
@ -1801,6 +1854,54 @@ searchpathfuncs_t *QDECL FSZIP_LoadArchive (vfsfile_t *packhandle, const char *d
}
}
zip->thisdisk = info.thisdisk;
if (info.diskcount > 1)
{
if (parent && filename)
{
zipfile_t *szip;
unsigned int s;
flocation_t loc;
char splitname[MAX_OSPATH];
char *ext;
zip->numspans = info.diskcount;
zip->spans = Z_Malloc(info.diskcount*sizeof(*zip->spans));
for(s = 0; s < zip->numspans; s++)
{
if (info.thisdisk == s)
continue; //would be weird.
Q_strncpyz(splitname, filename, sizeof(splitname));
ext = strrchr(splitname, '.');
if (ext)
{
ext++;
if (*ext)
ext++; //skip the first letter of the extension
}
else
ext = splitname + strlen(splitname);
Q_snprintfz(ext, sizeof(splitname)-(ext-splitname), *ext?"%02u":"%03u", s+1);
if (parent->FindFile(parent, &loc, splitname, NULL) != FF_FOUND)
continue;
packhandle = parent->OpenVFS(parent, &loc, "rb");
if (!packhandle)
continue;
zip->spans[s] = szip = Z_Malloc(sizeof(zipfile_t));
szip->thisdisk = s;
Q_strncpyz(szip->filename, splitname, sizeof(szip->filename));
szip->raw = packhandle;
szip->rawsize = VFS_GETLEN(szip->raw);
szip->references = 1;
szip->mutex = Sys_CreateMutex();
szip->pub.ClosePath = FSZIP_ClosePath;
}
}
else
Con_TPrintf ("spanned zip \"%s\" with no path info\n", desc);
}
zip->references = 1;
zip->mutex = Sys_CreateMutex();

View File

@ -2227,6 +2227,7 @@ static qboolean CModQ3_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
int i, count, j;
vec2_t *lmout, *stout;
vec4_t *cout;
extern cvar_t gl_overbright;
extern qbyte lmgamma[256];
in = (void *)(mod_base + l->fileofs);
@ -2243,6 +2244,8 @@ static qboolean CModQ3_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
return false;
}
BuildLightMapGammaTable(1, 1<<(2-gl_overbright.ival));
out = ZG_Malloc(&mod->memgroup, count*sizeof(*out));
stout = ZG_Malloc(&mod->memgroup, count*sizeof(*stout));
lmout = ZG_Malloc(&mod->memgroup, count*sizeof(*lmout));
@ -2274,9 +2277,9 @@ static qboolean CModQ3_LoadVertexes (model_t *mod, qbyte *mod_base, lump_t *l)
stout[i][j] = LittleFloat ( ((float *)in->texcoords)[j] );
lmout[i][j] = LittleFloat ( ((float *)in->texcoords)[j+2] );
}
cout[i][0] = lmgamma[in->color[0]]/255.0f;
cout[i][1] = lmgamma[in->color[1]]/255.0f;
cout[i][2] = lmgamma[in->color[2]]/255.0f;
cout[i][0] = (lmgamma[in->color[0]]<<gl_overbright.ival)/255.0f;
cout[i][1] = (lmgamma[in->color[1]]<<gl_overbright.ival)/255.0f;
cout[i][2] = (lmgamma[in->color[2]]<<gl_overbright.ival)/255.0f;
cout[i][3] = in->color[3]/255.0f;
}
@ -3490,7 +3493,7 @@ static void CModQ3_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l)
extern cvar_t gl_overbright;
extern qbyte lmgamma[256];
loadmodel->engineflags &= ~MDLF_RGBLIGHTING;
loadmodel->lightmaps.fmt = LM_L8;
//round up the samples, in case the last one is partial.
maps = ((samples+mapsize-1)&~(mapsize-1)) / mapsize;
@ -3506,7 +3509,7 @@ static void CModQ3_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l)
loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT;
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->lightmaps.fmt = LM_RGB8;
if (loadmodel->lightmaps.deluxemapping)
maps /= 2;
@ -4125,6 +4128,7 @@ static cmodel_t *CM_LoadMap (model_t *mod, qbyte *filein, size_t filelen, qboole
//q3 maps have built in 4-fold overbright.
//if we're not rendering with that, we need to brighten the lightmaps in order to keep the darker parts the same brightness. we loose the 2 upper bits. those bright areas become uniform and indistinct.
//this is used for both the lightmap AND vertex lighting
//FIXME: when not using overbrights, we suffer a loss of precision.
gl_overbright.flags |= CVAR_RENDERERLATCH;
BuildLightMapGammaTable(1, (1<<(2-gl_overbright.ival)));

View File

@ -25,6 +25,12 @@ typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
typedef vec_t vec5_t[5];
typedef int ivec_t;
typedef ivec_t ivec2_t[2];
typedef ivec_t ivec3_t[3];
typedef ivec_t ivec4_t[4];
typedef ivec_t ivec5_t[5];
/*16-byte aligned vectors, for auto-vectorising, should propogate to structs
sse and altivec can unroll loops using aligned reads, which should be faster... 4 at once.
*/

View File

@ -104,7 +104,7 @@ cvar_t net_enable_webrtcbroker = CVARD("net_enable_webrtcbroker", "1", "If 1, tc
#endif
#ifndef SERVERONLY
static void cl_delay_packets_Announce(cvar_t *var, char *oldval)
static void QDECL cl_delay_packets_Announce(cvar_t *var, char *oldval)
{
if (cls.state >= ca_connected && cl.fpd & FPD_ANOUNCE_FAKE_LAG)
Cbuf_AddText(va("say Fake lag now %ims\n", var->ival), RESTRICT_LOCAL);
@ -2850,6 +2850,7 @@ qboolean FTENET_Datagram_GetPacket(ftenet_generic_connection_t *con)
return false;
fromlen = sizeof(from);
((struct sockaddr*)&from)->sa_family = AF_UNSPEC;
ret = recvfrom (con->thesocket, (char *)net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr*)&from, &fromlen);
if (ret == -1)
@ -2876,7 +2877,7 @@ qboolean FTENET_Datagram_GetPacket(ftenet_generic_connection_t *con)
unsigned int curtime = Sys_Milliseconds();
if (curtime-resettime >= 5000 || err == NET_ECONNRESET) //throttle prints to once per 5 secs (even if they're about different clients, yay ddos)
{
if (err == NET_ECONNABORTED)
if (((struct sockaddr*)&from)->sa_family != AF_UNSPEC)
Con_TPrintf ("Connection lost or aborted (%s)\n", NET_AdrToString (adr, sizeof(adr), &net_from)); //server died/connection lost.
else
Con_TPrintf ("Connection lost or aborted\n"); //server died/connection lost.
@ -2896,8 +2897,10 @@ qboolean FTENET_Datagram_GetPacket(ftenet_generic_connection_t *con)
return false;
}
Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err));
if (((struct sockaddr*)&from)->sa_family != AF_UNSPEC)
Con_Printf ("NET_GetPacket: Error (%i): %s (%s)\n", err, strerror(err), NET_AdrToString (adr, sizeof(adr), &net_from));
else
Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err));
return false;
}
SockadrToNetadr (&from, &net_from);
@ -2905,7 +2908,7 @@ qboolean FTENET_Datagram_GetPacket(ftenet_generic_connection_t *con)
net_message.packing = SZ_RAWBYTES;
net_message.currentbit = 0;
net_message.cursize = ret;
if (net_message.cursize == sizeof(net_message_buffer) )
if (net_message.cursize >= sizeof(net_message_buffer) )
{
Con_TPrintf ("Warning: Oversize packet from %s\n", NET_AdrToString (adr, sizeof(adr), &net_from));
return false;

View File

@ -1234,8 +1234,8 @@ qintptr_t VARGS Plug_FS_Open(void *offset, quintptr_t mask, const qintptr_t *arg
}
qintptr_t VARGS Plug_FS_Seek(void *offset, quintptr_t mask, const qintptr_t *arg)
{
unsigned int handle = arg[0];
unsigned int low = arg[1], high = arg[2];
unsigned int handle = VM_LONG(arg[0]);
unsigned int low = VM_LONG(arg[1]), high = VM_LONG(arg[2]);
pluginstream_t *stream;
if (handle >= pluginstreamarraylen)
@ -1249,7 +1249,7 @@ qintptr_t VARGS Plug_FS_Seek(void *offset, quintptr_t mask, const qintptr_t *arg
qintptr_t VARGS Plug_FS_GetLength(void *offset, quintptr_t mask, const qintptr_t *arg)
{
unsigned int handle = arg[0];
unsigned int handle = VM_LONG(arg[0]);
unsigned int *low = VM_POINTER(arg[1]), *high = VM_POINTER(arg[2]);
pluginstream_t *stream;
qofs_t size;

View File

@ -6359,27 +6359,25 @@ void PR_ProgsAdded(pubprogfuncs_t *prinst, int newprogs, const char *modulename)
extern cvar_t language;
if (!prinst || newprogs < 0)
return;
if (*language.string)
Q_strncpyz(lang, language.string, sizeof(lang));
while ((h = strchr(lang, '-')))
*h = '_';
for(;;)
{
Q_strncpyz(lang, language.string, sizeof(lang));
while ((h = strchr(lang, '-')))
*h = '_';
for(;;)
{
if (!*lang)
break;
if (!f)
f = FS_OpenVFS(va("%s.%s.po", modulename, lang), "rb", FS_GAME);
if (!f2)
f2 = FS_OpenVFS(va("common.%s.po", lang), "rb", FS_GAME);
if (f && f2)
break;
h = strchr(lang, '_');
if (h)
*h = 0;
else
break;
}
if (!f)
f = FS_OpenVFS(va("%s.%s.po", modulename, *lang?lang:"default"), "rb", FS_GAME);
if (!f2)
f2 = FS_OpenVFS(va("common.%s.po", *lang?lang:"default"), "rb", FS_GAME);
if (f && f2)
break;
if (!*lang)
break;
h = strchr(lang, '_');
if (h)
*h = 0;
else
break;
}
if (f || f2)

View File

@ -247,6 +247,7 @@ void QCBUILTIN PF_setattachment(pubprogfuncs_t *prinst, struct globalvars_s *pr_
void QCBUILTIN PF_skel_ragedit(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_create (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_build (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_build_ptr (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_numbones (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_bonename (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_skel_get_boneparent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);

View File

@ -1330,8 +1330,9 @@ typedef struct q1usercmd_s
#define RDF_CUSTOMPOSTPROC (1u<<19)
#define RDF_ANTIALIAS (1u<<20) //fxaa, or possibly even just fsaa
#define RDF_RENDERSCALE (1u<<21)
#define RDF_SCENEGAMMA (1u<<22)
#define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS) //these flags require rendering to an fbo for the various different post-processing shaders.
#define RDF_ALLPOSTPROC (RDF_BLOOM|RDF_FISHEYE|RDF_WATERWARP|RDF_CUSTOMPOSTPROC|RDF_ANTIALIAS|RDF_SCENEGAMMA) //these flags require rendering to an fbo for the various different post-processing shaders.

View File

@ -67,7 +67,7 @@ struct vm_s {
void *hInst;
// native
qintptr_t (EXPORT_FN *vmMain)(qintptr_t command, qintptr_t arg0, qintptr_t arg1, qintptr_t arg2, qintptr_t arg3, qintptr_t arg4, qintptr_t arg5, qintptr_t arg6);
qintptr_t (EXPORT_FN *vmMain)(qintptr_t command, qintptr_t arg0, qintptr_t arg1, qintptr_t arg2, qintptr_t arg3, qintptr_t arg4, qintptr_t arg5, qintptr_t arg6, qintptr_t arg7);
};
//this is a bit weird. qvm plugins always come from $basedir/$mod/plugins/$foo.qvm
@ -1143,7 +1143,7 @@ qintptr_t VARGS VM_Call(vm_t *vm, qintptr_t instruction, ...)
switch(vm->type)
{
case VM_NATIVE:
return vm->vmMain(instruction, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6]);
return vm->vmMain(instruction, arg[0], arg[1], arg[2], arg[3], arg[4], arg[5], arg[6], arg[7]);
case VM_BYTECODE:
return QVM_ExecVM(vm->hInst, instruction, arg[0]&0xffffffff, arg[1]&0xffffffff, arg[2]&0xffffffff, arg[3]&0xffffffff, arg[4]&0xffffffff, arg[5]&0xffffffff, arg[6]&0xffffffff, arg[7]&0xffffffff);

View File

@ -13,7 +13,7 @@ extern ID3D11DepthStencilView *fb_backdepthstencil;
extern cvar_t r_shadow_realtime_world_lightmaps;
extern cvar_t gl_overbright;
extern cvar_t r_portalrecursion;
extern cvar_t r_portalrecursion, r_wireframe;
extern cvar_t r_polygonoffset_shadowmap_offset, r_polygonoffset_shadowmap_factor;
@ -137,7 +137,7 @@ typedef struct
vec3_t e_light_ambient; float pad1;
vec3_t e_light_dir; float pad2;
vec3_t e_light_mul; float pad3;
} cbuf_view_t;
} dx11_cbuf_view_t;
typedef struct
{
@ -147,7 +147,7 @@ typedef struct
vec3_t l_lightcolourscale; float l_lightradius;
vec4_t l_shadowmapproj;
vec2_t l_shadowmapscale; vec2_t pad3;
} cbuf_light_t;
} dx11_cbuf_light_t;
//entity-specific constant-buffer
typedef struct
@ -163,7 +163,7 @@ typedef struct
vec4_t e_lowercolour;
vec4_t e_colourmod;
vec4_t e_glowmod;
} cbuf_entity_t;
} dx11_cbuf_entity_t;
//vertex attributes
typedef struct
@ -175,7 +175,7 @@ typedef struct
vec3_t sdir;
vec3_t tdir;
byte_vec4_t colorsb;
} vbovdata_t;
} dx11_vbovdata_t;
enum
{
@ -794,7 +794,7 @@ void D3D11BE_Init(void)
for (i = 0; i < NUMECBUFFERS; i++)
{
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(cbuf_entity_t);
bd.ByteWidth = sizeof(dx11_cbuf_entity_t);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
@ -803,7 +803,7 @@ void D3D11BE_Init(void)
return;
}
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(cbuf_view_t);
bd.ByteWidth = sizeof(dx11_cbuf_view_t);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
@ -812,7 +812,7 @@ void D3D11BE_Init(void)
return;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = sizeof(cbuf_light_t);
bd.ByteWidth = sizeof(dx11_cbuf_light_t);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
@ -1006,19 +1006,19 @@ static texid_t T_Gen_CurrentRender(void)
{
if (!shaderstate.currentrender)
shaderstate.currentrender = Image_CreateTexture("***$currentrender***", NULL, 0);
if (!shaderstate.currentrender)
return r_nulltex; //err
if (shaderstate.currentrender)
{
shaderstate.currentrender->width = tdesc.Width;
shaderstate.currentrender->height = tdesc.Height;
shaderstate.currentrender->width = tdesc.Width;
shaderstate.currentrender->height = tdesc.Height;
tdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
tdesc.CPUAccessFlags = 0;
tdesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
tdesc.CPUAccessFlags = 0;
if (shaderstate.currentrender->ptr)
ID3D11Texture2D_Release((ID3D11Texture2D*)shaderstate.currentrender->ptr);
shaderstate.currentrender->ptr = NULL;
ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, NULL, (ID3D11Texture2D**)&shaderstate.currentrender->ptr);
if (shaderstate.currentrender->ptr)
ID3D11Texture2D_Release((ID3D11Texture2D*)shaderstate.currentrender->ptr);
shaderstate.currentrender->ptr = NULL;
ID3D11Device_CreateTexture2D(pD3DDev11, &tdesc, NULL, (ID3D11Texture2D**)&shaderstate.currentrender->ptr);
}
}
ID3D11DeviceContext_CopyResource(d3ddevctx, (ID3D11Resource*)shaderstate.currentrender->ptr, (ID3D11Resource*)backbuf);
@ -1026,6 +1026,8 @@ static texid_t T_Gen_CurrentRender(void)
ID3D11ShaderResourceView_Release((ID3D11ShaderResourceView*)shaderstate.currentrender->ptr2);
shaderstate.currentrender->ptr2 = NULL;
ID3D11Texture2D_Release(backbuf);
return shaderstate.currentrender;
}
@ -1470,7 +1472,7 @@ static void BE_GenerateColourMods(unsigned int vertcount, const shaderpass_t *pa
{
shaderstate.stream_buffer[D3D11_BUFF_COL] = shaderstate.batchvbo->colours[0].d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_COL] = shaderstate.batchvbo->colours[0].d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_COL] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_COL] = sizeof(dx11_vbovdata_t);
shaderstate.stream_rgbaf = false;
}
else
@ -1989,6 +1991,10 @@ static void D3D11BE_Cull(unsigned int cullflags, int depthbias, float depthfacto
else if (cullflags)
cullflags ^= r_refdef.flipcull;
#define SHADER_CULL_WIREFRAME SHADER_NODRAW //borrow a flag...
if (shaderstate.mode == BEM_WIREFRAME)
cullflags |= SHADER_CULL_WIREFRAME;
if (shaderstate.curcull != cullflags || shaderstate.depthbias != depthbias || shaderstate.depthfactor != depthfactor)
{
shaderstate.curcull = cullflags;
@ -2022,7 +2028,7 @@ static void D3D11BE_Cull(unsigned int cullflags, int depthbias, float depthfacto
rasterdesc.SlopeScaledDepthBias = shaderstate.depthfactor;
rasterdesc.DepthBiasClamp = 0.0f;
rasterdesc.DepthClipEnable = true;
rasterdesc.FillMode = 0?D3D11_FILL_WIREFRAME:D3D11_FILL_SOLID;
rasterdesc.FillMode = (shaderstate.curcull&SHADER_CULL_WIREFRAME)?D3D11_FILL_WIREFRAME:D3D11_FILL_SOLID;
rasterdesc.FrontCounterClockwise = false;
rasterdesc.MultisampleEnable = false;
rasterdesc.ScissorEnable = true;
@ -2091,6 +2097,15 @@ static void BE_DrawMeshChain_Internal(void)
case BEM_STANDARD:
altshader = shaderstate.curshader;
break;
case BEM_WIREFRAME:
altshader = R_RegisterShader("wireframe", SUF_NONE,
"{\n"
"{\n"
"map $whiteimage\n"
"}\n"
"}\n"
);
break;
}
if (!altshader)
return;
@ -2193,7 +2208,7 @@ static void BE_DrawMeshChain_Internal(void)
{
shaderstate.stream_buffer[D3D11_BUFF_POS] = shaderstate.batchvbo->coord.d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_POS] = shaderstate.batchvbo->coord.d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_POS] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_POS] = sizeof(dx11_vbovdata_t);
}
else
{
@ -2262,17 +2277,17 @@ static void BE_DrawMeshChain_Internal(void)
{
shaderstate.stream_buffer[D3D11_BUFF_COL] = shaderstate.batchvbo->colours[0].d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_COL] = shaderstate.batchvbo->colours[0].d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_COL] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_COL] = sizeof(dx11_vbovdata_t);
shaderstate.stream_rgbaf = false;
shaderstate.stream_buffer[D3D11_BUFF_TC] = shaderstate.batchvbo->texcoord.d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_TC] = shaderstate.batchvbo->texcoord.d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_TC] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_TC] = sizeof(dx11_vbovdata_t);
shaderstate.stream_buffer[D3D11_BUFF_LMTC] = shaderstate.batchvbo->lmcoord[0].d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_LMTC] = shaderstate.batchvbo->lmcoord[0].d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_LMTC] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_LMTC] = sizeof(dx11_vbovdata_t);
shaderstate.stream_buffer[D3D11_BUFF_NORM] = shaderstate.batchvbo->normals.d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_NORM] = shaderstate.batchvbo->normals.d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_NORM] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_NORM] = sizeof(dx11_vbovdata_t);
}
else
{
@ -2398,13 +2413,13 @@ static void BE_DrawMeshChain_Internal(void)
{
shaderstate.stream_buffer[D3D11_BUFF_TC] = shaderstate.batchvbo->lmcoord[0].d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_TC] = shaderstate.batchvbo->lmcoord[0].d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_TC] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_TC] = sizeof(dx11_vbovdata_t);
}
else if (p->tcgen == TC_GEN_BASE)
{
shaderstate.stream_buffer[D3D11_BUFF_TC] = shaderstate.batchvbo->texcoord.d3d.buff;
shaderstate.stream_offset[D3D11_BUFF_TC] = shaderstate.batchvbo->texcoord.d3d.offs;
shaderstate.stream_stride[D3D11_BUFF_TC] = sizeof(vbovdata_t);
shaderstate.stream_stride[D3D11_BUFF_TC] = sizeof(dx11_vbovdata_t);
}
else
{
@ -2516,7 +2531,7 @@ void D3D11BE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopba
ID3D11Buffer *vbuff;
ID3D11Buffer *ebuff;
index_t *vboedata, *vboedatastart;
vbovdata_t *vbovdata, *vbovdatastart;
dx11_vbovdata_t *vbovdata, *vbovdatastart;
D3D11_BUFFER_DESC vbodesc;
D3D11_BUFFER_DESC ebodesc;
D3D11_SUBRESOURCE_DATA srd;
@ -2765,14 +2780,14 @@ static float projgltod3d[16] =
};
static void D3D11BE_SetupViewCBuffer(void)
{
cbuf_view_t *cbv;
dx11_cbuf_view_t *cbv;
D3D11_MAPPED_SUBRESOURCE msr;
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.vcbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr)))
{
Con_Printf("BE_RotateForEntity: failed to map constant buffer\n");
return;
}
cbv = (cbuf_view_t*)msr.pData;
cbv = (dx11_cbuf_view_t*)msr.pData;
//we internally use gl-style projection matricies.
//gl's viewport is based upon -1 to 1 depth.
@ -2807,14 +2822,14 @@ void D3D11BE_Set2D(void)
void D3D11BE_SetupLightCBuffer(dlight_t *l, vec3_t colour)
{
extern cvar_t gl_specular;
cbuf_light_t *cbl;
dx11_cbuf_light_t *cbl;
D3D11_MAPPED_SUBRESOURCE msr;
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.lcbuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &msr)))
{
Con_Printf("BE_RotateForEntity: failed to map constant buffer\n");
return;
}
cbl = (cbuf_light_t*)msr.pData;
cbl = (dx11_cbuf_light_t*)msr.pData;
cbl->l_lightradius = l->radius;
@ -2871,7 +2886,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
float ndr;
float modelinv[16];
float *m = shaderstate.m_model;
cbuf_entity_t *cbe;
dx11_cbuf_entity_t *cbe;
D3D11_MAPPED_SUBRESOURCE msr;
shaderstate.ecbufferidx = (shaderstate.ecbufferidx + 1) & (NUMECBUFFERS-1);
if (FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)shaderstate.ecbuffers[shaderstate.ecbufferidx], 0, D3D11_MAP_WRITE_DISCARD, 0, &msr)))
@ -2879,7 +2894,7 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
Con_Printf("BE_RotateForEntity: failed to map constant buffer\n");
return;
}
cbe = (cbuf_entity_t*)msr.pData;
cbe = (dx11_cbuf_entity_t*)msr.pData;
shaderstate.curentity = e;
@ -3053,7 +3068,10 @@ static void BE_RotateForEntity (const entity_t *e, const model_t *mod)
R_FetchPlayerColour(e->topcolour, cbe->e_uppercolour);
R_FetchPlayerColour(e->bottomcolour, cbe->e_lowercolour);
R_FetchPlayerColour(e->bottomcolour, cbe->e_colourmod);
VectorCopy(e->shaderRGBAf, cbe->e_colourmod);
if (shaderstate.flags & BEF_FORCECOLOURMOD)
Vector4Copy(e->shaderRGBAf, cbe->e_colourmod);
else
Vector4Set(cbe->e_colourmod, 1, 1, 1, e->shaderRGBAf[3]);
VectorCopy(e->glowmod, cbe->e_glowmod);cbe->e_glowmod[3] = 1;
//various stuff in modelspace
@ -3688,6 +3706,13 @@ void D3D11BE_DrawWorld (batch_t **worldbatches)
RSpeedRemark();
D3D11BE_SubmitMeshes(worldbatches, batches, SHADER_SORT_SEETHROUGH+1, SHADER_SORT_COUNT);
RSpeedEnd(RSPEED_TRANSPARENTS);
if (r_wireframe.ival)
{
D3D11BE_SelectMode(BEM_WIREFRAME);
D3D11BE_SubmitMeshes(worldbatches, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST);
D3D11BE_SelectMode(BEM_STANDARD);
}
}
else
{

View File

@ -132,6 +132,7 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
tdesc.CPUAccessFlags = (mips->mip[0].data)?0:D3D11_CPU_ACCESS_WRITE;
tdesc.MiscFlags = 0;
tdesc.Format = DXGI_FORMAT_UNKNOWN;
if (tex->flags & IF_RENDERTARGET)
{
@ -145,16 +146,20 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
tdesc.ArraySize *= 6;
tdesc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE;
}
else if (mips->type == PTI_3D)
// else if (mips->type == PTI_2D_ARRAY)
// {
// tdesc.ArraySize *= mips->mip[0].depth;
// }
else if (mips->type != PTI_2D)
return false; //nyi
//d3d11.1 formats
#define DXGI_FORMAT_B4G4R4A4_UNORM 115
//dxgi formats are expressed in little-endian bit order. byte-aligned formats are always in byte order and are thus little-endian even on big-endian machines.
//so byte aligned have the same order, while misligned need reversed order.
switch(mips->encoding)
{
default:
return false;
case PTI_DEPTH16:
tdesc.Format = DXGI_FORMAT_D16_UNORM;
tdesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
@ -174,18 +179,24 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
case PTI_RGB565:
tdesc.Format = DXGI_FORMAT_B5G6R5_UNORM;
break;
// case PTI_RGBA5551:
// tdesc.Format = DXGI_FORMAT_A1B5G5R5_UNORM;
// break;
case PTI_ARGB1555:
tdesc.Format = DXGI_FORMAT_B5G5R5A1_UNORM;
break;
case PTI_RGBA4444:
tdesc.Format = DXGI_FORMAT_B4G4R4A4_UNORM;
case PTI_RGBA5551:
// tdesc.Format = DXGI_FORMAT_A1B5G5R5_UNORM;
break;
// case PTI_ARGB4444:
case PTI_ARGB4444:
tdesc.Format = DXGI_FORMAT_B4G4R4A4_UNORM; //DX11.1
break;
case PTI_RGBA4444:
// tdesc.Format = DXGI_FORMAT_A4B4G4R4_UNORM;
// break;
break;
case PTI_RGB8:
// tdesc.Format = DXGI_FORMAT_R8G8B8_UNORM;
break;
case PTI_BGR8:
// tdesc.Format = DXGI_FORMAT_B8G8R8_UNORM;
break;
case PTI_RGBA8:
tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
break;
@ -198,6 +209,12 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
case PTI_BGRX8:
tdesc.Format = DXGI_FORMAT_B8G8R8X8_UNORM;
break;
case PTI_A2BGR10: //mostly for rendertargets, might also be useful for overbight lightmaps.
tdesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
break;
case PTI_E5BGR9:
tdesc.Format = DXGI_FORMAT_R9G9B9E5_SHAREDEXP;
break;
case PTI_RGBA8_SRGB:
tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@ -235,19 +252,19 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
case PTI_BC4_R8:
tdesc.Format = DXGI_FORMAT_BC4_UNORM;
break;
case PTI_BC4_R8_SIGNED:
case PTI_BC4_R8_SNORM:
tdesc.Format = DXGI_FORMAT_BC4_SNORM;
break;
case PTI_BC5_RG8:
tdesc.Format = DXGI_FORMAT_BC5_UNORM;
break;
case PTI_BC5_RG8_SIGNED:
case PTI_BC5_RG8_SNORM:
tdesc.Format = DXGI_FORMAT_BC5_SNORM;
break;
case PTI_BC6_RGBF:
case PTI_BC6_RGB_UFLOAT:
tdesc.Format = DXGI_FORMAT_BC6H_UF16;
break;
case PTI_BC6_RGBF_SIGNED:
case PTI_BC6_RGB_SFLOAT:
tdesc.Format = DXGI_FORMAT_BC6H_SF16;
break;
case PTI_BC7_RGBA:
@ -256,6 +273,77 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
case PTI_BC7_RGBA_SRGB:
tdesc.Format = DXGI_FORMAT_BC7_UNORM_SRGB;
break;
case PTI_RGBA16F:
tdesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
break;
case PTI_RGBA32F:
tdesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
break;
case PTI_L8: //UNSUPPORTED
case PTI_R8:
tdesc.Format = DXGI_FORMAT_R8_UNORM;
break;
case PTI_L8A8: //UNSUPPORTED
case PTI_RG8:
tdesc.Format = DXGI_FORMAT_R8G8_UNORM;
break;
case PTI_R8_SNORM:
tdesc.Format = DXGI_FORMAT_R8_SNORM;
break;
case PTI_RG8_SNORM:
tdesc.Format = DXGI_FORMAT_R8G8_SNORM;
break;
case PTI_ETC1_RGB8: //not invented here...
case PTI_ETC2_RGB8:
case PTI_ETC2_RGB8A1:
case PTI_ETC2_RGB8A8:
case PTI_ETC2_RGB8_SRGB:
case PTI_ETC2_RGB8A1_SRGB:
case PTI_ETC2_RGB8A8_SRGB:
case PTI_EAC_R11:
case PTI_EAC_R11_SNORM:
case PTI_EAC_RG11:
case PTI_EAC_RG11_SNORM:
case PTI_ASTC_4X4: //not invented here...
case PTI_ASTC_4X4_SRGB:
case PTI_ASTC_5X4:
case PTI_ASTC_5X4_SRGB:
case PTI_ASTC_5X5:
case PTI_ASTC_5X5_SRGB:
case PTI_ASTC_6X5:
case PTI_ASTC_6X5_SRGB:
case PTI_ASTC_6X6:
case PTI_ASTC_6X6_SRGB:
case PTI_ASTC_8X5:
case PTI_ASTC_8X5_SRGB:
case PTI_ASTC_8X6:
case PTI_ASTC_8X6_SRGB:
case PTI_ASTC_10X5:
case PTI_ASTC_10X5_SRGB:
case PTI_ASTC_10X6:
case PTI_ASTC_10X6_SRGB:
case PTI_ASTC_8X8:
case PTI_ASTC_8X8_SRGB:
case PTI_ASTC_10X8:
case PTI_ASTC_10X8_SRGB:
case PTI_ASTC_10X10:
case PTI_ASTC_10X10_SRGB:
case PTI_ASTC_12X10:
case PTI_ASTC_12X10_SRGB:
case PTI_ASTC_12X12:
case PTI_ASTC_12X12_SRGB:
#ifdef FTE_TARGET_WEB
case PTI_WHOLEFILE: //basically webgl only...
#endif
case PTI_MAX: //not actually valid...
case PTI_EMULATED: //not hardware-compatible.
break;
}
if (tdesc.Format == DXGI_FORMAT_UNKNOWN)
{
return false;
}
Image_BlockSizeForEncoding(mips->encoding, &blockbytes, &blockwidth, &blockheight);
@ -284,13 +372,13 @@ qboolean D3D11_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mi
}
void D3D11_UploadLightmap(lightmapinfo_t *lm)
{
extern cvar_t gl_lightmap_nearest;
extern cvar_t r_lightmap_nearest;
struct pendingtextureinfo mips;
image_t *tex;
lm->modified = false;
if (!TEXVALID(lm->lightmap_texture))
{
lm->lightmap_texture = Image_CreateTexture("***lightmap***", NULL, (gl_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR));
lm->lightmap_texture = Image_CreateTexture("***lightmap***", NULL, (r_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR));
if (!lm->lightmap_texture)
return;
}
@ -305,15 +393,22 @@ void D3D11_UploadLightmap(lightmapinfo_t *lm)
mips.mip[0].datasize = lm->width*lm->height*4;
switch (lightmap_fmt)
{
case TF_BGRA32:
default:
case PTI_A2BGR10:
case PTI_E5BGR9:
case PTI_RGBA16F:
case PTI_RGBA32F:
mips.encoding = lightmap_fmt;
break;
case PTI_BGRA8:
mips.encoding = PTI_BGRX8;
break;
case TF_RGBA32:
case PTI_RGBA8:
mips.encoding = PTI_RGBX8;
break;
default:
Sys_Error("D3D11_UploadLightmap: Unsupported format");
return;
case PTI_L8:
mips.encoding = PTI_R8; //FIXME: unspported
break;
}
mips.mipcount = 1;
D3D11_LoadTextureMips(tex, &mips);

View File

@ -454,9 +454,6 @@ void D3D8BE_Reset(qboolean before)
/*force all state to change, thus setting a known state*/
shaderstate.shaderbits = ~0;
BE_ApplyShaderBits(0);
Surf_BuildLightmaps();
}
}
@ -2658,7 +2655,7 @@ static void BE_UploadLightmaps(qboolean force)
if (lightmap[i]->modified)
{
extern cvar_t gl_lightmap_nearest;
extern cvar_t r_lightmap_nearest;
IDirect3DTexture8 *tex;
D3DLOCKED_RECT lock;
RECT rect;
@ -2667,7 +2664,7 @@ static void BE_UploadLightmaps(qboolean force)
int w;
if (!TEXLOADED(lm->lightmap_texture))
lm->lightmap_texture = Image_CreateTexture("***lightmap***", NULL, (gl_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP);
lm->lightmap_texture = Image_CreateTexture("***lightmap***", NULL, (r_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP);
tex = lm->lightmap_texture->ptr;
if (!tex)
{

View File

@ -30,12 +30,15 @@ qboolean D3D8_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
qbyte *fte_restrict out, *fte_restrict in;
int x, y, i;
D3DLOCKED_RECT lock;
D3DFORMAT fmt;
D3DFORMAT fmt = D3DFMT_UNKNOWN;
D3DSURFACE_DESC desc;
IDirect3DTexture8 *dt;
qboolean swap = false;
unsigned int blockwidth, blockheight, blockbytes = 1;
if (mips->type != PTI_2D)
return false; //fixme: cube and volumes should work
switch(mips->encoding)
{
case PTI_RGB565:
@ -80,9 +83,12 @@ qboolean D3D8_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
fmt = D3DFMT_DXT5;
break;
case PTI_EMULATED:
default: //no idea
return false;
break;
}
if (fmt == D3DFMT_UNKNOWN)
return false;
Image_BlockSizeForEncoding(mips->encoding, &blockbytes, &blockwidth, &blockheight);

View File

@ -654,9 +654,6 @@ void D3D9BE_Reset(qboolean before)
/*force all state to change, thus setting a known state*/
shaderstate.shaderbits = ~0;
BE_ApplyShaderBits(0);
Surf_BuildLightmaps();
}
}
@ -3080,7 +3077,7 @@ static void BE_UploadLightmaps(qboolean force)
if (lightmap[i]->modified)
{
extern cvar_t gl_lightmap_nearest;
extern cvar_t r_lightmap_nearest;
IDirect3DTexture9 *tex;
D3DLOCKED_RECT lock;
RECT rect;
@ -3089,11 +3086,42 @@ static void BE_UploadLightmaps(qboolean force)
int w;
if (!TEXLOADED(lm->lightmap_texture))
lm->lightmap_texture = Image_CreateTexture("***lightmap***", NULL, (gl_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP);
lm->lightmap_texture = Image_CreateTexture("***lightmap***", NULL, (r_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP);
tex = lm->lightmap_texture->ptr;
if (!tex)
{
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL);
switch(lightmap_fmt)
{
default:
break;
case PTI_BGRA8:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_BGRX8:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_RGB565:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_ARGB4444:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_ARGB1555:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A1R5G5B5, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_A2BGR10:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A2B10G10R10, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_L8:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_RGBA16F:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A16B16G16R16F, D3DPOOL_MANAGED, &tex, NULL);
break;
case PTI_RGBA32F:
IDirect3DDevice9_CreateTexture(pD3DDev9, lm->width, lm->height, 1, 0, D3DFMT_A32B32G32R32F, D3DPOOL_MANAGED, &tex, NULL);
break;
}
if (!tex)
continue;
lm->lightmap_texture->ptr = tex;

View File

@ -23,7 +23,7 @@ qboolean D3D9_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
qbyte *fte_restrict out, *fte_restrict in;
int x, y, i;
D3DLOCKED_RECT lock;
D3DFORMAT fmt;
D3DFORMAT fmt = D3DFMT_UNKNOWN;
D3DSURFACE_DESC desc;
IDirect3DBaseTexture9 *dbt;
qboolean swap = false;
@ -65,6 +65,10 @@ qboolean D3D9_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
fmt = D3DFMT_X8R8G8B8;
break;
case PTI_A2BGR10:
fmt = D3DFMT_A2B10G10R10;
break;
//too lazy to support these for now
case PTI_BC1_RGB_SRGB:
case PTI_BC1_RGBA_SRGB: //d3d doesn't distinguish between these
@ -84,9 +88,12 @@ qboolean D3D9_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
//bc4-7 not supported on d3d9.
//etc2 have no chance.
default: //no idea
return false;
case PTI_EMULATED: //no idea
default:
break;
}
if (fmt == D3DFMT_UNKNOWN)
return false;
Image_BlockSizeForEncoding(mips->encoding, &blockbytes, &blockwidth, &blockheight);
@ -136,7 +143,7 @@ qboolean D3D9_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
IDirect3DCubeTexture9_UnlockRect(dt, i%6, i/6);
}
}
else
else if (mips->type == PTI_2D)
{
IDirect3DTexture9 *dt;
if (FAILED(IDirect3DDevice9_CreateTexture(pD3DDev9, mips->mip[0].width, mips->mip[0].height, mips->mipcount, 0, fmt, D3DPOOL_MANAGED, &dt, NULL)))
@ -180,6 +187,8 @@ qboolean D3D9_LoadTextureMips(image_t *tex, const struct pendingtextureinfo *mip
IDirect3DTexture9_UnlockRect(dt, i);
}
}
else
dbt = NULL;
D3D9_DestroyTexture(tex);
tex->ptr = dbt;

View File

@ -444,7 +444,7 @@ static LRESULT WINAPI D3D9_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
static void D3D9_VID_SwapBuffers(void)
{
if (d3dpp.Windowed && (vid_srgb.ival==1 || vid.srgb))
if (vid.flags&VID_SRGB_FB_FAKED)
{
IDirect3DSwapChain9 *swapchain;
IDirect3DDevice9_GetSwapChain(pD3DDev9, 0, &swapchain);
@ -526,6 +526,8 @@ static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int de
{
if (info->bpp == 16)
d3dpp.BackBufferFormat = D3DFMT_R5G6B5;
else if (info->bpp == 30)
d3dpp.BackBufferFormat = D3DFMT_A2R10G10B10;
else
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
}
@ -580,6 +582,8 @@ static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int de
vid.numpages = d3dpp.BackBufferCount;
vid.flags = VID_SRGB_CAPABLE;
if (d3dpp.Windowed) //fullscreen we get positioned automagically.
{ //windowed, we get positioned at 0,0... which is often going to be on the wrong screen
//the user can figure it out from here
@ -619,6 +623,10 @@ static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int de
{PTI_RGB565, D3DFMT_R5G6B5, D3DUSAGE_QUERY_FILTER},
{PTI_ARGB1555, D3DFMT_A1R5G5B5, D3DUSAGE_QUERY_FILTER},
{PTI_ARGB4444, D3DFMT_A4R4G4B4, D3DUSAGE_QUERY_FILTER},
{PTI_A2BGR10, D3DFMT_A2B10G10R10, D3DUSAGE_QUERY_FILTER},
{PTI_RGBA16F, D3DFMT_A16B16G16R16F, D3DUSAGE_QUERY_FILTER},
{PTI_RGBA32F, D3DFMT_A32B32G32R32F, D3DUSAGE_QUERY_FILTER},
{PTI_L8, D3DFMT_L8, D3DUSAGE_QUERY_FILTER},
{PTI_BGRX8_SRGB, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER|D3DUSAGE_QUERY_SRGBREAD},
{PTI_BGRA8_SRGB, D3DFMT_A8R8G8B8, D3DUSAGE_QUERY_FILTER|D3DUSAGE_QUERY_SRGBREAD},
@ -639,10 +647,10 @@ static qboolean initD3D9Device(HWND hWnd, rendererstate_t *info, unsigned int de
//fixme: the engine kinda insists on rgba textures, which d3d9 does NOT support.
//we currently have some swapping, so these load, just slowly.
sh_config.texfmt[PTI_RGBX8] = sh_config.texfmt[PTI_BGRX8];
sh_config.texfmt[PTI_RGBA8] = sh_config.texfmt[PTI_BGRA8];
sh_config.texfmt[PTI_RGBX8_SRGB] = sh_config.texfmt[PTI_BGRX8_SRGB];
sh_config.texfmt[PTI_RGBA8_SRGB] = sh_config.texfmt[PTI_BGRA8_SRGB];
sh_config.texfmt[PTI_RGBX8] |= sh_config.texfmt[PTI_BGRX8];
sh_config.texfmt[PTI_RGBA8] |= sh_config.texfmt[PTI_BGRA8];
sh_config.texfmt[PTI_RGBX8_SRGB] |= sh_config.texfmt[PTI_BGRX8_SRGB];
sh_config.texfmt[PTI_RGBA8_SRGB] |= sh_config.texfmt[PTI_BGRA8_SRGB];
return true; //successful
}
@ -975,7 +983,7 @@ static qboolean (D3D9_SCR_UpdateScreen) (void)
return false; // not initialized yet
}
if (d3d_resized && d3dpp.Windowed)
if (d3d_resized/* && d3dpp.Windowed*/)
{
extern cvar_t vid_conautoscale, vid_conwidth;
d3d_resized = false;
@ -998,7 +1006,11 @@ static qboolean (D3D9_SCR_UpdateScreen) (void)
if (vid_srgb.modified)
{
vid_srgb.modified = false;
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, (vid_srgb.ival==1 || vid.srgb) && !d3dpp.Windowed);
vid.flags &= VID_SRGB_FB;
if ((vid.flags & VID_SRGBAWARE) || vid_srgb.ival)
vid.flags |= (d3dpp.Windowed)?VID_SRGB_FB_FAKED:VID_SRGB_FB_LINEAR;
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, !!(vid.flags&VID_SRGB_FB_LINEAR));
}
switch (IDirect3DDevice9_TestCooperativeLevel(pD3DDev9))
@ -1168,8 +1180,14 @@ static qboolean (D3D9_SCR_UpdateScreen) (void)
static void (D3D9_Draw_Init) (void)
{
vid.srgb = vid_srgb.ival>1;
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, (vid_srgb.ival==1 || vid.srgb) && !d3dpp.Windowed);
{
vid_srgb.modified = false;
vid.flags &= VID_SRGB_FB;
if ((vid.flags & VID_SRGBAWARE) || vid_srgb.ival)
vid.flags |= (d3dpp.Windowed)?VID_SRGB_FB_FAKED:VID_SRGB_FB_LINEAR;
IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_SRGBWRITEENABLE, !!(vid.flags&VID_SRGB_FB_LINEAR));
}
R2D_Init();
}

View File

@ -7,6 +7,8 @@
#include "renderque.h"
#include "resource.h"
#define FUCKDXGI
#define COBJMACROS
#include <d3d11.h>
@ -144,14 +146,14 @@ static void D3D11_PresentOrCrash(void)
{
extern cvar_t vid_vsync;
RSpeedMark();
HRESULT hr = IDXGISwapChain_Present(d3dswapchain, vid_vsync.ival, 0);
HRESULT hr = IDXGISwapChain_Present(d3dswapchain, max(0,vid_vsync.ival), 0);
if (FAILED(hr))
Sys_Error("IDXGISwapChain_Present: %s\n", D3D_NameForResult(hr));
RSpeedEnd(RSPEED_PRESENT);
}
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLDIB, MS_UNINIT} modestate_t;
static modestate_t modestate;
typedef enum {MS_WINDOWED, MS_FULLSCREEN, MS_FULLWINDOW, MS_UNINIT} dx11modestate_t;
static dx11modestate_t modestate;
//FIXME: need to push/pop render targets like gl does, to not harm shadowmaps/refraction/etc.
void D3D11_ApplyRenderTargets(qboolean usedepth)
@ -285,7 +287,7 @@ static qboolean D3D11AppActivate(BOOL fActive, BOOL minimize)
return true;
}
#ifndef FUCKDXGI
static void D3D11_DoResize(void)
{
d3d_resized = true;
@ -312,14 +314,30 @@ static void D3D11_DoResize(void)
resetd3dbackbuffer(vid.pixelwidth, vid.pixelheight);
D3D11BE_Reset(false);
}
#endif
static void ClearAllStates (void)
{
int i;
// send an up event for each key, to make sure the server clears them all
for (i=0 ; i<256 ; i++)
{
Key_Event (0, i, 0, false);
}
Key_ClearStates ();
INS_ClearStates ();
}
static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LONG lRet = 0;
int fActive, fMinimized, temp;
int temp;
extern unsigned int uiWheelMessage;
#ifndef FUCKDXGI
extern qboolean keydown[K_MAX];
#endif
if ( uMsg == uiWheelMessage )
uMsg = WM_MOUSEWHEEL;
@ -327,11 +345,24 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
switch (uMsg)
{
#if 1
/* case WM_KILLFOCUS:
if (modestate == MS_FULLDIB)
case WM_KILLFOCUS:
if (modestate == MS_FULLWINDOW)
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
D3D11AppActivate(false, false);
break;
*/
case WM_SETFOCUS:
if (modestate == MS_FULLWINDOW)
ShowWindow(mainwindow, SW_SHOWMAXIMIZED);
D3D11AppActivate(true, false);
if (modestate == MS_FULLSCREEN && d3dswapchain)
IDXGISwapChain_SetFullscreenState(d3dswapchain, vid.activeapp, (vid.activeapp)?d3dscreen:NULL);
Cvar_ForceCallback(&v_gamma);
ClearAllStates ();
break;
// case WM_CREATE:
// break;
@ -342,6 +373,7 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
#ifndef FUCKDXGI
if (keydown[K_LALT] && wParam == '\r')
{
if (d3dscreen)
@ -402,7 +434,9 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
D3D11_DoResize();
Cvar_ForceCallback(&v_gamma);
}
else if (!vid_initializing)
else
#endif
if (!vid_initializing)
INS_TranslateKeyEvent (wParam, lParam, true, 0, false);
break;
@ -555,31 +589,6 @@ static LRESULT WINAPI D3D11_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
break;
case WM_ACTIVATE:
fActive = LOWORD(wParam);
fMinimized = (BOOL) HIWORD(wParam);
if (!D3D11AppActivate(!(fActive == WA_INACTIVE), fMinimized))
break;//so, urm, tell me microsoft, what changed?
if (modestate == MS_FULLDIB)
ShowWindow(mainwindow, SW_SHOWNORMAL);
if (modestate == MS_FULLSCREEN)
{
if (d3dswapchain)
{
IDXGISwapChain_SetFullscreenState(d3dswapchain, vid.activeapp, d3dscreen);
D3D11_DoResize();
}
}
Cvar_ForceCallback(&v_gamma);
// fix the leftover Alt from any Alt-Tab or the like that switched us away
// ClearAllStates ();
lRet = 1;
break;
case WM_DESTROY:
{
// if (dibwindow)
@ -791,7 +800,17 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
scd.BufferDesc.RefreshRate.Numerator = 0;
scd.BufferDesc.RefreshRate.Denominator = 0;
scd.BufferCount = 1+info->triplebuffer; //back buffer count
scd.BufferDesc.Format = info->srgb?DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:DXGI_FORMAT_R8G8B8A8_UNORM; //32bit colour
if (info->srgb)
{
if (info->srgb >= 3) //fixme: detect properly.
scd.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT; //on nvidia, outputs linear rgb to srgb devices, which means info->srgb is effectively set
else
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
}
else if (info->bpp == 30) //fixme: detect properly.
scd.BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM;
else
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = hWnd;
scd.SampleDesc.Count = d3d11multisample_count = max(1, info->multisample); //as we're starting up windowed (and switching to fullscreen after), the frontbuffer is handled by windows.
@ -856,29 +875,65 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
#define DXGI_FORMAT_B4G4R4A4_UNORM 115
//why does d3d11 have no rgbx format? anyone else think that weird?
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B5G6R5_UNORM, &support); sh_config.texfmt[PTI_RGB565] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B5G5R5A1_UNORM, &support); sh_config.texfmt[PTI_ARGB1555] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B4G4R4A4_UNORM, &support); sh_config.texfmt[PTI_ARGB4444] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R8G8B8A8_UNORM, &support); sh_config.texfmt[PTI_RGBA8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8A8_UNORM, &support); sh_config.texfmt[PTI_BGRA8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8X8_UNORM, &support); sh_config.texfmt[PTI_BGRX8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &support); sh_config.texfmt[PTI_RGBA8_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, &support); sh_config.texfmt[PTI_BGRA8_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, &support); sh_config.texfmt[PTI_BGRX8_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC1_UNORM, &support); sh_config.texfmt[PTI_BC1_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC2_UNORM, &support); sh_config.texfmt[PTI_BC2_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC3_UNORM, &support); sh_config.texfmt[PTI_BC3_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC1_UNORM_SRGB, &support); sh_config.texfmt[PTI_BC1_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC2_UNORM_SRGB, &support); sh_config.texfmt[PTI_BC2_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC3_UNORM_SRGB, &support); sh_config.texfmt[PTI_BC3_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC4_UNORM, &support); sh_config.texfmt[PTI_BC4_R8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC4_SNORM, &support); sh_config.texfmt[PTI_BC4_R8_SIGNED] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC5_UNORM, &support); sh_config.texfmt[PTI_BC5_RG8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC5_SNORM, &support); sh_config.texfmt[PTI_BC5_RG8_SIGNED] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC6H_UF16, &support); sh_config.texfmt[PTI_BC6_RGBF] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC6H_SF16, &support); sh_config.texfmt[PTI_BC6_RGBF_SIGNED] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC7_UNORM, &support); sh_config.texfmt[PTI_BC7_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC7_UNORM_SRGB, &support); sh_config.texfmt[PTI_BC7_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B5G6R5_UNORM, &support))) //crippled to win8+ only.
sh_config.texfmt[PTI_RGB565] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B5G5R5A1_UNORM, &support))) //crippled to win8+ only.
sh_config.texfmt[PTI_ARGB1555] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B4G4R4A4_UNORM, &support))) //crippled to win8+ only.
sh_config.texfmt[PTI_ARGB4444] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R8G8B8A8_UNORM, &support)))
sh_config.texfmt[PTI_RGBA8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_RGBA8_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R10G10B10A2_UNORM, &support)))
sh_config.texfmt[PTI_A2BGR10] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) && !!(support & D3D11_FORMAT_SUPPORT_RENDER_TARGET);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, &support)))
sh_config.texfmt[PTI_E5BGR9] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R16G16B16A16_FLOAT, &support)))
sh_config.texfmt[PTI_RGBA16F] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) && !!(support & D3D11_FORMAT_SUPPORT_RENDER_TARGET);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_R32G32B32A32_FLOAT, &support)))
sh_config.texfmt[PTI_RGBA32F] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D) && !!(support & D3D11_FORMAT_SUPPORT_RENDER_TARGET);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8A8_UNORM, &support)))
sh_config.texfmt[PTI_BGRA8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_BGRA8_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8X8_UNORM, &support)))
sh_config.texfmt[PTI_BGRX8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_B8G8R8X8_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_BGRX8_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
//compressed formats
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC1_UNORM, &support)))
sh_config.texfmt[PTI_BC1_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC1_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_BC1_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC2_UNORM, &support)))
sh_config.texfmt[PTI_BC2_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC2_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_BC2_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC3_UNORM, &support)))
sh_config.texfmt[PTI_BC3_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC3_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_BC3_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC4_UNORM, &support)))
sh_config.texfmt[PTI_BC4_R8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC4_SNORM, &support)))
sh_config.texfmt[PTI_BC4_R8_SNORM] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC5_UNORM, &support)))
sh_config.texfmt[PTI_BC5_RG8] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC5_SNORM, &support)))
sh_config.texfmt[PTI_BC5_RG8_SNORM] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC6H_UF16, &support)))
sh_config.texfmt[PTI_BC6_RGB_UFLOAT] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC6H_SF16, &support)))
sh_config.texfmt[PTI_BC6_RGB_SFLOAT] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC7_UNORM, &support)))
sh_config.texfmt[PTI_BC7_RGBA] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
if (SUCCEEDED(ID3D11Device_CheckFormatSupport(pD3DDev11, DXGI_FORMAT_BC7_UNORM_SRGB, &support)))
sh_config.texfmt[PTI_BC7_RGBA_SRGB] = !!(support & D3D11_FORMAT_SUPPORT_TEXTURE2D);
//these formats are not officially supported as specified, but noone cares
sh_config.texfmt[PTI_RGBX8] = sh_config.texfmt[PTI_RGBA8];
@ -886,7 +941,22 @@ static qboolean initD3D11Device(HWND hWnd, rendererstate_t *info, PFN_D3D11_CREA
sh_config.texfmt[PTI_BC1_RGB] = sh_config.texfmt[PTI_BC1_RGBA];
sh_config.texfmt[PTI_BC1_RGB_SRGB] = sh_config.texfmt[PTI_BC1_RGBA_SRGB];
vid.srgb = info->srgb>1;
switch(scd.BufferDesc.Format)
{
case DXGI_FORMAT_R16G16B16A16_FLOAT:
vid.flags |= VID_SRGB_FB_LINEAR|VID_FP16; //these are apparently linear already.
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
vid.flags |= VID_SRGB_FB_LINEAR; //effectively linear.
break;
default:
//non-linear formats.
break;
}
if ((vid.flags & VID_SRGB_FB) && info->srgb != 1)
vid.flags |= VID_SRGBAWARE;
vid.numpages = scd.BufferCount;
if (!D3D11Shader_Init(flevel))
@ -987,15 +1057,30 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
RegisterClass(&wc);
modestate = info->fullscreen?MS_FULLSCREEN:MS_WINDOWED;
if (info->fullscreen/* == 2*/)
modestate = MS_FULLWINDOW;
else if (info->fullscreen)
modestate = MS_FULLSCREEN; //FIXME: I'm done with fighting dxgi. I'm just going to pick the easy method that doesn't end up with totally fucked up behaviour.
else
modestate = MS_WINDOWED;
wstyle = WS_OVERLAPPEDWINDOW;
rect.left = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
rect.top = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
rect.right = rect.left+width;
rect.bottom = rect.top+height;
AdjustWindowRectEx(&rect, wstyle, FALSE, 0);
if (modestate == MS_FULLWINDOW)
{
wstyle = WS_POPUP;
rect.right = GetSystemMetrics(SM_CXSCREEN);
rect.bottom = GetSystemMetrics(SM_CYSCREEN);
rect.left = 0;
rect.top = 0;
}
else
{
wstyle = WS_OVERLAPPEDWINDOW;
rect.left = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
rect.top = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
rect.right = rect.left+width;
rect.bottom = rect.top+height;
AdjustWindowRectEx(&rect, wstyle, FALSE, 0);
}
mainwindow = CreateWindow(CLASSNAME, "Direct3D11", wstyle, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, NULL, NULL, NULL, NULL);
// Try as specified.
@ -1010,16 +1095,16 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
return false;
}
if (info->fullscreen)
vid.pixelwidth = width;
vid.pixelheight = height;
if (modestate == MS_FULLSCREEN)
{
if (!d3dscreen)
IDXGISwapChain_GetContainingOutput(d3dswapchain, &d3dscreen);
IDXGISwapChain_SetFullscreenState(d3dswapchain, true, d3dscreen);
}
vid.pixelwidth = width;
vid.pixelheight = height;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
@ -1028,7 +1113,10 @@ static qboolean D3D11_VID_Init(rendererstate_t *info, unsigned char *palette)
CL_UpdateWindowTitle();
ShowWindow(mainwindow, SW_SHOWNORMAL);
if (modestate == MS_FULLWINDOW)
ShowWindow(mainwindow, SW_SHOWMAXIMIZED);
else
ShowWindow(mainwindow, SW_SHOWNORMAL);
vid.width = vid.pixelwidth;
vid.height = vid.pixelheight;

View File

@ -827,8 +827,6 @@ static qboolean D3D8_VID_Init(rendererstate_t *info, unsigned char *palette)
vid.width = width;
vid.height = height;
vid.srgb = false;
vid_initializing = false;
IDirect3DDevice8_SetRenderState(pD3DDev8, D3DRS_LIGHTING, FALSE);

View File

@ -43,7 +43,7 @@
>
<Tool
Name="VCNMakeTool"
BuildCommandLine="cd $(InputDir)\.. &amp;&amp; vcify make droid-rel ANDROID_HOME=C:/Games/tools/android-sdk ANDROID_NDK_ROOT=C:/Games/tools/android-ndk-r8e ANT=C:/Games/tools/apache-ant-1.8.2/bin/ant JAVATOOL=&quot;C:/Program\ Files/Java/jdk1.7.0_02/bin/&quot; -j8 DROID_ARCH=&quot;armeabi x86&quot; ZIPALIGN=C:/Games/tools/android-sdk/build-tools/23.0.3/zipalign CFLAGS=-DCRAZYDEBUGGING DROID_ABI_VER=4.6"
BuildCommandLine="cd $(InputDir)\.. &amp;&amp; vcify make droid-rel ANDROID_HOME=C:/Games/tools/android-sdk ANDROID_NDK_ROOT=C:/Games/tools/android-ndk-r8e ANT=C:/Games/tools/apache-ant-1.8.2/bin/ant JAVATOOL=&quot;C:/Program\ Files/Java/jdk1.7.0_02/bin/&quot; -j8 DROID_ARCH=&quot;armeabi x86&quot; ZIPALIGN=C:/Games/tools/android-sdk/build-tools/23.0.3/zipalign CFLAGS=-ggdb DROID_ABI_VER=4.6 LDFLAGS=-ggdb"
ReBuildCommandLine=""
CleanCommandLine=""
Output="$(TargetDir)\FTEDroid.apk"

View File

@ -99,6 +99,8 @@ Global
VkDebug|x64 = VkDebug|x64
VkRelease|Win32 = VkRelease|Win32
VkRelease|x64 = VkRelease|x64
Wastes_Debug|Win32 = Wastes_Debug|Win32
Wastes_Debug|x64 = Wastes_Debug|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0018E098-B12A-4E4D-9B22-6772DA287080}.D3DDebug|Win32.ActiveCfg = Release|Win32
@ -141,6 +143,9 @@ Global
{0018E098-B12A-4E4D-9B22-6772DA287080}.VkRelease|Win32.ActiveCfg = Release|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.VkRelease|Win32.Build.0 = Release|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.VkRelease|x64.ActiveCfg = Release|x64
{0018E098-B12A-4E4D-9B22-6772DA287080}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{0018E098-B12A-4E4D-9B22-6772DA287080}.Wastes_Debug|x64.ActiveCfg = Debug|x64
{2866F783-6B44-4655-A38D-D53874037454}.D3DDebug|Win32.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.D3DDebug|x64.ActiveCfg = Release|x64
{2866F783-6B44-4655-A38D-D53874037454}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -157,7 +162,7 @@ Global
{2866F783-6B44-4655-A38D-D53874037454}.GLRelease|x64.ActiveCfg = Release|x64
{2866F783-6B44-4655-A38D-D53874037454}.MDebug|Win32.ActiveCfg = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.MDebug|Win32.Build.0 = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.MDebug|x64.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.MDebug|x64.ActiveCfg = Release|x64
{2866F783-6B44-4655-A38D-D53874037454}.MinGLDebug|Win32.ActiveCfg = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.MinGLDebug|x64.ActiveCfg = Debug|x64
{2866F783-6B44-4655-A38D-D53874037454}.MinGLRelease|Win32.ActiveCfg = Release|Win32
@ -180,6 +185,9 @@ Global
{2866F783-6B44-4655-A38D-D53874037454}.VkRelease|Win32.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.VkRelease|Win32.Build.0 = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.VkRelease|x64.ActiveCfg = Release|Win32
{2866F783-6B44-4655-A38D-D53874037454}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{2866F783-6B44-4655-A38D-D53874037454}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|Win32.ActiveCfg = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DDebug|x64.ActiveCfg = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -212,6 +220,8 @@ Global
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.VkDebug|x64.ActiveCfg = Debug|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.VkRelease|Win32.ActiveCfg = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.VkRelease|x64.ActiveCfg = Release|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DDebug|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -240,6 +250,8 @@ Global
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.VkDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.VkRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.VkRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32A7282F56}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|Win32.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DDebug|x64.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -270,6 +282,8 @@ Global
{873CCE24-3549-49D4-A4B4-653F91B1532A}.VkDebug|x64.ActiveCfg = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.VkRelease|Win32.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.VkRelease|x64.ActiveCfg = Release|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{873CCE24-3549-49D4-A4B4-653F91B1532A}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.D3DDebug|Win32.ActiveCfg = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.D3DDebug|Win32.Build.0 = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.D3DDebug|x64.ActiveCfg = Release|Win32
@ -303,6 +317,8 @@ Global
{4877586B-E85B-4DF8-BCCE-59D31514D240}.VkDebug|x64.ActiveCfg = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.VkRelease|Win32.ActiveCfg = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.VkRelease|x64.ActiveCfg = Release|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{4877586B-E85B-4DF8-BCCE-59D31514D240}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DDebug|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.D3DDebug|x64.ActiveCfg = Release|x64
@ -341,6 +357,9 @@ Global
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.VkRelease|Win32.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.VkRelease|Win32.Build.0 = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.VkRelease|x64.ActiveCfg = Release|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{32B12987-DF8C-4E40-B07C-B18586A4CA65}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DDebug|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -371,6 +390,8 @@ Global
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.VkDebug|x64.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.VkRelease|Win32.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.VkRelease|x64.ActiveCfg = Release|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{4735677B-6D5A-4BE6-A945-CB32DEADBEEF}.Wastes_Debug|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DDebug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -408,6 +429,9 @@ Global
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.VkDebug|x64.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.VkRelease|Win32.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.VkRelease|x64.ActiveCfg = Release|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{9767E236-8454-44E9-8999-CD5BDAFBE9BA}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.D3DDebug|Win32.Build.0 = Debug|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.D3DDebug|x64.ActiveCfg = Debug|x64
@ -447,6 +471,9 @@ Global
{72269FEE-293D-40BC-A7AE-E429F4496869}.VkRelease|Win32.ActiveCfg = Release|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.VkRelease|Win32.Build.0 = Release|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.VkRelease|x64.ActiveCfg = Release|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{72269FEE-293D-40BC-A7AE-E429F4496869}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.D3DDebug|Win32.Build.0 = Debug|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -487,6 +514,9 @@ Global
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.VkDebug|x64.ActiveCfg = Debug|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.VkRelease|Win32.ActiveCfg = Release|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.VkRelease|x64.ActiveCfg = Release|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{E6BAD203-4704-4860-9C38-D4702E9CAD7D}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DDebug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.ActiveCfg = D3DDebug|x64
@ -543,6 +573,10 @@ Global
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.VkRelease|Win32.Build.0 = VkRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.VkRelease|x64.ActiveCfg = VkRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.VkRelease|x64.Build.0 = VkRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Wastes_Debug|Win32.ActiveCfg = Wastes_Debug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Wastes_Debug|Win32.Build.0 = Wastes_Debug|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Wastes_Debug|x64.ActiveCfg = MDebug|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Wastes_Debug|x64.Build.0 = MDebug|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DDebug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DDebug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.D3DDebug|x64.Build.0 = Debug Dedicated Server|x64
@ -584,6 +618,9 @@ Global
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.VkRelease|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.VkRelease|x64.ActiveCfg = Release Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.VkRelease|x64.Build.0 = Release Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Wastes_Debug|Win32.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Wastes_Debug|x64.ActiveCfg = Debug Dedicated Server|x64
{482A886A-5755-4DAE-AD5F-D7CD4A990F9E}.Wastes_Debug|x64.Build.0 = Debug Dedicated Server|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.D3DDebug|x64.Build.0 = GLRelease|x64
@ -629,6 +666,9 @@ Global
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.VkRelease|Win32.Build.0 = GLRelease|Win32
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.VkRelease|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.VkRelease|x64.Build.0 = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Wastes_Debug|Win32.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Wastes_Debug|x64.ActiveCfg = GLRelease|x64
{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1365}.Wastes_Debug|x64.Build.0 = GLRelease|x64
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.D3DDebug|Win32.Build.0 = Debug|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -668,6 +708,9 @@ Global
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.VkRelease|Win32.ActiveCfg = Release|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.VkRelease|Win32.Build.0 = Release|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.VkRelease|x64.ActiveCfg = Release|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{6ABD62A3-C5A0-43E8-BA4F-84606057774F}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.D3DDebug|Win32.Build.0 = Debug|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -703,6 +746,9 @@ Global
{74542CA7-48C1-4664-9007-66F751131EA3}.VkDebug|x64.ActiveCfg = Debug|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.VkRelease|Win32.ActiveCfg = Release|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.VkRelease|x64.ActiveCfg = Release|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{74542CA7-48C1-4664-9007-66F751131EA3}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DDebug|x64.ActiveCfg = Debug|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.D3DRelease|Win32.ActiveCfg = Release|Win32
@ -737,6 +783,8 @@ Global
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.VkDebug|x64.ActiveCfg = Debug|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.VkRelease|Win32.ActiveCfg = Release|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.VkRelease|x64.ActiveCfg = Release|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{75D91BDE-CC30-4C53-BF33-5F69EF13A61B}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.D3DDebug|Win32.Build.0 = Debug|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -778,6 +826,9 @@ Global
{82285268-9C3B-44AD-BBE7-40670F9D2628}.VkRelease|Win32.ActiveCfg = Release|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.VkRelease|Win32.Build.0 = Release|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.VkRelease|x64.ActiveCfg = Release|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{82285268-9C3B-44AD-BBE7-40670F9D2628}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.D3DDebug|Win32.Build.0 = Debug|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -818,6 +869,9 @@ Global
{ED16B405-BDCD-4EB8-BF70-761964301368}.VkRelease|Win32.ActiveCfg = Release|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.VkRelease|Win32.Build.0 = Release|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.VkRelease|x64.ActiveCfg = Release|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{ED16B405-BDCD-4EB8-BF70-761964301368}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DDebug|Win32.Build.0 = Debug|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -859,6 +913,9 @@ Global
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.VkRelease|Win32.ActiveCfg = Release|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.VkRelease|Win32.Build.0 = Release|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.VkRelease|x64.ActiveCfg = Release|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{E475BFF0-6766-48BA-BE44-931C068AC5B0}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{F756A3D2-025A-43D4-9829-4074753B774B}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{F756A3D2-025A-43D4-9829-4074753B774B}.D3DDebug|Win32.Build.0 = Debug|Win32
{F756A3D2-025A-43D4-9829-4074753B774B}.D3DDebug|x64.ActiveCfg = Debug|x64
@ -910,6 +967,10 @@ Global
{F756A3D2-025A-43D4-9829-4074753B774B}.VkRelease|Win32.Build.0 = Release|Win32
{F756A3D2-025A-43D4-9829-4074753B774B}.VkRelease|x64.ActiveCfg = Release|x64
{F756A3D2-025A-43D4-9829-4074753B774B}.VkRelease|x64.Build.0 = Release|x64
{F756A3D2-025A-43D4-9829-4074753B774B}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{F756A3D2-025A-43D4-9829-4074753B774B}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{F756A3D2-025A-43D4-9829-4074753B774B}.Wastes_Debug|x64.ActiveCfg = Debug|x64
{F756A3D2-025A-43D4-9829-4074753B774B}.Wastes_Debug|x64.Build.0 = Debug|x64
{909E9AE0-0617-469C-954E-1ED09367F90E}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.D3DDebug|Win32.Build.0 = Debug|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.D3DDebug|x64.ActiveCfg = Debug|x64
@ -951,6 +1012,9 @@ Global
{909E9AE0-0617-469C-954E-1ED09367F90E}.VkRelease|Win32.ActiveCfg = Release|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.VkRelease|Win32.Build.0 = Release|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.VkRelease|x64.ActiveCfg = Release|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{909E9AE0-0617-469C-954E-1ED09367F90E}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.D3DDebug|Win32.Build.0 = Debug|Win32
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.D3DDebug|x64.ActiveCfg = Debug|x64
@ -1003,6 +1067,10 @@ Global
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.VkRelease|Win32.Build.0 = Release|Win32
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.VkRelease|x64.ActiveCfg = Release|x64
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.VkRelease|x64.Build.0 = Release|x64
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.Wastes_Debug|x64.ActiveCfg = Debug|x64
{E6CDA919-628B-45BF-A5DB-FB55179D6443}.Wastes_Debug|x64.Build.0 = Debug|x64
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|Win32.Build.0 = Debug|Win32
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.D3DDebug|x64.ActiveCfg = Debug|x64
@ -1055,6 +1123,10 @@ Global
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|Win32.Build.0 = Release|Win32
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|x64.ActiveCfg = Release|x64
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.VkRelease|x64.Build.0 = Release|x64
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Wastes_Debug|x64.ActiveCfg = Debug|x64
{0AE4667A-A446-44E7-A758-69CF5D9AF8FC}.Wastes_Debug|x64.Build.0 = Debug|x64
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.D3DDebug|Win32.Build.0 = Debug|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -1097,6 +1169,9 @@ Global
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|Win32.ActiveCfg = Release|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|Win32.Build.0 = Release|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.VkRelease|x64.ActiveCfg = Release|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{0B1B2549-24DE-4FF2-844B-7A93ED5CF919}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DDebug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DDebug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.D3DDebug|x64.ActiveCfg = Debug|Win32
@ -1139,6 +1214,9 @@ Global
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkRelease|Win32.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkRelease|Win32.Build.0 = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.VkRelease|x64.ActiveCfg = Release|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Wastes_Debug|Win32.ActiveCfg = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Wastes_Debug|Win32.Build.0 = Debug|Win32
{1E65A0D3-3371-4602-A69C-53BA389FFBD9}.Wastes_Debug|x64.ActiveCfg = Debug|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

File diff suppressed because it is too large Load Diff

View File

@ -61,6 +61,7 @@ struct cctx_s
};
void Mod_FlushSkin(skinid_t id)
{
#ifdef QWSKINS
skinfile_t *sk;
id--;
if (id >= numregisteredskins)
@ -69,6 +70,7 @@ void Mod_FlushSkin(skinid_t id)
if (!sk)
return;
sk->qwskin = NULL;
#endif
}
void Mod_WipeSkin(skinid_t id, qboolean force)
{
@ -268,8 +270,10 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
skin->refcount++;
skin->maxmappings = 4;
Q_strncpyz(skin->skinname, skinname, sizeof(skin->skinname));
#ifdef QWSKINS
skin->q1lower = Q1UNSPECIFIED;
skin->q1upper = Q1UNSPECIFIED;
#endif
while(skintext)
{
@ -359,6 +363,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
{
//ignore it. matches q3.
}
#ifdef QWSKINS
else if (!strcmp(com_token, "qwskin"))
{
skintext = COM_ParseToken(skintext, NULL);
@ -380,6 +385,7 @@ skinid_t Mod_ReadSkinFile(const char *skinname, const char *skintext)
else
skin->q1upper = atoi(com_token);
}
#endif
else
{
while(*skintext == ' ' || *skintext == '\t')
@ -591,18 +597,16 @@ void R_GAliasFlushSkinCache(qboolean final)
static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, entity_t *e, texnums_t **forcedtex)
{
galiasskin_t *skins;
#ifdef QWSKINS
shader_t *shader;
qwskin_t *plskin = NULL;
int frame;
unsigned int subframe;
extern int cl_playerindex; //so I don't have to strcmp
unsigned int tc, bc, pc;
qboolean forced;
unsigned int tc = e->topcolour, bc = e->bottomcolour, pc;
qboolean generateupperlower = false;
tc = e->topcolour;
bc = e->bottomcolour;
qboolean forced;
extern int cl_playerindex; //so I don't have to strcmp
#endif
int frame;
*forcedtex = NULL;
/*q3 .skin files*/
@ -629,13 +633,15 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
*forcedtex = &sk->mappings[fallback].texnums;
return sk->mappings[fallback].shader;
}
if (!sk->qwskin && *sk->qwskinname)
sk->qwskin = Skin_Lookup(sk->qwskinname);
#ifdef QWSKINS
if (sk->q1lower != Q1UNSPECIFIED)
bc = e->bottomcolour = sk->q1lower;
if (sk->q1upper != Q1UNSPECIFIED)
tc = e->topcolour = sk->q1upper;
if (!sk->qwskin && *sk->qwskinname)
sk->qwskin = Skin_Lookup(sk->qwskinname);
plskin = sk->qwskin;
#endif
}
}
else if (inf->geomset < MAX_GEOMSETS && 0 != inf->geomid)
@ -655,7 +661,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
}
}
#ifdef QWSKINS
if ((e->model->engineflags & MDLF_NOTREPLACEMENTS) && !ruleset_allow_sensitive_texture_replacements.ival)
forced = true;
else
@ -1069,7 +1075,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
cm->texnum.paletted = R_LoadTexture(va("paletted$%x$%x$%i$%i$%i$%s", tc, bc, cm->skinnum, subframe, pc, cm->name),
scaled_width, scaled_height, TF_LUM8, pixels8, IF_NEAREST|IF_NOMIPMAP);
scaled_width, scaled_height, PTI_R8, pixels8, IF_NEAREST|IF_NOMIPMAP);
}
@ -1160,7 +1166,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
return shader;
}
}
#endif
if (!inf->numskins)
return NULL;
@ -1487,19 +1493,28 @@ qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel)
}
}
m = max(max(ambientlight[0], ambientlight[1]), ambientlight[2]);
if (m > 255)
switch(lightmap_fmt)
{
ambientlight[0] *= 255.0/m;
ambientlight[1] *= 255.0/m;
ambientlight[2] *= 255.0/m;
}
m = max(max(shadelight[0], shadelight[1]), shadelight[2]);
if (m > 128)
{
shadelight[0] *= 128.0/m;
shadelight[1] *= 128.0/m;
shadelight[2] *= 128.0/m;
case PTI_E5BGR9:
case PTI_RGBA16F:
case PTI_RGBA32F:
break;
default:
m = max(max(ambientlight[0], ambientlight[1]), ambientlight[2]);
if (m > 255)
{
ambientlight[0] *= 255.0/m;
ambientlight[1] *= 255.0/m;
ambientlight[2] *= 255.0/m;
}
m = max(max(shadelight[0], shadelight[1]), shadelight[2]);
if (m > 128)
{
shadelight[0] *= 128.0/m;
shadelight[1] *= 128.0/m;
shadelight[2] *= 128.0/m;
}
break;
}
//MORE HUGE HACKS! WHEN WILL THEY CEASE!
@ -1664,6 +1679,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
return;
clmodel = e->model;
#ifdef QWSKINS
/*switch model if we're the player model, and the player skin says a new model*/
{
extern int cl_playerindex;
@ -1674,6 +1690,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches)
clmodel = e->model; //oops, never mind
}
}
#endif
if (!(e->flags & RF_WEAPONMODEL)
#ifdef SKELETALMODELS

View File

@ -1176,7 +1176,12 @@ static void T_Gen_CurrentRender(int tmu)
qglGenTextures(1, &shaderstate.temptexture->num);
}
GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture);
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0);
if (vid.flags&VID_FP16)
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, 0, 0, vwidth, vheight, 0);
else if (vid.flags&VID_SRGBAWARE)
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 0, 0, vwidth, vheight, 0);
else
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -1377,6 +1382,7 @@ static float *FTableForFunc ( unsigned int func )
{
switch (func)
{
default:
case SHADER_FUNC_SIN:
return r_sintable;
@ -1391,10 +1397,10 @@ static float *FTableForFunc ( unsigned int func )
case SHADER_FUNC_INVERSESAWTOOTH:
return r_inversesawtoothtable;
}
//bad values allow us to crash (so I can debug em)
return NULL;
case SHADER_FUNC_NOISE:
return NULL;
}
}
void Shader_LightPass(const char *shortname, shader_t *s, const void *args)
@ -1506,9 +1512,16 @@ void GLBE_DestroyFBOs(void)
void GLBE_Shutdown(void)
{
size_t u;
GLBE_FBO_Destroy(&shaderstate.fbo_2dfbo);
GLBE_DestroyFBOs();
for (u = 0; u < countof(shaderstate.programfixedemu); u++)
{
Shader_ReleaseGeneric(shaderstate.programfixedemu[u]);
shaderstate.programfixedemu[u] = NULL;
}
BZ_Free(shaderstate.wbatches);
shaderstate.wbatches = NULL;
shaderstate.maxwbatches = 0;
@ -1624,7 +1637,11 @@ void GLBE_Init(void)
memset(&shaderstate.streamebo, 0, sizeof(shaderstate.streamebo));
memset(&shaderstate.streamvao, 0, sizeof(shaderstate.streamvao));
//only do this where we have to.
if (qglBufferDataARB && gl_config_nofixedfunc)
if (qglBufferDataARB && gl_config_nofixedfunc
#ifndef FTE_TARGET_WEB
&& !gl_config_gles
#endif
)
{
qglGenBuffersARB(sizeof(shaderstate.streamvbo)/sizeof(shaderstate.streamvbo[0]), shaderstate.streamvbo);
qglGenBuffersARB(sizeof(shaderstate.streamebo)/sizeof(shaderstate.streamebo[0]), shaderstate.streamebo);
@ -1919,7 +1936,7 @@ static void GenerateTCMods3(const shaderpass_t *pass, int passnum)
if (src != texcoordarray[passnum]+mesh->vbofirstvert*3)
{
//this shouldn't actually ever be true
memcpy(texcoordarray[passnum]+mesh->vbofirstvert*3, src, 8*mesh->numvertexes);
memcpy(texcoordarray[passnum]+mesh->vbofirstvert*3, src, sizeof(vec3_t)*mesh->numvertexes);
}
}
shaderstate.pendingtexcoordparts[passnum] = 3;
@ -3046,6 +3063,8 @@ static void BE_SubmitMeshChain(qboolean usetesselation)
index_t *fte_restrict ilst; //FIXME: this should be cached for multiple-pass shaders.
GL_SelectEBO(0);
//FIXME: use a coherant persistently mapped buffer.
mesh = shaderstate.meshes[0];
startv = mesh->vbofirstvert;
endv = startv + mesh->numvertexes;
@ -5245,7 +5264,7 @@ static void GLBE_SubmitMeshesSortList(batch_t *sortlist)
shaderstate.tex_ripplemap[r_refdef.recurse]->width = r_refdef.pxrect.width;
shaderstate.tex_ripplemap[r_refdef.recurse]->height = r_refdef.pxrect.height;
GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_ripplemap[r_refdef.recurse]);
qglTexImage2D(GL_TEXTURE_2D, 0, /*(gl_config.glversion>3.1)?GL_RGBA8_SNORM:*/GL_RGBA16F_ARB, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
qglTexImage2D(GL_TEXTURE_2D, 0, /*(gl_config.glversion>3.1)?GL_RGBA8_SNORM:*/GL_RGBA16F_ARB, r_refdef.pxrect.width, r_refdef.pxrect.height, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -5304,20 +5323,6 @@ static void BE_UpdateLightmaps(void)
{
lightmapinfo_t *lm;
int lmidx;
int glformat, gltype;
int internalformat = /*vid.srgb?GL_SRGB8_ALPHA8_EXT:*/GL_RGBA;
switch (lightmap_fmt)
{
case TF_INVALID: return;
default: Sys_Error("Bad lightmap_fmt\n"); return;
case TF_BGRA32: glformat = GL_BGRA_EXT; gltype = GL_UNSIGNED_INT_8_8_8_8_REV; break;
// case TF_RGBA32: glformat = GL_RGBA; gltype = GL_UNSIGNED_INT_8_8_8_8_REV; break;
// case TF_BGR24: glformat = GL_BGR_EXT; gltype = GL_UNSIGNED_BYTE; break;
case TF_RGB24: glformat = GL_RGB; gltype = GL_UNSIGNED_BYTE; break;
case TF_LUM8: glformat = GL_LUMINANCE;gltype = GL_UNSIGNED_BYTE; break;
}
if (gl_config.gles)
internalformat = glformat;
for (lmidx = 0; lmidx < numlightmaps; lmidx++)
{
@ -5335,18 +5340,26 @@ static void BE_UpdateLightmaps(void)
#endif
if (!TEXVALID(lm->lightmap_texture))
{
extern cvar_t gl_lightmap_nearest;
TEXASSIGN(lm->lightmap_texture, Image_CreateTexture(va("***lightmap %i***", lmidx), NULL, (gl_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP));
extern cvar_t r_lightmap_nearest;
TEXASSIGN(lm->lightmap_texture, Image_CreateTexture(va("***lightmap %i***", lmidx), NULL, (r_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP));
qglGenTextures(1, &lm->lightmap_texture->num);
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D(GL_TEXTURE_2D, 0, internalformat, lm->width, lm->height, 0, glformat, gltype, lm->lightmaps);
qglTexImage2D(GL_TEXTURE_2D, 0, gl_config.formatinfo[lightmap_fmt].internalformat, lm->width, lm->height, 0, gl_config.formatinfo[lightmap_fmt].format, gl_config.formatinfo[lightmap_fmt].type, lm->lightmaps);
if (gl_config.glversion >= (gl_config.gles?3.0:3.3))
{
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[lightmap_fmt].swizzle_r);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[lightmap_fmt].swizzle_g);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[lightmap_fmt].swizzle_b);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[lightmap_fmt].swizzle_a);
}
}
else
{
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, lm->width, b-t, glformat, gltype, lm->lightmaps+t*lm->width*lightmap_bytes);
qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, t, lm->width, b-t, gl_config.formatinfo[lightmap_fmt].format, gl_config.formatinfo[lightmap_fmt].type, lm->lightmaps+t*lm->width*lightmap_bytes);
}
lm->modified = false;
lm->rectchange.l = lm->width;
@ -5839,7 +5852,7 @@ void GLBE_DrawLightPrePass(void)
{ //gles3
ifmt = GL_RGBA16F_ARB;
dfmt = GL_RGBA;
dtype = GL_FLOAT;
dtype = GL_HALF_FLOAT;
}
else
ifmt = GL_RGBA16F_ARB;
@ -6118,7 +6131,7 @@ void GLBE_DrawWorld (batch_t **worldbatches)
RSpeedEnd(RSPEED_TRANSPARENTS);
#ifndef GLSLONLY
if (r_refdef.globalfog.density && !gl_config.arb_shader_objects)
if (r_refdef.globalfog.density && (!gl_config.arb_shader_objects || !r_fog_permutation.ival))
{ //fixed function-only. with global fog. that means we need to hack something in.
//FIXME: should really be doing this on a per-shader basis, for custom shaders that don't use glsl
BE_SelectMode(BEM_FOG);

View File

@ -43,6 +43,8 @@ static int gl_filter_mip[3]; //everything else
int gl_mipcap_min = 0;
int gl_mipcap_max = 1000;
void Image_WriteKTXFile(const char *filename, struct pendingtextureinfo *mips);
void GL_DestroyTexture(texid_t tex)
{
if (!tex)
@ -52,6 +54,326 @@ void GL_DestroyTexture(texid_t tex)
tex->num = 0;
}
#define glfmtsw(qfmt,sz,in,fm,ty,cf,sr,sg,sb,sa) \
do { \
gl_config.formatinfo[qfmt].sizedformat = sz; \
gl_config.formatinfo[qfmt].cformat = cf; \
gl_config.formatinfo[qfmt].internalformat = in; \
gl_config.formatinfo[qfmt].format = fm; \
gl_config.formatinfo[qfmt].type = ty; \
gl_config.formatinfo[qfmt].swizzle_r = sr; \
gl_config.formatinfo[qfmt].swizzle_g = sg; \
gl_config.formatinfo[qfmt].swizzle_b = sb; \
gl_config.formatinfo[qfmt].swizzle_a = sa; \
sh_config.texfmt[qfmt] = true; \
} while(0)
#define glfmt(qfmt,sz,in,fm,ty) glfmtsw(qfmt, sz, in, fm, ty, 0, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA)
#define glfmtc(qfmt,sz,in,fm,ty,cf) glfmtsw(qfmt, sz, in, fm, ty, cf, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA)
#define glfmtb(qfmt,in) glfmtsw(qfmt, in, in, 0, 0, 0, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA)
#ifndef GL_RGB565
#define GL_RGB565 0x8D62
#endif
void GL_SetupFormats(void)
{
int tc_ru = 0, tc_rs = 0, tc_rgu = 0, tc_rgs = 0, tc_rgb = 0, tc_rgba1 = 0, tc_rgba8 = 0, tc_srgb = 0, tc_srgba8 = 0;
qboolean bc1=false, bc2=false, bc3=false, bc45=false, bc67=false;
float ver = gl_config.glversion;
qboolean srgb = (gl_config.glversion >= (gl_config_gles?3.0:2.1)) || GL_CheckExtension("GL_EXT_texture_sRGB");
if (gl_config_gles && ver >= 3.0 && ver <= 3.3)
ver = 3.3; //treat gles3.0 as desktop 3.3, they're roughly equivelent in feature set.
if (GL_CheckExtension("GL_EXT_texture_compression_s3tc"))
bc1=bc2=bc3=true;
if ((!gl_config_gles && ver >= 3.0) || GL_CheckExtension("GL_ARB_texture_compression_rgtc") || GL_CheckExtension("GL_EXT_texture_compression_rgtc"))
bc45 = true;
if ((!gl_config.gles && ver >= 4.2) || GL_CheckExtension("GL_ARB_texture_compression_bptc"))
bc67 = true;
if (bc45)
tc_ru = GL_COMPRESSED_RED_RGTC1;
if (bc45)
tc_rs = GL_COMPRESSED_SIGNED_RED_RGTC1;
if (bc45)
tc_rgu = GL_COMPRESSED_RG_RGTC2;
if (bc45)
tc_rgs = GL_COMPRESSED_SIGNED_RG_RGTC2;
if (bc1)
tc_rgb = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
if (bc1)
tc_srgb = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
if (bc3)
tc_rgba8 = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
if (bc3)
tc_srgba8 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
if (bc1)
tc_rgba1 = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
// if (bc1)
// tc_srgba1 = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
bc1 |= GL_CheckExtension("GL_EXT_texture_compression_dxt1");
bc2 |= GL_CheckExtension("GL_ANGLE_texture_compression_dxt3");
bc3 |= GL_CheckExtension("GL_ANGLE_texture_compression_dxt5");
/*else if (sh_config.texfmt[PTI_ETC2_RGB8A8])
{ //these are probably a bad choice...
tc_ru = GL_COMPRESSED_R11_EAC;
tc_rgu = GL_COMPRESSED_RG11_EAC;
tc_rgb = GL_COMPRESSED_RGB8_ETC2;
tc_rgba = GL_COMPRESSED_RGBA8_ETC2_EAC;
}*/
#ifdef FTE_TARGET_WEB
glfmt(PTI_WHOLEFILE, 0, 0, 0, 0);
// sh_config.texfmt[PTI_WHOLEFILE] = true;
#endif
if (gl_config_gles)
{
//pre-3 gles doesn't support sized formats, and only a limited number of them too
glfmtc(PTI_RGB8, GL_RGB, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, tc_rgb);
glfmtc(PTI_RGBA8, GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgba8);
glfmt(PTI_L8A8, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
glfmt(PTI_L8, GL_LUMINANCE, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);
// glfmt(PTI_RGBA8, GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
if (!gl_config.webgl_ie)
{ //these should work on all gles2+webgl1 devices, but microsoft doesn't give a shit.
glfmtc(PTI_RGB565, GL_RGB, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, tc_rgb);
// glfmtc(PTI_RGBA4444,GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, tc_rgba8);
// glfmtc(PTI_RGBA5551,GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, tc_rgba1);
}
if (GL_CheckExtension("GL_OES_texture_half_float"))
glfmtc(PTI_RGBA16F, GL_RGBA, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, 0); //not to be confused with GL_HALF_FLOAT[_ARB] which has a different value
if (GL_CheckExtension("GL_OES_texture_float"))
glfmtc(PTI_RGBA32F, GL_RGBA, GL_RGBA, GL_RGBA, GL_FLOAT, 0);
if (GL_CheckExtension("GL_OES_depth_texture"))
{ //16+32, not 24.
glfmt(PTI_DEPTH16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
glfmt(PTI_DEPTH32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
}
if (GL_CheckExtension("GL_EXT_texture_format_BGRA8888"))
glfmtc(PTI_BGRA8, GL_BGRA_EXT, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_rgba8);
if (GL_CheckExtension("GL_EXT_texture_type_2_10_10_10_REV"))
glfmtc(PTI_BGRA8, GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, tc_rgba8);
}
if (!gl_config_gles || ver >= 3.0)
{
if (ver >= 1.4 || GL_CheckExtension("GL_ARB_depth_texture"))
{ //depth formats
glfmt(PTI_DEPTH16, GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
glfmt(PTI_DEPTH24, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT/*FIXME*/);
if (gl_config_gles)// || ver >= 3.0)
glfmt(PTI_DEPTH32, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT);
else
glfmt(PTI_DEPTH32, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT);
}
// if (ver >= 3.0)
// glfmt(PTI_DEPTH32, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT);
if (GL_CheckExtension("GL_EXT_packed_depth_stencil"))
glfmt(PTI_DEPTH24_8,GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT);
glfmtc(PTI_RGBA8, GL_RGBA8, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgba8);
if (srgb)
glfmtc(PTI_RGBA8_SRGB, GL_SRGB8_ALPHA8_EXT,GL_SRGB_ALPHA_EXT, GL_RGBA, GL_UNSIGNED_BYTE, tc_srgba8);
if (!gl_config_gles)
{
if (ver >= 3.3) //I'm paranoid about performance, so lets swizzle the alpha to 1 to make the alignment explicit.
glfmtsw(PTI_RGBX8, GL_RGBA8, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgb, GL_RED, GL_GREEN, GL_BLUE, GL_ONE);
else
glfmtc(PTI_RGBX8, GL_RGB8, GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgb);
if (srgb)
glfmtc(PTI_RGBX8_SRGB, GL_SRGB8_EXT, GL_SRGB_EXT, GL_RGBA, GL_UNSIGNED_BYTE, tc_srgb);
}
if (ver >= 1.2 && !gl_config_gles)
{
glfmt(PTI_BGR8, GL_RGB8, GL_RGB, GL_BGR_EXT, GL_UNSIGNED_BYTE);
glfmtc(PTI_BGRX8, GL_RGB8, GL_RGB, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, tc_rgb);
glfmtc(PTI_BGRA8, GL_RGBA8, GL_RGBA, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, tc_rgba8);
if (srgb)
{
glfmtc(PTI_BGRX8_SRGB, GL_SRGB8_EXT, GL_SRGB_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_srgb);
glfmtc(PTI_BGRA8_SRGB, GL_SRGB8_ALPHA8_EXT,GL_SRGB_ALPHA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_srgba8);
}
}
else if (ver >= 3.3)
{
glfmtsw(PTI_BGR8, GL_RGB8, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, 0, GL_BLUE, GL_GREEN, GL_RED, GL_ONE);
glfmtsw(PTI_BGRX8, GL_RGB8, GL_RGB, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgb, GL_BLUE, GL_GREEN, GL_RED, GL_ONE);
glfmtsw(PTI_BGRA8, GL_RGBA8, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgba8, GL_BLUE, GL_GREEN, GL_RED, GL_ALPHA);
if (srgb)
{
glfmtc(PTI_BGRX8_SRGB, GL_SRGB8_EXT, GL_SRGB_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_srgb);
glfmtc(PTI_BGRA8_SRGB, GL_SRGB8_ALPHA8_EXT,GL_SRGB_ALPHA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_srgba8);
}
}
if (ver >= 3.0 || GL_CheckExtension("GL_EXT_texture_shared_exponent"))
glfmt(PTI_E5BGR9, GL_RGB9_E5, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV);
if (ver >= 3.0 || GL_CheckExtension("GL_EXT_packed_pixels")) //so gl1.2 then.
glfmt(PTI_A2BGR10, GL_RGB10_A2, GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
if (ver >= 3.0 || GL_CheckExtension("GL_ARB_texture_rg"))
{
glfmtc(PTI_R8, GL_R8, GL_RED, GL_RED, GL_UNSIGNED_BYTE, tc_ru);
glfmtc(PTI_RG8, GL_RG8, GL_RG, GL_RG, GL_UNSIGNED_BYTE, tc_rs);
}
if (ver >= 3.1 || (GL_CheckExtension("GL_EXT_texture_snorm") && GL_CheckExtension("GL_ARB_texture_rg")))
{
glfmtc(PTI_R8_SNORM, GL_R8_SNORM, GL_R8_SNORM, GL_RED, GL_BYTE, tc_rgu);
glfmtc(PTI_RG8_SNORM, GL_RG8_SNORM, GL_RG8_SNORM, GL_RG, GL_BYTE, tc_rgs);
}
if (ver >= 3.0)
{
glfmtc(PTI_RGBA16F, GL_RGBA16F_ARB, GL_RGBA, GL_RGBA, GL_HALF_FLOAT, 0);
glfmtc(PTI_RGBA32F, GL_RGBA32F_ARB, GL_RGBA, GL_RGBA, GL_FLOAT, 0);
}
if (ver >= 1.2 && !gl_config_gles)
{
glfmtc(PTI_RGBA4444, GL_RGBA4, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, tc_srgba8);
glfmtc(PTI_RGBA5551, GL_RGB5_A1, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, tc_rgba1);
glfmtc(PTI_ARGB4444, GL_RGBA4, GL_RGBA, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV, tc_srgba8);
glfmtc(PTI_ARGB1555, GL_RGB5_A1, GL_RGBA, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, tc_rgba1);
}
if (gl_config_gles || ver > 4.1) //rgb565 was a gles thing, desktop gl just has a 555 internal format despite the 565 data...
glfmtc(PTI_RGB565, GL_RGB565, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, tc_rgb);
else
glfmtc(PTI_RGB565, GL_RGB5, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, tc_rgb);
glfmt(PTI_RGB8, GL_RGB8, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE);
if (!gl_config_nofixedfunc)
{ //if we have fixed function, then we still have proper support. the driver can emulate with swizzles if it wants.
glfmtc(PTI_L8, GL_LUMINANCE8, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, tc_ru);
glfmtc(PTI_L8A8, GL_LUMINANCE8_ALPHA8,GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tc_rgu);
}
else if (ver >= 3.3)
{ //can emulate them with swizzles.
glfmtsw(PTI_L8, GL_R8, GL_RED, GL_RED, GL_UNSIGNED_BYTE, tc_ru, GL_RED, GL_RED, GL_RED, GL_ONE);
glfmtsw(PTI_L8A8, GL_RG8, GL_RG, GL_RG, GL_UNSIGNED_BYTE, tc_rgu, GL_RED, GL_RED, GL_RED, GL_GREEN);
}
}
//block compresion formats.
if (bc1)
{
glfmtb(PTI_BC1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
glfmtb(PTI_BC1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
if (srgb)
{
glfmtb(PTI_BC1_RGB_SRGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
glfmtb(PTI_BC1_RGBA_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
}
}
if (bc2)
{
glfmtb(PTI_BC2_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
if (srgb)
glfmtb(PTI_BC2_RGBA_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
}
if (bc3)
{
glfmtb(PTI_BC3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
if (srgb)
glfmtb(PTI_BC3_RGBA_SRGB, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
}
if (bc45)
{
glfmtb(PTI_BC4_R8, GL_COMPRESSED_RED_RGTC1);
glfmtb(PTI_BC4_R8_SNORM, GL_COMPRESSED_SIGNED_RED_RGTC1);
glfmtb(PTI_BC5_RG8, GL_COMPRESSED_RG_RGTC2);
glfmtb(PTI_BC5_RG8_SNORM, GL_COMPRESSED_SIGNED_RG_RGTC2);
}
if (bc67)
{
glfmtb(PTI_BC6_RGB_UFLOAT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB);
glfmtb(PTI_BC6_RGB_SFLOAT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB);
glfmtb(PTI_BC7_RGBA, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB);
glfmtb(PTI_BC7_RGBA_SRGB, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB);
}
#ifdef FTE_TARGET_WEB
if (GL_CheckExtension("WEBGL_compressed_texture_etc"))
#else
if ((gl_config.gles && gl_config.glversion >= 3.0) || (!gl_config.gles && (gl_config.glversion >= 4.3 || GL_CheckExtension("GL_ARB_ES3_compatibility"))))
#endif
{
glfmtb(PTI_ETC1_RGB8, GL_COMPRESSED_RGB8_ETC2);
glfmtb(PTI_ETC2_RGB8, GL_COMPRESSED_RGB8_ETC2);
glfmtb(PTI_ETC2_RGB8A1, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
glfmtb(PTI_ETC2_RGB8A8, GL_COMPRESSED_RGBA8_ETC2_EAC);
glfmtb(PTI_ETC2_RGB8_SRGB, GL_COMPRESSED_SRGB8_ETC2);
glfmtb(PTI_ETC2_RGB8A1_SRGB, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
glfmtb(PTI_ETC2_RGB8A8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
glfmtb(PTI_EAC_R11, GL_COMPRESSED_R11_EAC);
glfmtb(PTI_EAC_R11_SNORM, GL_COMPRESSED_SIGNED_R11_EAC);
glfmtb(PTI_EAC_RG11, GL_COMPRESSED_RG11_EAC);
glfmtb(PTI_EAC_RG11_SNORM, GL_COMPRESSED_SIGNED_RG11_EAC);
}
else
{
if (GL_CheckExtension("GL_OES_compressed_ETC1_RGB8_texture"))
glfmtb(PTI_ETC1_RGB8, GL_ETC1_RGB8_OES);
if (GL_CheckExtension("GL_OES_compressed_ETC2_RGB8_texture"))
glfmtb(PTI_ETC2_RGB8, GL_COMPRESSED_RGB8_ETC2);
if (GL_CheckExtension("GL_OES_compressed_ETC2_sRGB8_texture"))
glfmtb(PTI_ETC2_RGB8_SRGB, GL_COMPRESSED_SRGB8_ETC2);
if (GL_CheckExtension("GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture"))
glfmtb(PTI_ETC2_RGB8A1, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
if (GL_CheckExtension("GL_OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture"))
glfmtb(PTI_ETC2_RGB8A1_SRGB, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
if (GL_CheckExtension("GL_OES_compressed_ETC2_RGBA8_texture"))
glfmtb(PTI_ETC2_RGB8A8, GL_COMPRESSED_RGBA8_ETC2_EAC);
if (GL_CheckExtension("GL_OES_compressed_ETC2_sRGB8_alpha8_texture"))
glfmtb(PTI_ETC2_RGB8A8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
if (GL_CheckExtension("GL_OES_compressed_EAC_R11_unsigned_texture"))
glfmtb(PTI_EAC_R11, GL_COMPRESSED_R11_EAC);
if (GL_CheckExtension("GL_OES_compressed_EAC_R11_signed_texture"))
glfmtb(PTI_EAC_R11_SNORM, GL_COMPRESSED_SIGNED_R11_EAC);
if (GL_CheckExtension("GL_OES_compressed_EAC_RG11_unsigned_texture"))
glfmtb(PTI_EAC_RG11, GL_COMPRESSED_RG11_EAC);
if (GL_CheckExtension("GL_OES_compressed_EAC_RG11_signed_texture"))
glfmtb(PTI_EAC_RG11_SNORM, GL_COMPRESSED_SIGNED_RG11_EAC);
}
if (GL_CheckExtension("GL_KHR_texture_compression_astc_ldr") || (gl_config_gles && gl_config.glversion >= 3.2))
{ //astc ldr profile is a core part of gles 3.2
glfmtb(PTI_ASTC_4X4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR);
glfmtb(PTI_ASTC_4X4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
glfmtb(PTI_ASTC_5X4, GL_COMPRESSED_RGBA_ASTC_5x4_KHR);
glfmtb(PTI_ASTC_5X4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
glfmtb(PTI_ASTC_5X5, GL_COMPRESSED_RGBA_ASTC_5x5_KHR);
glfmtb(PTI_ASTC_5X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
glfmtb(PTI_ASTC_6X5, GL_COMPRESSED_RGBA_ASTC_6x5_KHR);
glfmtb(PTI_ASTC_6X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
glfmtb(PTI_ASTC_6X6, GL_COMPRESSED_RGBA_ASTC_6x6_KHR);
glfmtb(PTI_ASTC_6X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
glfmtb(PTI_ASTC_8X5, GL_COMPRESSED_RGBA_ASTC_8x5_KHR);
glfmtb(PTI_ASTC_8X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
glfmtb(PTI_ASTC_8X6, GL_COMPRESSED_RGBA_ASTC_8x6_KHR);
glfmtb(PTI_ASTC_8X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
glfmtb(PTI_ASTC_10X5, GL_COMPRESSED_RGBA_ASTC_10x5_KHR);
glfmtb(PTI_ASTC_10X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
glfmtb(PTI_ASTC_10X6, GL_COMPRESSED_RGBA_ASTC_10x6_KHR);
glfmtb(PTI_ASTC_10X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
glfmtb(PTI_ASTC_8X8, GL_COMPRESSED_RGBA_ASTC_8x8_KHR);
glfmtb(PTI_ASTC_8X8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
glfmtb(PTI_ASTC_10X8, GL_COMPRESSED_RGBA_ASTC_10x8_KHR);
glfmtb(PTI_ASTC_10X8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
glfmtb(PTI_ASTC_10X10, GL_COMPRESSED_RGBA_ASTC_10x10_KHR);
glfmtb(PTI_ASTC_10X10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
glfmtb(PTI_ASTC_12X10, GL_COMPRESSED_RGBA_ASTC_12x10_KHR);
glfmtb(PTI_ASTC_12X10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
glfmtb(PTI_ASTC_12X12, GL_COMPRESSED_RGBA_ASTC_12x12_KHR);
glfmtb(PTI_ASTC_12X12_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
}
}
/*
===============
Draw_Init
@ -59,6 +381,32 @@ Draw_Init
*/
void GLDraw_Init (void)
{
extern cvar_t scr_showloading;
extern cvar_t vid_srgb;
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
{ //srgb-capable
if (!vid_srgb.ival)
{ //srgb not wanted...
qglDisable(GL_FRAMEBUFFER_SRGB);
vid.flags &= ~VID_SRGB_FB_LINEAR;
}
else if (vid_srgb.ival > 1)
{ //full srgb wanted
qglEnable(GL_FRAMEBUFFER_SRGB);
vid.flags |= VID_SRGB_FB_LINEAR;
}
else
{ //srgb wanted only for the framebuffer, for gamma tricks.
vid.flags |= VID_SRGB_FB_LINEAR;
qglEnable(GL_FRAMEBUFFER_SRGB);
}
}
if ((vid.flags & VID_SRGB_FB) && vid_srgb.ival != 1)
vid.flags |= VID_SRGBAWARE;
else
vid.flags &= ~VID_SRGBAWARE;
//figure out which extra features we can support on these drivers.
r_deluxmapping = r_deluxmapping_cvar.ival;
r_lightprepass = r_lightprepass_cvar.ival && sh_config.progs_supported;
@ -66,33 +414,30 @@ void GLDraw_Init (void)
if (gl_config.gles && gl_config.glversion < 3.0)
r_softwarebanding = false;
if (gl_config.arb_framebuffer_srgb)
{
extern cvar_t vid_srgb;
vid.srgb = vid_srgb.ival>1;
if (vid.srgb)
qglEnable(GL_FRAMEBUFFER_SRGB);
}
else
vid.srgb = false;
GL_SetupFormats();
R2D_Init();
qglDisable(GL_SCISSOR_TEST);
GL_Set2D(false);
qglClearColor(0, 0, 0, 1);
qglClear(GL_COLOR_BUFFER_BIT);
if (scr_showloading.ival)
{
mpic_t *pic = R2D_SafeCachePic ("gfx/loading.lmp");
if (pic)
R2D_ScalePic ( ((int)vid.width - pic->width)/2,
((int)vid.height - 48 - pic->height)/2, pic->width, pic->height, pic);
}
if (pic && R_GetShaderSizes(pic, NULL, NULL, true))
{ //if its too big for the screen, letterbox it.
qglClearColor(0, 0, 0, 1);
qglClear(GL_COLOR_BUFFER_BIT);
if (pic->width > vid.width || pic->height > vid.height)
R2D_Letterbox(0, 0, vid.width, vid.height, pic, pic->width, pic->height);
else //otherwise draw it centred
R2D_ScalePic ( ((int)vid.width - pic->width)/2, ((int)vid.height - 48 - pic->height)/2, pic->width, pic->height, pic);
}
if (R2D_Flush)
R2D_Flush();
VID_SwapBuffers();
if (R2D_Flush)
R2D_Flush();
VID_SwapBuffers();
}
GL_SetupSceneProcessingTextures();
@ -128,9 +473,10 @@ void GLDraw_DeInit (void)
#ifdef RTLIGHTS
Sh_Shutdown();
#endif
Shader_Shutdown();
GLBE_Shutdown(); //to release its images.
Shader_Shutdown();
Image_Shutdown();
}
@ -281,7 +627,6 @@ static void GL_Texturemode_Apply(GLenum targ, unsigned int flags)
qglTexParameterf(targ, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
}
}
qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
{
static int cubeface[] =
@ -294,9 +639,9 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
};
int targ, targface;
int i, j;
int i, j, ifmt;
int nummips = mips->mipcount;
int encoding = mips->encoding;
uploadfmt_t encoding = mips->encoding;
qboolean compress;
@ -311,9 +656,6 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
if (encoding == PTI_BGRX8)
encoding = PTI_BGRA8;
}
if (!tex->num)
qglGenTextures(1, &tex->num);
switch((tex->flags & IF_TEXTYPE) >> IF_TEXTYPESHIFT)
{
@ -327,10 +669,27 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
case 2:
targ = GL_TEXTURE_CUBE_MAP_ARB;
break;
case 3:
targ = GL_TEXTURE_2D_ARRAY;
break;
}
GL_MTBind(0, targ, tex);
if (tex->num && qglTexStorage2D)
{
qglDeleteTextures(1, &tex->num);
qglGenTextures(1, &tex->num);
GL_MTBind(0, targ, tex);
qglBindTexture (targ, tex->num); //GL_MTBind caches, which is problematic when things are getting deleted.
}
else
{
if (!tex->num)
qglGenTextures(1, &tex->num);
GL_MTBind(0, targ, tex);
}
if (tex->flags&IF_CLAMP)
{
if (gl_config.glversion < 1.2 && !gl_config_gles)
@ -394,265 +753,225 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
// tex->width = mips->mip[0].width;
// tex->height = mips->mip[0].height;
GL_Texturemode_Apply(targ, tex->flags);
if (targ == GL_TEXTURE_3D)
#ifdef FTE_TARGET_WEB
if (encoding == PTI_WHOLEFILE)
{
targface = targ;
for (i = 0; i < nummips; i++)
emscriptenfte_gl_loadtexturefile(tex->num, &tex->width, &tex->height, mips->mip[i].data, mips->mip[i].datasize);
return true;
}
#endif
//arb_texture_compression is core in gl1.3
//gles doesn't support autocompression as of gles3.
//only autocompress if we have actually have data (gl errors otherwise).
if (gl_config.arb_texture_compression && mips->mip[0].data && !(tex->flags & IF_RENDERTARGET))
compress = !!gl_compress.ival;
else
compress = false;
if (compress & gl_config.formatinfo[encoding].cformat)
ifmt = gl_config.formatinfo[encoding].cformat;
else
ifmt = gl_config.formatinfo[encoding].sizedformat;
if (!ifmt)
return false;
if (gl_config.formatinfo[encoding].swizzle_r != GL_RED || gl_config.formatinfo[encoding].swizzle_g != GL_GREEN ||
gl_config.formatinfo[encoding].swizzle_b != GL_BLUE || gl_config.formatinfo[encoding].swizzle_a != GL_ALPHA)
{
qglTexParameteri(targ, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[encoding].swizzle_r);
qglTexParameteri(targ, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[encoding].swizzle_g);
qglTexParameteri(targ, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[encoding].swizzle_b);
qglTexParameteri(targ, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[encoding].swizzle_a);
}
if (targ == GL_TEXTURE_3D || targ == GL_TEXTURE_2D_ARRAY)
{
//FIXME: support array textures properly
if (qglTexStorage3D)
{
int size = mips->mip[i].height;
switch(encoding)
if (tex->flags & IF_TEXTYPE)
qglTexStorage3D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth);
else
qglTexStorage3D(targ, nummips, ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth);
for (i = 0; i < nummips; i++)
{
case PTI_RGBX8:
qglTexImage3D(targface, i, GL_RGB, size, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_RGBA8:
qglTexImage3D(targface, i, GL_RGBA, size, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_BGRX8:
qglTexImage3D(targface, i, GL_RGB, size, size, size, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, mips->mip[i].data);
break;
default:
case PTI_BGRA8:
qglTexImage3D(targface, i, GL_RGBA, size, size, size, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, mips->mip[i].data);
break;
case PTI_RGBA4444:
qglTexImage3D(targface, i, GL_RGBA, size, size, size, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, mips->mip[i].data);
break;
case PTI_RGBA5551:
qglTexImage3D(targface, i, GL_RGBA, size, size, size, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, mips->mip[i].data);
break;
case PTI_RGB565:
qglTexImage3D(targface, i, GL_RGB, size, size, size, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, mips->mip[i].data);
break;
if (!mips->mip[i].data) //already specified by gltexstorage
continue;
if (gl_config.formatinfo[encoding].type)
qglTexSubImage3D (targ, i, 0, 0, 0, mips->mip[i].width, mips->mip[i].height, mips->mip[0].depth, gl_config.formatinfo[encoding].format, gl_config.formatinfo[encoding].type, mips->mip[i].data);
else
qglCompressedTexSubImage3D (targ, i, 0, 0, 0, mips->mip[i].width, mips->mip[i].height, mips->mip[0].depth, ifmt, mips->mip[i].datasize, mips->mip[i].data);
}
}
else
{
for (i = 0; i < nummips; i++)
{
if (gl_config.formatinfo[encoding].type)
qglTexImage3D (targ, i, ifmt, mips->mip[i].width, mips->mip[i].height, mips->mip[0].depth, 0, gl_config.formatinfo[encoding].format, gl_config.formatinfo[encoding].type, mips->mip[i].data);
else
qglCompressedTexImage3DARB (targ, i, ifmt, mips->mip[i].width, mips->mip[i].height, mips->mip[0].depth, 0, mips->mip[i].datasize, mips->mip[i].data);
}
}
}
else
{
//2d or cubemaps
for (i = 0; i < nummips; i++)
{
//arb_texture_compression is core in gl1.3
//gles doesn't support autocompression as of gles3.
//only autocompress if we have actually have data (gl errors otherwise).
if (gl_config.arb_texture_compression && mips->mip[i].data)
compress = !!gl_compress.ival;
else
compress = false;
if (qglTexStorage2D)
{ //FIXME: destroy the old texture
if (tex->flags & IF_TEXTYPE)
{
targface = cubeface[i%countof(cubeface)];
j = i/countof(cubeface);
}
qglTexStorage2D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height);
else
qglTexStorage2D(targ, nummips, ifmt, mips->mip[0].width, mips->mip[0].height);
for (i = 0; i < nummips; i++)
{
targface = targ;
j = i;
}
switch(encoding)
{
case PTI_WHOLEFILE:
case PTI_MAX:
#ifdef FTE_TARGET_WEB
if (!i)
emscriptenfte_gl_loadtexturefile(tex->num, &tex->width, &tex->height, mips->mip[i].data, mips->mip[i].datasize);
#endif
break;
case PTI_DEPTH16:
qglTexImage2D(targface, j, gl_config.gles?GL_DEPTH_COMPONENT:GL_DEPTH_COMPONENT16_ARB, mips->mip[i].width, mips->mip[i].height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, mips->mip[i].data);
break;
case PTI_DEPTH24:
qglTexImage2D(targface, j, gl_config.gles?GL_DEPTH_COMPONENT:GL_DEPTH_COMPONENT24_ARB, mips->mip[i].width, mips->mip[i].height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, mips->mip[i].data);
break;
case PTI_DEPTH32:
qglTexImage2D(targface, j, gl_config.gles?GL_DEPTH_COMPONENT:GL_DEPTH_COMPONENT32_ARB, mips->mip[i].width, mips->mip[i].height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, mips->mip[i].data);
break;
case PTI_DEPTH24_8:
qglTexImage2D(targface, j, GL_DEPTH24_STENCIL8_EXT, mips->mip[i].width, mips->mip[i].height, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, mips->mip[i].data);
break;
//32bit formats
case PTI_RGBX8:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGB_ARB:GL_RGB, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_RGBA8:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGBA, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_BGRX8:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGB_ARB:GL_RGB, mips->mip[i].width, mips->mip[i].height, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, mips->mip[i].data);
break;
case PTI_BGRA8:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGBA, mips->mip[i].width, mips->mip[i].height, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, mips->mip[i].data);
break;
case PTI_RGBX8_SRGB:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_SRGB_EXT:GL_SRGB_EXT, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_RGBA8_SRGB:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_SRGB_ALPHA_EXT:GL_SRGB_ALPHA_EXT, mips->mip[i].width, mips->mip[i].height, 0, gl_config.gles?GL_SRGB_ALPHA_EXT:GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_BGRX8_SRGB:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_SRGB_EXT:GL_SRGB_EXT, mips->mip[i].width, mips->mip[i].height, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, mips->mip[i].data);
break;
case PTI_BGRA8_SRGB:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_SRGB_ALPHA_EXT:GL_SRGB_ALPHA_EXT, mips->mip[i].width, mips->mip[i].height, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, mips->mip[i].data);
break;
case PTI_RGBA16F:
qglTexImage2D(targface, j, GL_RGBA16F_ARB, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
case PTI_RGBA32F:
qglTexImage2D(targface, j, GL_RGBA32F_ARB, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
//16bit formats
case PTI_RGBA4444:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGBA, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, mips->mip[i].data);
break;
case PTI_RGBA5551:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGBA, mips->mip[i].width, mips->mip[i].height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, mips->mip[i].data);
break;
case PTI_ARGB4444:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGBA, mips->mip[i].width, mips->mip[i].height, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV, mips->mip[i].data);
break;
case PTI_ARGB1555:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGBA, mips->mip[i].width, mips->mip[i].height, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV, mips->mip[i].data);
break;
case PTI_RGB565:
qglTexImage2D(targface, j, compress?GL_COMPRESSED_RGBA_ARB:GL_RGB, mips->mip[i].width, mips->mip[i].height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, mips->mip[i].data);
break;
//legacy formats
case PTI_RGB8:
#ifdef GLESONLY
return false;
#else
qglTexImage2D(targface, j, GL_RGB8, mips->mip[i].width, mips->mip[i].height, 0, GL_RGB, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
#endif
case PTI_LUMINANCE8_ALPHA8:
#ifdef GLESONLY
return false;
#else
qglTexImage2D(targface, j, GL_LUMINANCE8_ALPHA8, mips->mip[i].width, mips->mip[i].height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, mips->mip[i].data);
break;
#endif
//s3tc (desktop) compressed formats
case PTI_BC1_RGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC1_RGBA:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC2_RGBA:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC3_RGBA:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC1_RGB_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC1_RGBA_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC2_RGBA_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC3_RGBA_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
//atin/rgtc (desktop) compressed formats (derived from bc3's alpha channel)
case PTI_BC4_R8:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RED_RGTC1, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC4_R8_SIGNED:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SIGNED_RED_RGTC1, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC5_RG8:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RG_RGTC2, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC5_RG8_SIGNED:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SIGNED_RG_RGTC2, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
//bptc desktop formats
case PTI_BC6_RGBF:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC6_RGBF_SIGNED:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC7_RGBA:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_BC7_RGBA_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
//(mobile) compressed formats
case PTI_ETC1_RGB8:
case PTI_ETC2_RGB8:
//etc2 is a superset of etc1. we distinguish only for hardware that cannot recognise etc2's 'invalid' encodings
if (sh_config.texfmt[PTI_ETC2_RGB8])
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGB8_ETC2, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
if (tex->flags & IF_TEXTYPE)
{ //cubemap face
targface = cubeface[i%countof(cubeface)];
j = i/countof(cubeface);
}
else
qglCompressedTexImage2DARB(targface, j, GL_ETC1_RGB8_OES, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_ETC2_RGB8A1:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_ETC2_RGB8A8:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA8_ETC2_EAC, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_ETC2_RGB8_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ETC2, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_ETC2_RGB8A1_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_ETC2_RGB8A8_SRGB:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_EAC_R11:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_R11_EAC, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_EAC_R11_SIGNED:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SIGNED_R11_EAC, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_EAC_RG11:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RG11_EAC, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
case PTI_EAC_RG11_SIGNED:
qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SIGNED_RG11_EAC, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
break;
//astc variations...
case PTI_ASTC_4X4: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_4X4_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_5X4: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_5X4_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_5X5: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_5X5_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_6X5: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_6X5_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_6X6: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_6X6_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_8X5: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_8X5_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_8X6: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_8X6_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X5: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X5_SRGB: qglCompressedTexImage2DARB(targface, j,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X6: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X6_SRGB: qglCompressedTexImage2DARB(targface, j,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_8X8: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_8X8_SRGB: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X8: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X8_SRGB: qglCompressedTexImage2DARB(targface, j,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X10: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_10X10_SRGB: qglCompressedTexImage2DARB(targface, j,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_12X10: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_12X10_SRGB: qglCompressedTexImage2DARB(targface, j,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_12X12: qglCompressedTexImage2DARB(targface, j, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
case PTI_ASTC_12X12_SRGB: qglCompressedTexImage2DARB(targface, j,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data); break;
{ //2d
targface = targ;
j = i;
}
if (!mips->mip[i].data) //already specified by gltexstorage, don't bother wiping it or anything.
continue;
if (gl_config.formatinfo[encoding].type)
qglTexSubImage2D (targface, j, 0, 0, mips->mip[i].width, mips->mip[i].height, gl_config.formatinfo[encoding].format, gl_config.formatinfo[encoding].type, mips->mip[i].data);
else
qglCompressedTexSubImage2D (targface, j, 0, 0, mips->mip[i].width, mips->mip[i].height, ifmt, mips->mip[i].datasize, mips->mip[i].data);
}
}
else
{
for (i = 0; i < nummips; i++)
{
if (tex->flags & IF_TEXTYPE)
{ //cubemap face
targface = cubeface[i%countof(cubeface)];
j = i/countof(cubeface);
}
else
{ //2d
targface = targ;
j = i;
}
if (gl_config.formatinfo[encoding].type)
qglTexImage2D (targface, j, ifmt, mips->mip[i].width, mips->mip[i].height, 0, gl_config.formatinfo[encoding].format, gl_config.formatinfo[encoding].type, mips->mip[i].data);
else
qglCompressedTexImage2DARB (targface, j, ifmt, mips->mip[i].width, mips->mip[i].height, 0, mips->mip[i].datasize, mips->mip[i].data);
}
}
#ifdef IMAGEFMT_KTX
if (compress && gl_compress.ival>1 && gl_config.formatinfo[encoding].type)
{
GLint fmt;
GLint csize;
struct pendingtextureinfo out = {mips->type};
out.type = mips->type;
out.mipcount = mips->mipcount;
out.encoding = 0;
out.extrafree = NULL;
qglGetTexLevelParameteriv(targ, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
switch(fmt)
{
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: out.encoding = PTI_BC1_RGB; break;
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: out.encoding = PTI_BC1_RGBA; break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: out.encoding = PTI_BC2_RGBA; break;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: out.encoding = PTI_BC3_RGBA; break;
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: out.encoding = PTI_BC1_RGB_SRGB; break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: out.encoding = PTI_BC1_RGBA_SRGB; break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: out.encoding = PTI_BC2_RGBA_SRGB; break;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: out.encoding = PTI_BC3_RGBA_SRGB; break;
case GL_COMPRESSED_RED_RGTC1: out.encoding = PTI_BC4_R8; break;
case GL_COMPRESSED_SIGNED_RED_RGTC1: out.encoding = PTI_BC4_R8_SNORM; break;
case GL_COMPRESSED_RG_RGTC2: out.encoding = PTI_BC5_RG8; break;
case GL_COMPRESSED_SIGNED_RG_RGTC2: out.encoding = PTI_BC5_RG8_SNORM; break;
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB: out.encoding = PTI_BC6_RGB_UFLOAT; break;
case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: out.encoding = PTI_BC6_RGB_SFLOAT; break;
case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: out.encoding = PTI_BC7_RGBA; break;
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: out.encoding = PTI_BC7_RGBA_SRGB; break;
case GL_ETC1_RGB8_OES: out.encoding = PTI_ETC1_RGB8; break;
case GL_COMPRESSED_RGB8_ETC2: out.encoding = PTI_ETC2_RGB8; break;
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: out.encoding = PTI_ETC2_RGB8A1; break;
case GL_COMPRESSED_RGBA8_ETC2_EAC: out.encoding = PTI_ETC2_RGB8A8; break;
case GL_COMPRESSED_SRGB8_ETC2: out.encoding = PTI_ETC2_RGB8_SRGB; break;
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: out.encoding = PTI_ETC2_RGB8A1_SRGB; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: out.encoding = PTI_ETC2_RGB8A8_SRGB; break;
case GL_COMPRESSED_R11_EAC: out.encoding = PTI_EAC_R11; break;
case GL_COMPRESSED_SIGNED_R11_EAC: out.encoding = PTI_EAC_R11_SNORM; break;
case GL_COMPRESSED_RG11_EAC: out.encoding = PTI_EAC_RG11; break;
case GL_COMPRESSED_SIGNED_RG11_EAC: out.encoding = PTI_EAC_RG11_SNORM; break;
case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10_SRGB; break;
case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12; break;
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12_SRGB; break;
}
if (out.encoding)
{
for (i = 0; i < nummips; i++)
{
if (tex->flags & IF_TEXTYPE)
{ //cubemap face
targface = cubeface[i%countof(cubeface)];
j = i/countof(cubeface);
}
else
{ //2d
targface = targ;
j = i;
}
qglGetTexLevelParameteriv(targ, j, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, &csize);
out.mip[i].datasize = csize;
out.mip[i].data = BZ_Malloc(csize);
out.mip[i].needfree = true;
out.mip[i].width = mips->mip[i].width;
out.mip[i].height = mips->mip[i].height;
out.mip[i].depth = mips->mip[i].depth;
qglGetCompressedTexImageARB(targ, j, out.mip[i].data);
}
Image_WriteKTXFile(va("textures/%s.ktx", tex->ident), &out);
}
}
#endif
}
return true;

View File

@ -329,7 +329,6 @@ static qboolean curfont_scaled;
extern cvar_t r_font_linear;
//^Ue2XX
static struct
{
@ -1855,6 +1854,17 @@ struct font_s *Font_LoadFont(float vheight, const char *fontfilename)
}
}
if (vid.flags&VID_SRGBAWARE)
{
f->tint[0] = M_SRGBToLinear(f->tint[0], 1);
f->tint[1] = M_SRGBToLinear(f->tint[1], 1);
f->tint[2] = M_SRGBToLinear(f->tint[2], 1);
f->alttint[0] = M_SRGBToLinear(f->alttint[0], 1);
f->alttint[1] = M_SRGBToLinear(f->alttint[1], 1);
f->alttint[2] = M_SRGBToLinear(f->alttint[2], 1);
}
#ifdef PACKAGE_DOOMWAD
if (!*fontfilename)
{
@ -2662,6 +2672,13 @@ int Font_DrawChar(int px, int py, unsigned int charflags, unsigned int codepoint
rgba[3] = 255;
}
if (vid.flags&VID_SRGBAWARE)
{
rgba[0] = M_SRGBToLinear(rgba[0], 255);
rgba[1] = M_SRGBToLinear(rgba[1], 255);
rgba[2] = M_SRGBToLinear(rgba[2], 255);
}
col = (charflags&CON_BGMASK)>>CON_BGSHIFT;
if (charflags & CON_NONCLEARBG)
{

View File

@ -5774,9 +5774,43 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e)
for (numverts = 0, numindicies = 0; i < hm->numbrushes; i++, br++)
{
//if a single batch has too many verts, cut it off before it overflows our maximum batch size, and hope we don't get a really really complex brush.
if (numverts > 0xf000 || numindicies > 0xf000)
if (numverts >= 0xf000 || numindicies >= 0xf000)
break;
if (br->patch && br->patch->tex == bt && lmnum == -1)
{
int x, y;
index_t r1, r2;
for (y = 0, r1 = numverts, r2 = 0; y < br->patch->ypoints; y++)
{
for (x = 0; x < br->patch->xpoints; x++, r1++, r2++)
{
VectorCopy(br->patch->verts[r2].v, arrays->coord[r1]);
Vector2Copy(br->patch->verts[r2].tc, arrays->texcoord[r1]);
VectorCopy(br->patch->verts[r2].norm, arrays->normal[r1]);
VectorCopy(br->patch->verts[r2].sdir, arrays->svector[r1]);
VectorCopy(br->patch->verts[r2].tdir, arrays->tvector[r1]);
Vector2Copy(br->patch->verts[r2].tc, arrays->lmcoord[r1]);
}
}
for (y = 0, r1 = numverts, r2 = r1 + br->patch->xpoints; y < br->patch->ypoints-1; y++)
{
for (x = 0; x < br->patch->xpoints-1; x++, r1++, r2++)
{
arrays->index[numindicies++] = r1;
arrays->index[numindicies++] = r1+1;
arrays->index[numindicies++] = r2;
arrays->index[numindicies++] = r1+1;
arrays->index[numindicies++] = r2+1;
arrays->index[numindicies++] = r2;
}
r1++; r2++;
}
numverts += br->patch->ypoints*br->patch->xpoints;
}
for (j = 0; j < br->numplanes; j++)
{
if (br->faces[j].tex == bt && !br->selected && br->faces[j].lightmap == lmnum)
@ -6915,27 +6949,58 @@ void QCBUILTIN PF_brush_findinvolume(pubprogfuncs_t *prinst, struct globalvars_s
void Terr_WriteBrushInfo(vfsfile_t *file, brushes_t *br)
{
//valve 220 format:
//{
//( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname [x y z d] [x y z d] rotation sscale tscale
//}
float *point[3];
int i;
int i, x, y;
VFS_PRINTF(file, "\n{");
for (i = 0; i < br->numplanes; i++)
if (br->patch)
{
point[0] = br->faces[i].points[0];
point[1] = br->faces[i].points[1];
point[2] = br->faces[i].points[2];
//%.9g is 'meant' to be lossless for a standard ieee single-precision float. (%.17g for a double)
VFS_PRINTF(file, "\n( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) \"%s\" [ %.9g %.9g %.9g %.9g ] [ %.9g %.9g %.9g %.9g ] 0 1 1",
point[0][0], point[0][1], point[0][2],
point[1][0], point[1][1], point[1][2],
point[2][0], point[2][1], point[2][2],
br->faces[i].tex?br->faces[i].tex->shadername:"",
br->faces[i].stdir[0][0], br->faces[i].stdir[0][1], br->faces[i].stdir[0][2], br->faces[i].stdir[0][3],
br->faces[i].stdir[1][0], br->faces[i].stdir[1][1], br->faces[i].stdir[1][2], br->faces[i].stdir[1][3]
);
VFS_PRINTF(file, "\n\tpatchDef2\n\t{\n\t\"%s\"\n\t( %.9g %.9g %.9g %.9g %.9g )\n\t(\t\n",
br->patch->tex?br->patch->tex->shadername:"",
0.0/*xoffset*/,
0.0/*yoffset*/,
0.0/*rotation*/,
1.0/*xscale*/,
1.0/*yscale*/);
for (y = 0; y < br->patch->ypoints; y++)
{
VFS_PRINTF(file, "\t\t( ");
for (x = 0; x < br->patch->xpoints; x++)
{
VFS_PRINTF(file, "( %.9g %.9g %.9g %.9g %.9g )", br->patch->verts[x + y*br->patch->xpoints].v[0],
br->patch->verts[x + y*br->patch->xpoints].v[1],
br->patch->verts[x + y*br->patch->xpoints].v[2],
br->patch->verts[x + y*br->patch->xpoints].tc[0],
br->patch->verts[x + y*br->patch->xpoints].tc[1]);
}
VFS_PRINTF(file, " )");
}
VFS_PRINTF(file, " )\n\t}\n");
}
else
{
for (i = 0; i < br->numplanes; i++)
{
point[0] = br->faces[i].points[0];
point[1] = br->faces[i].points[1];
point[2] = br->faces[i].points[2];
//%.9g is 'meant' to be lossless for a standard ieee single-precision float. (%.17g for a double)
VFS_PRINTF(file, "\n( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) ( %.9g %.9g %.9g ) \"%s\" [ %.9g %.9g %.9g %.9g ] [ %.9g %.9g %.9g %.9g ] 0 1 1",
point[0][0], point[0][1], point[0][2],
point[1][0], point[1][1], point[1][2],
point[2][0], point[2][1], point[2][2],
br->faces[i].tex?br->faces[i].tex->shadername:"",
br->faces[i].stdir[0][0], br->faces[i].stdir[0][1], br->faces[i].stdir[0][2], br->faces[i].stdir[0][3],
br->faces[i].stdir[1][0], br->faces[i].stdir[1][1], br->faces[i].stdir[1][2], br->faces[i].stdir[1][3]
);
}
}
VFS_PRINTF(file, "\n}");
}
void Terr_WriteMapFile(vfsfile_t *file, model_t *mod)
@ -7219,12 +7284,14 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
}
else if (inbrush && !strcmp(token, "patchDef2"))
{
vec5_t pvert[64][64];
int x, y;
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*validate {*/
if (strcmp(token, "{")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*parse texture name*/
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*validate (*/
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*xoffset = atof(token);*/
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
@ -7236,46 +7303,53 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*yscale = atof(token);*/
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*validate )*/
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*validate (*/
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
y = 0;
while (!strcmp(token, "("))
{
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
x = 0;
while (!strcmp(token, "("))
{
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//x = atof(token);
pvert[y][x][0] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//y = atof(token);
pvert[y][x][1] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//z = atof(token);
pvert[y][x][2] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//s = atof(token);
pvert[y][x][3] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
//t = atof(token);
pvert[y][x][4] = atof(token);
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*validate )*/
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (x < countof(pvert[y])-1)
x++;
}
/*validate )*/
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
if (y < countof(pvert)-1)
y++;
}
/*validate )*/
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
/*validate }*/
if (strcmp(token, "}")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
}
else if (inbrush)
{
//parse a plane
//Quake: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname 0 -32 rotation sscale tscale
//hexen2: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname 0 -32 rotation sscale tscale utterlypointless
//Quake: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale
//hexen2:( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname soffset toffset rotation sscale tscale utterlypointless
//Valve: ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) texname [x y z d] [x y z d] rotation sscale tscale
//fte : ( px py pz pd ) texname [sx sy sz sd] [tx ty tz td] 0 1 1
//q3 : (( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) common/caulk common/caulk rotation sscale tscale detailcontents unused unused
//q3 : ( -0 -0 16 ) ( -0 -0 32 ) ( 64 -0 16 ) common/caulk common/caulk rotation sscale tscale detailcontents unused unused
//doom3: brushdef3 { ( px py pz pd ) ( ( x y z ) ( x y z ) ) texture detailcontents unused unused }
brushtex_t *bt;
vec3_t d1,d2;
vec3_t points[3];
@ -7331,7 +7405,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
else if (!Q_strncasecmp(token, "*sky", 4))
brushcontents = FTECONTENTS_SKY;
else if (!Q_strcasecmp(token, "clip"))
brushcontents = FTECONTENTS_PLAYERCLIP;
brushcontents = FTECONTENTS_PLAYERCLIP|FTECONTENTS_MONSTERCLIP;
else
brushcontents = FTECONTENTS_SOLID;

View File

@ -657,7 +657,7 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
if (sequence->hasblendseq>1)
{
int bf0, bf1;
int bweights;
unsigned int bweights;
struct
{
int frame;
@ -766,6 +766,7 @@ void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, fl
}
if (frame1 != frame2)
{
//bweights can be 0-4 here..
for (i = 0; i < bweights; i++)
{
blend[bweights+i].frame = frame2;

View File

@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern cvar_t r_shadow_bumpscale_basetexture;
extern cvar_t r_replacemodels;
extern cvar_t gl_lightmap_average;
extern cvar_t r_lightmap_average;
cvar_t mod_loadentfiles = CVAR("sv_loadentfiles", "1");
cvar_t mod_loadentfiles_dir = CVAR("sv_loadentfiles_dir", "");
cvar_t mod_external_vis = CVARD("mod_external_vis", "1", "Attempt to load .vis patches for quake maps, allowing transparent water to work properly.");
@ -1670,15 +1670,17 @@ Mod_LoadLighting
void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean interleaveddeluxe, lightmapoverrides_t *overrides)
{
qboolean luxtmp = true;
qboolean exptmp = true;
qboolean littmp = true;
qbyte *luxdata = NULL;
qbyte *litdata = NULL;
qbyte *lumdata = NULL;
qbyte *luxdata = NULL; //rgb8
qbyte *expdata = NULL; //e5bgr9 (hdr!)
qbyte *litdata = NULL; //xyz8
qbyte *lumdata = NULL; //l8
qbyte *out;
unsigned int samples;
extern cvar_t gl_overbright;
loadmodel->engineflags &= ~MDLF_RGBLIGHTING;
loadmodel->lightmaps.fmt = LM_L8;
//q3 maps have built in 4-fold overbright.
//if we're not rendering with that, we need to brighten the lightmaps in order to keep the darker parts the same brightness. we loose the 2 upper bits. those bright areas become uniform and indistinct.
@ -1687,9 +1689,8 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
gl_overbright.flags |= CVAR_RENDERERLATCH;
BuildLightMapGammaTable(1, (1<<(2-gl_overbright.ival)));
}
else
//lit file light intensity is made to match the world's light intensity.
BuildLightMapGammaTable(1, 1);
else //lit file light intensity is made to match the world's light intensity.
BuildLightMapGammaTable(1, 1);
loadmodel->lightdata = NULL;
loadmodel->deluxdata = NULL;
@ -1707,17 +1708,23 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
samples >>= 1;
if (!samples)
{
litdata = Q1BSPX_FindLump("RGBLIGHTING", &samples);
samples /= 3;
expdata = Q1BSPX_FindLump("LIGHTING_E5BGR9", &samples); //expressed as a big-endian packed int - 0xEBGR type thing, except misaligned and 32bit.
samples /= 4;
if (!samples)
return;
{
litdata = Q1BSPX_FindLump("RGBLIGHTING", &samples); //RGB packed data
samples /= 3;
if (!samples)
return;
}
}
#ifndef SERVERONLY
if (!litdata && r_loadlits.value)
if (!expdata && !litdata && r_loadlits.value)
{
char *litnames[] = {
"%s.lit2",
"%s.hdr",
"%s.lit",
"lits/%s.lit2",
"lits/%s.lit"
@ -1765,22 +1772,31 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
if (litdata && litsize >= 8)
{ //validate it, if we loaded one.
int litver = LittleLong(*(int *)&litdata[4]);
if (litdata[0] != 'Q' || litdata[1] != 'L' || litdata[2] != 'I' || litdata[3] != 'T')
{
litdata = NULL;
Con_Printf("lit \"%s\" isn't a lit\n", litname);
}
else if (LittleLong(*(int *)&litdata[4]) == 1 && l->filelen && samples*3 != (litsize-8))
else if (litver == 1)
{
if (l->filelen && samples*3 != (litsize-8))
{
litdata = NULL;
Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname);
}
else
litdata += 8; //header+version
}
else if (litver == 0x10001)
{
if (l->filelen && samples*4 != (litsize-8))
Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname);
else
expdata = litdata+8; //header+version
litdata = NULL;
Con_Printf("lit \"%s\" doesn't match level. Ignored.\n", litname);
}
else if (LittleLong(*(int *)&litdata[4]) == 1)
{
//header+version
litdata += 8;
}
else if (LittleLong(*(int *)&litdata[4]) == 2 && overrides)
else if (litver == 2 && overrides)
{
qlit2_t *ql2 = (qlit2_t*)litdata;
unsigned int *offsets = (unsigned int*)(ql2+1);
@ -1822,15 +1838,22 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
}
}
littmp = false;
exptmp = littmp = false;
if (!litdata)
{
int size;
/*FIXME: bspx support for extents+lmscale, may require style+offset lumps too, not sure what to do here*/
litdata = Q1BSPX_FindLump("RGBLIGHTING", &size);
if (size != samples*3)
litdata = NULL;
littmp = true;
expdata = Q1BSPX_FindLump("LIGHTING_E5BGR9", &size);
exptmp = true;
if (size != samples*4)
{
expdata = NULL;
litdata = Q1BSPX_FindLump("RGBLIGHTING", &size);
littmp = true;
if (size != samples*3)
litdata = NULL;
}
}
else if (!inhibitvalidation)
{
@ -2011,36 +2034,42 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
overrides->styles = NULL;
}
}
if (luxdata && luxtmp)
{
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->deluxdata = ZG_Malloc(&loadmodel->memgroup, samples*3);
memcpy(loadmodel->deluxdata, luxdata, samples*3);
}
else if (luxdata)
{
loadmodel->deluxdata = luxdata;
}
else if (interleaveddeluxe)
loadmodel->deluxdata = ZG_Malloc(&loadmodel->memgroup, samples*3);
if (litdata && littmp)
if (expdata)
{
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->lightdata = ZG_Malloc(&loadmodel->memgroup, samples*3);
/*the memcpy is below*/
samples*=3;
loadmodel->lightmaps.fmt = LM_E5BGR9;
loadmodel->lightdatasize = samples*4;
if (exptmp)
{
loadmodel->lightdata = ZG_Malloc(&loadmodel->memgroup, samples*4);
memcpy(loadmodel->lightdata, expdata, samples*4);
}
else
loadmodel->lightdata = expdata;
return;
}
else if (litdata)
{
loadmodel->engineflags |= MDLF_RGBLIGHTING;
loadmodel->lightdata = litdata;
loadmodel->lightmaps.fmt = LM_RGB8;
if (littmp)
loadmodel->lightdata = ZG_Malloc(&loadmodel->memgroup, samples*3); /*the memcpy is below*/
else
loadmodel->lightdata = litdata;
samples*=3;
}
else if (lumdata)
{
loadmodel->engineflags &= ~MDLF_RGBLIGHTING;
loadmodel->lightmaps.fmt = LM_L8;
loadmodel->lightdata = ZG_Malloc(&loadmodel->memgroup, samples);
litdata = lumdata;
}
@ -2071,7 +2100,7 @@ void Mod_LoadLighting (model_t *loadmodel, qbyte *mod_base, lump_t *l, qboolean
}
#ifndef SERVERONLY
if ((loadmodel->engineflags & MDLF_RGBLIGHTING) && r_lightmap_saturation.value != 1.0f)
if ((loadmodel->lightmaps.fmt == LM_RGB8) && r_lightmap_saturation.value != 1.0f)
SaturateR8G8B8(loadmodel->lightdata, l->filelen, r_lightmap_saturation.value);
#endif
}
@ -2362,7 +2391,7 @@ void ModQ1_Batches_BuildQ1Q2Poly(model_t *mod, msurface_t *surf, builddata_t *co
}
#ifndef SERVERONLY
if (gl_lightmap_average.ival)
if (r_lightmap_average.ival)
{
for (sty = 0; sty < 1; sty++)
{
@ -3716,6 +3745,8 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, l
char buf[64];
lightmapoverrides_t overrides;
int lofsscale = 1;
memset(&overrides, 0, sizeof(overrides));
lmscale = atoi(Mod_ParseWorldspawnKey(loadmodel, "lightmap_scale", buf, sizeof(buf)));
@ -3757,6 +3788,22 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, l
Mod_LoadLighting (loadmodel, mod_base, lightlump, false, &overrides);
switch(loadmodel->lightmaps.fmt)
{
case LM_E5BGR9:
lofsscale = 4;
break;
case LM_RGB8:
lofsscale = 3;
break;
default:
case LM_L8:
lofsscale = 1;
break;
}
if (loadmodel->fromgame == fg_halflife)
lofsscale /= 3; //halflife has rgb offsets already (this should drop to 1, preserving any misaligned offsets...
for ( surfnum=0 ; surfnum<count ; surfnum++, out++)
{
if (lm)
@ -3810,8 +3857,8 @@ static qboolean Mod_LoadFaces (model_t *loadmodel, qbyte *mod_base, lump_t *l, l
out->styles[i] = overrides.styles[surfnum*4+i];
CalcSurfaceExtents (loadmodel, out);
if (lofs != (unsigned int)-1 && (loadmodel->engineflags & MDLF_RGBLIGHTING) && loadmodel->fromgame != fg_halflife)
lofs *= 3;
if (lofs != (unsigned int)-1)
lofs *= lofsscale;
lend = lofs+(out->extents[0]+1)*(out->extents[1]+1);
if (lofs > loadmodel->lightdatasize || lend < lofs)
out->samples = NULL; //should includes -1
@ -4824,6 +4871,7 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
}
}
#if defined(Q3BSPS) || defined(RFBSPS)
if (mod->fromgame == fg_quake3)
{
if (mod->lightmaps.deluxemapping && mod->lightmaps.deluxemapping_modelspace)
@ -4850,7 +4898,10 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
}
mod->textures[2*mod->numtexinfo]->shader = R_RegisterShader_Flare("noshader");
}
else if (mod->fromgame == fg_quake2)
else
#endif
#ifdef Q2BSPS
if (mod->fromgame == fg_quake2)
{
COM_FileBase (mod->name, loadname, sizeof(loadname));
for(a = 0; a < mod->numtextures; a++)
@ -4866,11 +4917,12 @@ void ModBrush_LoadGLStuff(void *ctx, void *data, size_t a, size_t b)
// maps |= SHADER_HASNORMALMAP;
if (gl_specular.ival)
maps |= SHADER_HASGLOSS;
R_BuildLegacyTexnums(mod->textures[a]->shader, mod->textures[a]->name, loadname, maps, 0, TF_MIP4_SOLID8, mod->textures[a]->width, mod->textures[a]->height, mod->textures[a]->mips, mod->textures[a]->palette);
R_BuildLegacyTexnums(mod->textures[a]->shader, mod->textures[a]->name, loadname, maps, 0, TF_MIP4_8PAL24, mod->textures[a]->width, mod->textures[a]->height, mod->textures[a]->mips, mod->textures[a]->palette);
BZ_Free(mod->textures[a]->mips[0]);
}
}
else
#endif
{
COM_FileBase (mod->name, loadname, sizeof(loadname));
if (!strncmp(loadname, "b_", 2))

View File

@ -423,7 +423,7 @@ typedef struct msurface_s
qbyte styles[MAXQ1LIGHTMAPS];
qbyte vlstyles[MAXRLIGHTMAPS];
int cached_light[MAXQ1LIGHTMAPS]; // values currently used in lightmap
int cached_colour[MAXQ1LIGHTMAPS];
int cached_colour[MAXQ1LIGHTMAPS]; // values currently used in lightmap
qboolean cached_dlight; // true if dynamic light in cache
#ifndef NOSTAINS
qboolean stained;
@ -997,6 +997,14 @@ typedef struct model_s
int width; //x size of lightmaps
int height; //y size of lightmaps
int surfstyles; //numbers of style per surface.
enum {
//vanilla used byte values, with 255 being a value of about 2.
//float/hdr formats use 1 to mean 1, however.
//internally, we still use integers for lighting, with .7 bits of extra precision.
LM_L8,
LM_RGB8,
LM_E5BGR9
} fmt;
qboolean deluxemapping; //lightmaps are interleaved with deluxemap data (lightmap indicies should only be even values)
qboolean deluxemapping_modelspace; //deluxemaps are in modelspace - we need different glsl.
} lightmaps;
@ -1018,7 +1026,7 @@ typedef struct model_s
#define MDLF_EMITREPLACE 0x0001 // particle effect engulphs model (don't draw)
#define MDLF_EMITFORWARDS 0x0002
#define MDLF_NODEFAULTTRAIL 0x0004
#define MDLF_RGBLIGHTING 0x0008
//#define MDLF_RGBLIGHTING 0x0008
#define MDLF_PLAYER 0x0010 // players have specific lighting values
#define MDLF_FLAME 0x0020 // can be excluded with r_drawflame, fullbright render hack
#define MDLF_DOCRC 0x0040 // model needs CRC built

View File

@ -1541,30 +1541,39 @@ static int GLRecursiveLightPoint (mnode_t *node, vec3_t start, vec3_t end)
r = 0;
if (lightmap)
{
if (cl.worldmodel->engineflags & MDLF_RGBLIGHTING)
switch(cl.worldmodel->lightmaps.fmt)
{
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
case LM_E5BGR9:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
unsigned int l = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]];
scale *= pow(2, (int)(l>>27)-15-9+7);
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
r += max3(((l>> 0)&0x1ff), ((l>> 9)&0x1ff), ((l>>18)&0x1ff)) * scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1)<<2;
}
break;
case LM_RGB8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
r += (lightmap[0]+lightmap[1]+lightmap[2]) * scale / 3;
r += max3(lightmap[0],lightmap[1],lightmap[2]) * scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1)*3;
}
}
else
{
break;
case LM_L8:
lightmap += dt * ((surf->extents[0]>>surf->lmshift)+1) + ds;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]];
r += *lightmap * scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) * ((surf->extents[1]>>surf->lmshift)+1);
}
break;
}
r >>= 8;
@ -1703,14 +1712,39 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
overbright = 1/255.0f;
if (mod->deluxdata)
{
if (mod->engineflags & MDLF_RGBLIGHTING)
switch(mod->lightmaps.fmt)
{
case LM_E5BGR9:
deluxmap = ((surf->samples - mod->lightdata)>>2)*3 + mod->deluxdata;
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<4;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
unsigned int lm = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
scale *= pow(2, (int)(lm>>27)-15-9+8);
l[0] += ((lm>> 0)&0x1ff) * scale * cl_lightstyle[surf->styles[maps]].colours[0];
l[1] += ((lm>> 9)&0x1ff) * scale * cl_lightstyle[surf->styles[maps]].colours[1];
l[2] += ((lm>>18)&0x1ff) * scale * cl_lightstyle[surf->styles[maps]].colours[2];
l[3] += (deluxmap[0]-127)*scale;
l[4] += (deluxmap[1]-127)*scale;
l[5] += (deluxmap[2]-127)*scale;
lightmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1)<<2;
deluxmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1) * 3;
}
break;
case LM_RGB8:
deluxmap = surf->samples - mod->lightdata + mod->deluxdata;
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -1727,16 +1761,13 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
deluxmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1) * 3;
}
}
else
{
break;
case LM_L8:
deluxmap = (surf->samples - mod->lightdata)*3 + mod->deluxdata;
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds);
deluxmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -1753,16 +1784,33 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
deluxmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1) * 3;
}
break;
}
}
else
{
if (mod->engineflags & MDLF_RGBLIGHTING)
switch(mod->lightmaps.fmt)
{
case LM_E5BGR9:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)<<2;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
unsigned int lm = *(unsigned int*)lightmap;
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
scale *= pow(2, (int)(lm>>27)-15-9+8);
l[0] += ((lm>> 0)&0x1ff) * scale * cl_lightstyle[surf->styles[maps]].colours[0];
l[1] += ((lm>> 9)&0x1ff) * scale * cl_lightstyle[surf->styles[maps]].colours[1];
l[2] += ((lm>>18)&0x1ff) * scale * cl_lightstyle[surf->styles[maps]].colours[2];
lightmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1)<<2;
}
break;
case LM_RGB8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds)*3;
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -1773,13 +1821,10 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
lightmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1) * 3;
}
}
else
{
break;
case LM_L8:
lightmap += (dt * ((surf->extents[0]>>surf->lmshift)+1) + ds);
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ;
maps++)
for (maps = 0 ; maps < MAXQ1LIGHTMAPS && surf->styles[maps] != 255 ; maps++)
{
scale = d_lightstylevalue[surf->styles[maps]]*overbright;
@ -1790,6 +1835,7 @@ static float *GLRecursiveLightPoint3C (model_t *mod, mnode_t *node, vec3_t start
lightmap += ((surf->extents[0]>>surf->lmshift)+1) *
((surf->extents[1]>>surf->lmshift)+1);
}
break;
}
}
}
@ -1849,9 +1895,9 @@ void GLQ1BSP_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse,
}
else
{
res_diffuse[0] = r[0]*2;
res_diffuse[1] = r[1]*2;
res_diffuse[2] = r[2]*2;
res_diffuse[0] = r[0];
res_diffuse[1] = r[1];
res_diffuse[2] = r[2];
/*bright on one side, dark on the other, but not too dark*/
res_ambient[0] = r[0]/2;

View File

@ -33,6 +33,7 @@ void R_RenderBrushPoly (msurface_t *fa);
extern int gl_stencilbits;
FTEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC qglCompressedTexImage3DARB;
FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
@ -60,6 +61,7 @@ extern cvar_t r_stereo_separation;
extern cvar_t r_stereo_convergence;
extern cvar_t r_stereo_method;
extern cvar_t r_postprocshader, r_fxaa;
extern cvar_t r_hdr_framebuffer;
extern cvar_t gl_screenangle;
@ -88,6 +90,7 @@ extern cvar_t scr_fov;
shader_t *scenepp_rescaled;
shader_t *scenepp_antialias;
shader_t *scenepp_waterwarp;
shader_t *scenepp_gamma;
// post processing stuff
texid_t sceneblur_texture;
@ -143,19 +146,34 @@ void GL_InitSceneProcessingShaders (void)
GL_InitSceneProcessingShaders_WaterWarp();
}
scenepp_gamma = R_RegisterShader("fte_scenegamma", 0,
"{\n"
"program defaultgammacb\n"
"affine\n"
"{\n"
"map $sourcecolour\n"
"nodepthtest\n"
"}\n"
"}\n"
);
scenepp_rescaled = R_RegisterShader("fte_rescaler", 0,
"{\n"
"program default2d\n"
"affine\n"
"{\n"
"map $sourcecolour\n"
"nodepthtest\n"
"}\n"
"}\n"
);
scenepp_antialias = R_RegisterShader("fte_ppantialias", 0,
"{\n"
"program fxaa\n"
"affine\n"
"{\n"
"map $sourcecolour\n"
"nodepthtest\n"
"}\n"
"}\n"
);
@ -641,14 +659,6 @@ void R_SetupGL (float stereooffset, int i)
qglDisable(GL_DITHER);
}
}
if (vid_srgb.modified && !gl_config_gles)
{
vid_srgb.modified = false;
if (vid_srgb.ival == 1 || vid.srgb)
qglEnable(GL_FRAMEBUFFER_SRGB); //specifies that the glsl is writing colours in the linear colour space, even if the framebuffer is not sRGB.
else
qglDisable(GL_FRAMEBUFFER_SRGB);
}
}
void Surf_SetupFrame(void);
@ -1846,6 +1856,7 @@ void GLR_RenderView (void)
shader_t *custompostproc = NULL;
float renderscale; //extreme, but whatever
int oldfbo = 0;
qboolean forcedfb = false;
checkglerror();
@ -1873,9 +1884,7 @@ void GLR_RenderView (void)
r_refdef.flags &= ~(RDF_ALLPOSTPROC|RDF_RENDERSCALE);
if (dofbo || (r_refdef.flags & RDF_NOWORLDMODEL))
{
renderscale = 1;
}
else
{
renderscale = r_renderscale.value;
@ -1917,10 +1926,21 @@ void GLR_RenderView (void)
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && r_fxaa.ival) //overlays will have problems.
r_refdef.flags |= RDF_ANTIALIAS;
if (!(r_refdef.flags & RDF_NOWORLDMODEL) && r_hdr_framebuffer.ival && !(vid.flags & VID_FP16)) //primary use of this cvar is to fix q3shader overbrights (so bright lightmaps can oversaturate then drop below 1 by modulation with the lightmap
forcedfb = true;
if (vid_hardwaregamma.ival == 4 && (v_gamma.value != 1 || v_contrast.value != 1 || v_brightness.value != 0))
r_refdef.flags |= RDF_SCENEGAMMA;
//disable stuff if its simply not supported.
if (dofbo || !gl_config.arb_shader_objects || !gl_config.ext_framebuffer_objects || !sh_config.texture_non_power_of_two_pic)
{
forcedfb &= !dofbo && gl_config.ext_framebuffer_objects && sh_config.texture_non_power_of_two_pic;
r_refdef.flags &= ~(RDF_ALLPOSTPROC); //block all of this stuff
}
if (dofbo)
forcedfb = false;
else if (r_renderscale.value != 1)
forcedfb = true;
BE_Scissor(NULL);
if (dofbo)
@ -1969,9 +1989,10 @@ void GLR_RenderView (void)
flags |= FBO_RB_DEPTH;
oldfbo = GLBE_FBO_Update(&fbo_gameview, flags, col, mrt, depth, vid.fbpwidth, vid.fbpheight, 0);
}
else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || renderscale != 1)
else if ((r_refdef.flags & (RDF_ALLPOSTPROC)) || forcedfb)
{
unsigned int rtflags = IF_NOMIPMAP|IF_CLAMP|IF_RENDERTARGET;
enum uploadfmt fmt;
r_refdef.flags |= RDF_RENDERSCALE;
@ -2008,7 +2029,16 @@ void GLR_RenderView (void)
vid.fbvwidth = vid.fbpwidth;
vid.fbvheight = vid.fbpheight;
sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, /*(r_refdef.flags&RDF_BLOOM)?TF_RGBA16F:*/TF_RGBA32, rtflags);
fmt = PTI_RGBA8;
if ((r_refdef.flags&RDF_SCENEGAMMA)||(vid.flags&(VID_SRGBAWARE|VID_FP16))||r_hdr_framebuffer.ival)
{ //gamma ramps really need higher colour precision, otherwise the entire thing looks terrible.
if (sh_config.texfmt[PTI_RGBA16F])
fmt = PTI_RGBA16F;
else if (sh_config.texfmt[PTI_A2BGR10])
fmt = PTI_A2BGR10;
}
sourcetex = R2D_RT_Configure("rt/$lastgameview", vid.fbpwidth, vid.fbpheight, fmt, rtflags);
oldfbo = GLBE_FBO_Update(&fbo_gameview, FBO_RB_DEPTH, &sourcetex, 1, r_nulltex, vid.fbpwidth, vid.fbpheight, 0);
dofbo = true;
@ -2095,13 +2125,19 @@ void GLR_RenderView (void)
// SCENE POST PROCESSING
if (renderscale != 1 && !(r_refdef.flags & RDF_ALLPOSTPROC))
if (forcedfb && !(r_refdef.flags & RDF_ALLPOSTPROC))
{
GLBE_FBO_Sources(sourcetex, r_nulltex);
R2D_Image(r_refdef.vrect.x, r_refdef.vrect.y, r_refdef.vrect.width, r_refdef.vrect.height, 0, 1, 1, 0, scenepp_rescaled);
}
else
{
if (r_refdef.flags & RDF_SCENEGAMMA)
{
R2D_ImageColours (v_gamma.value, v_contrast.value, v_brightness.value, 1);
sourcetex = R_RenderPostProcess (sourcetex, RDF_SCENEGAMMA, scenepp_gamma, "rt/$gammaed");
R2D_ImageColours (1, 1, 1, 1);
}
sourcetex = R_RenderPostProcess (sourcetex, RDF_WATERWARP, scenepp_waterwarp, "rt/$waterwarped");
sourcetex = R_RenderPostProcess (sourcetex, RDF_CUSTOMPOSTPROC, custompostproc, "rt/$postproced");
sourcetex = R_RenderPostProcess (sourcetex, RDF_ANTIALIAS, scenepp_antialias, "rt/$antialiased");

View File

@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "renderque.h"
#include <math.h>
extern cvar_t gl_lightmap_nearest;
extern cvar_t r_lightmap_nearest;
void GLBE_ClearVBO(vbo_t *vbo, qboolean dataonly)
{
@ -543,11 +543,11 @@ void GLBE_UploadAllLightmaps(void)
continue;
lm->modified = false;
if (!TEXVALID(lm->lightmap_texture))
TEXASSIGN(lm->lightmap_texture, Image_CreateTexture(va("***lightmap %i***", i), NULL, (gl_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP));
TEXASSIGN(lm->lightmap_texture, Image_CreateTexture(va("***lightmap %i***", i), NULL, (r_lightmap_nearest.ival?IF_NEAREST:IF_LINEAR)|IF_NOMIPMAP));
if (!lm->lightmap_texture->num)
qglGenTextures(1, &lm->lightmap_texture->num);
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
if (gl_lightmap_nearest.ival)
if (r_lightmap_nearest.ival)
{
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
@ -557,15 +557,17 @@ void GLBE_UploadAllLightmaps(void)
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
switch(lightmap_fmt) //bgra32, rgba32, rgb24, lum8
qglTexImage2D(GL_TEXTURE_2D, 0, gl_config.formatinfo[lightmap_fmt].internalformat, lm->width, lm->height, 0, gl_config.formatinfo[lightmap_fmt].format, gl_config.formatinfo[lightmap_fmt].type, lightmap[i]->lightmaps);
if (gl_config.glversion >= (gl_config.gles?3.0:3.3))
{
default: Sys_Error("Bad lightmap_fmt\n"); break;
case TF_BGRA32: qglTexImage2D(GL_TEXTURE_2D, 0, /*vid.srgb?GL_SRGB8_ALPHA8_EXT:*/GL_RGBA, lm->width, lm->height, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,lightmap[i]->lightmaps); break;
// case TF_RGBA32: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lm->width, lm->height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV,lightmap[i]->lightmaps); break;
// case TF_BGR24: qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, lm->width, lm->height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
case TF_RGB24: qglTexImage2D(GL_TEXTURE_2D, 0, /*vid.srgb?GL_SRGB8_EXT:*/GL_RGB, lm->width, lm->height, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
case TF_LUM8: qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, lm->width, lm->height, 0, GL_LUMINANCE,GL_UNSIGNED_BYTE, lightmap[i]->lightmaps); break;
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, gl_config.formatinfo[lightmap_fmt].swizzle_r);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, gl_config.formatinfo[lightmap_fmt].swizzle_g);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, gl_config.formatinfo[lightmap_fmt].swizzle_b);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[lightmap_fmt].swizzle_a);
}
//for completeness.
lm->lightmap_texture->width = lm->width;
lm->lightmap_texture->height = lm->height;

View File

@ -64,6 +64,7 @@ qboolean GLSCR_UpdateScreen (void)
int uimenu;
qboolean nohud;
qboolean noworld;
extern cvar_t vid_srgb;
r_refdef.pxrect.maxheight = vid.pixelheight;
@ -71,6 +72,31 @@ qboolean GLSCR_UpdateScreen (void)
R2D_Font_Changed();
if (vid_srgb.modified)
{
vid_srgb.modified = false;
//vid_srgb can be changed between 0 and 1, but other values need texture reloads. do that without too much extra weirdness.
if ((vid.flags & VID_SRGB_CAPABLE) && gl_config.arb_framebuffer_srgb)
{ //srgb-capable
if (vid_srgb.ival > 1 && (vid.flags & VID_SRGBAWARE))
{ //full srgb wanted (and textures are loaded)
qglEnable(GL_FRAMEBUFFER_SRGB);
vid.flags |= VID_SRGB_FB_LINEAR;
}
else if (vid_srgb.ival==1 || (vid.flags & VID_SRGBAWARE))
{ //srgb wanted only for the framebuffer, for gamma tricks.
qglEnable(GL_FRAMEBUFFER_SRGB);
vid.flags |= VID_SRGB_FB_LINEAR;
}
else
{ //srgb not wanted...
qglDisable(GL_FRAMEBUFFER_SRGB);
vid.flags &= ~VID_SRGB_FB_LINEAR;
}
}
}
if (!scr_initialized || !con_initialized)
{
return false; // not initialized yet

View File

@ -661,6 +661,16 @@ static void Shader_ParseFunc (shader_t *shader, char **ptr, shaderfunc_t *func)
func->type = SHADER_FUNC_INVERSESAWTOOTH;
else if (!Q_stricmp (token, "noise"))
func->type = SHADER_FUNC_NOISE;
else if (!Q_stricmp (token, "distanceramp")) //QFusion
{
func->type = SHADER_FUNC_CONSTANT; //not supported...
Shader_ParseFloat (shader, ptr, 0);
Shader_ParseFloat (shader, ptr, 0);
Shader_ParseFloat (shader, ptr, 0);
Shader_ParseFloat (shader, ptr, 0);
Vector4Set(func->args, 255, 255, 255, 255);
return;
}
func->args[0] = Shader_ParseFloat (shader, ptr, 0);
func->args[1] = Shader_ParseFloat (shader, ptr, 0);
@ -1254,42 +1264,49 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
}
}
}
else if (!strncmp(script, "!!cvardf", 8))
else if (!strncmp(script, "!!cvardf", 8) || !strncmp(script, "!!cvard3", 8) || !strncmp(script, "!!cvard4", 8) || !strncmp(script, "!!cvard_srgb", 11))
{
script += 8;
while (*script == ' ' || *script == '\t')
script++;
end = script;
while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_')
end++;
if (nummodifiers < MAXMODIFIERS && end - script < 64)
qboolean srgb = false;
float div = 1;
char type = script[7];
script+=8;
if (type == '_')
{
cvar_t *var;
char namebuf[64];
char valuebuf[64];
memcpy(namebuf, script, end - script);
namebuf[end - script] = 0;
while (*end == ' ' || *end == '\t')
end++;
if (*end == '=')
if (*script == 's')
{
script = ++end;
while (*end && *end != '\n' && *end != '\r' && end < script+sizeof(namebuf)-1)
end++;
memcpy(valuebuf, script, end - script);
valuebuf[end - script] = 0;
srgb = true;
script+=1;
}
else
strcpy(valuebuf, "0");
var = Cvar_Get(namebuf, valuebuf, CVAR_SHADERSYSTEM, "GLSL Variables");
if (var)
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, var->value));
if (!strncmp(script, "rgba", 4))
{
type = '4';
script+=4;
}
else if (!strncmp(script, "rgb", 3))
{
type = '3';
script+=3;
}
else if (!strncmp(script, "rg", 2))
{
type = '2';
script+=2;
}
else if (!strncmp(script, "r", 1) || !strncmp(script, "f", 1))
{
type = 'f';
script+=1;
}
if (!strncmp(script, "_b", 2))
{
div = 255;
script+=2;
}
else if (!strncmp(script, "_", 1))
div = strtod(script, &script);
}
script = end;
}
else if (!strncmp(script, "!!cvard3", 8))
{
script += 8;
while (*script == ' ' || *script == '\t')
script++;
end = script;
@ -1316,40 +1333,26 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
strcpy(valuebuf, "0");
var = Cvar_Get(namebuf, valuebuf, CVAR_SHADERSYSTEM, "GLSL Variables");
if (var)
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), var->vec4[0], var->vec4[1], var->vec4[2]));
}
script = end;
}
else if (!strncmp(script, "!!cvard4", 8))
{
script += 8;
while (*script == ' ' || *script == '\t')
script++;
end = script;
while ((*end >= 'A' && *end <= 'Z') || (*end >= 'a' && *end <= 'z') || (*end >= '0' && *end <= '9') || *end == '_')
end++;
if (nummodifiers < MAXMODIFIERS && end - script < 64)
{
cvar_t *var;
char namebuf[64];
char valuebuf[64];
memcpy(namebuf, script, end - script);
namebuf[end - script] = 0;
while (*end == ' ' || *end == '\t')
end++;
if (*end == '=')
{
script = ++end;
while (*end && *end != '\n' && *end != '\r' && end < script+sizeof(namebuf)-1)
end++;
memcpy(valuebuf, script, end - script);
valuebuf[end - script] = 0;
if (srgb)
{
if (type == '4')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), SRGBf(var->vec4[0]/div), SRGBf(var->vec4[1]/div), SRGBf(var->vec4[2]/div), var->vec4[3]/div));
else if (type == '3')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), SRGBf(var->vec4[0]/div), SRGBf(var->vec4[1]/div), SRGBf(var->vec4[2]/div)));
else
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, SRGBf(var->value/div)));
}
else
{
if (type == '4')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), var->vec4[0]/div, var->vec4[1]/div, var->vec4[2]/div, var->vec4[3]/div));
else if (type == '3')
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec3":"float3"), var->vec4[0]/div, var->vec4[1]/div, var->vec4[2]/div));
else
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %g\n", namebuf, var->value/div));
}
}
else
strcpy(valuebuf, "0");
var = Cvar_Get(namebuf, valuebuf, CVAR_SHADERSYSTEM, "GLSL Variables");
if (var)
permutationdefines[nummodifiers++] = Z_StrDup(va("#define %s %s(%g,%g,%g,%g)\n", namebuf, ((qrenderer == QR_OPENGL)?"vec4":"float4"), var->vec4[0], var->vec4[1], var->vec4[2], var->vec4[3]));
}
script = end;
}
@ -1449,6 +1452,9 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
else
blobfile = NULL;
if (!r_fog_permutation.ival)
nopermutation |= PERMUTATION_BIT_FOG;
if (blobfile)
{
unsigned int magic;
@ -3118,6 +3124,17 @@ static void Shaderpass_RGBGen (shader_t *shader, shaderpass_t *pass, char **ptr)
Shader_ParseVector (shader, ptr, pass->rgbgen_func.args);
}
else if (!Q_stricmp (token, "srgb") || !Q_stricmp (token, "srgbconst"))
{
pass->rgbgen = RGB_GEN_CONST;
pass->rgbgen_func.type = SHADER_FUNC_CONSTANT;
Shader_ParseVector (shader, ptr, pass->rgbgen_func.args);
pass->rgbgen_func.args[0] = SRGBf(pass->rgbgen_func.args[0]);
pass->rgbgen_func.args[1] = SRGBf(pass->rgbgen_func.args[1]);
pass->rgbgen_func.args[2] = SRGBf(pass->rgbgen_func.args[2]);
}
else if (!Q_stricmp (token, "topcolor"))
pass->rgbgen = RGB_GEN_TOPCOLOR;
else if (!Q_stricmp (token, "bottomcolor"))
@ -3962,7 +3979,7 @@ char *Shader_Skip ( char *ptr )
tok = COM_ParseExt (&ptr, true, true);
}
for (brace_count = 1; brace_count > 0 ; ptr++)
for (brace_count = 1; brace_count > 0; )
{
tok = COM_ParseExt (&ptr, true, true);
@ -4809,7 +4826,7 @@ void Shader_Finish (shader_t *s)
"sort sky\n"
"{\n"
"map $whiteimage\n"
"rgbgen const $r_fastskycolour\n"
"rgbgen srgb $r_fastskycolour\n"
"}\n"
"surfaceparm nodlight\n"
"}\n"
@ -5536,6 +5553,35 @@ void QDECL R_BuildDefaultTexnums(texnums_t *src, shader_t *shader)
}
}
#if 0//def Q2BSPS
static qbyte *ReadRGBA8ImageFile(const char *fname, const char *subpath, int *width, int *height)
{
qboolean hasalpha;
qofs_t filesize;
qbyte *img, *filedata = NULL;
char *patterns[] =
{
"*overrides/%s.tga",
"*overrides/%s.jpg",
"textures/%s.tga",
"textures/%s.jpg",
};
char nname[MAX_QPATH];
size_t p;
for (p = 0; p < countof(patterns) && !filedata; p++)
{
if (*patterns[p] == '*')
Q_snprintfz(nname, sizeof(nname), patterns[p]+1, COM_SkipPath(fname));
else
Q_snprintfz(nname, sizeof(nname), patterns[p], fname);
filedata = FS_MallocFile(nname, FS_GAME, &filesize);
}
img = filedata?Read32BitImageFile(filedata, filesize, width, height, &hasalpha, fname):NULL;
BZ_Free(filedata);
return img;
}
#endif
//call this with some fallback textures to directly load some textures
void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, const char *subpath, unsigned int loadflags, unsigned int imageflags, uploadfmt_t basefmt, size_t width, size_t height, qbyte *mipdata[4], qbyte *palette)
{
@ -5634,6 +5680,62 @@ void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, cons
{
COM_StripExtension(tex->mapname, mapname, sizeof(mapname));
#if 0//def Q2BSPS
if (gl_load24bit.ival == 2)
{
qbyte *base;
int basewidth, baseheight;
qbyte *norm;
int normwidth, normheight;
qbyte tmp;
int x, y;
base = ReadRGBA8ImageFile(imagename, subpath, &basewidth, &baseheight);
//base contains diffuse RGB, and height
if (base)
{
tex->base = Image_GetTexture(va("%s_diff", imagename), subpath, imageflags|IF_NOREPLACE, base, NULL, basewidth, baseheight, TF_RGBX32); //queues the texture creation.
norm = ReadRGBA8ImageFile(va("%s_bump", imagename), subpath, &normwidth, &normheight);
if (norm)
{
if (normwidth != basewidth || normheight != baseheight)
{
//sucks...
tex->bump = Image_GetTexture(va("%s_norm", imagename), subpath, imageflags|IF_NOREPLACE, norm, NULL, normwidth, normheight, TF_RGBX32); //queues the texture creation.
}
else
{
//so we have a base texture, and normalmap
//we already uploaded the diffuse, so now we can just pretend that the base is the specularmap.
//we just need to swap the two alpha channels.
for (y = 0; y < baseheight; y++)
{
for (x = 0; x < basewidth; x++)
{
tmp = base[(x+y*basewidth)*4+3];
base[(x+y*basewidth)*4+3] = norm[(x+y*basewidth)*4+3];
norm[(x+y*basewidth)*4+3] = ((x+y)&1)*255;//tmp;
}
}
tex->bump = Image_GetTexture(va("%s_norm", imagename), subpath, imageflags|IF_NOREPLACE, norm, NULL, normwidth, normheight, TF_RGBA32); //queues the texture creation.
tex->specular = Image_GetTexture(va("%s_spec", imagename), subpath, imageflags|IF_NOREPLACE, base, NULL, basewidth, baseheight, TF_RGBA32); //queues the texture creation.
}
BZ_Free(norm);
}
else
{
//generate a height8 image from the alpha channel. we can do it in place
for (y = 0; y < baseheight; y++)
{
for (x = 0; x < basewidth; x++)
base[(x+y*basewidth)] = base[(x+y*basewidth)*4+3];
}
tex->bump = Image_GetTexture(va("%s_norm", imagename), subpath, imageflags|IF_NOREPLACE, base, NULL, basewidth, baseheight, TF_HEIGHT8);
}
BZ_Free(base);
}
}
#endif
/*dlights/realtime lighting needs some stuff*/
if (loadflags & SHADER_HASDIFFUSE)
{
@ -5663,7 +5765,7 @@ void QDECL R_BuildLegacyTexnums(shader_t *shader, const char *fallbackname, cons
if (!TEXVALID(tex->paletted) && *mapname)
tex->paletted = R_LoadHiResTexture(va("%s_pal", mapname), NULL, imageflags|IF_NEAREST);
if (!TEXVALID(tex->paletted))
tex->paletted = Image_GetTexture(va("%s_pal", imagename), subpath, imageflags|IF_NEAREST, mipdata[0], palette, width, height, (basefmt==TF_MIP4_SOLID8)?TF_MIP4_LUM8:TF_LUM8);
tex->paletted = Image_GetTexture(va("%s_pal", imagename), subpath, imageflags|IF_NEAREST|IF_NOSRGB, mipdata[0], palette, width, height, (basefmt==TF_MIP4_SOLID8)?TF_MIP4_R8:TF_R8);
}
imageflags |= IF_LOWPRIORITY;
@ -5768,7 +5870,7 @@ void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args)
"{\n"
"map $lightmap\n"
"tcgen lightmap\n"
"rgbgen const 255 255 255\n"
"rgbgen srgb 255 255 255\n"
"}\n"
"}\n"
);
@ -5780,7 +5882,7 @@ void Shader_DefaultBSPLM(const char *shortname, shader_t *s, const void *args)
"{\n"
"map $lightmap\n"
"tcgen lightmap\n"
"rgbgen const $r_floorcolour\n"
"rgbgen srgb $r_floorcolour\n"
"}\n"
"}\n"
);
@ -6021,7 +6123,7 @@ char *Shader_DefaultBSPWater(shader_t *s, const char *shortname, char *buffer, s
// "program defaultfill\n"
"{\n"
"map $whiteimage\n"
"rgbgen const $r_fastturbcolour\n"
"rgbgen srgb $r_fastturbcolour\n"
"}\n"
"surfaceparm nodlight\n"
"surfaceparm nomarks\n"
@ -6220,7 +6322,7 @@ void Shader_DefaultBSPQ1(const char *shortname, shader_t *s, const void *args)
"sort sky\n"
"{\n"
"map $whiteimage\n"
"rgbgen const $r_fastskycolour\n"
"rgbgen srgb $r_fastskycolour\n"
"}\n"
"surfaceparm nodlight\n"
"}\n"
@ -6921,7 +7023,36 @@ static char *Shader_DecomposeSubPass(char *o, shaderpass_t *p, qboolean simple)
case T_GEN_SINGLEMAP:
if (p->anim_frames[0])
{
sprintf(o, "singlemap \"%s\" %ix%i", p->anim_frames[0]->ident, p->anim_frames[0]->width, p->anim_frames[0]->height);
unsigned int flags = p->anim_frames[0]->flags;
sprintf(o, "singlemap \"%s\" %ix%i%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", p->anim_frames[0]->ident, p->anim_frames[0]->width, p->anim_frames[0]->height,
(p->anim_frames[0]->status == TEX_FAILED)?" FAILED":"",
(flags&IF_CLAMP)?" clamp":"",
(flags&IF_NOMIPMAP)?" nomipmap":"",
(flags&IF_NEAREST)?" nearest":"",
(flags&IF_LINEAR)?" linear":"",
(flags&IF_UIPIC)?" uipic":"",
(flags&IF_SRGB)?" srgb":"",
(flags&IF_NOPICMIP)?" nopicmip":"",
(flags&IF_NOALPHA)?" noalpha":"",
(flags&IF_NOGAMMA)?" noalpha":"",
(flags&IF_TEXTYPE)?" non-2d":"",
(flags&IF_MIPCAP)?"":" nomipcap",
(flags&IF_PREMULTIPLYALPHA)?" premultiply":"",
(flags&IF_NOSRGB)?" nosrgb":"",
(flags&IF_PALETTIZE)?" palettize":"",
(flags&IF_NOPURGE)?" nopurge":"",
(flags&IF_HIGHPRIORITY)?" highpri":"",
(flags&IF_LOWPRIORITY)?" lowpri":"",
(flags&IF_LOADNOW)?" loadnow":"",
(flags&IF_TRYBUMP)?" trybump":"",
(flags&IF_RENDERTARGET)?" rendertarget":"",
(flags&IF_EXACTEXTENSION)?" exactext":"",
(flags&IF_NOREPLACE)?" noreplace":"",
(flags&IF_NOWORKER)?" noworker":""
);
}
else
sprintf(o, "singlemap ");

View File

@ -3445,7 +3445,7 @@ void Sh_PreGenerateLights(void)
shadowtype = SMT_STENCILVOLUME;
//shadowless and lights with an ambient term pass through walls, so need to affect EVERY leaf withing the sphere.
if (shadowtype == SMT_SHADOWLESS || dl->lightcolourscales[0])
if ((shadowtype == SMT_SHADOWLESS || dl->lightcolourscales[0]) && cl.worldmodel->funcs.ClustersInSphere)
lvis = cl.worldmodel->funcs.ClustersInSphere(cl.worldmodel, dl->origin, dl->radius, &lvisb2, NULL);
else
{ //other lights only want to use the source leaf's pvs (clamped by the sphere)

View File

@ -265,9 +265,23 @@ typedef struct
unsigned int id; //networked/gamecode id.
unsigned int axialplanes; //+x,+y,+z,-x,-y,-z. used for bevel stuff.
unsigned int numplanes;
qboolean selected; //different shader stuff
unsigned char selected:1; //different shader stuff
vec4_t *planes;
vec3_t mins, maxs; //for optimisation and stuff
struct patchdata_s
{ //unlit, always...
brushtex_t *tex;
unsigned short xpoints;
unsigned short ypoints;
struct
{
vec3_t v;
vec2_t tc;
vec3_t norm;
vec3_t sdir;
vec3_t tdir;
} verts[1]; //x+(y*xpoints)
} *patch;
struct brushface_s
{
brushtex_t *tex;
@ -277,8 +291,8 @@ typedef struct
unsigned short lmscale;
int lightmap;
unsigned short lmbase[2]; //min st coord of the lightmap atlas, in texels.
unsigned int relight:1;
unsigned int relit:1;
unsigned short relight:1;
unsigned short relit:1;
int lmbias[2];
unsigned short lmextents[2];
qbyte *lightdata;

View File

@ -153,6 +153,7 @@ void (APIENTRY *qglTexEnvi) (GLenum target, GLenum pname, GLint param);
void (APIENTRY *qglTexGeni) (GLenum coord, GLenum pname, GLint param);
void (APIENTRY *qglTexGenfv) (GLenum coord, GLenum pname, const GLfloat *param);
void (APIENTRY *qglTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void (APIENTRY *qglTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
void (APIENTRY *qglTranslatef) (GLfloat x, GLfloat y, GLfloat z);
void (APIENTRY *qglVertex2f) (GLfloat x, GLfloat y);
void (APIENTRY *qglVertex3f) (GLfloat x, GLfloat y, GLfloat z);
@ -190,6 +191,11 @@ GLboolean (APIENTRY *qglUnmapBufferARB)(GLenum target);
void *(APIENTRY *qglMapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
#endif
void (APIENTRY *qglTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); //gl4.2
void (APIENTRY *qglTexStorage3D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); //gl4.2
void (APIENTRY *qglCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); //gl1.3
void (APIENTRY *qglCompressedTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); //gl1.3
void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
@ -342,7 +348,6 @@ void (APIENTRY myGLDEBUGPROCAMD)(GLenum source,
}
#endif
int gl_mtexarbable=0; //max texture units
qboolean gl_mtexable = false;
@ -779,17 +784,26 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
if (gl_config.gles)
{ //GL_ARB_texture_compression is not quite supported in gles, but works for custom compressed formats (like etc2).
qglCompressedTexImage2DARB = (void *)getglext("glCompressedTexImage2D");
qglCompressedTexImage3DARB = (void *)getglext("glCompressedTexImage3D");
qglCompressedTexSubImage2D = (void *)getglext("glCompressedTexSubImage2D");
qglCompressedTexSubImage3D = (void *)getglext("glCompressedTexSubImage3D");
qglGetCompressedTexImageARB = NULL;
}
else if (!gl_config.gles && gl_config.glversion > 1.3)
{ //GL_ARB_texture_compression is core in gl1.3
qglCompressedTexImage2DARB = (void *)getglext("glCompressedTexImage2D");
qglCompressedTexImage3DARB = (void *)getglext("glCompressedTexImage3D");
qglCompressedTexSubImage2D = (void *)getglext("glCompressedTexSubImage2D");
qglCompressedTexSubImage3D = (void *)getglext("glCompressedTexSubImage3D");
qglGetCompressedTexImageARB = (void *)getglext("glGetCompressedTexImage");
gl_config.arb_texture_compression = true;
}
else if (GL_CheckExtension("GL_ARB_texture_compression"))
{
qglCompressedTexImage2DARB = (void *)getglext("glCompressedTexImage2DARB");
qglCompressedTexImage3DARB = (void *)getglext("glCompressedTexImage3DARB");
qglCompressedTexSubImage2D = (void *)getglext("glCompressedTexSubImage2DARB");
qglCompressedTexSubImage3D = (void *)getglext("glCompressedTexSubImage3DARB");
qglGetCompressedTexImageARB = (void *)getglext("glGetCompressedTexImageARB");
if (!qglCompressedTexImage2DARB || !qglGetCompressedTexImageARB)
@ -835,6 +849,11 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglLockArraysEXT = (void *)getglext("glLockArraysEXT");
qglUnlockArraysEXT = (void *)getglext("glUnlockArraysEXT");
}
else
{
qglLockArraysEXT = NULL;
qglUnlockArraysEXT = NULL;
}
/*various combiner features*/
gl_config.tex_env_combine = GL_CheckExtension("GL_EXT_texture_env_combine");
@ -1095,12 +1114,24 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
else
gl_config.geometryshaders = false;
if ((!gl_config.gles && gl_config.glversion >= 4.2) ||
( gl_config.gles && gl_config.glversion >= 3.0))
{ //from gles3.0 or gl4.2 onwards
qglTexStorage2D = getglext("glTexStorage2D");
qglTexStorage3D = getglext("glTexStorage3D");
}
else
{
qglTexStorage2D = NULL;
qglTexStorage3D = NULL;
}
#ifdef GL_STATIC
gl_config.ext_framebuffer_objects = true; //exists as core in gles2
#else
if ((gl_config.gles && gl_config.glversion >= 2) || //exists as core in gles2
(!gl_config.gles && gl_config.glversion >= 3) || //exists as core in gl3
GL_CheckExtension("GL_ARB_framebuffer_object")) //exists as an extension in gl2
GL_CheckExtension("GL_ARB_framebuffer_object")) //exists as an extension in gl2 (defined in terms of gl3 so no ARB postfix needed)
{
gl_config.ext_framebuffer_objects = true;
qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffers");
@ -2783,6 +2814,7 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
qglTexGeni = (void *)getglcore("glTexGeni");
qglTexGenfv = (void *)getglcore("glTexGenfv");
qglTexImage3D = (void *)getglext("glTexImage3D");
qglTexSubImage3D = (void *)getglext("glTexSubImage3D");
qglTranslatef = (void *)getglcore("glTranslatef");
qglVertex2f = (void *)getglcore("glVertex2f");
qglVertex3f = (void *)getglcore("glVertex3f");
@ -2899,75 +2931,6 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
sh_config.texture2d_maxsize = 256; //early minidrivers might not implement this, but anything else should.
qglGetIntegerv(GL_MAX_TEXTURE_SIZE, &sh_config.texture2d_maxsize);
//always supported
sh_config.texfmt[PTI_RGBA8] = true;
if (GL_CheckExtension("GL_EXT_texture_compression_s3tc"))
{
sh_config.texfmt[PTI_BC1_RGB] = true;
sh_config.texfmt[PTI_BC1_RGBA] = true;
sh_config.texfmt[PTI_BC2_RGBA] = true;
sh_config.texfmt[PTI_BC3_RGBA] = true;
}
else if (gl_config.gles)
{
sh_config.texfmt[PTI_BC1_RGB] =
sh_config.texfmt[PTI_BC1_RGBA] = GL_CheckExtension("GL_EXT_texture_compression_dxt1");
sh_config.texfmt[PTI_BC2_RGBA] = GL_CheckExtension("GL_ANGLE_texture_compression_dxt3");
sh_config.texfmt[PTI_BC3_RGBA] = GL_CheckExtension("GL_ANGLE_texture_compression_dxt5");
}
if (GL_CheckExtension("GL_ARB_texture_compression_rgtc") || GL_CheckExtension("GL_EXT_texture_compression_rgtc"))
{
sh_config.texfmt[PTI_BC4_R8] = true;
sh_config.texfmt[PTI_BC4_R8_SIGNED] = true;
sh_config.texfmt[PTI_BC5_RG8] = true;
sh_config.texfmt[PTI_BC5_RG8_SIGNED] = true;
}
if ((!gl_config.gles && gl_config.glversion >= 4.2) || GL_CheckExtension("GL_ARB_texture_compression_bptc"))
sh_config.texfmt[PTI_BC6_RGBF] = sh_config.texfmt[PTI_BC6_RGBF_SIGNED] =
sh_config.texfmt[PTI_BC7_RGBA] = sh_config.texfmt[PTI_BC7_RGBA_SRGB] = true;
#ifdef FTE_TARGET_WEB
if (GL_CheckExtension("WEBGL_compressed_texture_etc"))
#else
if ((gl_config.gles && gl_config.glversion >= 3.0) || (!gl_config.gles && (gl_config.glversion >= 4.3 || GL_CheckExtension("GL_ARB_ES3_compatibility"))))
#endif
{ //gles3 and gl4.3 have mandatory support for etc2. probably desktop drivers will pre-decompress, but whatever.
//webgl tries to cater to d3d, so doesn't support this gles3 feature, because browser writers are lazy.
//warning: while support is mandatory, it may just be a driver trick with the hardware using uncompressed data.
sh_config.texfmt[PTI_ETC1_RGB8] = true;
sh_config.texfmt[PTI_ETC2_RGB8] = true;
sh_config.texfmt[PTI_ETC2_RGB8A1] = true;
sh_config.texfmt[PTI_ETC2_RGB8A8] = true;
sh_config.texfmt[PTI_EAC_R11] = true;
sh_config.texfmt[PTI_EAC_R11_SIGNED] = true;
sh_config.texfmt[PTI_EAC_RG11] = true;
sh_config.texfmt[PTI_EAC_RG11_SIGNED] = true;
}
else
{
sh_config.texfmt[PTI_ETC1_RGB8] = GL_CheckExtension("GL_OES_compressed_ETC1_RGB8_texture");
sh_config.texfmt[PTI_ETC2_RGB8] = GL_CheckExtension("GL_OES_compressed_ETC2_RGB8_texture"); //or OES_compressed_ETC2_sRGB8_texture...
sh_config.texfmt[PTI_ETC2_RGB8A1] = GL_CheckExtension("GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture"); //or OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture...
sh_config.texfmt[PTI_ETC2_RGB8A8] = GL_CheckExtension("GL_OES_compressed_ETC2_RGBA8_texture"); //or OES_compressed_ETC2_sRGB8_alpha8_texture
sh_config.texfmt[PTI_EAC_R11] = GL_CheckExtension("GL_OES_compressed_EAC_R11_unsigned_texture");
sh_config.texfmt[PTI_EAC_R11_SIGNED] = GL_CheckExtension("GL_OES_compressed_EAC_R11_signed_texture");
sh_config.texfmt[PTI_EAC_RG11] = GL_CheckExtension("GL_OES_compressed_EAC_RG11_unsigned_texture");
sh_config.texfmt[PTI_EAC_RG11_SIGNED] = GL_CheckExtension("GL_OES_compressed_EAC_RG11_signed_texture");
}
sh_config.texfmt[PTI_ETC1_RGB8] |= sh_config.texfmt[PTI_ETC2_RGB8];
if (GL_CheckExtension("GL_KHR_texture_compression_astc_ldr"))
{ //24 different formats...
//hdr profile adds 3d slices, and support for the hdr subblocks (ldr-only will decode them as fixed-colour errors)
//full profile adds 3d blocks
//we don't do 3d astc textures, so the api doesn't change. either the gpu supports the data or parts get decoded as fixed colours, which is still better than our crappy fallback texture.
int gah;
for (gah = PTI_ASTC_4X4; gah <= PTI_ASTC_12X12_SRGB; gah++)
sh_config.texfmt[gah] = true;
}
/*note regarding GL_COMPRESSED_TEXTURE_FORMATS:
nvidia lists bc1-3, oes paletted, etc2, astc, astc_srgb.
so the only listed formats that the hardware actually supports are bc1-3.
@ -2977,21 +2940,6 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
if (gl_config.gles)
{
qboolean srgb = false;//TEST ME GL_CheckExtension("GL_EXT_sRGB");
sh_config.texfmt[PTI_RGBX8] = sh_config.texfmt[PTI_RGBA8]; //FIXME: this is faked with PTI_RGBA8
sh_config.texfmt[PTI_RGB565] = !gl_config.webgl_ie; //ie sucks and doesn't support things that webgl requires it to support.
sh_config.texfmt[PTI_RGBA4444] = !gl_config.webgl_ie;
sh_config.texfmt[PTI_RGBA5551] = !gl_config.webgl_ie;
sh_config.texfmt[PTI_BGRX8] = sh_config.texfmt[PTI_BGRA8] = false;
// sh_config.texfmt[PTI_RGBX8_SRGB] = sh_config.texfmt[PTI_RGBX8] && srgb;
sh_config.texfmt[PTI_RGBA8_SRGB] = sh_config.texfmt[PTI_RGBA8] && srgb;
// sh_config.texfmt[PTI_BGRX8_SRGB] = sh_config.texfmt[PTI_BGRX8] && srgb;
sh_config.texfmt[PTI_BGRA8_SRGB] = sh_config.texfmt[PTI_BGRA8] && srgb;
vid.srgb = info->srgb && srgb;
sh_config.minver = 100;
if (gl_config.glversion >= 3.1)
sh_config.maxver = 310;
@ -3009,45 +2957,10 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
}
else
{
GLint srgb = gl_config.glversion >= 2.1 || GL_CheckExtension("GL_EXT_texture_sRGB"); //became core in gl 2.1
sh_config.can_mipcap = gl_config.glversion >= 1.2;
sh_config.havecubemaps = gl_config.glversion >= 1.3; //cubemaps AND clamp-to-edge.
sh_config.texfmt[PTI_RGBX8] = true; //proper support
//these require stuff like GL_UNSIGNED_SHORT_5_5_5_1 etc, which needs gl 1.2+
if (gl_config.glversion >= 1.2)
{
//16bit formats
sh_config.texfmt[PTI_RGB565] = true;
sh_config.texfmt[PTI_RGBA4444] = true;
sh_config.texfmt[PTI_RGBA5551] = true;
//bgr formats
if (GL_CheckExtension("GL_EXT_bgra"))
{
//32bit formats
sh_config.texfmt[PTI_BGRX8] = true;
sh_config.texfmt[PTI_BGRA8] = true;
//16bit formats
sh_config.texfmt[PTI_ARGB4444] = true;
sh_config.texfmt[PTI_ARGB1555] = true;
}
}
if (!gl_config.gles && (gl_config.glversion >= 1.4 || GL_CheckExtension("GL_ARB_depth_texture")))
{ //depth formats
sh_config.texfmt[PTI_DEPTH16] = true;
sh_config.texfmt[PTI_DEPTH24] = true;
sh_config.texfmt[PTI_DEPTH32] = true;
}
else if (gl_config.gles && GL_CheckExtension("GL_OES_depth_texture"))
{ //16+32, not 24.
sh_config.texfmt[PTI_DEPTH16] = true;
sh_config.texfmt[PTI_DEPTH32] = true;
}
if (GL_CheckExtension("GL_EXT_packed_depth_stencil"))
sh_config.texfmt[PTI_DEPTH24_8] = true;
if (gl_config.nofixedfunc)
{ //core contexts don't normally support glsl < 140 (such glsl versions have lots of compat syntax still, which will not function on core. drivers might accept it anyway, but yeah, lots of crap that shouldn't work)
//FIXME: GL_NUM_SHADING_LANGUAGE_VERSIONS and GL_SHADING_LANGUAGE_VERSION might allow for earlier versions.
@ -3068,18 +2981,6 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
sh_config.blobpath = "glsl/%s.blob";
sh_config.progpath = "glsl/%s.glsl";
sh_config.shadernamefmt = "%s_glsl";
sh_config.texfmt[PTI_RGBX8_SRGB] = sh_config.texfmt[PTI_RGBX8] && srgb;
sh_config.texfmt[PTI_RGBA8_SRGB] = sh_config.texfmt[PTI_RGBA8] && srgb;
sh_config.texfmt[PTI_BGRX8_SRGB] = sh_config.texfmt[PTI_BGRX8] && srgb;
sh_config.texfmt[PTI_BGRA8_SRGB] = sh_config.texfmt[PTI_BGRA8] && srgb;
sh_config.texfmt[PTI_BC1_RGB_SRGB] = sh_config.texfmt[PTI_BC1_RGB] && srgb;
sh_config.texfmt[PTI_BC1_RGBA_SRGB] = sh_config.texfmt[PTI_BC1_RGBA] && srgb;
sh_config.texfmt[PTI_BC2_RGBA_SRGB] = sh_config.texfmt[PTI_BC2_RGBA] && srgb;
sh_config.texfmt[PTI_BC3_RGBA_SRGB] = sh_config.texfmt[PTI_BC3_RGBA] && srgb;
sh_config.texfmt[PTI_ETC2_RGB8_SRGB] = sh_config.texfmt[PTI_ETC2_RGB8] && srgb;
sh_config.texfmt[PTI_ETC2_RGB8A1_SRGB] = sh_config.texfmt[PTI_ETC2_RGB8A1] && srgb;
sh_config.texfmt[PTI_ETC2_RGB8A8_SRGB] = sh_config.texfmt[PTI_ETC2_RGB8A8] && srgb;
}
sh_config.texturecube_maxsize = 0;
@ -3111,6 +3012,8 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
sh_config.env_add = gl_config.env_add;
}
GL_SetupFormats();
return true;
}

View File

@ -208,6 +208,12 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, EGLNativeWindo
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLint wndattrib[] =
{
// EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_LINEAR_KHR,
EGL_NONE
};
EGLint contextattr[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2, //requires EGL 1.3
@ -256,7 +262,7 @@ qboolean EGL_Init (rendererstate_t *info, unsigned char *palette, EGLNativeWindo
return false;
}
eglsurf = qeglCreateWindowSurface(egldpy, cfg, window, NULL);
eglsurf = qeglCreateWindowSurface(egldpy, cfg, window, info->srgb?wndattrib:NULL);
if (eglsurf == EGL_NO_SURFACE)
{
Con_Printf(CON_ERROR "EGL: eglCreateWindowSurface failed: %x\n", qeglGetError());

View File

@ -132,6 +132,8 @@ qboolean X11_CheckFeature(const char *featurename, qboolean defaultval)
struct _XrmHashBucketRec;
typedef int (*qXErrorHandler) (Display*, XErrorEvent*);
static struct
{
void *lib;
@ -187,6 +189,8 @@ static struct
int (*pXWarpPointer)(Display *display, Window src_w, Window dest_w, int src_x, int src_y, unsigned int src_width, unsigned int src_height, int dest_x, int dest_y);
Status (*pXMatchVisualInfo)(Display *display, int screen, int depth, int class, XVisualInfo *vinfo_return);
qXErrorHandler (*pXSetErrorHandler)(XErrorHandler);
#define XI_RESOURCENAME "FTEQW"
#define XI_RESOURCECLASS "FTEQW"
char *(*pXSetLocaleModifiers)(char *modifier_list);
@ -207,6 +211,15 @@ static struct
XIM inputmethod;
} x11;
static int X11_ErrorHandler(Display *dpy, XErrorEvent *e)
{
char msg[80];
// XGetErrorText(dpy, e->error_code, msg, sizeof(msg));
*msg = 0;
Con_Printf(CON_ERROR "XLib Error %d (%s): request %d.%d\n", e->error_code, msg, e->request_code, e->minor_code);
return 0; //ignored.
}
static qboolean x11_initlib(void)
{
static dllfunction_t x11_functable[] =
@ -276,6 +289,11 @@ static qboolean x11_initlib(void)
//these ones are extensions, and the reason we're doing this.
if (x11.lib)
{
x11.pXSetErrorHandler = Sys_GetAddressForName(x11.lib, "XSetErrorHandler");
if (x11.pXSetErrorHandler)
x11.pXSetErrorHandler(X11_ErrorHandler);
//raw input (yay mouse deltas)
x11.pXGetEventData = Sys_GetAddressForName(x11.lib, "XGetEventData");
x11.pXFreeEventData = Sys_GetAddressForName(x11.lib, "XFreeEventData");
@ -1253,68 +1271,382 @@ char clipboard_buffer[SYS_CLIPBOARD_SIZE];
/*-----------------------------------------------------------------------*/
#ifdef GLQUAKE
static dllhandle_t *gllibrary;
static struct
{
dllhandle_t *gllibrary;
XVisualInfo* (*qglXChooseVisual) (Display *dpy, int screen, int *attribList);
void (*qglXSwapBuffers) (Display *dpy, GLXDrawable drawable);
Bool (*qglXMakeCurrent) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
GLXContext (*qglXCreateContext) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
void (*qglXDestroyContext) (Display *dpy, GLXContext ctx);
void *(*qglXGetProcAddress) (char *name);
const char *glxextensions;
XVisualInfo* (*ChooseVisual) (Display *dpy, int screen, int *attribList);
void (*SwapBuffers) (Display *dpy, GLXDrawable drawable);
Bool (*MakeCurrent) (Display *dpy, GLXDrawable drawable, GLXContext ctx);
GLXContext (*CreateContext) (Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
void (*DestroyContext) (Display *dpy, GLXContext ctx);
const char * (*QueryExtensionsString)(Display * dpy, int screen);
void *(*GetProcAddress) (char *name);
GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attrib_list, int *nelements);
int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int * value);
XVisualInfo *(*GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config);
GLXContext (*CreateContextAttribs)(Display *dpy, GLXFBConfig config, GLXContext share_context, Bool direct, const int *attrib_list);
} glx;
void GLX_CloseLibrary(void)
{
Sys_CloseLibrary(gllibrary);
gllibrary = NULL;
}
qboolean GLX_InitLibrary(char *driver)
{
dllfunction_t funcs[] =
{
{(void*)&qglXChooseVisual, "glXChooseVisual"},
{(void*)&qglXSwapBuffers, "glXSwapBuffers"},
{(void*)&qglXMakeCurrent, "glXMakeCurrent"},
{(void*)&qglXCreateContext, "glXCreateContext"},
{(void*)&qglXDestroyContext, "glXDestroyContext"},
{NULL, NULL}
};
if (driver && *driver)
gllibrary = Sys_LoadLibrary(driver, funcs);
else
gllibrary = NULL;
#ifdef __CYGWIN__
if (!gllibrary)
gllibrary = Sys_LoadLibrary("cygGL-1.dll", funcs);
#endif
if (!gllibrary) //I hate this.
gllibrary = Sys_LoadLibrary("libGL.so.1", funcs);
if (!gllibrary)
gllibrary = Sys_LoadLibrary("libGL", funcs);
if (!gllibrary)
return false;
qglXGetProcAddress = Sys_GetAddressForName(gllibrary, "glXGetProcAddress");
if (!qglXGetProcAddress)
qglXGetProcAddress = Sys_GetAddressForName(gllibrary, "glXGetProcAddressARB");
return true;
Sys_CloseLibrary(glx.gllibrary);
glx.gllibrary = NULL;
}
void *GLX_GetSymbol(char *name)
{
void *symb;
if (qglXGetProcAddress)
symb = qglXGetProcAddress(name);
if (glx.GetProcAddress)
symb = glx.GetProcAddress(name);
else
symb = NULL;
if (!symb)
symb = Sys_GetAddressForName(gllibrary, name);
symb = Sys_GetAddressForName(glx.gllibrary, name);
return symb;
}
qboolean GLX_InitLibrary(char *driver)
{
dllfunction_t funcs[] =
{
{(void*)&glx.ChooseVisual, "glXChooseVisual"},
{(void*)&glx.SwapBuffers, "glXSwapBuffers"},
{(void*)&glx.MakeCurrent, "glXMakeCurrent"},
{(void*)&glx.CreateContext, "glXCreateContext"},
{(void*)&glx.DestroyContext, "glXDestroyContext"},
{NULL, NULL}
};
memset(&glx, 0, sizeof(glx));
if (driver && *driver)
glx.gllibrary = Sys_LoadLibrary(driver, funcs);
else
glx.gllibrary = NULL;
#ifdef __CYGWIN__
if (!glx.gllibrary)
glx.gllibrary = Sys_LoadLibrary("cygGL-1.dll", funcs);
#endif
if (!glx.gllibrary) //I hate this.
glx.gllibrary = Sys_LoadLibrary("libGL.so.1", funcs);
if (!glx.gllibrary)
glx.gllibrary = Sys_LoadLibrary("libGL", funcs);
if (!glx.gllibrary)
return false;
glx.GetProcAddress = GLX_GetSymbol("glXGetProcAddress");
if (!glx.GetProcAddress)
glx.GetProcAddress = GLX_GetSymbol("glXGetProcAddressARB");
glx.QueryExtensionsString = GLX_GetSymbol("glXQueryExtensionsString");
glx.ChooseFBConfig = GLX_GetSymbol("glXChooseFBConfig");
glx.GetFBConfigAttrib = GLX_GetSymbol("glXGetFBConfigAttrib");
glx.GetVisualFromFBConfig = GLX_GetSymbol("glXGetVisualFromFBConfig");
glx.CreateContextAttribs = GLX_GetSymbol("glXCreateContextAttribsARB");
return true;
}
#ifndef GLX_RGBA_FLOAT_BIT
#define GLX_RGBA_FLOAT_BIT 0x00000004
#endif
#ifndef GLX_CONTEXT_OPENGL_NO_ERROR_ARB
#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
#endif
qboolean GLX_CheckExtension(const char *ext)
{
const char *e = glx.glxextensions, *n;
size_t el = strlen(ext);
while(e && *e)
{
while (*e == ' ')
e++;
n = strchr(e, ' ');
if (!n)
n = n+strlen(e);
if (n-e == el && !strncmp(ext, e, el))
{
Con_DPrintf("GLX: Found %s\n", ext);
return true;
}
e = n;
}
Con_DPrintf("GLX: Missing %s\n", ext);
return false;
}
//Since GLX1.3 (equivelent to gl1.2)
GLXFBConfig GLX_GetFBConfig(rendererstate_t *info)
{
int attrib[32];
int n, i;
int numconfigs;
GLXFBConfig *fbconfigs;
qboolean hassrgb, hasmultisample, hasfloats;
if (glx.QueryExtensionsString)
glx.glxextensions = glx.QueryExtensionsString(vid_dpy, scrnum);
if (!glx.ChooseFBConfig || !glx.GetVisualFromFBConfig)
{
Con_Printf("Missing function pointer\n");
return NULL;
}
if (!glx.CreateContextAttribs)
{
Con_Printf("Missing CreateContextAttribs\n");
return NULL; //don't worry about it
}
hassrgb = GLX_CheckExtension("GLX_ARB_framebuffer_sRGB");
hasmultisample = GLX_CheckExtension("GLX_ARB_multisample");
hasfloats = GLX_CheckExtension("GLX_ARB_fbconfig_float");
//do it in a loop, mostly to disable extensions that are unlikely to be supported on various glx implementations.
for (i = 0; i < (16<<1); i++)
{
n = 0;
//attrib[n++] = GLX_LEVEL; attrib[n++] = 0; //overlays
attrib[n++] = GLX_DOUBLEBUFFER; attrib[n++] = True;
if (!(i&1))
{
if (!info->stereo)
continue;
attrib[n++] = GLX_STEREO; attrib[n++] = True;
}
if (!(i&2))
{
if (!info->srgb || !hassrgb)
continue;
attrib[n++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB; attrib[n++] = True;
}
//attrib[n++] = GLX_AUX_BUFFERS; attrib[n++] = 0;
if (!(i&4))
{
if (info->srgb <= 2 || !hasfloats)
continue; //skip fp16 framebuffers
attrib[n++] = GLX_RENDER_TYPE; attrib[n++] = GLX_RGBA_FLOAT_BIT;
attrib[n++] = GLX_RED_SIZE; attrib[n++] = info->bpp?info->bpp/3:4;
attrib[n++] = GLX_GREEN_SIZE; attrib[n++] = info->bpp?info->bpp/3:4;
attrib[n++] = GLX_BLUE_SIZE; attrib[n++] = info->bpp?info->bpp/3:4;
}
else
{
if (info->bpp > 24)
{
attrib[n++] = GLX_RED_SIZE; attrib[n++] = 8;
attrib[n++] = GLX_GREEN_SIZE; attrib[n++] = 8;
attrib[n++] = GLX_BLUE_SIZE; attrib[n++] = 8;
}
else
{
attrib[n++] = GLX_RED_SIZE; attrib[n++] = info->bpp?info->bpp/3:4;
attrib[n++] = GLX_GREEN_SIZE; attrib[n++] = info->bpp?info->bpp/3:4;
attrib[n++] = GLX_BLUE_SIZE; attrib[n++] = info->bpp?info->bpp/3:4;
}
}
//attrib[n++] = GLX_ALPHA_SIZE; attrib[n++] = GLX_DONT_CARE;
attrib[n++] = GLX_DEPTH_SIZE; attrib[n++] = 16;
attrib[n++] = GLX_STENCIL_SIZE; attrib[n++] = (i&16)?0:4;
if (!(i&8))
{
if (!info->multisample || !hasmultisample)
continue;
attrib[n++] = GLX_SAMPLE_BUFFERS_ARB; attrib[n++] = True;
attrib[n++] = GLX_SAMPLES_ARB, attrib[n++] = info->multisample;
}
//attrib[n++] = GLX_ACCUM_RED_SIZE; attrib[n++] = 0;
//attrib[n++] = GLX_ACCUM_GREEN_SIZE; attrib[n++] = 0;
//attrib[n++] = GLX_ACCUM_BLUE_SIZE; attrib[n++] = 0;
//attrib[n++] = GLX_ACCUM_ALPHA_SIZE; attrib[n++] = 0;
attrib[n++] = GLX_DRAWABLE_TYPE; attrib[n++] = GLX_WINDOW_BIT;
attrib[n++] = GLX_X_RENDERABLE; attrib[n++] = True;
//attrib[n++] = GLX_X_VISUAL_TYPE; attrib[n++] = info->srgb?GLX_TRUE_COLOR:GLX_DIRECT_COLOR;
//attrib[n++] = GLX_CONFIG_CAVEAT; attrib[n++] = GLX_DONT_CARE; GLX_NONE||GLX_SLOW_CONFIG||GLX_NON_CONFORMANT_CONFIG
//attrib[n++] = GLX_TRANSPARENT_TYPE;attrib[n++] = GLX_NONE;
//attrib[n++] = GLX_TRANSPARENT_ALPHA_VALUE;attrib[n++] = 0;
attrib[n++] = None;
numconfigs = 0;
fbconfigs = glx.ChooseFBConfig(vid_dpy, scrnum, attrib, &numconfigs);
if (fbconfigs)
{
if (numconfigs)
{
GLXFBConfig r = fbconfigs[0];
x11.pXFree(fbconfigs);
return r;
}
x11.pXFree(fbconfigs);
}
}
return NULL;
}
//for GLX<1.3
XVisualInfo *GLX_GetVisual(rendererstate_t *info)
{
XVisualInfo *visinfo;
int attrib[32];
int numattrib, i;
//do it in a loop, mostly to disable extensions that are unlikely to be supported on various glx implementations.
for (i = 0; i < (8<<1); i++)
{
numattrib = 0;
attrib[numattrib++] = GLX_RGBA;
attrib[numattrib++] = GLX_DOUBLEBUFFER;
if (!(i&1))
{
if (!info->stereo)
continue;
attrib[numattrib++] = GLX_STEREO;
}
if (!(i&2))
{
if (!info->srgb)
continue;
attrib[numattrib++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB;
}
if (!(i&4))
{
if (!info->multisample)
continue;
attrib[numattrib++] = GLX_SAMPLE_BUFFERS_ARB; attrib[numattrib++] = info->multisample;
}
if (!(i&8))
{
attrib[numattrib++] = GLX_STENCIL_SIZE; attrib[numattrib++] = 4;
}
attrib[numattrib++] = GLX_RED_SIZE; attrib[numattrib++] = 4;
attrib[numattrib++] = GLX_GREEN_SIZE; attrib[numattrib++] = 4;
attrib[numattrib++] = GLX_BLUE_SIZE; attrib[numattrib++] = 4;
attrib[numattrib++] = GLX_DEPTH_SIZE; attrib[numattrib++] = 16;
attrib[numattrib++] = None;
visinfo = glx.ChooseVisual(vid_dpy, scrnum, attrib);
if (visinfo)
return visinfo;
}
return NULL;
}
qboolean GLX_Init(rendererstate_t *info, GLXFBConfig fbconfig, XVisualInfo *visinfo)
{
extern cvar_t vid_gl_context_version;
extern cvar_t vid_gl_context_forwardcompatible;
extern cvar_t vid_gl_context_compatibility;
extern cvar_t vid_gl_context_debug;
extern cvar_t vid_gl_context_es;
extern cvar_t vid_gl_context_robustness;
// extern cvar_t vid_gl_context_selfreset;
extern cvar_t vid_gl_context_noerror;
if (fbconfig && glx.CreateContextAttribs)
{
unsigned int majorver=1, minorver=1;
unsigned profile = 0;
unsigned contextflags = 0;
int attrib[16*2+1];
int n, val;
char *ver;
ver = vid_gl_context_version.string;
if (!*ver && vid_gl_context_es.ival && GLX_CheckExtension("GLX_EXT_create_context_es_profile"))
ver = vid_gl_context_es.string;
if (!*ver && !vid_gl_context_compatibility.ival && *vid_gl_context_compatibility.string)
ver = "3.2"; //if the user explicitly disabled compat, then they'll want a version that actually supports doing so.
majorver = strtoul(ver, &ver, 10);
if (*ver == '.')
minorver = strtoul(ver+1, &ver, 10);
else
minorver = 0;
//some weirdness for you:
//3.0 simply marked stuff as deprecated, without removing it.
//3.1 removed it (moved to the optional GL_ARB_compatibility extension, which shouldn't be supported in a forward-compatible context).
//3.2 added the concept of profiles.
if (vid_gl_context_debug.ival)
contextflags |= GLX_CONTEXT_DEBUG_BIT_ARB;
if (vid_gl_context_forwardcompatible.ival) //treat this as a dev/debug thing.
contextflags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
if (vid_gl_context_robustness.ival && GLX_CheckExtension("GLX_ARB_create_context_robustness"))
contextflags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
if (vid_gl_context_es.ival && GLX_CheckExtension("GLX_EXT_create_context_es_profile"))
profile = GLX_CONTEXT_ES_PROFILE_BIT_EXT;
else if (majorver>3 || (majorver==3&&minorver>=2))
{ //profiles only started with 3.2
if (vid_gl_context_compatibility.ival)
profile = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
else
profile = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
}
else
profile = 0;
n = 0;
if (majorver || minorver)
{
attrib[n++] = GLX_CONTEXT_MAJOR_VERSION_ARB; attrib[n++] = majorver;
attrib[n++] = GLX_CONTEXT_MINOR_VERSION_ARB; attrib[n++] = minorver;
}
if (contextflags)
{
attrib[n++] = GLX_CONTEXT_FLAGS_ARB; attrib[n++] = contextflags;
}
if (profile)
{
attrib[n++] = GLX_CONTEXT_PROFILE_MASK_ARB; attrib[n++] = profile;
}
if (vid_gl_context_noerror.ival && GLX_CheckExtension("GLX_ARB_create_context_no_error"))
{
attrib[n++] = GLX_CONTEXT_OPENGL_NO_ERROR_ARB; attrib[n++] = !vid_gl_context_robustness.ival && !vid_gl_context_debug.ival;
}
attrib[n++] = None;
if (glx.GetFBConfigAttrib)
{
if (glx.GetFBConfigAttrib(vid_dpy, fbconfig, GLX_RENDER_TYPE, &val) && val == GLX_RGBA_FLOAT_BIT)
vid.flags |= VID_FP16; //other things need to be 16bit too, to avoid loss of precision.
if (glx.GetFBConfigAttrib(vid_dpy, fbconfig, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &val) && val)
vid.flags |= VID_SRGB_CAPABLE; //can use srgb properly, without faking it etc.
}
ctx = glx.CreateContextAttribs(vid_dpy, fbconfig, NULL, True, attrib);
}
else
ctx = glx.CreateContext(vid_dpy, visinfo, NULL, True);
if (!ctx)
{
Con_Printf("Failed to create GLX context.\n");
return false;
}
if (!glx.MakeCurrent(vid_dpy, vid_window, ctx))
{
Con_Printf("glXMakeCurrent failed\n");
return false;
}
//okay, we have a context, now init OpenGL-proper.
return GL_Init(info, &GLX_GetSymbol);
}
#endif
static void X_ShutdownUnicode(void)
@ -2082,7 +2414,7 @@ void GLVID_Shutdown(void)
case PSL_GLX:
if (ctx)
{
qglXDestroyContext(vid_dpy, ctx);
glx.DestroyContext(vid_dpy, ctx);
ctx = NULL;
}
break;
@ -2393,7 +2725,7 @@ void GLVID_SwapBuffers (void)
case PSL_GLX:
//we don't need to flush, XSawpBuffers does it for us.
//chances are, it's version is more suitable anyway. At least there's the chance that it might be.
qglXSwapBuffers(vid_dpy, vid_window);
glx.SwapBuffers(vid_dpy, vid_window);
break;
#endif
#ifdef VKQUAKE
@ -2414,11 +2746,19 @@ void X_StoreIcon(Window wnd)
Atom proptype = x11.pXInternAtom(vid_dpy, "CARDINAL", false);
size_t filesize;
qbyte *filedata = FS_LoadMallocFile("icon.png", &filesize);
qbyte *filedata = NULL;
#ifdef AVAIL_PNGLIB
if (!filedata)
FS_LoadMallocFile("icon.tga", &filesize);
filedata = FS_LoadMallocFile("icon.png", &filesize);
#endif
if (!filedata)
FS_LoadMallocFile("icon.jpg", &filesize);
filedata = FS_LoadMallocFile("icon.tga", &filesize);
#ifdef AVAIL_JPEGLIB
if (!filedata)
filedata = FS_LoadMallocFile("icon.jpg", &filesize);
#endif
if (!filedata)
filedata = FS_LoadMallocFile("icon.ico", &filesize);
if (filedata)
{
int imagewidth, imageheight;
@ -2638,22 +2978,13 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
int width = info->width; //can override these if vmode isn't available
int height = info->height;
int rate = info->rate;
#ifdef GLQUAKE
int attrib[] = {
GLX_RGBA,
GLX_RED_SIZE, 4,
GLX_GREEN_SIZE, 4,
GLX_BLUE_SIZE, 4,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 16,
GLX_STENCIL_SIZE, 4,
None
};
#endif
#if defined(USE_EGL) || defined(VKQUAKE)
XVisualInfo vinfodef;
#endif
XVisualInfo *visinfo;
#ifdef GLQUAKE
GLXFBConfig fbconfig = NULL;
#endif
qboolean fullscreen = false;
if (!x11_initlib())
@ -2780,10 +3111,16 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
break;
#endif
case PSL_GLX:
visinfo = qglXChooseVisual(vid_dpy, scrnum, attrib);
fbconfig = GLX_GetFBConfig(info);
if (fbconfig)
visinfo = glx.GetVisualFromFBConfig(vid_dpy, fbconfig);
else
visinfo = GLX_GetVisual(info);
if (!visinfo)
{
Sys_Error("X11VID_Init: Error couldn't get an RGB, Double-buffered, Depth visual\n");
Con_Printf("X11VID_Init: Error couldn't get an RGB, Double-buffered, Depth visual\n");
GLVID_Shutdown();
return false;
}
break;
#endif
@ -2841,7 +3178,7 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
if (rampsize > countof(vm.originalramps[0]))
{
vm.originalapplied = false;
Con_Printf("Gamma ramps are not of 256 components (but %i).\n", rampsize);
Con_Printf("Gamma ramps have more than %zi entries (%i).\n", countof(vm.originalramps[0]), rampsize);
}
else
{
@ -2855,23 +3192,11 @@ qboolean X11VID_Init (rendererstate_t *info, unsigned char *palette, int psl)
{
#ifdef GLQUAKE
case PSL_GLX:
ctx = qglXCreateContext(vid_dpy, visinfo, NULL, True);
if (!ctx)
if (!GLX_Init(info, fbconfig, visinfo))
{
Con_Printf("Failed to create GLX context.\n");
GLVID_Shutdown();
return false;
}
if (!qglXMakeCurrent(vid_dpy, vid_window, ctx))
{
Con_Printf("glXMakeCurrent failed\n");
GLVID_Shutdown();
return false;
}
if (!GL_Init(info, &GLX_GetSymbol))
return false;
break;
#ifdef USE_EGL
case PSL_EGL:
@ -3083,7 +3408,7 @@ void Force_CenterView_f (void)
//these are done from the x11 event handler. we don't support evdev.
void INS_Move(float *movements, int pnum)
void INS_Move(void)
{
}
void INS_Commands(void)

View File

@ -208,7 +208,7 @@ void INS_Commands (void)
void INS_EnumerateDevices(void *ctx, void(*callback)(void *ctx, const char *type, const char *devicename, unsigned int *qdevid))
{
}
void INS_Move (float *movements, int pnum)
void INS_Move (void)
{
}

View File

@ -264,6 +264,12 @@ static HGLRC (APIENTRY *qwglCreateContextAttribsARB)(HDC hDC, HGLRC hShareContex
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_FULL_ACCELERATION_ARB 0x2027
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_TYPE_RGBA_ARB 0x202B
#define WGL_TYPE_RGBA_FLOAT_ARB 0x21A0
#define WGL_RED_BITS_ARB 0x2015
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_BLUE_BITS_ARB 0x2019
@ -1263,9 +1269,9 @@ static qboolean VID_SetFullDIBMode (rendererstate_t *info)
SendMessage (dibwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
if (modestate == MS_FULLWINDOW)
ShowWindow (dibwindow, SW_SHOWMAXIMIZED);
ShowWindow (dibwindow, SW_HIDE);//SW_SHOWMAXIMIZED);
else
ShowWindow (dibwindow, SW_SHOWDEFAULT);
ShowWindow (dibwindow, SW_HIDE);//SW_SHOWDEFAULT);
UpdateWindow (dibwindow);
// Because we have set the background brush for the window to NULL
@ -1487,6 +1493,16 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
return false;
}
}
else
{
TRACE(("dbg: GLVID_SetMode: unable to create window\n"));
return false;
}
if (modestate == MS_FULLWINDOW)
ShowWindow (dibwindow, SW_SHOWMAXIMIZED);
else
ShowWindow (dibwindow, SW_SHOWDEFAULT);
if (!GL_Init(info, getglfunc))
return false;
@ -1509,7 +1525,7 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
stat = EGL_Init (info, palette, mainwindow, maindc);
if (stat)
if (GL_Init(info, &EGL_Proc))
if (!GL_Init(info, &EGL_Proc))
return false;
}
break;
@ -1558,6 +1574,7 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
#ifndef NPFTE
/*I don't like this, but if we */
Sleep (100);
while (PeekMessage (&msg, mainwindow, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
@ -1572,6 +1589,14 @@ static int GLVID_SetMode (rendererstate_t *info, unsigned char *palette)
SetForegroundWindow (mainwindow);
Sleep (100);
while (PeekMessage (&msg, mainwindow, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Sleep (100);
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
@ -1778,6 +1803,9 @@ static qboolean WGL_CheckExtension(char *extname)
qboolean VID_AttachGL (rendererstate_t *info)
{ //make sure we can get a valid renderer.
int iAttributeNames[2];
FLOAT fAttributeValues[countof(iAttributeNames)];
do
{
TRACE(("dbg: VID_AttachGL: GLInitialise\n"));
@ -1981,6 +2009,14 @@ qboolean VID_AttachGL (rendererstate_t *info)
TRACE(("dbg: VID_AttachGL: qwglSwapIntervalEXT\n"));
qwglSwapIntervalEXT(vid_vsync.value);
}
vid.flags = 0;
iAttributeNames[0] = WGL_PIXEL_TYPE_ARB;
iAttributeNames[1] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
if (qwglGetPixelFormatAttribfvARB && qwglGetPixelFormatAttribfvARB(maindc, currentpixelformat, 0, 1, iAttributeNames+0, fAttributeValues+0) && fAttributeValues[0] == WGL_TYPE_RGBA_FLOAT_ARB)
vid.flags |= VID_FP16 | VID_SRGB_FB_LINEAR;
if (qwglGetPixelFormatAttribfvARB && qwglGetPixelFormatAttribfvARB(maindc, currentpixelformat, 0, 1, iAttributeNames+1, fAttributeValues+1) && fAttributeValues[1] == TRUE)
vid.flags |= VID_SRGB_CAPABLE;
return true;
}
#endif
@ -2153,6 +2189,7 @@ qboolean GLVID_ApplyGammaRamps (unsigned int gammarampsize, unsigned short *ramp
{
case 0: //never use hardware/glsl gamma
case 2: //ALWAYS use glsl gamma
case 4: //scene-only gamma
return false;
default:
case 1: //no hardware gamma when windowed
@ -2244,7 +2281,7 @@ void GLVID_Shutdown (void)
#ifdef USE_WGL
static BOOL CheckForcePixelFormat(rendererstate_t *info)
{
if (qwglChoosePixelFormatARB && (info->multisample || info->srgb))
if (qwglChoosePixelFormatARB && (info->multisample || info->srgb || info->bpp==30))
{
HDC hDC;
int valid;
@ -2257,8 +2294,44 @@ static BOOL CheckForcePixelFormat(rendererstate_t *info)
iAttribute[iAttributes++] = WGL_DRAW_TO_WINDOW_ARB; iAttribute[iAttributes++] = GL_TRUE;
iAttribute[iAttributes++] = WGL_SUPPORT_OPENGL_ARB; iAttribute[iAttributes++] = GL_TRUE;
iAttribute[iAttributes++] = WGL_ACCELERATION_ARB; iAttribute[iAttributes++] = WGL_FULL_ACCELERATION_ARB;
iAttribute[iAttributes++] = WGL_COLOR_BITS_ARB; iAttribute[iAttributes++] = (info->bpp>24)?24:info->bpp;
// iAttribute[iAttributes++] = WGL_ALPHA_BITS_ARB; iAttribute[iAttributes++] = 4;
if (info->srgb>=3 && modestate != MS_WINDOWED)
{ //half-float backbuffers!
//'as has been the case since Windows Vista, fp16 swap chains are expected to have linear color data'
//if we try using WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB, then we won't actually get a pixelformat.
//we just have to assume that its a linear colour space.
//we ONLY use this fullscreen, because its totally fucked on nvidia otherwise.
//when windowed, its an scRGB image but with and srgb capable false, when fullscreen its always linear until something else takes focus...
//so if windowed or unfocused or whatever, we would need to use custom glsl to fix the gamma settings.
//additionally, a single program using floats will disable the desktop compositor, which can be a bit jarring.
iAttribute[iAttributes++] = WGL_PIXEL_TYPE_ARB; iAttribute[iAttributes++] = WGL_TYPE_RGBA_FLOAT_ARB;
iAttribute[iAttributes++] = WGL_RED_BITS_ARB; iAttribute[iAttributes++] = 16;
iAttribute[iAttributes++] = WGL_GREEN_BITS_ARB; iAttribute[iAttributes++] = 16;
iAttribute[iAttributes++] = WGL_BLUE_BITS_ARB; iAttribute[iAttributes++] = 16;
}
else
{
if (info->srgb)
{
iAttribute[iAttributes++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; iAttribute[iAttributes++] = info->bpp<=32;
}
if (info->bpp==30)
{ //10-bit backbuffers!
// iAttribute[iAttributes++] = WGL_PIXEL_TYPE_ARB; iAttribute[iAttributes++] = WGL_TYPE_RGBA_FLOAT_ARB;
iAttribute[iAttributes++] = WGL_RED_BITS_ARB; iAttribute[iAttributes++] = 10;
iAttribute[iAttributes++] = WGL_GREEN_BITS_ARB; iAttribute[iAttributes++] = 10;
iAttribute[iAttributes++] = WGL_BLUE_BITS_ARB; iAttribute[iAttributes++] = 10;
}
else
{
iAttribute[iAttributes++] = WGL_COLOR_BITS_ARB; iAttribute[iAttributes++] = (info->bpp>24)?24:info->bpp;
}
}
// iAttribute[iAttributes++] = WGL_ALPHA_BITS_ARB; iAttribute[iAttributes++] = 2;
iAttribute[iAttributes++] = WGL_DEPTH_BITS_ARB; iAttribute[iAttributes++] = 16;
iAttribute[iAttributes++] = WGL_STENCIL_BITS_ARB; iAttribute[iAttributes++] = 8;
iAttribute[iAttributes++] = WGL_DOUBLE_BUFFER_ARB; iAttribute[iAttributes++] = GL_TRUE;
@ -2268,10 +2341,6 @@ static BOOL CheckForcePixelFormat(rendererstate_t *info)
iAttribute[iAttributes++] = WGL_SAMPLE_BUFFERS_ARB; iAttribute[iAttributes++] = GL_TRUE;
iAttribute[iAttributes++] = WGL_SAMPLES_ARB, iAttribute[iAttributes++] = info->multisample; // Check For 4x Multisampling
}
if (info->srgb)
{
iAttribute[iAttributes++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB; iAttribute[iAttributes++] = GL_TRUE;
}
iAttribute[iAttributes++] = 0; iAttribute[iAttributes++] = 0;
@ -2318,7 +2387,7 @@ static BOOL CheckForcePixelFormat(rendererstate_t *info)
{"WGL_SUPPORT_OPENGL", WGL_SUPPORT_OPENGL_ARB},
{"WGL_DOUBLE_BUFFER", WGL_DOUBLE_BUFFER_ARB},
{"WGL_STEREO", WGL_STEREO_ARB},
{"WGL_PIXEL_TYPE", 0x2013},
{"WGL_PIXEL_TYPE", WGL_PIXEL_TYPE_ARB},
{"WGL_COLOR_BITS", WGL_COLOR_BITS_ARB},
{"WGL_RED_BITS", 0x2015},
{"WGL_RED_SHIFT", 0x2016},
@ -2352,9 +2421,7 @@ static BOOL CheckForcePixelFormat(rendererstate_t *info)
{"WGL_COLORSPACE_EXT", 0x309D}, //WGL_EXT_colorspace
//stuff my drivers don't support
// {"WGL_TYPE_RGBA_FLOAT_ARB", 0x21A0},
// {"WGL_DEPTH_FLOAT_EXT", 0x2040},
// {"WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT",0x20A8}, //EXT_packed_float
};
int iAttributeNames[countof(iAttributeTable)];
float fAttributeValues[countof(iAttributeTable)];
@ -2380,7 +2447,11 @@ static BOOL CheckForcePixelFormat(rendererstate_t *info)
Sys_Printf("%s: WGL_COLORSPACE_SRGB\n", iAttributeTable[j].name);
else if (iAttributeTable[j].id == 0x309D && fAttributeValues[j] == 0x308A)
Sys_Printf("%s: WGL_COLORSPACE_LINEAR\n", iAttributeTable[j].name);
else if (iAttributeTable[j].id == 0x202E)
else if (iAttributeTable[j].id == WGL_PIXEL_TYPE_ARB && fAttributeValues[j] == WGL_TYPE_RGBA_FLOAT_ARB)
Sys_Printf("%s: WGL_TYPE_RGBA_FLOAT_ARB\n", iAttributeTable[j].name);
else if (iAttributeTable[j].id == WGL_PIXEL_TYPE_ARB && fAttributeValues[j] == 0x20A8)
Sys_Printf("%s: WGL_TYPE_RGBA_UNSIGNED_FLOAT_EXT\n", iAttributeTable[j].name);
else if (iAttributeTable[j].id == 0x202E || iAttributeTable[j].id == WGL_PIXEL_TYPE_ARB)
Sys_Printf("%s: %#x\n", iAttributeTable[j].name, (int)fAttributeValues[j]);
else
Sys_Printf("%s: %g\n", iAttributeTable[j].name, fAttributeValues[j]);
@ -2482,7 +2553,7 @@ static BOOL bSetupPixelFormat(HDC hDC, rendererstate_t *info)
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
#ifndef RTLIGHTS
32, // 32-bit z-buffer
24, // 24-bit z-buffer
0, // 0 stencil, don't need it unless we're using rtlights
#else
24, // 24-bit z-buffer
@ -2501,50 +2572,27 @@ static BOOL bSetupPixelFormat(HDC hDC, rendererstate_t *info)
if (info->bpp == 15 || info->bpp == 16)
pfd.cColorBits = 16;
if (shouldforcepixelformat && qwglChoosePixelFormatARB) //the extra && is paranoia
if (shouldforcepixelformat && qwglChoosePixelFormatARB &&
qDescribePixelFormat(hDC, forcepixelformat, sizeof(pfd), &pfd) &&
qSetPixelFormat(hDC, forcepixelformat, &pfd)) //the extra && is paranoia
{
shouldforcepixelformat = false;
currentpixelformat = forcepixelformat;
}
else if ((currentpixelformat = qChoosePixelFormat(hDC, &pfd)) && qDescribePixelFormat(hDC, currentpixelformat, sizeof(pfd), &pfd) && qSetPixelFormat(hDC, currentpixelformat, &pfd))
; //we got our desired pixel format, or close enough
else
{
if ((currentpixelformat = qChoosePixelFormat(hDC, &pfd)))
{
TRACE(("dbg: ChoosePixelFormat 1: worked\n"));
if (qSetPixelFormat(hDC, currentpixelformat, &pfd))
{
TRACE(("dbg: bSetupPixelFormat: we can use the stencil buffer. woot\n"));
qDescribePixelFormat(hDC, currentpixelformat, sizeof(pfd), &pfd);
FixPaletteInDescriptor(hDC, &pfd);
if ((pfd.dwFlags & PFD_GENERIC_FORMAT) && !(pfd.dwFlags & PFD_GENERIC_ACCELERATED))
{
Con_Printf(CON_WARNING "WARNING: software-rendered opengl context\nPlease install appropriate graphics drivers, or try d3d rendering instead\n");
}
else if (pfd.dwFlags & PFD_SWAP_COPY)
Con_Printf(CON_WARNING "WARNING: buffer swaps will use copy operations\n");
return TRUE;
}
}
TRACE(("dbg: ChoosePixelFormat 1: no stencil buffer for us\n"));
pfd.cStencilBits = 0;
if ( (currentpixelformat = qChoosePixelFormat(hDC, &pfd)) == 0 )
if ((currentpixelformat = qChoosePixelFormat(hDC, &pfd)) && qDescribePixelFormat(hDC, currentpixelformat, sizeof(pfd), &pfd) && qSetPixelFormat(hDC, currentpixelformat, &pfd))
;
else
{
Con_Printf("bSetupPixelFormat: ChoosePixelFormat failed (%i)\n", (int)GetLastError());
Con_Printf("Unable to find suitable pixel format: %i\n", (int)GetLastError());
return FALSE;
}
}
qDescribePixelFormat(hDC, currentpixelformat, sizeof(pfd), &pfd);
if (qSetPixelFormat(hDC, currentpixelformat, &pfd) == FALSE)
{
Con_Printf("bSetupPixelFormat: SetPixelFormat failed (%i)\n", (int)GetLastError());
return FALSE;
}
shouldforcepixelformat = false;
if ((pfd.dwFlags & PFD_GENERIC_FORMAT) && !(pfd.dwFlags & PFD_GENERIC_ACCELERATED))
{
@ -2599,6 +2647,8 @@ static qboolean GLAppActivate(BOOL fActive, BOOL minimize)
{
static BOOL sound_active;
// Con_Printf("GLAppActivate: %i %i\n", fActive, minimize);
if (vid.activeapp == fActive && Minimized == minimize)
return false; //so windows doesn't crash us over and over again.
@ -2746,18 +2796,16 @@ void MainThreadWndProc(void *ctx, void *data, size_t msg, size_t ex)
break;
case WM_SIZE:
case WM_MOVE:
Cvar_ForceCallback(&vid_conautoscale); //FIXME: thread
Cvar_ForceCallback(&vid_conautoscale);
break;
case WM_KILLFOCUS:
GLAppActivate(FALSE, Minimized);//FIXME: thread
if (modestate == MS_FULLDIB)
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
ClearAllStates (); //FIXME: thread
GLAppActivate(FALSE, Minimized);
ClearAllStates ();
break;
case WM_SETFOCUS:
if (!GLAppActivate(TRUE, Minimized))//FIXME: thread
if (!GLAppActivate(TRUE, Minimized))
break;
ClearAllStates (); //FIXME: thread
ClearAllStates ();
break;
#ifdef HAVE_CDPLAYER
@ -2807,10 +2855,10 @@ static LONG WINAPI GLMainWndProc (
COM_AddWork(WG_MAIN, MainThreadWndProc, NULL, NULL, uMsg, 0);
#else
GLAppActivate(FALSE, Minimized);//FIXME: thread
if (modestate == MS_FULLDIB)
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
ClearAllStates (); //FIXME: thread
#endif
if (modestate == MS_FULLDIB)
ShowWindow(mainwindow, SW_SHOWMINNOACTIVE);
break;
case WM_SETFOCUS:
#ifdef WTHREAD

View File

@ -153,7 +153,10 @@ static qboolean SDLVID_Init (rendererstate_t *info, unsigned char *palette, r_qr
if (info->stereo)
SDL_GL_SetAttribute(SDL_GL_STEREO, 1);
#if 0//SDL_MAJOR_VERSION >= 2
if (info->srgb)
SDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 1);
#if SDL_MAJOR_VERSION >= 2
//FIXME: this stuff isn't part of info.
//this means it shouldn't be exposed to the menu or widely advertised.
if (*vid_gl_context_version.string)
@ -245,12 +248,26 @@ static qboolean SDLVID_Init (rendererstate_t *info, unsigned char *palette, r_qr
#ifdef OPENGL_SDL
if (qrenderer == QR_OPENGL)
{
int srgb;
sdlcontext = SDL_GL_CreateContext(sdlwindow);
if (!sdlcontext)
{
Con_Printf("Couldn't initialize GL context: %s\n", SDL_GetError());
return false;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
sdlcontext = SDL_GL_CreateContext(sdlwindow);
if (!sdlcontext)
{
Con_Printf("Couldn't initialize GL context: %s\n", SDL_GetError());
return false;
}
}
srgb = 0;
SDL_GL_GetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, &srgb);
if (srgb)
vid.flags |= VID_SRGB_CAPABLE;
}
#endif

View File

@ -156,6 +156,7 @@ typedef void (APIENTRY *PRIORTEXFUNCPTR)(GLsizei, const GLuint *,
const GLclampf *);
typedef void (APIENTRY *TEXSUBIMAGEPTR)(int, int, int, int, int, int, int, int, void *);
typedef void (APIENTRY *FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
typedef void (APIENTRY *FTEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
typedef void (APIENTRY *FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC) (GLenum target, GLint lod, const GLvoid* img);
typedef void (APIENTRY *FTEPFNGLPNTRIANGLESIATIPROC)(GLenum pname, GLint param);
typedef void (APIENTRY *FTEPFNGLPNTRIANGLESFATIPROC)(GLenum pname, GLfloat param);
@ -198,6 +199,7 @@ extern TEXSUBIMAGEPTR TexSubImage2DFunc;
extern void (APIENTRY *qglStencilOpSeparateATI) (GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
#endif
extern FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
extern FTEPFNGLCOMPRESSEDTEXIMAGE3DARBPROC qglCompressedTexImage3DARB;
extern FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
extern FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
extern FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
@ -205,6 +207,19 @@ extern void (APIENTRY *qglPatchParameteriARB)(GLenum pname, GLint value); //core
qboolean GL_CheckExtension(char *extname);
struct glfmt_s
{
int sizedformat; //texstorage
int cformat; //sized format used when gl_compress is set
int internalformat; //used instead of internal format when gl_compress is set, or 0
int format; //0 for compressed data
int type; //0 for compressed data
int swizzle_r;
int swizzle_g;
int swizzle_b;
int swizzle_a;
};
typedef struct {
float glversion;
int maxglslversion;
@ -236,6 +251,8 @@ typedef struct {
qboolean ext_packed_depth_stencil;
qboolean arb_depth_clamp;
int ext_texture_filter_anisotropic;
struct glfmt_s formatinfo[PTI_MAX];
} gl_config_t;
extern gl_config_t gl_config;
@ -245,6 +262,7 @@ extern float gldepthmin, gldepthmax;
void GL_UpdateFiltering(image_t *imagelist, int filtermip[3], int filterpic[3], int mipcap[2], float anis);
qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips);
void GL_DestroyTexture(texid_t tex);
void GL_SetupFormats(void);
/*
typedef struct
@ -996,6 +1014,7 @@ extern void (APIENTRY *qglTexGeniv) (GLenum coord, GLenum pname, const GLint *pa
extern void (APIENTRY *qglTexImage1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTexImage3D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTexSubImage1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
extern void (APIENTRY *qglTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
extern void (APIENTRY *qglTranslated) (GLdouble x, GLdouble y, GLdouble z);
extern void (APIENTRY *qglTranslatef) (GLfloat x, GLfloat y, GLfloat z);
@ -1060,6 +1079,11 @@ extern void (APIENTRY *qglVertexPointer) (GLint size, GLenum type, GLsizei strid
extern void (APIENTRY *qglGenVertexArrays)(GLsizei n, GLuint *arrays);
extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
extern void (APIENTRY *qglTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); //gl4.2
extern void (APIENTRY *qglTexStorage3D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); //gl4.2
extern void (APIENTRY *qglCompressedTexSubImage3D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); //gl1.3
extern void (APIENTRY *qglCompressedTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); //gl1.3
//glslang helper api

View File

@ -44,30 +44,40 @@ extern qlpMTex2FUNC qglMultiTexCoord2fARB;
./gl/gl_draw.c:3251: error: for each function it appears in.)
*/
#ifndef GL_EXT_bgra
#define GL_BGR_EXT 0x80E0 /*core in opengl 1.2*/
#define GL_BGRA_EXT 0x80E1
#define GL_BGR_EXT 0x80E0 /*core in opengl 1.2*/
#define GL_BGRA_EXT 0x80E1
#endif
#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 /*opengl 1.2*/
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 /*opengl 1.2*/
#endif
#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 /*opengl 1.2*/
#endif
#ifndef GL_UNSIGNED_INT_5_9_9_9_REV
#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E /*opengl 3.0*/
#endif
#ifndef GL_UNSIGNED_SHORT_4_4_4_4_REV
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
#endif
#ifndef GL_UNSIGNED_SHORT_1_5_5_5_REV
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#endif
#ifndef GL_UNSIGNED_SHORT_4_4_4_4
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#endif
#ifndef GL_UNSIGNED_SHORT_5_5_5_1
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#endif
#ifndef GL_UNSIGNED_SHORT_5_6_5
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#endif
#ifndef GL_HALF_FLOAT
#define GL_HALF_FLOAT 0x140B /*GL_ARB_half_float_pixel*/
#endif
#ifndef GL_HALF_FLOAT_OES
#define GL_HALF_FLOAT_OES 0x8D61 /*GL_OES_texture_half_float*/
#endif
#ifndef GL_ARB_multitexture
#define GL_ARB_multitexture 1
@ -124,6 +134,11 @@ extern qlpMTex2FUNC qglMultiTexCoord2fARB;
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
#endif
#ifndef GL_TEXTURE_2D_ARRAY //gl 3.0 or GL_EXT_texture_array
#define GL_TEXTURE_2D_ARRAY 0x8C1A
#endif
#ifndef GL_ARB_depth_texture
#define GL_ARB_depth_texture
#define GL_DEPTH_COMPONENT16_ARB 0x81A5
@ -132,6 +147,9 @@ extern qlpMTex2FUNC qglMultiTexCoord2fARB;
#define GL_TEXTURE_DEPTH_SIZE_ARB 0x884A
#define GL_DEPTH_TEXTURE_MODE_ARB 0x884B
#endif
#ifndef GL_DEPTH_COMPONENT32F
#define GL_DEPTH_COMPONENT32F 0x8CAC
#endif
//GL_OES_depth_texture adds this because gles otherwise lacks it.
#ifndef GL_UNSIGNED_INT
@ -655,6 +673,24 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
#endif /* GL_EXT_texture_sRGB */
#ifndef GL_RG
#define GL_RG 0x8227
#define GL_RGB9_E5 0x8C3D /*opengl 3.0*/
#define GL_R8 0x8229 /*opengl 3.0*/
#define GL_RG8 0x822B /*opengl 3.0*/
#endif
#ifndef GL_RG8_SNORM
#define GL_R8_SNORM 0x8F94 /*opengl 3.1*/
#define GL_RG8_SNORM 0x8F95 /*opengl 3.1*/
#endif
#ifndef GL_TEXTURE_SWIZZLE_R
#define GL_TEXTURE_SWIZZLE_R 0x8E42
#define GL_TEXTURE_SWIZZLE_G 0x8E43
#define GL_TEXTURE_SWIZZLE_B 0x8E44
#define GL_TEXTURE_SWIZZLE_A 0x8E45
#endif
#ifndef GL_ETC1_RGB8_OES
#define GL_ETC1_RGB8_OES 0x8D64 //4*4 blocks of 8 bytes
#endif

View File

@ -7423,7 +7423,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"attribute vec4 v_colour;\n"
"void main ()\n"
"{\n"
"tc = v_texcoord;\n"
"tc = vec2(v_texcoord.s, 1.0-v_texcoord.t);\n"
"vc = v_colour;\n"
"gl_Position = ftetransform();\n"
"}\n"
@ -7656,8 +7656,8 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#endif
#ifdef GLQUAKE
{QR_OPENGL, 110, "drawflat_wall",
"!!cvarv r_floorcolor\n"
"!!cvarv r_wallcolor\n"
"!!cvard_srgb_b r_floorcolor\n"
"!!cvard_srgb_b r_wallcolor\n"
"!!permu FOG\n"
//this is for the '286' preset walls, and just draws lightmaps coloured based upon surface normals.
@ -7668,12 +7668,10 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"attribute vec3 v_normal;\n"
"attribute vec2 v_lmcoord;\n"
"varying vec2 lm;\n"
"uniform vec3 cvar_r_wallcolor;\n"
"uniform vec3 cvar_r_floorcolor;\n"
"uniform vec4 e_lmscale;\n"
"void main ()\n"
"{\n"
"col = vec4(e_lmscale.rgb/255.0 * ((v_normal.z < 0.73)?cvar_r_wallcolor:cvar_r_floorcolor), e_lmscale.a);\n"
"col = vec4(e_lmscale.rgb * ((v_normal.z < 0.73)?r_wallcolor:r_floorcolor), e_lmscale.a);\n"
"lm = v_lmcoord;\n"
"gl_Position = ftetransform();\n"
"}\n"
@ -10202,7 +10200,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
#ifdef GLQUAKE
{QR_OPENGL, 110, "menutint",
"!!cvari r_menutint_inverse\n"
"!!cvarv r_menutint\n"
"!!cvard_srgb r_menutint\n"
"#ifdef VERTEX_SHADER\n"
"attribute vec2 v_texcoord;\n"
@ -10218,7 +10216,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"#ifdef FRAGMENT_SHADER\n"
"varying vec2 texcoord;\n"
"uniform vec3 cvar_r_menutint;\n"
"uniform sampler2D s_t0;\n"
"uniform int cvar_r_menutint_inverse;\n"
"const vec3 lumfactors = vec3(0.299, 0.587, 0.114);\n"
@ -10228,7 +10225,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
"vec3 texcolor = texture2D(s_t0, texcoord).rgb;\n"
"float luminance = dot(lumfactors, texcolor);\n"
"texcolor = vec3(luminance, luminance, luminance);\n"
"texcolor *= cvar_r_menutint;\n"
"texcolor *= r_menutint;\n"
"texcolor = (cvar_r_menutint_inverse > 0) ? (invertvec - texcolor) : texcolor;\n"
"gl_FragColor = vec4(texcolor, 1.0);\n"
"}\n"

View File

@ -370,6 +370,8 @@ enum{
};
#define PERMUTATIONS (1u<<PERMUTATION_BIT_MAX)
extern cvar_t r_fog_permutation;
enum shaderattribs_e
{
//GLES2 has a limit of 8.

View File

@ -154,7 +154,7 @@ void Sys_Shutdown(void)
}
//this is already done using the ppapi event callback. can't poll any of this stuff.
void INS_Move(float *movements, int pnum)
void INS_Move(void)
{
}
void INS_Commands(void)

View File

@ -13,7 +13,7 @@ void GUI_DialogPrint(char *title, char *text);
void *GUIReadFile(const char *fname, unsigned char *(*buf_get)(void *ctx, size_t len), void *buf_ctx, size_t *out_size);
int GUIFileSize(const char *fname);
void GUI_ParseCommandLine(char *args);
int GUI_ParseCommandLine(char *args); //0=gui, 1=commandline
void GUI_SaveConfig(void);
void GUI_RevealOptions(void);
int GUIprintf(const char *msg, ...);

View File

@ -2,6 +2,11 @@
#include <time.h>
void QCC_Canonicalize(char *fullname, size_t fullnamesize, const char *newfile, const char *base);
//package formats:
//pakzip - files are uncompressed, with both a pak header and a zip trailer, allowing it to be read as either type of file.
//zip - standard zips
//spanned zip - the full list of files is written into a separate central-directory-only zip, the actual file data comes from regular zips named foo.z##/.p## instead of foo.zip/foo.pk3
/*
dataset common
{
@ -46,6 +51,9 @@ texa0
}
*/
#define quint64_t long long
#define qofs_t size_t
#define countof(x) (sizeof(x)/sizeof((x)[0]))
struct pkgctx_s
@ -55,8 +63,10 @@ struct pkgctx_s
char *listfile;
pbool test;
pbool readoldpacks;
char gamepath[MAX_PATH];
char sourcepath[MAX_PATH];
time_t buildtime;
//skips the file if its listed in one of these packages, unless the modification time on disk is newer.
@ -68,9 +78,14 @@ struct pkgctx_s
struct
{
char name[128];
size_t size;
// unsigned int zcrc;
// timestamp;
unsigned short zmethod;
unsigned int zcrc;
qofs_t zhdrofs;
qofs_t rawsize;
qofs_t zipsize;
unsigned short dostime;
unsigned short dosdate;
} *file;
} *oldpacks;
@ -85,6 +100,10 @@ struct pkgctx_s
char code[128];
char filename[128];
struct file_s *files;
pbool usediffs;
unsigned int numparts;
struct oldpack_s *oldparts;
} *outputs;
char name[1];
@ -126,16 +145,31 @@ struct pkgctx_s
char name[128];
struct file_s *nextwrite;
struct rule_s *rule;
unsigned int zdisk;
unsigned short zmethod;
unsigned int zcrc;
unsigned int zhdrofs;
unsigned int pakofs;
unsigned int rawsize;
unsigned int zipsize;
qofs_t zhdrofs;
qofs_t pakofs;
qofs_t rawsize;
qofs_t zipsize;
unsigned short dostime;
unsigned short dosdate;
time_t timestamp;
} write;
} *files;
} *classes;
};
#ifdef _WIN32
static time_t filetime_to_timet(FILETIME ft)
{
ULARGE_INTEGER ull;
ull.LowPart = ft.dwLowDateTime;
ull.HighPart = ft.dwHighDateTime;
return ull.QuadPart / 10000000ULL - 11644473600ULL;
}
#endif
static struct rule_s *PKG_FindRule(struct pkgctx_s *ctx, char *code)
{
struct rule_s *o;
@ -304,7 +338,7 @@ static void PKG_ReplaceString(char *str, char *find, char *newpart)
str = oldpart+nlen;
}
}
static void PKG_CreateOutput(struct pkgctx_s *ctx, struct dataset_s *s, const char *code, const char *filename)
static void PKG_CreateOutput(struct pkgctx_s *ctx, struct dataset_s *s, const char *code, const char *filename, pbool diff)
{
char path[MAX_PATH];
char date[64];
@ -331,12 +365,13 @@ static void PKG_CreateOutput(struct pkgctx_s *ctx, struct dataset_s *s, const ch
o = malloc(sizeof(*o));
memset(o, 0, sizeof(*o));
strcpy(o->code, code);
o->usediffs = diff;
QCC_Canonicalize(o->filename, sizeof(o->filename), path, ctx->gamepath);
o->next = s->outputs;
s->outputs = o;
}
static void PKG_ParseOutput(struct pkgctx_s *ctx)
static void PKG_ParseOutput(struct pkgctx_s *ctx, pbool diff)
{
struct dataset_s *s;
char name[128];
@ -352,7 +387,7 @@ static void PKG_ParseOutput(struct pkgctx_s *ctx)
if (PKG_GetStringToken(ctx, prop, sizeof(prop)))
{
s = PKG_GetDataset(ctx, "core");
PKG_CreateOutput(ctx, s, name, prop);
PKG_CreateOutput(ctx, s, name, prop, diff);
}
else
{
@ -370,7 +405,7 @@ static void PKG_ParseOutput(struct pkgctx_s *ctx)
*e = 0;
s = PKG_GetDataset(ctx, prop);
if (PKG_GetStringToken(ctx, fname, sizeof(fname)))
PKG_CreateOutput(ctx, s, name, fname);
PKG_CreateOutput(ctx, s, name, fname, diff);
else
ctx->messagecallback(ctx->userctx, "Output '%s[%s]' filename omitted\n", name, prop);
}
@ -555,9 +590,10 @@ static void PKG_ParseRule(struct pkgctx_s *ctx)
r->next = ctx->rules;
ctx->rules = r;
}
static void PKG_AddClassFile(struct pkgctx_s *ctx, struct class_s *c, const char *fname)
static void PKG_AddClassFile(struct pkgctx_s *ctx, struct class_s *c, const char *fname, time_t mtime)
{
struct file_s *f;
struct tm *t;
if (strlen(fname) >= sizeof(f->name))
{
@ -568,6 +604,10 @@ static void PKG_AddClassFile(struct pkgctx_s *ctx, struct class_s *c, const char
f = malloc(sizeof(*f));
memset(f, 0, sizeof(*f));
strcpy(f->name, fname);
f->write.timestamp = mtime;
t = localtime(&f->write.timestamp);
f->write.dostime = (t->tm_sec>>1)|(t->tm_min<<5)|(t->tm_hour<<11);
f->write.dosdate = (t->tm_mday<<0)|(t->tm_mon<<5)|((t->tm_year+1900-1980)<<9);
f->next = c->files;
c->files = f;
}
@ -577,7 +617,7 @@ static void PKG_AddClassFiles(struct pkgctx_s *ctx, struct class_s *c, const cha
WIN32_FIND_DATA fd;
HANDLE h;
char basepath[MAX_PATH];
QCC_Canonicalize(basepath, sizeof(basepath), fname, ctx->gamepath);
QCC_Canonicalize(basepath, sizeof(basepath), fname, ctx->sourcepath);
h = FindFirstFile(basepath, &fd);
if (h == INVALID_HANDLE_VALUE)
ctx->messagecallback(ctx->userctx, "wildcard string '%s' found no files\n", fname);
@ -586,7 +626,7 @@ static void PKG_AddClassFiles(struct pkgctx_s *ctx, struct class_s *c, const cha
do
{
QCC_Canonicalize(basepath, sizeof(basepath), fd.cFileName, fname);
PKG_AddClassFile(ctx, c, basepath);
PKG_AddClassFile(ctx, c, basepath, filetime_to_timet(fd.ftLastWriteTime));
} while(FindNextFile(h, &fd));
}
#else
@ -693,10 +733,10 @@ static void PKG_ParseClass(struct pkgctx_s *ctx, char *output)
}
else if (strchr(prop, '.'))
{
if (strchr(prop, '*') || strchr(prop, '?'))
// if (strchr(prop, '*') || strchr(prop, '?'))
PKG_AddClassFiles(ctx, c, prop);
else
PKG_AddClassFile(ctx, c, prop);
// else
// PKG_AddClassFile(ctx, c, prop);
}
else
ctx->messagecallback(ctx->userctx, "Class '%s' has unknown property '%s'\n", name, prop);
@ -724,10 +764,10 @@ static void PKG_ParseClassFiles(struct pkgctx_s *ctx, struct class_s *c)
if (!strcmp(prop, ";"))
continue;
if (strchr(prop, '*') || strchr(prop, '?'))
// if (strchr(prop, '*') || strchr(prop, '?'))
PKG_AddClassFiles(ctx, c, prop);
else
PKG_AddClassFile(ctx, c, prop);
// else
// PKG_AddClassFile(ctx, c, prop);
}
}
}
@ -774,9 +814,9 @@ static unsigned int PKG_DeflateToFile(FILE *f, unsigned int rawsize, void *in, i
strm.next_out = out;
strm.avail_out = sizeof(out);
}
deflateEnd(&strm);
fwrite(out, 1, sizeof(out) - strm.avail_out, f);
i+=sizeof(out) - strm.avail_out;
deflateEnd(&strm);
return i;
}
#endif
@ -836,7 +876,8 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
*fsize = 0;
QCC_Canonicalize(fullname, sizeof(fullname), file->name, ctx->gamepath);
QCC_Canonicalize(fullname, sizeof(fullname), file->name, ctx->sourcepath);
strcpy(file->write.name, file->name);
f = fopen(fullname, "rb");
if (!f)
@ -847,7 +888,6 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
else
ctx->messagecallback(ctx->userctx, "\t\tCompressing %s\n", file->name);
strcpy(file->write.name, file->name);
if (rule)
{
data = strrchr(file->write.name, '.');
@ -873,7 +913,7 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
//delete temp file...
fclose(f);
QCC_Canonicalize(tempname, sizeof(tempname), file->write.name, ctx->gamepath);
QCC_Canonicalize(tempname, sizeof(tempname), file->write.name, ctx->sourcepath);
f = fopen(tempname, "rb");
if (f)
{
@ -958,20 +998,22 @@ static void *PKG_OpenSourceFile(struct pkgctx_s *ctx, struct file_s *file, size_
return data;
}
static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out)
static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out, unsigned int index, pbool directoryonly)
{
//helpers to deal with misaligned data. writes little-endian.
#define misbyte(ptr,ofs,data) ((unsigned char*)(ptr))[ofs] = (data)&0xff;
#define misshort(ptr,ofs,data) misbyte((ptr),(ofs),(data));misbyte((ptr),(ofs)+1,(data)>>8);
#define misint(ptr,ofs,data) misshort((ptr),(ofs),(data));misshort((ptr),(ofs)+2,(data)>>16);
int num=0;
int ofs;
#define misbyte(ptr,ofs,data) ((unsigned char*)(ptr))[ofs] = (data)&0xff
#define misshort(ptr,ofs,data) do{misbyte((ptr),(ofs),(data));misbyte((ptr),(ofs)+1,(data)>>8);}while(0)
#define misint(ptr,ofs,data) do{misshort((ptr),(ofs),(data));misshort((ptr),(ofs)+2,(data)>>16);}while(0)
#define misint64(ptr,ofs,data) do{misint((ptr),(ofs),(data));misint((ptr),(ofs)+4,((quint64_t)(data))>>32);}while(0)
qofs_t num=0;
pbool pak = false;
int startofs = 0;
struct file_s *f;
char centralheader[46+sizeof(f->write.name)];
int centraldirsize;
qofs_t centraldirsize;
qofs_t centraldirofs;
qofs_t z64eocdofs;
char *filedata;
@ -984,18 +1026,35 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out)
} pakheader = {"PACK", 0, 0};
char *ext;
#define GPF_TRAILINGSIZE (1u<<3)
#define GPF_UTF8 (1u<<11)
#ifdef AVAIL_ZLIB
#define compmethod (pak?0:8)/*Z_DEFLATED*/
#else
#define compmethod 0/*Z_RAW*/
#endif
if (!compmethod)
if (!compmethod && !directoryonly)
pak = true; //might as well boost compat...
ext = strrchr(out->filename, '.');
if (ext && !QC_strcasecmp(ext, ".pak"))
if (ext && !QC_strcasecmp(ext, ".pak") && !index)
pak = true;
outf = fopen(out->filename, "wb");
if (out->usediffs && !directoryonly)
{
char newname[MAX_PATH];
memcpy(newname, out->filename, sizeof(newname));
if (ext)
{
ext = newname+(ext-out->filename);
ext+=1;
if (*ext)
ext++;
QC_snprintfz(ext, sizeof(newname)-(ext-newname), "%02u", index+1);
}
outf = fopen(newname, "wb");
}
else
outf = fopen(out->filename, "wb");
if (!outf)
{
ctx->messagecallback(ctx->userctx, "Unable to open %s\n", out->filename);
@ -1005,58 +1064,94 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out)
if (pak) //reserve space for the pak header
fwrite(&pakheader, 1, sizeof(pakheader), outf);
for (f = out->files; f ; f=f->write.nextwrite)
if (!directoryonly)
{
char header[32+sizeof(f->write.name)];
size_t fnamelen = strlen(f->write.name);
filedata = PKG_OpenSourceFile(ctx, f, &f->write.rawsize);
if (!filedata)
for (f = out->files; f ; f=f->write.nextwrite)
{
ctx->messagecallback(ctx->userctx, "Unable to open %s\n", f->name);
}
char header[32+sizeof(f->write.name)];
size_t fnamelen = strlen(f->write.name);
size_t hofs;
unsigned short gpflags = GPF_UTF8;
f->write.zcrc = QC_encodecrc(f->write.rawsize, filedata);
misint (header, 0, 0x04034b50);
misshort(header, 4, 0);//minver
misshort(header, 6, 0);//general purpose flags
misshort(header, 8, 0);//compression method, 0=store, 8=deflate
misshort(header, 10, 0);//lastmodfiletime
misshort(header, 12, 0);//lastmodfiledate
misint (header, 14, f->write.zcrc);//crc32
misint (header, 18, f->write.rawsize);//compressed size
misint (header, 22, f->write.rawsize);//uncompressed size
misshort(header, 26, fnamelen);//filename length
misshort(header, 28, 0);//extradata length
strcpy(header+30, f->write.name);
if (index != f->write.zdisk)
continue; //not in this disk...
f->write.zhdrofs = ftell(outf);
fwrite(header, 1, 30+fnamelen, outf);
filedata = PKG_OpenSourceFile(ctx, f, &f->write.rawsize);
if (!filedata)
{
ctx->messagecallback(ctx->userctx, "Unable to open %s\n", f->name);
}
f->write.zcrc = QC_encodecrc(f->write.rawsize, filedata);
misint (header, 0, 0x04034b50);
misshort(header, 4, 45);//minver
misshort(header, 6, gpflags);//general purpose flags
misshort(header, 8, 0);//compression method, 0=store, 8=deflate
misshort(header, 10, f->write.dostime);//lastmodfiletime
misshort(header, 12, f->write.dosdate);//lastmodfiledate
misint (header, 14, f->write.zcrc);//crc32
misint (header, 18, f->write.rawsize);//compressed size
misint (header, 22, f->write.rawsize);//uncompressed size
misshort(header, 26, fnamelen);//filename length
misshort(header, 28, 0);//extradata length
strcpy(header+30, f->write.name);
hofs = 30+fnamelen;
misshort(header, 28, hofs-(30+fnamelen));//extradata length
f->write.zhdrofs = ftell(outf);
fwrite(header, 1, hofs, outf);
#ifdef AVAIL_ZLIB
if (compmethod == 2 || compmethod == 8)
{
size_t end;
f->write.pakofs = 0;
if (f->write.rawsize && (compmethod == 2 || compmethod == 8))
{
gpflags |= 1u<<1;
f->write.pakofs = 0;
f->write.zipsize = PKG_DeflateToFile(outf, f->write.rawsize, filedata, compmethod);
misshort(header, 8, compmethod);//compression method, 0=store, 8=deflate
misint (header, 18, f->write.zipsize);
end = ftell(outf);
fseek(outf, f->write.zhdrofs, SEEK_SET);
fwrite(header, 1, 30+fnamelen, outf);
fseek(outf, end, SEEK_SET);
}
else
f->write.zmethod = compmethod;
f->write.zipsize = PKG_DeflateToFile(outf, f->write.rawsize, filedata, compmethod);
}
else
#endif
{
f->write.pakofs = ftell(outf);
f->write.zipsize = fwrite(filedata, 1, f->write.rawsize, outf);
{
f->write.zmethod = 0;
f->write.pakofs = ftell(outf);
f->write.zipsize = fwrite(filedata, 1, f->write.rawsize, outf);
}
//update the header
misshort(header, 8, f->write.zmethod);//compression method, 0=store, 8=deflate
if (f->write.zipsize > 0xffffffff)
{
misint (header, 18, 0xffffffff);//compressed size
gpflags |= GPF_TRAILINGSIZE;
}
else
misint (header, 18, f->write.zipsize);//compressed size
if (f->write.rawsize > 0xffffffff)
{
misint (header, 22, 0xffffffff);//compressed size
gpflags |= GPF_TRAILINGSIZE;
}
else
misint (header, 22, f->write.rawsize);//compressed size
misshort(header, 6, gpflags);//general purpose flags
fseek(outf, f->write.zhdrofs, SEEK_SET);
fwrite(header, 1, hofs, outf);
fseek(outf, 0, SEEK_END);
if (gpflags & GPF_TRAILINGSIZE) //if (gpflags & GPF_TRAILINGSIZE)
{
misint (header, 0, 0x08074b50);
misint (header, 4, f->write.zcrc);
misint64(header, 8, f->write.zipsize);
misint64(header, 16, f->write.rawsize);
fwrite(header, 1, 24, outf);
}
free(filedata);
num++;
}
free(filedata);
num++;
}
if (pak)
@ -1067,15 +1162,14 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out)
unsigned int size;
unsigned int offset;
} pakentry;
//prepare the header
pakheader.tabbytes = num * sizeof(pakentry);
pakheader.tabofs = ftell(outf);
fseek(outf, 0, SEEK_SET);
fwrite(&pakheader, 1, sizeof(pakheader), outf);
//now go and write the file table.
fseek(outf, pakheader.tabofs, SEEK_SET);
//write the pak file table.
for (f = out->files,num=0; f ; f=f->write.nextwrite)
{
if (index != f->write.zdisk)
continue; //not in this disk...
memset(&pakentry, 0, sizeof(pakentry));
QC_strlcpy(pakentry.name, f->write.name, sizeof(pakentry.name));
pakentry.size = (f->write.pakofs==0)?0:f->write.rawsize;
@ -1083,43 +1177,106 @@ static void PKG_WritePackageData(struct pkgctx_s *ctx, struct output_s *out)
fwrite(&pakentry, 1, sizeof(pakentry), outf);
num++;
}
//replace the pak header, then return to the end of the file for the zip end-of-central-directory
pakheader.tabbytes = num * sizeof(pakentry);
fseek(outf, 0, SEEK_SET);
fwrite(&pakheader, 1, sizeof(pakheader), outf);
fseek(outf, 0, SEEK_END);
}
ofs = ftell(outf);
centraldirofs = ftell(outf);
for (f = out->files,num=0; f ; f=f->write.nextwrite)
{
size_t hofs;
size_t fnamelen;
if (!directoryonly && index != f->write.zdisk)
continue;
fnamelen = strlen(f->write.name);
misint (centralheader, 0, 0x02014b50);
misshort(centralheader, 4, 0);//ourver
misshort(centralheader, 6, 0);//minver
misshort(centralheader, 8, 0);//general purpose flags
misshort(centralheader, 10, compmethod);//compression method, 0=store, 8=deflate
misshort(centralheader, 12, 0);//lastmodfiletime
misshort(centralheader, 14, 0);//lastmodfiledate
misshort(centralheader, 4, (3<<8)|63);//ourver
misshort(centralheader, 6, 45);//minver
misshort(centralheader, 8, GPF_UTF8);//general purpose flags
misshort(centralheader, 10, f->write.rawsize?compmethod:0);//compression method, 0=store, 8=deflate
misshort(centralheader, 12, f->write.dostime);//lastmodfiletime
misshort(centralheader, 14, f->write.dosdate);//lastmodfiledate
misint (centralheader, 16, f->write.zcrc);//crc32
misint (centralheader, 20, f->write.zipsize);//compressed size
misint (centralheader, 24, f->write.rawsize);//uncompressed size
misshort(centralheader, 28, fnamelen);//filename length
misshort(centralheader, 30, 0);//extradata length
misshort(centralheader, 32, 0);//comment length
misshort(centralheader, 34, 0);//first disk number
misshort(centralheader, 34, f->write.zdisk);//first disk number
misshort(centralheader, 36, 0);//internal file attribs
misint (centralheader, 38, 0);//external file attribs
misint (centralheader, 42, f->write.zhdrofs);//local header offset
strcpy(centralheader+46, f->write.name);
fwrite(centralheader, 1, 46 + fnamelen, outf);
hofs = 46+fnamelen;
if (f->write.zdisk >= 0xffff || f->write.zhdrofs >= 0xffffffff || f->write.rawsize >= 0xffffffff || f->write.zipsize >= 0xffffffff)
{
misshort(centralheader, hofs, 0x0001);//zip64 tagid
misshort(centralheader, hofs+2, 0x0001);//zip64 tag size
hofs+=4;
if (f->write.rawsize >= 0xffffffff)
{
misint64(centralheader, hofs, f->write.rawsize);//uncompressed size
hofs += 8;
}
if (f->write.zipsize >= 0xffffffff)
{
misint64(centralheader, hofs, f->write.zipsize);//compressed size
hofs += 8;
}
if (f->write.zhdrofs >= 0xffffffff)
{
misint64(centralheader, hofs, f->write.zhdrofs);//localheader offset
hofs += 8;
}
if (f->write.zdisk >= 0xffff)
{
misint (centralheader, hofs, f->write.zdisk);//compressed size
hofs += 4;
}
}
misshort(centralheader, 30, hofs-(46+fnamelen));//extradata length
fwrite(centralheader, 1, hofs, outf);
num++;
}
centraldirsize = ftell(outf)-centraldirofs;
centraldirsize = ftell(outf)-ofs;
//zip64 end of central dir
z64eocdofs = ftell(outf);
misint (centralheader, 0, 0x06064b50);
misint64(centralheader, 4, (qofs_t)(56-16));
misshort(centralheader, 12, (3<<8)|63); //ver made by = unix|appnote ver
misshort(centralheader, 14, 45); //ver needed
misint (centralheader, 16, index); //thisdisk number
misint (centralheader, 20, index); //centraldir start disk
misint64(centralheader, 24, num); //centraldir entry count (disk)
misint64(centralheader, 32, num); //centraldir entry count (total)
misint64(centralheader, 40, centraldirsize);//centraldir entry bytes
misint64(centralheader, 48, centraldirofs); //centraldir start offset
fwrite(centralheader, 1, 56, outf);
//zip64 end of central dir locator
misint (centralheader, 0, 0x07064b50);
misint (centralheader, 4, index); //centraldir first disk
misint64(centralheader, 8, z64eocdofs);
misint (centralheader, 16, index+1); //total disk count
fwrite(centralheader, 1, 20, outf);
// centraldirofs = ftell(outf) - centraldirofs;
//write zip end-of-central-directory
misint (centralheader, 0, 0x06054b50);
misshort(centralheader, 4, 0); //this disk number
misshort(centralheader, 6, 0); //centraldir first disk
misshort(centralheader, 8, num); //centraldir entries
misshort(centralheader, 10, num); //total centraldir entries
misint (centralheader, 12, centraldirsize); //centraldir size
misint (centralheader, 16, ofs); //centraldir offset
misshort(centralheader, 4, (index > 0xffff)? 0xffff:index); //this disk number
misshort(centralheader, 6, (index > 0xffff)? 0xffff:index); //centraldir first disk
misshort(centralheader, 8, (num > 0xffff)? 0xffff:num); //centraldir entries
misshort(centralheader, 10, (num > 0xffff)? 0xffff:num); //total centraldir entries
misint (centralheader, 12, (centraldirsize>0xffffffff)?0xffffffff:centraldirsize); //centraldir size
misint (centralheader, 16, (centraldirofs >0xffffffff)?0xffffffff:centraldirofs); //centraldir offset
misshort(centralheader, 20, 0); //comment length
fwrite(centralheader, 1, 22, outf);
@ -1161,13 +1318,19 @@ static void PKG_ReadPackContents(struct pkgctx_s *ctx, struct oldpack_s *old)
if (f)
{
//find end-of-central-dir
//assume no comment
fseek(f, -22, SEEK_END);
fread(header, 1, 22, f);
if (header[0] == 'P' && header[1] == 'K' && header[2] == 5 && header[3] == 6)
{
//thisdisk = shortfromptr(header+4);
//centraldirstart = shortfromptr(header+6);
old->numfiles = shortfromptr(header+8);
//numfiles_all = shortfromptr(header+10);
//centaldirsize = shortfromptr(header+12);
foffset = longfromptr(header+16);
//commentength = shortfromptr(header+20);
old->file = malloc(sizeof(*old->file)*old->numfiles);
@ -1175,13 +1338,30 @@ static void PKG_ReadPackContents(struct pkgctx_s *ctx, struct oldpack_s *old)
fseek(f, foffset, SEEK_SET);
for(u = 0; u < old->numfiles; u++)
{
unsigned int extra_len, comment_len;
fread(header, 1, 46, f);
//zcrc @ 16
old->file[u].size = longfromptr(header+24);
//version_madeby = shortfromptr(header+4);
//version_needed = shortfromptr(header+6);
//gflags = shortfromptr(header+8);
old->file[u].zmethod = shortfromptr(header+10);
old->file[u].dostime = shortfromptr(header+12);
old->file[u].dosdate = shortfromptr(header+12);
old->file[u].zcrc = longfromptr(header+16);
old->file[u].zipsize = longfromptr(header+20);
old->file[u].rawsize = longfromptr(header+24);
namelen = shortfromptr(header+28);
extra_len = shortfromptr(header+30);
comment_len = shortfromptr(header+32);
//disknum = shortfromptr(header+34);
//iattributes = shortfromptr(header+36);
//eattributes = longfromptr(header+38);
//localheaderoffset = longfromptr(header+42);
fread(old->file[u].name, 1, namelen, f);
old->file[u].name[namelen] = 0;
i = shortfromptr(header+30)+shortfromptr(header+32);
i = extra_len+comment_len;
if (i)
fseek(f, i, SEEK_CUR);
}
@ -1208,7 +1388,7 @@ static void PKG_ReadPackContents(struct pkgctx_s *ctx, struct oldpack_s *old)
for (u = 0; u < old->numfiles; u++)
{
strcpy(old->file[u].name, files[u].name);
old->file[u].size = files[u].size;
old->file[u].rawsize = files[u].size;
}
free(files);
}
@ -1221,17 +1401,26 @@ static void PKG_ReadPackContents(struct pkgctx_s *ctx, struct oldpack_s *old)
}
}
static pbool PKG_FileIsModified(struct pkgctx_s *ctx, const char *filename)
static pbool PKG_FileIsModified(struct pkgctx_s *ctx, struct oldpack_s *old, struct file_s *file)
{
struct oldpack_s *old;
size_t u;
for (old = ctx->oldpacks; old; old = old->next)
for (u = 0; u < old->numfiles; u++)
{
for (u = 0; u < old->numfiles; u++)
//should check filesize etc, but rules and extension changes make that messy
if (!strcmp(old->file[u].name, file->name))
{
if (!strcmp(old->file[u].name, filename))
if(file->write.dosdate < old->file[u].dosdate || (file->write.dosdate == old->file[u].dosdate && file->write.dostime <= old->file[u].dostime))
{
ctx->messagecallback(ctx->userctx, "\t%s already contains %s\n", old->filename, filename);
file->write.zmethod = old->file[u].zmethod;
//char name[128];
file->write.zcrc = old->file[u].zcrc;
file->write.zhdrofs = old->file[u].zhdrofs;
file->write.pakofs = 0;
file->write.rawsize = old->file[u].rawsize;
file->write.zipsize = old->file[u].zipsize;
file->write.dostime = old->file[u].dostime;
file->write.dosdate = old->file[u].dosdate;
return false;
}
}
@ -1256,6 +1445,14 @@ static void PKG_WriteDataset(struct pkgctx_s *ctx, struct dataset_s *set)
{ //fixme: strip any wildcarded paks that match an output, to avoid weirdness.
PKG_ReadPackContents(ctx, old);
}
for (out = set->outputs; out; out = out->next)
{
if(out->usediffs)
{ //FIXME: look for old parts
}
}
}
ctx->messagecallback(ctx->userctx, "Building dataset %s\n", set->name);
@ -1285,13 +1482,32 @@ static void PKG_WriteDataset(struct pkgctx_s *ctx, struct dataset_s *set)
for (file = cls->files; file; file = file->next)
{
if (!PKG_FileIsModified(ctx, file->name))
continue;
// ctx->messagecallback(ctx->userctx, "\t\tFile %s, rule %s\n", file->name, rule?rule->name:"");
for (old = ctx->oldpacks; old; old = old->next)
{
if (!PKG_FileIsModified(ctx, old, file))
break;
}
if (old)
{
ctx->messagecallback(ctx->userctx, "\t\tFile %s found inside %s\n", file->name, old->filename);
file->write.zdisk = ~0u;
}
else
{
// ctx->messagecallback(ctx->userctx, "\t\tFile %s, rule %s\n", file->name, rule?rule->name:"");
file->write.nextwrite = out->files;
file->write.rule = rule;
out->files = file;
file->write.zdisk = out->numparts;
for (old = out->oldparts; old; old = old->next)
{
if (!PKG_FileIsModified(ctx, old, file))
break;
}
file->write.nextwrite = out->files;
file->write.rule = rule;
out->files = file;
}
}
}
@ -1302,9 +1518,25 @@ static void PKG_WriteDataset(struct pkgctx_s *ctx, struct dataset_s *set)
ctx->messagecallback(ctx->userctx, "\tOutput %s[%s] \"%s\" has no files\n", out->code, set->name, out->filename);
continue;
}
ctx->messagecallback(ctx->userctx, "\tGenerating %s[%s] \"%s\"\n", out->code, set->name, out->filename);
PKG_WritePackageData(ctx, out);
if (ctx->test)
{
for (file = out->files; file; file = file->write.nextwrite)
{
if (file->write.rule)
ctx->messagecallback(ctx->userctx, "\t\tFile %s has changed (rule %s)\n", file->name, file->write.rule->name);
else
ctx->messagecallback(ctx->userctx, "\t\tFile %s has changed\n", file->name);
}
}
else
{
ctx->messagecallback(ctx->userctx, "\tGenerating %s[%s] \"%s\"\n", out->code, set->name, out->filename);
PKG_WritePackageData(ctx, out, out->numparts, false);
}
if(out->usediffs)
PKG_WritePackageData(ctx, out, out->numparts+1, true);
}
}
void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname)
@ -1324,31 +1556,40 @@ void Packager_WriteDataset(struct pkgctx_s *ctx, char *setname)
PKG_WriteDataset(ctx, dataset);
}
}
struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, char *message), void *userctx)
struct pkgctx_s *Packager_Create(void (*messagecallback)(void *userctx, char *message, ...), void *userctx)
{
struct pkgctx_s *ctx;
ctx = malloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
ctx->messagecallback = messagecallback;
ctx->userctx = userctx;
ctx->test = false;
time(&ctx->buildtime);
return ctx;
}
void Packager_Parse(struct pkgctx_s *ctx, char *scriptname)
void Packager_ParseText(struct pkgctx_s *ctx, char *scripttext)
{
size_t remaining = 0;
char *file = QCC_ReadFile(scriptname, NULL, NULL, &remaining);
char cmd[128];
strcpy(ctx->gamepath, scriptname);
ctx->listfile = file;
ctx->listfile = scripttext;
while (PKG_GetToken(ctx, cmd, sizeof(cmd), true))
{
// if (!strcmp(cmd, "dataset"))
// PKG_ParseDataset(ctx);
if (!strcmp(cmd, "output"))
PKG_ParseOutput(ctx);
PKG_ParseOutput(ctx, false);
else if (!strcmp(cmd, "diffoutput") || !strcmp(cmd, "splitoutput"))
PKG_ParseOutput(ctx, true);
else if (!strcmp(cmd, "inputdir"))
{
char old[MAX_PATH];
memcpy(old, ctx->sourcepath, sizeof(old));
if (PKG_GetStringToken(ctx, cmd, sizeof(cmd)))
{
QC_strlcat(cmd, "/", sizeof(cmd));
QCC_Canonicalize(ctx->sourcepath, sizeof(ctx->sourcepath), cmd, old);
}
}
else if (!strcmp(cmd, "rule"))
PKG_ParseRule(ctx);
else if (!strcmp(cmd, "class"))
@ -1379,6 +1620,15 @@ void Packager_Parse(struct pkgctx_s *ctx, char *scriptname)
break;
}
}
}
void Packager_ParseFile(struct pkgctx_s *ctx, char *scriptname)
{
size_t remaining = 0;
char *file = qccprogfuncs->funcs.parms->ReadFile(scriptname, NULL, NULL, &remaining);
strcpy(ctx->gamepath, scriptname);
strcpy(ctx->sourcepath, scriptname);
Packager_ParseText(ctx, file);
free(file);
}

Some files were not shown because too many files have changed in this diff Show More