From a0465ad2ee16719587b0b7a80d4c1c2f7df1ac0e Mon Sep 17 00:00:00 2001 From: havoc Date: Wed, 17 Jul 2013 05:44:37 +0000 Subject: [PATCH] Steel Storm additions for mobile (EluanCM) engine support for Android (EluanCM's port, some cleanup by Forest Hale) engine support for iPhoneOS (Forest Hale) credit: EluanCM, myself (Forest Hale) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11973 d7cf8633-e32d-0410-b094-e92efae38249 --- DPiOS.xcodeproj/project.pbxproj | 136 ++-- .../contents.xcworkspacedata | 7 + Info.plist | 16 +- cl_screen.c | 19 +- fs.c | 25 +- gl_backend.c | 117 ++- gl_rmain.c | 72 +- gl_textures.c | 189 +++++ glquake.h | 27 +- image_png.c | 2 + jpeg.c | 6 + quakedef.h | 22 +- r_shadow.c | 8 +- r_textures.h | 3 + screen.h | 7 +- snd_modplug.c | 5 + sys_sdl.c | 22 + sys_shared.c | 21 +- vid.h | 10 + vid_sdl.c | 699 ++++++++++++++---- vid_shared.c | 40 + 21 files changed, 1179 insertions(+), 274 deletions(-) create mode 100644 DPiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/DPiOS.xcodeproj/project.pbxproj b/DPiOS.xcodeproj/project.pbxproj index e73b85ca..f55f5fa6 100755 --- a/DPiOS.xcodeproj/project.pbxproj +++ b/DPiOS.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 45; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -11,15 +11,19 @@ 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 28FD15000DC6FC520079059D /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28FD14FF0DC6FC520079059D /* OpenGLES.framework */; }; 28FD15080DC6FC5B0079059D /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28FD15070DC6FC5B0079059D /* QuartzCore.framework */; }; + 74063A3E1751ADDB0015D12C /* mod_skeletal_animatevertices_sse.c in Sources */ = {isa = PBXBuildFile; fileRef = 74063A3C1751ADDA0015D12C /* mod_skeletal_animatevertices_sse.c */; }; + 74063A401751B0250015D12C /* cd_null.c in Sources */ = {isa = PBXBuildFile; fileRef = 74063A3F1751B0250015D12C /* cd_null.c */; }; + 74063A421751B0AF0015D12C /* clvm_cmds.c in Sources */ = {isa = PBXBuildFile; fileRef = 74063A411751B0AF0015D12C /* clvm_cmds.c */; }; + 74063A491751B9B60015D12C /* libSDL2-ios-armv7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74063A471751B9B60015D12C /* libSDL2-ios-armv7.a */; }; + 74063A4A1751B9B60015D12C /* libSDL2-ios-simulator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74063A481751B9B60015D12C /* libSDL2-ios-simulator.a */; }; + 74063A511751C4560015D12C /* gamedata in Resources */ = {isa = PBXBuildFile; fileRef = 74063A501751C4560015D12C /* gamedata */; }; 7463B77812F9CE6B00983F6A /* bih.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6C012F9CE6B00983F6A /* bih.c */; }; 7463B77912F9CE6B00983F6A /* cap_avi.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6C312F9CE6B00983F6A /* cap_avi.c */; }; 7463B77A12F9CE6B00983F6A /* cap_ogg.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6C512F9CE6B00983F6A /* cap_ogg.c */; }; - 7463B77B12F9CE6B00983F6A /* cd_sdl.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6C712F9CE6B00983F6A /* cd_sdl.c */; }; 7463B77C12F9CE6B00983F6A /* cd_shared.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6C812F9CE6B00983F6A /* cd_shared.c */; }; 7463B77D12F9CE6B00983F6A /* cl_collision.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6CA12F9CE6B00983F6A /* cl_collision.c */; }; 7463B77E12F9CE6B00983F6A /* cl_demo.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6CC12F9CE6B00983F6A /* cl_demo.c */; }; 7463B77F12F9CE6B00983F6A /* cl_dyntexture.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6CD12F9CE6B00983F6A /* cl_dyntexture.c */; }; - 7463B78012F9CE6B00983F6A /* cl_gecko.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6CF12F9CE6B00983F6A /* cl_gecko.c */; }; 7463B78112F9CE6B00983F6A /* cl_input.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6D112F9CE6B00983F6A /* cl_input.c */; }; 7463B78212F9CE6B00983F6A /* cl_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6D212F9CE6B00983F6A /* cl_main.c */; }; 7463B78312F9CE6B00983F6A /* cl_parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B6D312F9CE6B00983F6A /* cl_parse.c */; }; @@ -104,12 +108,9 @@ 7463B7D212F9CE6B00983F6A /* world.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B77412F9CE6B00983F6A /* world.c */; }; 7463B7D312F9CE6B00983F6A /* zone.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B77612F9CE6B00983F6A /* zone.c */; }; 7463B7D912F9CF8F00983F6A /* darkplaces64x64.png in Resources */ = {isa = PBXBuildFile; fileRef = 7463B7D812F9CF8F00983F6A /* darkplaces64x64.png */; }; - 7463B7EA12F9D11E00983F6A /* mod_skeletal_animatevertices_sse.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B7E812F9D11E00983F6A /* mod_skeletal_animatevertices_sse.c */; }; 7463B7EF12F9D17D00983F6A /* builddate.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B7ED12F9D17D00983F6A /* builddate.c */; }; - 7463B7F012F9D17D00983F6A /* clvm_cmds.c in Sources */ = {isa = PBXBuildFile; fileRef = 7463B7EE12F9D17D00983F6A /* clvm_cmds.c */; }; + 7463B7F012F9D17D00983F6A /* (null) in Sources */ = {isa = PBXBuildFile; }; 7487D481130102AA00AEE909 /* thread_sdl.c in Sources */ = {isa = PBXBuildFile; fileRef = 7487D47F130102AA00AEE909 /* thread_sdl.c */; }; - FD779ED20E26B9B000F39101 /* libSDLSimulator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD779ED00E26B9B000F39101 /* libSDLSimulator.a */; }; - FD779ED30E26B9B000F39101 /* libSDLiPhoneOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD779ED10E26B9B000F39101 /* libSDLiPhoneOS.a */; }; FD779EDE0E26BA1200F39101 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD779EDD0E26BA1200F39101 /* CoreAudio.framework */; }; FD77A0850E26BDB800F39101 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FD77A0840E26BDB800F39101 /* AudioToolbox.framework */; }; FDB8BFC60E5A0F6A00980157 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FDB8BFC50E5A0F6A00980157 /* CoreGraphics.framework */; }; @@ -121,6 +122,13 @@ 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 28FD14FF0DC6FC520079059D /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; 28FD15070DC6FC5B0079059D /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 74063A3C1751ADDA0015D12C /* mod_skeletal_animatevertices_sse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mod_skeletal_animatevertices_sse.c; sourceTree = ""; }; + 74063A3D1751ADDA0015D12C /* mod_skeletal_animatevertices_sse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mod_skeletal_animatevertices_sse.h; sourceTree = ""; }; + 74063A3F1751B0250015D12C /* cd_null.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cd_null.c; sourceTree = ""; }; + 74063A411751B0AF0015D12C /* clvm_cmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clvm_cmds.c; sourceTree = ""; }; + 74063A471751B9B60015D12C /* libSDL2-ios-armv7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libSDL2-ios-armv7.a"; path = "lib/libSDL2-ios-armv7.a"; sourceTree = ""; }; + 74063A481751B9B60015D12C /* libSDL2-ios-simulator.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libSDL2-ios-simulator.a"; path = "lib/libSDL2-ios-simulator.a"; sourceTree = ""; }; + 74063A501751C4560015D12C /* gamedata */ = {isa = PBXFileReference; lastKnownFileType = folder; path = gamedata; sourceTree = ""; }; 7463B6C012F9CE6B00983F6A /* bih.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bih.c; sourceTree = ""; }; 7463B6C112F9CE6B00983F6A /* bih.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bih.h; sourceTree = ""; }; 7463B6C212F9CE6B00983F6A /* bspfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bspfile.h; sourceTree = ""; }; @@ -128,7 +136,6 @@ 7463B6C412F9CE6B00983F6A /* cap_avi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cap_avi.h; sourceTree = ""; }; 7463B6C512F9CE6B00983F6A /* cap_ogg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cap_ogg.c; sourceTree = ""; }; 7463B6C612F9CE6B00983F6A /* cap_ogg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cap_ogg.h; sourceTree = ""; }; - 7463B6C712F9CE6B00983F6A /* cd_sdl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cd_sdl.c; sourceTree = ""; }; 7463B6C812F9CE6B00983F6A /* cd_shared.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cd_shared.c; sourceTree = ""; }; 7463B6C912F9CE6B00983F6A /* cdaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cdaudio.h; sourceTree = ""; }; 7463B6CA12F9CE6B00983F6A /* cl_collision.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_collision.c; sourceTree = ""; }; @@ -136,8 +143,6 @@ 7463B6CC12F9CE6B00983F6A /* cl_demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_demo.c; sourceTree = ""; }; 7463B6CD12F9CE6B00983F6A /* cl_dyntexture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_dyntexture.c; sourceTree = ""; }; 7463B6CE12F9CE6B00983F6A /* cl_dyntexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_dyntexture.h; sourceTree = ""; }; - 7463B6CF12F9CE6B00983F6A /* cl_gecko.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_gecko.c; sourceTree = ""; }; - 7463B6D012F9CE6B00983F6A /* cl_gecko.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_gecko.h; sourceTree = ""; }; 7463B6D112F9CE6B00983F6A /* cl_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_input.c; sourceTree = ""; }; 7463B6D212F9CE6B00983F6A /* cl_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_main.c; sourceTree = ""; }; 7463B6D312F9CE6B00983F6A /* cl_parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_parse.c; sourceTree = ""; }; @@ -262,7 +267,6 @@ 7463B74A12F9CE6B00983F6A /* r_sprites.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_sprites.c; sourceTree = ""; }; 7463B74B12F9CE6B00983F6A /* r_textures.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_textures.h; sourceTree = ""; }; 7463B74C12F9CE6B00983F6A /* render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render.h; sourceTree = ""; }; - 7463B74D12F9CE6B00983F6A /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; 7463B74E12F9CE6B00983F6A /* sbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sbar.c; sourceTree = ""; }; 7463B74F12F9CE6B00983F6A /* sbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sbar.h; sourceTree = ""; }; 7463B75012F9CE6B00983F6A /* screen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = screen.h; sourceTree = ""; }; @@ -292,7 +296,6 @@ 7463B76812F9CE6B00983F6A /* sys_sdl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_sdl.c; sourceTree = ""; }; 7463B76912F9CE6B00983F6A /* sys_shared.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_shared.c; sourceTree = ""; }; 7463B76A12F9CE6B00983F6A /* sys.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys.h; sourceTree = ""; }; - 7463B76B12F9CE6B00983F6A /* timing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timing.h; sourceTree = ""; }; 7463B76C12F9CE6B00983F6A /* utf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utf8lib.c; sourceTree = ""; }; 7463B76D12F9CE6B00983F6A /* utf8lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utf8lib.h; sourceTree = ""; }; 7463B76E12F9CE6B00983F6A /* vid_sdl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vid_sdl.c; sourceTree = ""; }; @@ -306,15 +309,10 @@ 7463B77612F9CE6B00983F6A /* zone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zone.c; sourceTree = ""; }; 7463B77712F9CE6B00983F6A /* zone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zone.h; sourceTree = ""; }; 7463B7D812F9CF8F00983F6A /* darkplaces64x64.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = darkplaces64x64.png; sourceTree = ""; }; - 7463B7E812F9D11E00983F6A /* mod_skeletal_animatevertices_sse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mod_skeletal_animatevertices_sse.c; sourceTree = ""; }; - 7463B7E912F9D11E00983F6A /* mod_skeletal_animatevertices_sse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mod_skeletal_animatevertices_sse.h; sourceTree = ""; }; 7463B7ED12F9D17D00983F6A /* builddate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = builddate.c; sourceTree = ""; }; - 7463B7EE12F9D17D00983F6A /* clvm_cmds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clvm_cmds.c; sourceTree = ""; }; 7487D47F130102AA00AEE909 /* thread_sdl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thread_sdl.c; sourceTree = ""; }; 7487D480130102AA00AEE909 /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = thread.h; sourceTree = ""; }; 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - FD779ED00E26B9B000F39101 /* libSDLSimulator.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSDLSimulator.a; path = lib/libSDLSimulator.a; sourceTree = ""; }; - FD779ED10E26B9B000F39101 /* libSDLiPhoneOS.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSDLiPhoneOS.a; path = lib/libSDLiPhoneOS.a; sourceTree = ""; }; FD779EDD0E26BA1200F39101 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; }; FD77A0840E26BDB800F39101 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; FDB8BFC50E5A0F6A00980157 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; @@ -325,8 +323,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - FD779ED20E26B9B000F39101 /* libSDLSimulator.a in Frameworks */, - FD779ED30E26B9B000F39101 /* libSDLiPhoneOS.a in Frameworks */, 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 28FD15000DC6FC520079059D /* OpenGLES.framework in Frameworks */, @@ -334,6 +330,8 @@ FD779EDE0E26BA1200F39101 /* CoreAudio.framework in Frameworks */, FD77A0850E26BDB800F39101 /* AudioToolbox.framework in Frameworks */, FDB8BFC60E5A0F6A00980157 /* CoreGraphics.framework in Frameworks */, + 74063A491751B9B60015D12C /* libSDL2-ios-armv7.a in Frameworks */, + 74063A4A1751B9B60015D12C /* libSDL2-ios-simulator.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -363,20 +361,16 @@ 29B97315FDCFA39411CA2CEA /* Sources */ = { isa = PBXGroup; children = ( - 7487D47F130102AA00AEE909 /* thread_sdl.c */, - 7487D480130102AA00AEE909 /* thread.h */, - 7463B7ED12F9D17D00983F6A /* builddate.c */, - 7463B7EE12F9D17D00983F6A /* clvm_cmds.c */, - 7463B7E812F9D11E00983F6A /* mod_skeletal_animatevertices_sse.c */, - 7463B7E912F9D11E00983F6A /* mod_skeletal_animatevertices_sse.h */, + 74063A411751B0AF0015D12C /* clvm_cmds.c */, + 74063A3F1751B0250015D12C /* cd_null.c */, 7463B6C012F9CE6B00983F6A /* bih.c */, 7463B6C112F9CE6B00983F6A /* bih.h */, 7463B6C212F9CE6B00983F6A /* bspfile.h */, + 7463B7ED12F9D17D00983F6A /* builddate.c */, 7463B6C312F9CE6B00983F6A /* cap_avi.c */, 7463B6C412F9CE6B00983F6A /* cap_avi.h */, 7463B6C512F9CE6B00983F6A /* cap_ogg.c */, 7463B6C612F9CE6B00983F6A /* cap_ogg.h */, - 7463B6C712F9CE6B00983F6A /* cd_sdl.c */, 7463B6C812F9CE6B00983F6A /* cd_shared.c */, 7463B6C912F9CE6B00983F6A /* cdaudio.h */, 7463B6CA12F9CE6B00983F6A /* cl_collision.c */, @@ -384,8 +378,6 @@ 7463B6CC12F9CE6B00983F6A /* cl_demo.c */, 7463B6CD12F9CE6B00983F6A /* cl_dyntexture.c */, 7463B6CE12F9CE6B00983F6A /* cl_dyntexture.h */, - 7463B6CF12F9CE6B00983F6A /* cl_gecko.c */, - 7463B6D012F9CE6B00983F6A /* cl_gecko.h */, 7463B6D112F9CE6B00983F6A /* cl_input.c */, 7463B6D212F9CE6B00983F6A /* cl_main.c */, 7463B6D312F9CE6B00983F6A /* cl_parse.c */, @@ -422,10 +414,10 @@ 7463B6F212F9CE6B00983F6A /* fractalnoise.c */, 7463B6F312F9CE6B00983F6A /* fs.c */, 7463B6F412F9CE6B00983F6A /* fs.h */, - 7463B6F512F9CE6B00983F6A /* ft2_defs.h */, - 7463B6F612F9CE6B00983F6A /* ft2_fontdefs.h */, 7463B6F712F9CE6B00983F6A /* ft2.c */, 7463B6F812F9CE6B00983F6A /* ft2.h */, + 7463B6F512F9CE6B00983F6A /* ft2_defs.h */, + 7463B6F612F9CE6B00983F6A /* ft2_fontdefs.h */, 7463B6F912F9CE6B00983F6A /* gl_backend.c */, 7463B6FA12F9CE6B00983F6A /* gl_backend.h */, 7463B6FB12F9CE6B00983F6A /* gl_draw.c */, @@ -435,12 +427,12 @@ 7463B6FF12F9CE6B00983F6A /* glquake.h */, 7463B70012F9CE6B00983F6A /* hmac.c */, 7463B70112F9CE6B00983F6A /* hmac.h */, - 7463B70212F9CE6B00983F6A /* host_cmd.c */, 7463B70312F9CE6B00983F6A /* host.c */, - 7463B70412F9CE6B00983F6A /* image_png.c */, - 7463B70512F9CE6B00983F6A /* image_png.h */, + 7463B70212F9CE6B00983F6A /* host_cmd.c */, 7463B70612F9CE6B00983F6A /* image.c */, 7463B70712F9CE6B00983F6A /* image.h */, + 7463B70412F9CE6B00983F6A /* image_png.c */, + 7463B70512F9CE6B00983F6A /* image_png.h */, 7463B70812F9CE6B00983F6A /* input.h */, 7463B70912F9CE6B00983F6A /* intoverflow.h */, 7463B70A12F9CE6B00983F6A /* jpeg.c */, @@ -464,6 +456,8 @@ 7463B71C12F9CE6B00983F6A /* meshqueue.h */, 7463B71D12F9CE6B00983F6A /* mod_skeletal_animatevertices_generic.c */, 7463B71E12F9CE6B00983F6A /* mod_skeletal_animatevertices_generic.h */, + 74063A3C1751ADDA0015D12C /* mod_skeletal_animatevertices_sse.c */, + 74063A3D1751ADDA0015D12C /* mod_skeletal_animatevertices_sse.h */, 7463B71F12F9CE6B00983F6A /* model_alias.c */, 7463B72012F9CE6B00983F6A /* model_alias.h */, 7463B72112F9CE6B00983F6A /* model_brush.c */, @@ -510,7 +504,6 @@ 7463B74A12F9CE6B00983F6A /* r_sprites.c */, 7463B74B12F9CE6B00983F6A /* r_textures.h */, 7463B74C12F9CE6B00983F6A /* render.h */, - 7463B74D12F9CE6B00983F6A /* resource.h */, 7463B74E12F9CE6B00983F6A /* sbar.c */, 7463B74F12F9CE6B00983F6A /* sbar.h */, 7463B75012F9CE6B00983F6A /* screen.h */, @@ -537,15 +530,16 @@ 7463B76512F9CE6B00983F6A /* svbsp.c */, 7463B76612F9CE6B00983F6A /* svbsp.h */, 7463B76712F9CE6B00983F6A /* svvm_cmds.c */, + 7463B76A12F9CE6B00983F6A /* sys.h */, 7463B76812F9CE6B00983F6A /* sys_sdl.c */, 7463B76912F9CE6B00983F6A /* sys_shared.c */, - 7463B76A12F9CE6B00983F6A /* sys.h */, - 7463B76B12F9CE6B00983F6A /* timing.h */, + 7487D480130102AA00AEE909 /* thread.h */, + 7487D47F130102AA00AEE909 /* thread_sdl.c */, 7463B76C12F9CE6B00983F6A /* utf8lib.c */, 7463B76D12F9CE6B00983F6A /* utf8lib.h */, + 7463B77012F9CE6B00983F6A /* vid.h */, 7463B76E12F9CE6B00983F6A /* vid_sdl.c */, 7463B76F12F9CE6B00983F6A /* vid_shared.c */, - 7463B77012F9CE6B00983F6A /* vid.h */, 7463B77112F9CE6B00983F6A /* view.c */, 7463B77212F9CE6B00983F6A /* wad.c */, 7463B77312F9CE6B00983F6A /* wad.h */, @@ -560,6 +554,7 @@ 29B97317FDCFA39411CA2CEA /* Resources */ = { isa = PBXGroup; children = ( + 74063A501751C4560015D12C /* gamedata */, 7463B7D812F9CF8F00983F6A /* darkplaces64x64.png */, 8D1107310486CEB800E47090 /* Info.plist */, ); @@ -583,8 +578,8 @@ FD779EC50E26B99E00F39101 /* Libraries */ = { isa = PBXGroup; children = ( - FD779ED00E26B9B000F39101 /* libSDLSimulator.a */, - FD779ED10E26B9B000F39101 /* libSDLiPhoneOS.a */, + 74063A471751B9B60015D12C /* libSDL2-ios-armv7.a */, + 74063A481751B9B60015D12C /* libSDL2-ios-simulator.a */, ); name = Libraries; sourceTree = ""; @@ -614,8 +609,11 @@ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; + attributes = { + LastUpgradeCheck = 0420; + }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "DPiOS" */; - compatibilityVersion = "Xcode 3.1"; + compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( @@ -639,6 +637,7 @@ buildActionMask = 2147483647; files = ( 7463B7D912F9CF8F00983F6A /* darkplaces64x64.png in Resources */, + 74063A511751C4560015D12C /* gamedata in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -652,12 +651,10 @@ 7463B77812F9CE6B00983F6A /* bih.c in Sources */, 7463B77912F9CE6B00983F6A /* cap_avi.c in Sources */, 7463B77A12F9CE6B00983F6A /* cap_ogg.c in Sources */, - 7463B77B12F9CE6B00983F6A /* cd_sdl.c in Sources */, 7463B77C12F9CE6B00983F6A /* cd_shared.c in Sources */, 7463B77D12F9CE6B00983F6A /* cl_collision.c in Sources */, 7463B77E12F9CE6B00983F6A /* cl_demo.c in Sources */, 7463B77F12F9CE6B00983F6A /* cl_dyntexture.c in Sources */, - 7463B78012F9CE6B00983F6A /* cl_gecko.c in Sources */, 7463B78112F9CE6B00983F6A /* cl_input.c in Sources */, 7463B78212F9CE6B00983F6A /* cl_main.c in Sources */, 7463B78312F9CE6B00983F6A /* cl_parse.c in Sources */, @@ -741,10 +738,12 @@ 7463B7D112F9CE6B00983F6A /* wad.c in Sources */, 7463B7D212F9CE6B00983F6A /* world.c in Sources */, 7463B7D312F9CE6B00983F6A /* zone.c in Sources */, - 7463B7EA12F9D11E00983F6A /* mod_skeletal_animatevertices_sse.c in Sources */, 7463B7EF12F9D17D00983F6A /* builddate.c in Sources */, - 7463B7F012F9D17D00983F6A /* clvm_cmds.c in Sources */, + 7463B7F012F9D17D00983F6A /* (null) in Sources */, 7487D481130102AA00AEE909 /* thread_sdl.c in Sources */, + 74063A3E1751ADDB0015D12C /* mod_skeletal_animatevertices_sse.c in Sources */, + 74063A401751B0250015D12C /* cd_null.c in Sources */, + 74063A421751B0AF0015D12C /* clvm_cmds.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -754,34 +753,53 @@ 1D6058940D05DD3E006BFB54 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; + ALWAYS_SEARCH_USER_PATHS = YES; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + __IPHONEOS__, + USE_GLES2, + "FORCEGAME=\\\"steelstorm\\\"", + "DP_FS_BASEDIR=\\\"\\\"", + "DP_GAME_STEELSTORM=1", + ); INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/lib\"", ); PRODUCT_NAME = DPiOS; + TARGETED_DEVICE_FAMILY = 2; + USER_HEADER_SEARCH_PATHS = ""; }; name = Debug; }; 1D6058950D05DD3E006BFB54 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; + ALWAYS_SEARCH_USER_PATHS = YES; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + __IPHONEOS__, + USE_GLES2, + "FORCEGAME=\\\"steelstorm\\\"", + "DP_FS_BASEDIR=\\\"\\\"", + "DP_GAME_STEELSTORM=1", + ); INFOPLIST_FILE = Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 5.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/lib\"", ); PRODUCT_NAME = DPiOS; + TARGETED_DEVICE_FAMILY = 2; }; name = Release; }; @@ -790,15 +808,20 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ./include; - LIBRARY_SEARCH_PATHS = ./lib; + HEADER_SEARCH_PATHS = "$(SRCROOT)/include"; + LIBRARY_SEARCH_PATHS = "$(SRCROOT)/lib"; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ""; - PREBINDING = NO; + OTHER_LDFLAGS = ( + "-ObjC", + "-lz", + ); + PRODUCT_NAME = Darkplaces; SDKROOT = iphoneos; + VALID_ARCHS = armv7; }; name = Debug; }; @@ -807,14 +830,19 @@ buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_BIT)"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - GCC_C_LANGUAGE_STANDARD = c99; + GCC_C_LANGUAGE_STANDARD = "compiler-default"; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - HEADER_SEARCH_PATHS = ./include; - LIBRARY_SEARCH_PATHS = ./lib; + HEADER_SEARCH_PATHS = "$(SRCROOT)/include"; + LIBRARY_SEARCH_PATHS = "$(SRCROOT)/lib"; OTHER_CFLAGS = ""; - PREBINDING = NO; + OTHER_LDFLAGS = ( + "-ObjC", + "-lz", + ); + PRODUCT_NAME = Darkplaces; SDKROOT = iphoneos; + VALID_ARCHS = armv7; }; name = Release; }; diff --git a/DPiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DPiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..67e15a2b --- /dev/null +++ b/DPiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Info.plist b/Info.plist index 3873788b..55160a83 100644 --- a/Info.plist +++ b/Info.plist @@ -11,18 +11,32 @@ CFBundleIconFile darkplaces64x64 CFBundleIdentifier - com.yourcompany.${PRODUCT_NAME:identifier} + com.ghdigital.${PRODUCT_NAME:identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL + CFBundleShortVersionString + 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationPortrait + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationPortrait + diff --git a/cl_screen.c b/cl_screen.c index a37dfed4..bf562e0c 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -82,7 +82,7 @@ cvar_t scr_screenshot_name_in_mapdir = {CVAR_SAVE, "scr_screenshot_name_in_mapdi cvar_t shownetgraph = {CVAR_SAVE, "shownetgraph", "0", "shows a graph of packet sizes and other information, 0 = off, 1 = show client netgraph, 2 = show client and server netgraphs (when hosting a server)"}; cvar_t cl_demo_mousegrab = {0, "cl_demo_mousegrab", "0", "Allows reading the mouse input while playing demos. Useful for camera mods developed in csqc. (0: never, 1: always)"}; cvar_t timedemo_screenshotframelist = {0, "timedemo_screenshotframelist", "", "when performing a timedemo, take screenshots of each frame in this space-separated list - example: 1 201 401"}; -cvar_t vid_touchscreen_outlinealpha = {0, "vid_touchscreen_outlinealpha", "0.25", "opacity of touchscreen area outlines"}; +cvar_t vid_touchscreen_outlinealpha = {0, "vid_touchscreen_outlinealpha", "0", "opacity of touchscreen area outlines"}; cvar_t vid_touchscreen_overlayalpha = {0, "vid_touchscreen_overlayalpha", "0.25", "opacity of touchscreen area icons"}; cvar_t r_speeds_graph = {CVAR_SAVE, "r_speeds_graph", "0", "display a graph of renderer statistics "}; cvar_t r_speeds_graph_filter[8] = @@ -2039,7 +2039,7 @@ qboolean SCR_ScreenShot(char *filename, unsigned char *buffer1, unsigned char *b //============================================================================= int scr_numtouchscreenareas; -scr_touchscreenarea_t scr_touchscreenareas[16]; +scr_touchscreenarea_t scr_touchscreenareas[128]; static void SCR_DrawTouchscreenOverlay(void) { @@ -2048,7 +2048,7 @@ static void SCR_DrawTouchscreenOverlay(void) cachepic_t *pic; for (i = 0, a = scr_touchscreenareas;i < scr_numtouchscreenareas;i++, a++) { - if (vid_touchscreen_outlinealpha.value > 0 && a->rect[0] >= 0 && a->rect[1] >= 0 && a->rect[2] >= 4 && a->rect[3] >= 4) + if (developer.integer && vid_touchscreen_outlinealpha.value > 0 && a->rect[0] >= 0 && a->rect[1] >= 0 && a->rect[2] >= 4 && a->rect[3] >= 4) { DrawQ_Fill(a->rect[0] + 2, a->rect[1] , a->rect[2] - 4, 1 , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0); DrawQ_Fill(a->rect[0] + 1, a->rect[1] + 1, a->rect[2] - 2, 1 , 1, 1, 1, vid_touchscreen_outlinealpha.value * (0.5f + 0.5f * a->active), 0); @@ -2060,14 +2060,19 @@ static void SCR_DrawTouchscreenOverlay(void) pic = a->pic ? Draw_CachePic(a->pic) : NULL; if (pic && pic->tex != r_texture_notexture) DrawQ_Pic(a->rect[0], a->rect[1], Draw_CachePic(a->pic), a->rect[2], a->rect[3], 1, 1, 1, vid_touchscreen_overlayalpha.value * (0.5f + 0.5f * a->active), 0); + if (a->text && a->text[0]) + { + int textwidth = DrawQ_TextWidth(a->text, 0, a->textheight, a->textheight, false, FONT_CHAT); + DrawQ_String(a->rect[0] + (a->rect[2] - textwidth) * 0.5f, a->rect[1] + (a->rect[3] - a->textheight) * 0.5f, a->text, 0, a->textheight, a->textheight, 1.0f, 1.0f, 1.0f, vid_touchscreen_overlayalpha.value, 0, NULL, false, FONT_CHAT); + } } } void R_ClearScreen(qboolean fogcolor) { float clearcolor[4]; - // clear to black - Vector4Clear(clearcolor); + // clear to opaque black (if we're being composited it might otherwise render as transparent) + Vector4Set(clearcolor, 0.0f, 0.0f, 0.0f, 1.0f); if (fogcolor && r_fog_clear.integer) { R_UpdateFog(); @@ -2893,10 +2898,14 @@ void CL_UpdateScreen(void) qglDrawBuffer(GL_BACK_LEFT); SCR_DrawScreen(); + r_stereo_side = 0; } else #endif + { + r_stereo_side = 0; SCR_DrawScreen(); + } SCR_CaptureVideo(); diff --git a/fs.c b/fs.c index b026b6ed..a32d6fab 100644 --- a/fs.c +++ b/fs.c @@ -1073,6 +1073,8 @@ static qboolean FS_AddPack_Fullpath(const char *pakfile, const char *shortname, pak = FS_LoadPackPAK (pakfile); else if(!strcasecmp(ext, "pk3")) pak = FS_LoadPackPK3 (pakfile); + else if(!strcasecmp(ext, "obb")) // android apk expansion + pak = FS_LoadPackPK3 (pakfile); else Con_Printf("\"%s\" does not have a pack extension\n", pakfile); @@ -1214,7 +1216,7 @@ static void FS_AddGameDirectory (const char *dir) // add any PK3 package in the directory for (i = 0;i < list.numstrings;i++) { - if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3") || !strcasecmp(FS_FileExtension(list.strings[i]), "pk3dir")) + if (!strcasecmp(FS_FileExtension(list.strings[i]), "pk3") || !strcasecmp(FS_FileExtension(list.strings[i]), "obb") || !strcasecmp(FS_FileExtension(list.strings[i]), "pk3dir")) { FS_AddPack_Fullpath(list.strings[i], list.strings[i] + strlen(dir), NULL, false); } @@ -1746,7 +1748,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use { // fs_basedir is "" by default, to utilize this you can simply add your gamedir to the Resources in xcode // fs_userdir stores configurations to the Documents folder of the app - strlcpy(userdir, maxlength, "../Documents/"); + strlcpy(userdir, "../Documents/", MAX_OSPATH); return 1; } return -1; @@ -1875,6 +1877,8 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use #endif +#if !defined(__IPHONEOS__) + #ifdef WIN32 // historical behavior... if (userdirmode == USERDIRMODE_NOHOME && strcmp(gamedirname1, "id1")) @@ -1905,6 +1909,7 @@ static int FS_ChooseUserDir(userdirmode_t userdirmode, char *userdir, size_t use else return 0; // probably good - failed to write but maybe we need to create path } +#endif } /* @@ -1937,6 +1942,8 @@ void FS_Init (void) // If the base directory is explicitly defined by the compilation process #ifdef DP_FS_BASEDIR strlcpy(fs_basedir, DP_FS_BASEDIR, sizeof(fs_basedir)); +#elif defined(__ANDROID__) + dpsnprintf(fs_basedir, sizeof(fs_basedir), "/sdcard/%s/", gameuserdirname); #elif defined(MACOSX) // FIXME: is there a better way to find the directory outside the .app, without using Objective-C? if (strstr(com_argv[0], ".app/")) @@ -2355,17 +2362,9 @@ int FS_CheckNastyPath (const char *path, qboolean isgamedir) if (path[0] == '/') return 2; // attempt to go outside the game directory - // all: don't allow . characters before the last slash (it should only be used in filenames, not path elements), this catches all imaginable cases of ./, ../, .../, etc - if (strchr(path, '.')) - { - if (isgamedir) - { - // gamedir is entirely path elements, so simply forbid . entirely - return 2; - } - if (strchr(path, '.') < strrchr(path, '/')) - return 2; // possible attempt to go outside the game directory - } + // all: don't allow . character immediately before a slash, this catches all imaginable cases of ./, ../, .../, etc + if (strstr(path, "./")) + return 2; // possible attempt to go outside the game directory // all: forbid trailing slash on gamedir if (isgamedir && path[strlen(path)-1] == '/') diff --git a/gl_backend.c b/gl_backend.c index 1b32c346..8dc6d236 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -1156,7 +1156,6 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri void R_SetViewport(const r_viewport_t *v) { - float m[16]; gl_viewport = *v; // FIXME: v_flipped_state is evil, this probably breaks somewhere @@ -1171,14 +1170,17 @@ void R_SetViewport(const r_viewport_t *v) case RENDERPATH_GL13: case RENDERPATH_GL11: case RENDERPATH_GLES1: -#ifdef GL_PROJECTION - CHECKGLERROR - qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR - // Load the projection matrix into OpenGL - qglMatrixMode(GL_PROJECTION);CHECKGLERROR - Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m); - qglLoadMatrixf(m);CHECKGLERROR - qglMatrixMode(GL_MODELVIEW);CHECKGLERROR +#ifndef USE_GLES2 + { + float m[16]; + CHECKGLERROR + qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR + // Load the projection matrix into OpenGL + qglMatrixMode(GL_PROJECTION);CHECKGLERROR + Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m); + qglLoadMatrixf(m);CHECKGLERROR + qglMatrixMode(GL_MODELVIEW);CHECKGLERROR + } #endif break; case RENDERPATH_D3D9: @@ -1246,8 +1248,10 @@ static void GL_BindUBO(int bufferobject) if (gl_state.uniformbufferobject != bufferobject) { gl_state.uniformbufferobject = bufferobject; +#ifdef GL_UNIFORM_BUFFER CHECKGLERROR qglBindBufferARB(GL_UNIFORM_BUFFER, bufferobject);CHECKGLERROR +#endif } } @@ -1271,10 +1275,11 @@ int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colorte #ifdef USE_GLES2 // FIXME: separate stencil attachment on GLES if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR + if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR #else if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR -#endif if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, depthtexture->glisdepthstencil ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR +#endif if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR @@ -1602,13 +1607,20 @@ static void GL_Backend_ResetState(void) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: -#ifdef GL_ALPHA_TEST +#ifndef USE_GLES2 CHECKGLERROR qglColorMask(1, 1, 1, 1);CHECKGLERROR qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR qglDisable(GL_ALPHA_TEST);CHECKGLERROR - qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + if (qglBlendFuncSeparate) + { + qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround + } + else + { + qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + } qglDisable(GL_BLEND);CHECKGLERROR qglCullFace(gl_state.cullface);CHECKGLERROR qglDisable(GL_CULL_FACE);CHECKGLERROR @@ -1767,12 +1779,14 @@ void GL_ClientActiveTexture(unsigned int num) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 if (qglActiveTexture) { CHECKGLERROR qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit); CHECKGLERROR } +#endif break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -1803,7 +1817,14 @@ void GL_BlendFunc(int blendfunc1, int blendfunc2) case RENDERPATH_GLES1: case RENDERPATH_GLES2: CHECKGLERROR - qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + if (qglBlendFuncSeparate) + { + qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround + } + else + { + qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + } if (gl_state.blend != blendenable) { gl_state.blend = blendenable; @@ -2044,7 +2065,7 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro } else if (vid.support.ext_stencil_two_side) { -#ifdef GL_STENCIL_TEST_TWO_SIDE_EXT +#if defined(GL_STENCIL_TEST_TWO_SIDE_EXT) && !defined(USE_GLES2) qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR qglStencilMask(writemask);CHECKGLERROR @@ -2412,9 +2433,11 @@ void GL_Color(float cr, float cg, float cb, float ca) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 CHECKGLERROR qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]); CHECKGLERROR +#endif break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -2508,7 +2531,8 @@ void GL_ScissorTest(int state) void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue) { - static const float blackcolor[4] = {0, 0, 0, 0}; + // opaque black - if you want transparent black, you'll need to pass in a colorvalue + static const float blackcolor[4] = {0.0f, 0.0f, 0.0f, 1.0f}; // prevent warnings when trying to clear a buffer that does not exist if (!colorvalue) colorvalue = blackcolor; @@ -2573,8 +2597,30 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi case RENDERPATH_GLES1: case RENDERPATH_GLES2: CHECKGLERROR +#ifndef GL_BGRA + { + int i; + int r; + // int g; + int b; + // int a; + qglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR + for (i = 0;i < width * height * 4;i += 4) + { + r = outpixels[i+0]; + // g = outpixels[i+1]; + b = outpixels[i+2]; + // a = outpixels[i+3]; + outpixels[i+0] = b; + // outpixels[i+1] = g; + outpixels[i+2] = r; + // outpixels[i+3] = a; + } + } +#else qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR - break; +#endif + break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D { @@ -2696,7 +2742,7 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list)) goto cleanup; -#ifdef GL_GEOMETRY_SHADER +#if defined(GL_GEOMETRY_SHADER) && !defined(USE_GLES2) if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list)) goto cleanup; #endif @@ -2707,10 +2753,13 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver qglLinkProgram(programobject);CHECKGLERROR qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR + if (linklog[0]) { + if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer) Con_DPrintf("program link log:\n%s\n", linklog); + // software vertex shader is ok but software fragment shader is WAY // too slow, fail program if so. // NOTE: this string might be ATI specific, but that's ok because the @@ -2720,8 +2769,10 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver if (strstr(linklog, "fragment shader will run in software")) programlinked = false; } + if (!programlinked) goto cleanup; + return programobject; cleanup: qglDeleteProgram(programobject);CHECKGLERROR @@ -3310,10 +3361,19 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si GL_BindEBO(buffer->bufferobject); else GL_BindVBO(buffer->bufferobject); - if (subdata) - qglBufferSubDataARB(buffer->isuniformbuffer ? GL_UNIFORM_BUFFER : (buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER), offset, size, data); - else - qglBufferDataARB(buffer->isuniformbuffer ? GL_UNIFORM_BUFFER : (buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER), size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW); + + { + int buffertype; + buffertype = buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER; +#ifdef GL_UNIFORM_BUFFER + if (buffer->isuniformbuffer) + buffertype = GL_UNIFORM_BUFFER; +#endif + if (subdata) + qglBufferSubDataARB(buffertype, offset, size, data); + else + qglBufferDataARB(buffertype, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW); + } if (buffer->isuniformbuffer) GL_BindUBO(0); break; @@ -3482,6 +3542,7 @@ void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 if (gl_state.pointer_vertex_components != components || gl_state.pointer_vertex_gltype != gltype || gl_state.pointer_vertex_stride != stride || gl_state.pointer_vertex_pointer != pointer || gl_state.pointer_vertex_vertexbuffer != vertexbuffer || gl_state.pointer_vertex_offset != bufferoffset) { int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0; @@ -3495,6 +3556,7 @@ void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void GL_BindVBO(bufferobject); qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } +#endif break; case RENDERPATH_GL20: case RENDERPATH_GLES2: @@ -3530,7 +3592,7 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: -#ifdef GL_MODELVIEW +#ifndef USE_GLES2 CHECKGLERROR if (pointer) { @@ -3628,7 +3690,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: -#ifdef GL_MODELVIEW +#ifndef USE_GLES2 CHECKGLERROR if (pointer) { @@ -3968,7 +4030,6 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex) void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) { - gltextureunit_t *unit = gl_state.units + unitnum; switch(vid.renderpath) { case RENDERPATH_GL11: @@ -3979,6 +4040,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) #ifdef GL_MODELVIEW if (matrix && matrix->m[3][3]) { + gltextureunit_t *unit = gl_state.units + unitnum; // texmatrix specified, check if it is different if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t))) { @@ -3996,6 +4058,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) else { // no texmatrix specified, revert to identity + gltextureunit_t *unit = gl_state.units + unitnum; if (unit->texmatrixenabled) { unit->texmatrixenabled = false; @@ -4020,6 +4083,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale) { +#if defined(GL_TEXTURE_ENV) && !defined(USE_GLES2) gltextureunit_t *unit = gl_state.units + unitnum; CHECKGLERROR switch(vid.renderpath) @@ -4030,7 +4094,6 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i break; case RENDERPATH_GL13: case RENDERPATH_GLES1: -#ifdef GL_TEXTURE_ENV // GL_ARB_texture_env_combine if (!combinergb) combinergb = GL_MODULATE; @@ -4085,11 +4148,9 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR } } -#endif break; case RENDERPATH_GL11: // normal GL texenv -#ifdef GL_TEXTURE_ENV if (!combinergb) combinergb = GL_MODULATE; if (unit->combine != combinergb) @@ -4098,7 +4159,6 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i GL_ActiveTexture(unitnum); qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR } -#endif break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -4107,6 +4167,7 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i case RENDERPATH_SOFT: break; } +#endif } void R_Mesh_ResetTextureState(void) diff --git a/gl_rmain.c b/gl_rmain.c index 14e2551c..755925c9 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -1163,6 +1163,26 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode // look up all the uniform variable names we care about, so we don't // have to look them up every time we set them +#if 0 + // debugging aid + { + GLint activeuniformindex = 0; + GLint numactiveuniforms = 0; + char uniformname[128]; + GLsizei uniformnamelength = 0; + GLint uniformsize = 0; + GLenum uniformtype = 0; + memset(uniformname, 0, sizeof(uniformname)); + qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms); + Con_Printf("Shader has %i uniforms\n", numactiveuniforms); + for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++) + { + qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname); + Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype); + } + } +#endif + p->loc_Texture_First = qglGetUniformLocation(p->program, "Texture_First"); p->loc_Texture_Second = qglGetUniformLocation(p->program, "Texture_Second"); p->loc_Texture_GammaRamps = qglGetUniformLocation(p->program, "Texture_GammaRamps"); @@ -1311,15 +1331,19 @@ static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode if (p->loc_Texture_ReflectCube >= 0) {p->tex_Texture_ReflectCube = sampler;qglUniform1i(p->loc_Texture_ReflectCube , sampler);sampler++;} if (p->loc_Texture_BounceGrid >= 0) {p->tex_Texture_BounceGrid = sampler;qglUniform1i(p->loc_Texture_BounceGrid , sampler);sampler++;} // get the uniform block indices so we can bind them +#ifndef USE_GLES2 /* FIXME: GLES3 only */ if (vid.support.arb_uniform_buffer_object) p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock"); else +#endif p->ubiloc_Skeletal_Transform12_UniformBlock = -1; // clear the uniform block bindings p->ubibind_Skeletal_Transform12_UniformBlock = -1; // bind the uniform blocks in use ubibind = 0; +#ifndef USE_GLES2 /* FIXME: GLES3 only */ if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;} +#endif // we're done compiling and setting up the shader, at least until it is used CHECKGLERROR Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler); @@ -1341,7 +1365,10 @@ static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int per if (!r_glsl_permutation->program) { if (!r_glsl_permutation->compiled) + { + Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation); R_GLSL_CompilePermutation(perm, mode, permutation); + } if (!r_glsl_permutation->program) { // remove features until we find a valid permutation @@ -2068,7 +2095,9 @@ void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean case RENDERPATH_GL20: case RENDERPATH_GLES2: R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation); +#ifndef USE_GLES2 /* FIXME: GLES3 only */ if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size); +#endif break; case RENDERPATH_GL13: case RENDERPATH_GLES1: @@ -2726,7 +2755,9 @@ void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, if (rsurface.batchskeletaltransform3x4buffer) permutation |= SHADERPERMUTATION_SKELETAL; R_SetupShader_SetPermutationGLSL(mode, permutation); +#ifndef USE_GLES2 /* FIXME: GLES3 only */ if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size); +#endif if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);} if (mode == SHADERMODE_LIGHTSOURCE) { @@ -4008,9 +4039,11 @@ static void gl_main_start(void) r_loadnormalmap = true; r_loadgloss = true; r_loadfog = false; +#ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT if (vid.support.arb_uniform_buffer_object) qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment); - break; +#endif + break; case RENDERPATH_GL13: case RENDERPATH_GLES1: Cvar_SetValueQuick(&r_textureunits, vid.texunits); @@ -4078,6 +4111,27 @@ static void gl_main_start(void) r_texture_numcubemaps = 0; r_refdef.fogmasktable_density = 0; + +#ifdef __ANDROID__ + // For Steelstorm Android + // FIXME CACHE the program and reload + // FIXME see possible combinations for SS:BR android + Con_DPrintf("Compiling most used shaders for SS:BR android... START\n"); + R_SetupShader_SetPermutationGLSL(0, 12); + R_SetupShader_SetPermutationGLSL(0, 13); + R_SetupShader_SetPermutationGLSL(0, 8388621); + R_SetupShader_SetPermutationGLSL(3, 0); + R_SetupShader_SetPermutationGLSL(3, 2048); + R_SetupShader_SetPermutationGLSL(5, 0); + R_SetupShader_SetPermutationGLSL(5, 2); + R_SetupShader_SetPermutationGLSL(5, 2048); + R_SetupShader_SetPermutationGLSL(5, 8388608); + R_SetupShader_SetPermutationGLSL(11, 1); + R_SetupShader_SetPermutationGLSL(11, 2049); + R_SetupShader_SetPermutationGLSL(11, 8193); + R_SetupShader_SetPermutationGLSL(11, 10241); + Con_DPrintf("Compiling most used shaders for SS:BR android... END\n"); +#endif } static void gl_main_shutdown(void) @@ -4095,7 +4149,7 @@ static void gl_main_shutdown(void) case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: -#ifdef GL_SAMPLES_PASSED_ARB +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) if (r_maxqueries) qglDeleteQueriesARB(r_maxqueries, r_queries); #endif @@ -4361,6 +4415,13 @@ void GL_Main_Init(void) Cvar_RegisterVariable(&r_batch_dynamicbuffer); if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE) Cvar_SetValue("r_fullbrights", 0); +#ifdef DP_MOBILETOUCH + // GLES devices have terrible depth precision in general, so... + Cvar_SetValueQuick(&r_nearclip, 4); + Cvar_SetValueQuick(&r_farclip_base, 4096); + Cvar_SetValueQuick(&r_farclip_world, 0); + Cvar_SetValueQuick(&r_useinfinitefarclip, 0); +#endif R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL); } @@ -5637,7 +5698,9 @@ void R_EntityMatrix(const matrix4x4_t *matrix) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 qglLoadMatrixf(gl_modelview16f);CHECKGLERROR +#endif break; case RENDERPATH_SOFT: DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f); @@ -12178,10 +12241,9 @@ extern cvar_t mod_collision_bih; static void R_DrawDebugModel(void) { entity_render_t *ent = rsurface.entity; - int i, j, k, l, flagsmask; + int i, j, flagsmask; const msurface_t *surface; dp_model_t *model = ent->model; - vec3_t v; if (!sv.active && !cls.demoplayback && ent != r_refdef.scene.worldentity) return; @@ -12313,6 +12375,8 @@ static void R_DrawDebugModel(void) if (r_shownormals.value != 0 && qglBegin) { + int l, k; + vec3_t v; if (r_showdisabledepthtest.integer) { GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); diff --git a/gl_textures.c b/gl_textures.c index 2dd11ebf..077d918f 100644 --- a/gl_textures.c +++ b/gl_textures.c @@ -81,6 +81,11 @@ typedef struct textypeinfo_s textypeinfo_t; #ifdef USE_GLES2 + +// we use these internally even if we never deliver such data to the driver +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 + // framebuffer texture formats // GLES2 devices rarely support depth textures, so we actually use a renderbuffer there static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16 , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; @@ -102,6 +107,9 @@ static textypeinfo_t textype_rgba = {"rgba", static textypeinfo_t textype_rgba_alpha = {"rgba_alpha", TEXTYPE_RGBA , 4, 4, 4.0f, GL_RGBA , GL_RGBA , GL_UNSIGNED_BYTE }; static textypeinfo_t textype_bgra = {"bgra", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; static textypeinfo_t textype_bgra_alpha = {"bgra_alpha", TEXTYPE_BGRA , 4, 4, 4.0f, GL_RGBA , GL_BGRA , GL_UNSIGNED_BYTE }; +#ifdef __ANDROID__ +static textypeinfo_t textype_etc1 = {"etc1", TEXTYPE_ETC1 , 1, 3, 0.5f, GL_ETC1_RGB8_OES , 0 , 0 }; +#endif #else // framebuffer texture formats static textypeinfo_t textype_shadowmap16_comp = {"shadowmap16_comp", TEXTYPE_SHADOWMAP16_COMP , 2, 2, 2.0f, GL_DEPTH_COMPONENT16_ARB , GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}; @@ -157,7 +165,9 @@ typedef enum gltexturetype_e gltexturetype_t; static int gltexturetypeenums[GLTEXTURETYPE_TOTAL] = {GL_TEXTURE_2D, GL_TEXTURE_3D, GL_TEXTURE_CUBE_MAP}; +#ifdef GL_TEXTURE_WRAP_R static int gltexturetypedimensions[GLTEXTURETYPE_TOTAL] = {2, 3, 2}; +#endif static int cubemapside[6] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X, @@ -268,6 +278,25 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags) { switch(textype) { +#ifdef USE_GLES2 + case TEXTYPE_PALETTE: return (flags & TEXF_ALPHA) ? &textype_palette_alpha : &textype_palette; + case TEXTYPE_RGBA: return ((flags & TEXF_ALPHA) ? &textype_rgba_alpha : &textype_rgba); + case TEXTYPE_BGRA: return ((flags & TEXF_ALPHA) ? &textype_bgra_alpha : &textype_bgra); +#ifdef __ANDROID__ + case TEXTYPE_ETC1: return &textype_etc1; +#endif + case TEXTYPE_ALPHA: return &textype_alpha; + case TEXTYPE_COLORBUFFER: return &textype_colorbuffer; + case TEXTYPE_COLORBUFFER16F: return &textype_colorbuffer16f; + case TEXTYPE_COLORBUFFER32F: return &textype_colorbuffer32f; + case TEXTYPE_DEPTHBUFFER16: return &textype_depth16; + case TEXTYPE_DEPTHBUFFER24: return &textype_depth24; + case TEXTYPE_DEPTHBUFFER24STENCIL8: return &textype_depth24stencil8; + case TEXTYPE_SHADOWMAP16_COMP: return &textype_shadowmap16_comp; + case TEXTYPE_SHADOWMAP16_RAW: return &textype_shadowmap16_raw; + case TEXTYPE_SHADOWMAP24_COMP: return &textype_shadowmap24_comp; + case TEXTYPE_SHADOWMAP24_RAW: return &textype_shadowmap24_raw; +#else case TEXTYPE_DXT1: return &textype_dxt1; case TEXTYPE_DXT1A: return &textype_dxt1a; case TEXTYPE_DXT3: return &textype_dxt3; @@ -293,6 +322,7 @@ static textypeinfo_t *R_GetTexTypeInfo(textype_t textype, int flags) case TEXTYPE_SRGB_PALETTE: return (flags & TEXF_ALPHA) ? &textype_sRGB_palette_alpha : &textype_sRGB_palette; case TEXTYPE_SRGB_RGBA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_rgba_alpha_compress : &textype_sRGB_rgba_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_rgba_alpha : &textype_sRGB_rgba); case TEXTYPE_SRGB_BGRA: return ((flags & TEXF_COMPRESS) && vid.support.ext_texture_compression_s3tc) ? ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha_compress : &textype_sRGB_bgra_compress) : ((flags & TEXF_ALPHA) ? &textype_sRGB_bgra_alpha : &textype_sRGB_bgra); +#endif default: Host_Error("R_GetTexTypeInfo: unknown texture format"); break; @@ -964,7 +994,9 @@ void R_Textures_Init (void) void R_Textures_Frame (void) { +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT static int old_aniso = 0; +#endif // could do procedural texture animation here, if we keep track of which // textures were accessed this frame... @@ -982,6 +1014,7 @@ void R_Textures_Frame (void) colorconvertbuffer = NULL; } +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT if (old_aniso != gl_texture_anisotropy.integer) { gltexture_t *glt; @@ -1025,6 +1058,7 @@ void R_Textures_Frame (void) break; } } +#endif } static void R_MakeResizeBufferBigger(int size) @@ -1050,6 +1084,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet CHECKGLERROR +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT if (vid.support.ext_texture_filter_anisotropic && (flags & TEXF_MIPMAP)) { int aniso = bound(1, gl_texture_anisotropy.integer, (int)vid.max_anisotropy); @@ -1057,6 +1092,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet Cvar_SetValueQuick(&gl_texture_anisotropy, aniso); qglTexParameteri(textureenum, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);CHECKGLERROR } +#endif qglTexParameteri(textureenum, GL_TEXTURE_WRAP_S, wrapmode);CHECKGLERROR qglTexParameteri(textureenum, GL_TEXTURE_WRAP_T, wrapmode);CHECKGLERROR #ifdef GL_TEXTURE_WRAP_R @@ -1111,6 +1147,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet qglTexParameteri(textureenum, GL_TEXTURE_MAG_FILTER, gl_filter_mag);CHECKGLERROR } +#ifdef GL_TEXTURE_COMPARE_MODE_ARB switch(textype) { case TEXTYPE_SHADOWMAP16_COMP: @@ -1128,6 +1165,7 @@ static void GL_SetupTextureParameters(int flags, textype_t textype, int texturet default: break; } +#endif CHECKGLERROR } @@ -1281,6 +1319,7 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[glt->texturetype]); qglBindTexture(gltexturetypeenums[glt->texturetype], glt->texnum);CHECKGLERROR +#ifndef USE_GLES2 #ifdef GL_TEXTURE_COMPRESSION_HINT_ARB if (qglGetCompressedTexImageARB) { @@ -1290,6 +1329,7 @@ static void R_UploadFullTexture(gltexture_t *glt, const unsigned char *data) qglHint(GL_TEXTURE_COMPRESSION_HINT_ARB, GL_FASTEST); CHECKGLERROR } +#endif #endif switch(glt->texturetype) { @@ -2148,6 +2188,11 @@ int R_SaveTextureDDSFile(rtexture_t *rt, const char *filename, qboolean skipunco #endif } +#ifdef __ANDROID__ +// ELUAN: FIXME: separate this code +#include "ktx10/include/ktx.h" +#endif + rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filename, qboolean srgb, int flags, qboolean *hasalphaflag, float *avgcolor, int miplevel, qboolean optionaltexture) // DDS textures are opaque, so miplevel isn't a pointer but just seen as a hint { int i, size, dds_format_flags, dds_miplevels, dds_width, dds_height; @@ -2168,10 +2213,154 @@ rtexture_t *R_LoadTextureDDSFile(rtexturepool_t *rtexturepool, const char *filen fs_offset_t ddsfilesize; unsigned int ddssize; qboolean force_swdecode, npothack; +#ifdef __ANDROID__ + // ELUAN: FIXME: separate this code + char vabuf[1024]; + char vabuf2[1024]; + int strsize; + KTX_dimensions sizes; +#endif if (cls.state == ca_dedicated) return NULL; +#ifdef __ANDROID__ + // ELUAN: FIXME: separate this code + if (vid.renderpath != RENDERPATH_GLES2) + { + Con_DPrintf("KTX texture format is only supported on the GLES2 renderpath\n"); + return NULL; + } + + // some textures are specified with extensions, so it becomes .tga.dds + FS_StripExtension (filename, vabuf2, sizeof(vabuf2)); + FS_StripExtension (vabuf2, vabuf, sizeof(vabuf)); + FS_DefaultExtension (vabuf, ".ktx", sizeof(vabuf)); + strsize = strlen(vabuf); + if (strsize > 5) + for (i = 0; i <= strsize - 4; i++) // copy null termination + vabuf[i] = vabuf[i + 4]; + + Con_DPrintf("Loading %s...\n", vabuf); + dds = FS_LoadFile(vabuf, tempmempool, true, &ddsfilesize); + ddssize = ddsfilesize; + + if (!dds) + { + Con_DPrintf("Not found!\n"); + return NULL; // not found + } + Con_DPrintf("Found!\n"); + + if (flags & TEXF_ALPHA) + { + Con_DPrintf("KTX texture with alpha not supported yet, disabling\n"); + flags &= ~TEXF_ALPHA; + } + + { + GLenum target; + GLenum glerror; + GLboolean isMipmapped; + KTX_error_code ktxerror; + + glt = (gltexture_t *)Mem_ExpandableArray_AllocRecord(&texturearray); + + // texture uploading can take a while, so make sure we're sending keepalives + CL_KeepaliveMessage(false); + + // create the texture object + CHECKGLERROR + GL_ActiveTexture(0); + oldbindtexnum = R_Mesh_TexBound(0, gltexturetypeenums[GLTEXTURETYPE_2D]); + qglGenTextures(1, (GLuint *)&glt->texnum);CHECKGLERROR + qglBindTexture(gltexturetypeenums[GLTEXTURETYPE_2D], glt->texnum);CHECKGLERROR + + // upload the texture + // we need to restore the texture binding after finishing the upload + + // NOTE: some drivers fail with ETC1 NPOT (only PowerVR?). This may make the driver crash later. + ktxerror = ktxLoadTextureM(dds, ddssize, &glt->texnum, &target, &sizes, &isMipmapped, &glerror, + 0, NULL);// can't CHECKGLERROR, the lib catches it + + // FIXME: delete texture if we fail here + if (target != GL_TEXTURE_2D) + { + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR + Mem_Free(dds); + Con_DPrintf("%s target != GL_TEXTURE_2D, target == %x\n", vabuf, target); + return NULL; // FIXME: delete the texture from memory + } + + if (KTX_SUCCESS == ktxerror) + { + textype = TEXTYPE_ETC1; + flags &= ~TEXF_COMPRESS; // don't let the textype be wrong + + // return whether this texture is transparent + if (hasalphaflag) + *hasalphaflag = (flags & TEXF_ALPHA) != 0; + + // TODO: apply gl_picmip + // TODO: avgcolor + // TODO: srgb + // TODO: only load mipmaps if requested + + if (isMipmapped) + flags |= TEXF_MIPMAP; + else + flags &= ~TEXF_MIPMAP; + + texinfo = R_GetTexTypeInfo(textype, flags); + + strlcpy (glt->identifier, vabuf, sizeof(glt->identifier)); + glt->pool = pool; + glt->chain = pool->gltchain; + pool->gltchain = glt; + glt->inputwidth = sizes.width; + glt->inputheight = sizes.height; + glt->inputdepth = 1; + glt->flags = flags; + glt->textype = texinfo; + glt->texturetype = GLTEXTURETYPE_2D; + glt->inputdatasize = ddssize; + glt->glinternalformat = texinfo->glinternalformat; + glt->glformat = texinfo->glformat; + glt->gltype = texinfo->gltype; + glt->bytesperpixel = texinfo->internalbytesperpixel; + glt->sides = 1; + glt->gltexturetypeenum = gltexturetypeenums[glt->texturetype]; + glt->tilewidth = sizes.width; + glt->tileheight = sizes.height; + glt->tiledepth = 1; + glt->miplevels = isMipmapped ? 1 : 0; // FIXME + + // after upload we have to set some parameters... +#ifdef GL_TEXTURE_MAX_LEVEL + /* FIXME + if (dds_miplevels >= 1 && !mipcomplete) + { + // need to set GL_TEXTURE_MAX_LEVEL + qglTexParameteri(gltexturetypeenums[glt->texturetype], GL_TEXTURE_MAX_LEVEL, dds_miplevels - 1);CHECKGLERROR + } + */ +#endif + GL_SetupTextureParameters(glt->flags, glt->textype->textype, glt->texturetype); + + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR + Mem_Free(dds); + return (rtexture_t *)glt; + } + else + { + qglBindTexture(gltexturetypeenums[glt->texturetype], oldbindtexnum);CHECKGLERROR + Mem_Free(dds); + Con_DPrintf("KTX texture %s failed to load: %x\n", vabuf, ktxerror); + return NULL; + } + } +#endif // __ANDROID__ + dds = FS_LoadFile(filename, tempmempool, true, &ddsfilesize); ddssize = ddsfilesize; diff --git a/glquake.h b/glquake.h index f925b83f..1505cef6 100644 --- a/glquake.h +++ b/glquake.h @@ -1100,6 +1100,15 @@ extern void (GLAPIENTRY *qglPointSize)(GLfloat size); #define GL_UNSIGNED_INT_24_8_EXT 0x84FA #define GL_DEPTH24_STENCIL8_EXT 0x88F0 +//GL_EXT_blend_func_separate +#ifndef GL_BLEND_DST_RGB +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#endif +extern void (GLAPIENTRY *qglBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + #endif #define DEBUGGL @@ -1123,7 +1132,7 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber); //#define qglIsQueryARB glIsQuery #define qglIsRenderbufferEXT glIsRenderbuffer //#define qglUnmapBufferARB glUnmapBuffer -#define qglCheckFramebufferStatusEXT glCheckFramebufferStatus +#define qglCheckFramebufferStatus glCheckFramebufferStatus #define qglGetError glGetError #define qglCreateProgram glCreateProgram #define qglCreateShader glCreateShader @@ -1142,11 +1151,12 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber); #define qglBindAttribLocation glBindAttribLocation //#define qglBindFragDataLocation glBindFragDataLocation #define qglBindBufferARB glBindBuffer -#define qglBindFramebufferEXT glBindFramebuffer -#define qglBindRenderbufferEXT glBindRenderbuffer +#define qglBindFramebuffer glBindFramebuffer +#define qglBindRenderbuffer glBindRenderbuffer #define qglBindTexture glBindTexture #define qglBlendEquationEXT glBlendEquation #define qglBlendFunc glBlendFunc +#define qglBlendFuncSeparate glBlendFuncSeparate #define qglBufferDataARB glBufferData #define qglBufferSubDataARB glBufferSubData #define qglClear glClear @@ -1168,11 +1178,11 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber); #define qglCopyTexSubImage3D glCopyTexSubImage3D #define qglCullFace glCullFace #define qglDeleteBuffersARB glDeleteBuffers -#define qglDeleteFramebuffersEXT glDeleteFramebuffers +#define qglDeleteFramebuffers glDeleteFramebuffers #define qglDeleteProgram glDeleteProgram #define qglDeleteShader glDeleteShader //#define qglDeleteQueriesARB glDeleteQueries -#define qglDeleteRenderbuffersEXT glDeleteRenderbuffers +#define qglDeleteRenderbuffers glDeleteRenderbuffers #define qglDeleteTextures glDeleteTextures #define qglDepthFunc glDepthFunc #define qglDepthMask glDepthMask @@ -1197,9 +1207,9 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber); #define qglFramebufferTexture2D glFramebufferTexture2D #define qglFramebufferTexture3DEXT glFramebufferTexture3D #define qglGenBuffersARB glGenBuffers -#define qglGenFramebuffersEXT glGenFramebuffers +#define qglGenFramebuffers glGenFramebuffers //#define qglGenQueriesARB glGenQueries -#define qglGenRenderbuffersEXT glGenRenderbuffers +#define qglGenRenderbuffers glGenRenderbuffers #define qglGenTextures glGenTextures #define qglGenerateMipmapEXT glGenerateMipmap #define qglGetActiveAttrib glGetActiveAttrib @@ -1245,7 +1255,7 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber); //#define qglPolygonStipple glPolygonStipple #define qglReadBuffer glReadBuffer #define qglReadPixels glReadPixels -#define qglRenderbufferStorageEXT glRenderbufferStorage +#define qglRenderbufferStorage glRenderbufferStorage #define qglScissor glScissor #define qglShaderSource glShaderSource #define qglStencilFunc glStencilFunc @@ -1338,4 +1348,3 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber); #endif #endif - diff --git a/image_png.c b/image_png.c index 04419bd0..96fb4955 100644 --- a/image_png.c +++ b/image_png.c @@ -516,6 +516,8 @@ qboolean PNG_SaveImage_preflipped (const char *filename, int width, int height, if (setjmp((_JBTYPE *)png)) #elif defined(MACOSX) || defined(WIN32) if (setjmp((int *)png)) +#elif defined(__ANDROID__) + if (setjmp((long *)png)) #else if (setjmp((__jmp_buf_tag *)png)) #endif diff --git a/jpeg.c b/jpeg.c index 4b276d2e..8d32adcb 100644 --- a/jpeg.c +++ b/jpeg.c @@ -515,6 +515,12 @@ qboolean JPEG_OpenLibrary (void) jpeg_tried_loading = true; +#ifdef __ANDROID__ + // loading the native Android libjpeg.so causes crashes + Con_Printf("Not opening libjpeg.so dynamically on Android - use LINK_TO_LIBJPEG instead if it is needed.\n"); + return false; +#endif + // Load the DLL return Sys_LoadLibrary (dllnames, &jpeg_dll, jpegfuncs); #endif diff --git a/quakedef.h b/quakedef.h index 6bd5ddfa..0edfd695 100644 --- a/quakedef.h +++ b/quakedef.h @@ -417,7 +417,23 @@ extern cvar_t sessionid; DP_OS_STR - "identifier" of the OS, more suited for code to use DP_ARCH_STR - "identifier" of the processor architecture */ -#if defined(__linux__) +#if defined(__ANDROID__) /* must come first because it also defines linux */ +# define DP_OS_NAME "Android" +# define DP_OS_STR "android" +# define USE_GLES2 1 +# define LINK_TO_ZLIB 1 +# define LINK_TO_LIBVORBIS 1 +# define DP_MOBILETOUCH 1 +# define DP_FREETYPE_STATIC 1 +#elif defined(TARGET_OS_IPHONE) /* must come first because it also defines MACOSX */ +# define DP_OS_NAME "iPhoneOS" +# define DP_OS_STR "iphoneos" +# define USE_GLES2 1 +# define LINK_TO_ZLIB 1 +# define LINK_TO_LIBVORBIS 1 +# define DP_MOBILETOUCH 1 +# define DP_FREETYPE_STATIC 1 +#elif defined(__linux__) # define DP_OS_NAME "Linux" # define DP_OS_STR "linux" #elif defined(_WIN64) @@ -435,10 +451,6 @@ extern cvar_t sessionid; #elif defined(__OpenBSD__) # define DP_OS_NAME "OpenBSD" # define DP_OS_STR "openbsd" -#elif defined(TARGET_OS_IPHONE) -# define DP_OS_NAME "iPhoneOS" -# define DP_OS_STR "iphoneos" -# define USE_GLES2 1 #elif defined(MACOSX) # define DP_OS_NAME "Mac OS X" # define DP_OS_STR "osx" diff --git a/r_shadow.c b/r_shadow.c index 0c0b7722..c183be35 100644 --- a/r_shadow.c +++ b/r_shadow.c @@ -5078,7 +5078,9 @@ static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequer { float zdist; vec3_t centerorigin; +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) float vertex3f[12]; +#endif // if it's too close, skip it if (VectorLength(rtlight->currentcolor) < (1.0f / 256.0f)) return; @@ -5099,7 +5101,7 @@ static void R_BeginCoronaQuery(rtlight_t *rtlight, float scale, qboolean usequer case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: -#ifdef GL_SAMPLES_PASSED_ARB +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) CHECKGLERROR // NOTE: GL_DEPTH_TEST must be enabled or ATI won't count samples, so use GL_DepthFunc instead qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, rtlight->corona_queryindex_allpixels); @@ -5150,7 +5152,7 @@ static void R_DrawCorona(rtlight_t *rtlight, float cscale, float scale) case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: -#ifdef GL_SAMPLES_PASSED_ARB +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) CHECKGLERROR qglGetQueryObjectivARB(rtlight->corona_queryindex_visiblepixels, GL_QUERY_RESULT_ARB, &visiblepixels); qglGetQueryObjectivARB(rtlight->corona_queryindex_allpixels, GL_QUERY_RESULT_ARB, &allpixels); @@ -5229,7 +5231,7 @@ void R_Shadow_DrawCoronas(void) case RENDERPATH_GLES1: case RENDERPATH_GLES2: usequery = vid.support.arb_occlusion_query && r_coronas_occlusionquery.integer; -#ifdef GL_SAMPLES_PASSED_ARB +#if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2) if (usequery) { GL_ColorMask(0,0,0,0); diff --git a/r_textures.h b/r_textures.h index e9c9aaba..e06f035d 100644 --- a/r_textures.h +++ b/r_textures.h @@ -56,6 +56,9 @@ typedef enum textype_e // 4x4 block compressed 15bit color plus 8bit alpha (8 bits per pixel) TEXTYPE_DXT5, + // default compressed type for GLES2 + TEXTYPE_ETC1, + // 8bit paletted in sRGB colorspace TEXTYPE_SRGB_PALETTE, // 32bit RGBA in sRGB colorspace diff --git a/screen.h b/screen.h index 68a2998d..4d473244 100644 --- a/screen.h +++ b/screen.h @@ -74,13 +74,18 @@ extern int r_stereo_side; typedef struct scr_touchscreenarea_s { const char *pic; + const char *text; float rect[4]; + float textheight; float active; + float activealpha; + float inactivealpha; } scr_touchscreenarea_t; +// FIXME: should resize dynamically? extern int scr_numtouchscreenareas; -extern scr_touchscreenarea_t scr_touchscreenareas[16]; +extern scr_touchscreenarea_t scr_touchscreenareas[128]; #endif diff --git a/snd_modplug.c b/snd_modplug.c index 6dc3fce2..52a152a3 100644 --- a/snd_modplug.c +++ b/snd_modplug.c @@ -163,6 +163,11 @@ qboolean ModPlug_OpenLibrary (void) if (COM_CheckParm("-nomodplug")) return false; +#ifdef __ANDROID__ + Con_Print("Warning: no modplug support in Android yet.\n"); + return false; +#endif + // Load the DLLs // We need to load both by hand because some OSes seem to not load // the modplug DLL automatically when loading the modplugFile DLL diff --git a/sys_sdl.c b/sys_sdl.c index 13be11ea..cd769979 100644 --- a/sys_sdl.c +++ b/sys_sdl.c @@ -12,6 +12,14 @@ #include #endif +#ifdef __ANDROID__ +#include + +#ifndef FNDELAY +#define FNDELAY O_NDELAY +#endif +#endif + #include #include @@ -24,6 +32,9 @@ void Sys_Shutdown (void) { +#ifdef __ANDROID__ + Sys_AllowProfiling(false); +#endif #ifndef WIN32 fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~FNDELAY); #endif @@ -55,6 +66,12 @@ void Sys_Error (const char *error, ...) static int outfd = 1; void Sys_PrintToTerminal(const char *text) { +#ifdef __ANDROID__ + if (developer.integer > 0) + { + __android_log_write(ANDROID_LOG_DEBUG, com_argv[0], text); + } +#else if(outfd < 0) return; #ifdef FNDELAY @@ -79,6 +96,7 @@ void Sys_PrintToTerminal(const char *text) } #endif //fprintf(stdout, "%s", text); +#endif } char *Sys_ConsoleInput(void) @@ -178,6 +196,10 @@ int main (int argc, char *argv[]) { signal(SIGFPE, SIG_IGN); +#ifdef __ANDROID__ + Sys_AllowProfiling(true); +#endif + com_argc = argc; com_argv = (const char **)argv; Sys_ProvideSelfFD(); diff --git a/sys_shared.c b/sys_shared.c index 10f5a60e..970d9204 100644 --- a/sys_shared.c +++ b/sys_shared.c @@ -5,6 +5,7 @@ #endif #include "quakedef.h" +#include "thread.h" #define SUPPORTDLL @@ -43,6 +44,10 @@ char *Sys_TimeString(const char *timeformat) extern qboolean host_shuttingdown; void Sys_Quit (int returnvalue) { + // Unlock mutexes because the quit command may jump directly here, causing a deadlock + Cbuf_UnlockThreadMutex(); + SV_UnlockThreadMutex(); + if (COM_CheckParm("-profilegameonly")) Sys_AllowProfiling(false); host_shuttingdown = true; @@ -50,16 +55,22 @@ void Sys_Quit (int returnvalue) exit(returnvalue); } -#if defined(__linux__) || defined(__FreeBSD__) #ifdef __cplusplus extern "C" #endif -int moncontrol(int); -#endif - void Sys_AllowProfiling(qboolean enable) { -#if defined(__linux__) || defined(__FreeBSD__) +#ifdef __ANDROID__ +#ifdef USE_PROFILER + extern void monstartup(const char *libname); + extern void moncleanup(void); + if (enable) + monstartup("libmain.so"); + else + moncleanup(); +#endif +#elif defined(__linux__) || defined(__FreeBSD__) + extern int moncontrol(int); moncontrol(enable); #endif } diff --git a/vid.h b/vid.h index 1b960d4a..650d3223 100644 --- a/vid.h +++ b/vid.h @@ -64,6 +64,7 @@ typedef struct viddef_support_s qboolean ati_separate_stencil; qboolean ext_blend_minmax; qboolean ext_blend_subtract; + qboolean ext_blend_func_separate; qboolean ext_draw_range_elements; qboolean ext_framebuffer_object; qboolean ext_packed_depth_stencil; @@ -187,10 +188,15 @@ extern cvar_t vid_bitsperpixel; extern cvar_t vid_samples; extern cvar_t vid_refreshrate; extern cvar_t vid_userefreshrate; +extern cvar_t vid_touchscreen_density; +extern cvar_t vid_touchscreen_xdpi; +extern cvar_t vid_touchscreen_ydpi; extern cvar_t vid_vsync; extern cvar_t vid_mouse; extern cvar_t vid_grabkeyboard; extern cvar_t vid_touchscreen; +extern cvar_t vid_touchscreen_showkeyboard; +extern cvar_t vid_touchscreen_supportshowkeyboard; extern cvar_t vid_stick_mouse; extern cvar_t vid_resizable; extern cvar_t vid_minwidth; @@ -270,6 +276,10 @@ void VID_UpdateGamma(qboolean force, int rampsize); // (called from various shutdown/deactivation functions) void VID_RestoreSystemGamma(void); +qboolean VID_HasScreenKeyboardSupport(void); +void VID_ShowKeyboard(qboolean show); +qboolean VID_ShowingKeyboard(void); + void VID_SetMouse (qboolean fullscreengrab, qboolean relative, qboolean hidecursor); void VID_Finish (void); diff --git a/vid_sdl.c b/vid_sdl.c index 0aba7111..ab754107 100644 --- a/vid_sdl.c +++ b/vid_sdl.c @@ -74,6 +74,9 @@ static qboolean vid_isfullscreen; static qboolean vid_usingvsync = false; #endif static SDL_Joystick *vid_sdljoystick = NULL; +// GAME_STEELSTORM specific +static cvar_t *steelstorm_showing_map = NULL; // detect but do not create the cvar +static cvar_t *steelstorm_showing_mousecursor = NULL; // detect but do not create the cvar static int win_half_width = 50; static int win_half_height = 50; @@ -337,6 +340,7 @@ static int MapKey( unsigned int sdlkey ) case SDLK_RALT: return K_ALT; // case SDLK_RGUI: return K_RGUI; // case SDLK_MODE: return K_MODE; +#if SDL_MAJOR_VERSION != 1 // case SDLK_AUDIONEXT: return K_AUDIONEXT; // case SDLK_AUDIOPREV: return K_AUDIOPREV; // case SDLK_AUDIOSTOP: return K_AUDIOSTOP; @@ -347,13 +351,13 @@ static int MapKey( unsigned int sdlkey ) // case SDLK_MAIL: return K_MAIL; // case SDLK_CALCULATOR: return K_CALCULATOR; // case SDLK_COMPUTER: return K_COMPUTER; -// case SDLK_AC_SEARCH: return K_AC_SEARCH; -// case SDLK_AC_HOME: return K_AC_HOME; -// case SDLK_AC_BACK: return K_AC_BACK; -// case SDLK_AC_FORWARD: return K_AC_FORWARD; -// case SDLK_AC_STOP: return K_AC_STOP; -// case SDLK_AC_REFRESH: return K_AC_REFRESH; -// case SDLK_AC_BOOKMARKS: return K_AC_BOOKMARKS; +// case SDLK_AC_SEARCH: return K_AC_SEARCH; // Android button +// case SDLK_AC_HOME: return K_AC_HOME; // Android button + case SDLK_AC_BACK: return K_ESCAPE; // Android button +// case SDLK_AC_FORWARD: return K_AC_FORWARD; // Android button +// case SDLK_AC_STOP: return K_AC_STOP; // Android button +// case SDLK_AC_REFRESH: return K_AC_REFRESH; // Android button +// case SDLK_AC_BOOKMARKS: return K_AC_BOOKMARKS; // Android button // case SDLK_BRIGHTNESSDOWN: return K_BRIGHTNESSDOWN; // case SDLK_BRIGHTNESSUP: return K_BRIGHTNESSUP; // case SDLK_DISPLAYSWITCH: return K_DISPLAYSWITCH; @@ -362,42 +366,50 @@ static int MapKey( unsigned int sdlkey ) // case SDLK_KBDILLUMUP: return K_KBDILLUMUP; // case SDLK_EJECT: return K_EJECT; // case SDLK_SLEEP: return K_SLEEP; +#endif } } -#ifdef __IPHONEOS__ -int SDL_iPhoneKeyboardShow(SDL_Window * window); // reveals the onscreen keyboard. Returns 0 on success and -1 on error. -int SDL_iPhoneKeyboardHide(SDL_Window * window); // hides the onscreen keyboard. Returns 0 on success and -1 on error. -SDL_bool SDL_iPhoneKeyboardIsShown(SDL_Window * window); // returns whether or not the onscreen keyboard is currently visible. -int SDL_iPhoneKeyboardToggle(SDL_Window * window); // toggles the visibility of the onscreen keyboard. Returns 0 on success and -1 on error. +qboolean VID_HasScreenKeyboardSupport(void) +{ +#if SDL_MAJOR_VERSION != 1 + return SDL_HasScreenKeyboardSupport() != SDL_FALSE; +#else + return false; #endif +} -static void VID_ShowKeyboard(qboolean show) +void VID_ShowKeyboard(qboolean show) { -#ifdef __IPHONEOS__ +#if SDL_MAJOR_VERSION != 1 + if (!SDL_HasScreenKeyboardSupport()) + return; + if (show) { - if (!SDL_iPhoneKeyboardIsShown(window)) - SDL_iPhoneKeyboardShow(window); + if (!SDL_IsTextInputActive()) + SDL_StartTextInput(); } else { - if (SDL_iPhoneKeyboardIsShown(window)) - SDL_iPhoneKeyboardHide(window); + if (SDL_IsTextInputActive()) + SDL_StopTextInput(); } #endif } -#ifdef __IPHONEOS__ qboolean VID_ShowingKeyboard(void) { - return SDL_iPhoneKeyboardIsShown(window); -} +#if SDL_MAJOR_VERSION != 1 + return SDL_IsTextInputActive() != 0; +#else + return false; #endif +} void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecursor) { -#ifndef __IPHONEOS__ +#ifndef DP_MOBILETOUCH #ifdef MACOSX if(relative) if(vid_usingmouse && (vid_usingnoaccel != !!apple_mouse_noaccel.integer)) @@ -475,50 +487,96 @@ void VID_SetMouse(qboolean fullscreengrab, qboolean relative, qboolean hidecurso } // multitouch[10][] represents the mouse pointer -// X and Y coordinates are 0-32767 as per SDL spec +// multitouch[][0]: finger active +// multitouch[][1]: Y +// multitouch[][2]: Y +// X and Y coordinates are 0-1. #define MAXFINGERS 11 -int multitouch[MAXFINGERS][3]; +float multitouch[MAXFINGERS][3]; -static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float *resultmove, qboolean *resultbutton, keynum_t key) +// this one stores how many areas this finger has touched +int multitouchs[MAXFINGERS]; + +// modified heavily by ELUAN +static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth, float pheight, const char *icon, float textheight, const char *text, float *resultmove, qboolean *resultbutton, keynum_t key, const char *typedtext, float deadzone, float oversizepixels_x, float oversizepixels_y, qboolean iamexclusive) { int finger; float fx, fy, fwidth, fheight; + float overfx, overfy, overfwidth, overfheight; float rel[3]; + float sqsum; qboolean button = false; VectorClear(rel); if (pwidth > 0 && pheight > 0) -#ifdef __IPHONEOS__ - if (!VID_ShowingKeyboard()) -#endif { if (corner & 1) px += vid_conwidth.value; if (corner & 2) py += vid_conheight.value; if (corner & 4) px += vid_conwidth.value * 0.5f; if (corner & 8) py += vid_conheight.value * 0.5f; if (corner & 16) {px *= vid_conwidth.value * (1.0f / 640.0f);py *= vid_conheight.value * (1.0f / 480.0f);pwidth *= vid_conwidth.value * (1.0f / 640.0f);pheight *= vid_conheight.value * (1.0f / 480.0f);} - fx = px * 32768.0f / vid_conwidth.value; - fy = py * 32768.0f / vid_conheight.value; - fwidth = pwidth * 32768.0f / vid_conwidth.value; - fheight = pheight * 32768.0f / vid_conheight.value; + fx = px / vid_conwidth.value; + fy = py / vid_conheight.value; + fwidth = pwidth / vid_conwidth.value; + fheight = pheight / vid_conheight.value; + + // try to prevent oversizepixels_* from interfering with the iamexclusive cvar by not letting we start controlling from too far of the actual touch area (areas without resultbuttons should NEVER have the oversizepixels_* parameters set to anything other than 0) + if (resultbutton) + if (!(*resultbutton)) + { + oversizepixels_x *= 0.2; + oversizepixels_y *= 0.2; + } + + oversizepixels_x /= vid_conwidth.value; + oversizepixels_y /= vid_conheight.value; + + overfx = fx - oversizepixels_x; + overfy = fy - oversizepixels_y; + overfwidth = fwidth + 2*oversizepixels_x; + overfheight = fheight + 2*oversizepixels_y; + for (finger = 0;finger < MAXFINGERS;finger++) { - if (multitouch[finger][0] && multitouch[finger][1] >= fx && multitouch[finger][2] >= fy && multitouch[finger][1] < fx + fwidth && multitouch[finger][2] < fy + fheight) + if (multitouchs[finger] && iamexclusive) // for this to work correctly, you must call touch areas in order of highest to lowest priority + continue; + + if (multitouch[finger][0] && multitouch[finger][1] >= overfx && multitouch[finger][2] >= overfy && multitouch[finger][1] < overfx + overfwidth && multitouch[finger][2] < overfy + overfheight) { - rel[0] = (multitouch[finger][1] - (fx + 0.5f * fwidth)) * (2.0f / fwidth); - rel[1] = (multitouch[finger][2] - (fy + 0.5f * fheight)) * (2.0f / fheight); + multitouchs[finger]++; + + rel[0] = bound(-1, (multitouch[finger][1] - (fx + 0.5f * fwidth)) * (2.0f / fwidth), 1); + rel[1] = bound(-1, (multitouch[finger][2] - (fy + 0.5f * fheight)) * (2.0f / fheight), 1); rel[2] = 0; + + sqsum = rel[0]*rel[0] + rel[1]*rel[1]; + // 2d deadzone + if (sqsum < deadzone*deadzone) + { + rel[0] = 0; + rel[1] = 0; + } + else if (sqsum > 1) + { + // ignore the third component + Vector2Normalize2(rel, rel); + } button = true; break; } } - if (scr_numtouchscreenareas < 16) + if (scr_numtouchscreenareas < 128) { scr_touchscreenareas[scr_numtouchscreenareas].pic = icon; + scr_touchscreenareas[scr_numtouchscreenareas].text = text; + scr_touchscreenareas[scr_numtouchscreenareas].textheight = textheight; scr_touchscreenareas[scr_numtouchscreenareas].rect[0] = px; scr_touchscreenareas[scr_numtouchscreenareas].rect[1] = py; scr_touchscreenareas[scr_numtouchscreenareas].rect[2] = pwidth; scr_touchscreenareas[scr_numtouchscreenareas].rect[3] = pheight; scr_touchscreenareas[scr_numtouchscreenareas].active = button; + // the pics may have alpha too. + scr_touchscreenareas[scr_numtouchscreenareas].activealpha = 1.f; + scr_touchscreenareas[scr_numtouchscreenareas].inactivealpha = 0.95f; scr_numtouchscreenareas++; } } @@ -531,13 +589,146 @@ static qboolean VID_TouchscreenArea(int corner, float px, float py, float pwidth } if (resultbutton) { - if (*resultbutton != button && (int)key > 0) - Key_Event(key, 0, button); + if (*resultbutton != button) + { + if ((int)key > 0) + Key_Event(key, 0, button); + if (typedtext && typedtext[0] && !*resultbutton) + { + // FIXME: implement UTF8 support - nothing actually specifies a UTF8 string here yet, but should support it... + int i; + for (i = 0;typedtext[i];i++) + { + Key_Event(K_TEXT, typedtext[i], true); + Key_Event(K_TEXT, typedtext[i], false); + } + } + } *resultbutton = button; } return button; } +// ELUAN: +// not reentrant, but we only need one mouse cursor anyway... +static void VID_TouchscreenCursor(float px, float py, float pwidth, float pheight, qboolean *resultbutton, keynum_t key) +{ + int finger; + float fx, fy, fwidth, fheight; + qboolean button = false; + static int cursorfinger = -1; + static int cursorfreemovement = false; + static int canclick = false; + static int clickxy[2]; + static int relclickxy[2]; + static double clickrealtime = 0; + + if (steelstorm_showing_mousecursor && steelstorm_showing_mousecursor->integer) + if (pwidth > 0 && pheight > 0) + { + fx = px / vid_conwidth.value; + fy = py / vid_conheight.value; + fwidth = pwidth / vid_conwidth.value; + fheight = pheight / vid_conheight.value; + for (finger = 0;finger < MAXFINGERS;finger++) + { + if (multitouch[finger][0] && multitouch[finger][1] >= fx && multitouch[finger][2] >= fy && multitouch[finger][1] < fx + fwidth && multitouch[finger][2] < fy + fheight) + { + if (cursorfinger == -1) + { + clickxy[0] = multitouch[finger][1] * vid_width.value - 0.5f * pwidth; + clickxy[1] = multitouch[finger][2] * vid_height.value - 0.5f * pheight; + relclickxy[0] = (multitouch[finger][1] - fx) * vid_width.value - 0.5f * pwidth; + relclickxy[1] = (multitouch[finger][2] - fy) * vid_height.value - 0.5f * pheight; + } + cursorfinger = finger; + button = true; + canclick = true; + cursorfreemovement = false; + break; + } + } + if (scr_numtouchscreenareas < 128) + { + if (clickrealtime + 1 > realtime) + { + scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_click.tga"; + } + else if (button) + { + scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_touch.tga"; + } + else + { + switch ((int)realtime * 10 % 20) + { + case 0: + scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_touch.tga"; + break; + default: + scr_touchscreenareas[scr_numtouchscreenareas].pic = "gfx/gui/touch_puck_cur_idle.tga"; + } + } + scr_touchscreenareas[scr_numtouchscreenareas].text = ""; + scr_touchscreenareas[scr_numtouchscreenareas].textheight = 0; + scr_touchscreenareas[scr_numtouchscreenareas].rect[0] = px; + scr_touchscreenareas[scr_numtouchscreenareas].rect[1] = py; + scr_touchscreenareas[scr_numtouchscreenareas].rect[2] = pwidth; + scr_touchscreenareas[scr_numtouchscreenareas].rect[3] = pheight; + scr_touchscreenareas[scr_numtouchscreenareas].active = button; + scr_touchscreenareas[scr_numtouchscreenareas].activealpha = 1.0f; + scr_touchscreenareas[scr_numtouchscreenareas].inactivealpha = 1.0f; + scr_numtouchscreenareas++; + } + } + + if (cursorfinger != -1) + { + if (multitouch[cursorfinger][0]) + { + if (multitouch[cursorfinger][1] * vid_width.value - 0.5f * pwidth < clickxy[0] - 1 || + multitouch[cursorfinger][1] * vid_width.value - 0.5f * pwidth > clickxy[0] + 1 || + multitouch[cursorfinger][2] * vid_height.value - 0.5f * pheight< clickxy[1] - 1 || + multitouch[cursorfinger][2] * vid_height.value - 0.5f * pheight> clickxy[1] + 1) // finger drifted more than the allowed amount + { + cursorfreemovement = true; + } + if (cursorfreemovement) + { + // in_windowmouse_x* is in screen resolution coordinates, not console resolution + in_windowmouse_x = multitouch[cursorfinger][1] * vid_width.value - 0.5f * pwidth - relclickxy[0]; + in_windowmouse_y = multitouch[cursorfinger][2] * vid_height.value - 0.5f * pheight - relclickxy[1]; + } + } + else + { + cursorfinger = -1; + } + } + + if (resultbutton) + { + if (/**resultbutton != button && */(int)key > 0) + { + if (!button && !cursorfreemovement && canclick) + { + Key_Event(key, 0, true); + canclick = false; + clickrealtime = realtime; + } + + // SS:BR can't qc can't cope with presses and releases on the same frame + if (clickrealtime && clickrealtime + 0.1 < realtime) + { + Key_Event(key, 0, false); + clickrealtime = 0; + } + } + + *resultbutton = button; + } +} + void VID_BuildJoyState(vid_joystate_t *joystate) { VID_Shared_BuildJoyState_Begin(joystate); @@ -559,10 +750,233 @@ void VID_BuildJoyState(vid_joystate_t *joystate) VID_Shared_BuildJoyState_Finish(joystate); } +// clear every touch screen area, except the one with button[skip] +#define Vid_ClearAllTouchscreenAreas(skip) \ + if (skip != 0) \ + VID_TouchscreenCursor(0, 0, 0, 0, &buttons[0], K_MOUSE1); \ + if (skip != 1) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[1], K_MOUSE4, NULL, 0, 0, 0, false); \ + if (skip != 2) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, aim, &buttons[2], K_MOUSE5, NULL, 0, 0, 0, false); \ + if (skip != 3) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[3], K_SHIFT, NULL, 0, 0, 0, false); \ + if (skip != 4) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, false); \ + if (skip != 9) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[9], K_MOUSE3, NULL, 0, 0, 0, false); \ + if (skip != 10) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[10], (keynum_t)'m', NULL, 0, 0, 0, false); \ + if (skip != 11) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[11], (keynum_t)'b', NULL, 0, 0, 0, false); \ + if (skip != 12) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[12], 'q', NULL, 0, 0, 0, false); \ + if (skip != 13) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, false); \ + if (skip != 14) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, false); \ + if (skip != 15) \ + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, false); \ + ///////////////////// // Movement handling //// +static void IN_Move_TouchScreen_SteelStorm(void) +{ + // ELUAN + int i, numfingers; + float xscale, yscale; + float move[3], aim[3]; + static qboolean oldbuttons[128]; + static qboolean buttons[128]; + static keydest_t oldkeydest; + keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest; + memcpy(oldbuttons, buttons, sizeof(oldbuttons)); + memset(multitouchs, 0, sizeof(multitouchs)); + + for (i = 0, numfingers = 0; i < MAXFINGERS - 1; i++) + if (multitouch[i][0]) + numfingers++; + + /* + Enable this to use a mouse as a touch device (it may conflict with the iamexclusive parameter if a finger is also reported as a mouse at the same location + if (numfingers == 1) + { + multitouch[MAXFINGERS-1][0] = SDL_GetMouseState(&x, &y) ? 11 : 0; + multitouch[MAXFINGERS-1][1] = (float)x / vid.width; + multitouch[MAXFINGERS-1][2] = (float)y / vid.height; + } + else + { + // disable it so it doesn't get stuck, because SDL seems to stop updating it if there are more than 1 finger on screen + multitouch[MAXFINGERS-1][0] = 0; + }*/ + + if (oldkeydest != keydest) + { + switch(keydest) + { + case key_game: VID_ShowKeyboard(false);break; + case key_console: VID_ShowKeyboard(true);break; + case key_message: VID_ShowKeyboard(true);break; + default: break; /* qc extensions control the other cases */ + } + } + oldkeydest = keydest; + // TODO: make touchscreen areas controlled by a config file or the VMs. THIS IS A MESS! + // TODO: can't just clear buttons[] when entering a new keydest, some keys would remain pressed + // SS:BR menuqc has many peculiarities, including that it can't accept more than one command per frame and pressing and releasing on the same frame + + // Tuned for the SGS3, use it's value as a base. CLEAN THIS. + xscale = vid_touchscreen_density.value / 2.0f; + yscale = vid_touchscreen_density.value / 2.0f; + switch(keydest) + { + case key_console: + Vid_ClearAllTouchscreenAreas(14); + VID_TouchscreenArea( 0, 0, 160, 64, 64, "gfx/gui/touch_menu_button.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, false); + break; + case key_game: + if (steelstorm_showing_map && steelstorm_showing_map->integer) // FIXME: another hack to be removed when touchscreen areas go to QC + { + VID_TouchscreenArea( 0, 0, 0, vid_conwidth.value, vid_conheight.value, NULL , 0.0f, NULL, NULL, &buttons[10], (keynum_t)'m', NULL, 0, 0, 0, false); + Vid_ClearAllTouchscreenAreas(10); + } + else if (steelstorm_showing_mousecursor && steelstorm_showing_mousecursor->integer) + { + // in_windowmouse_x* is in screen resolution coordinates, not console resolution + VID_TouchscreenCursor((float)in_windowmouse_x/vid_width.value*vid_conwidth.value, (float)in_windowmouse_y/vid_height.value*vid_conheight.value, 192*xscale, 192*yscale, &buttons[0], K_MOUSE1); + Vid_ClearAllTouchscreenAreas(0); + } + else + { + VID_TouchscreenCursor(0, 0, 0, 0, &buttons[0], K_MOUSE1); + + VID_TouchscreenArea( 2,16*xscale,-240*yscale, 224*xscale, 224*yscale, "gfx/gui/touch_l_thumb_dpad.tga", 0.0f, NULL, move, &buttons[1], 0, NULL, 0.15, 112*xscale, 112*yscale, false); + + VID_TouchscreenArea( 3,-240*xscale,-160*yscale, 224*xscale, 128*yscale, "gfx/gui/touch_r_thumb_turn_n_shoot.tga" , 0.0f, NULL, NULL, 0, 0, NULL, 0, 56*xscale, 0, false); + VID_TouchscreenArea( 3,-240*xscale,-256*yscale, 224*xscale, 224*yscale, NULL , 0.0f, NULL, aim, &buttons[2], 0, NULL, 0.2, 56*xscale, 0, false); + + VID_TouchscreenArea( 2, (vid_conwidth.value / 2) - 128,-80, 256, 80, NULL, 0.0f, NULL, NULL, &buttons[3], K_SHIFT, NULL, 0, 0, 0, true); + + VID_TouchscreenArea( 3,-240*xscale,-256*yscale, 224*xscale, 64*yscale, "gfx/gui/touch_secondary_slide.tga", 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 56*xscale, 0, false); + VID_TouchscreenArea( 3,-240*xscale,-256*yscale, 224*xscale, 160*yscale, NULL , 0.0f, NULL, NULL, &buttons[9], K_MOUSE3, NULL, 0.2, 56*xscale, 0, false); + + VID_TouchscreenArea( 1,-100, 0, 100, 100, NULL , 0.0f, NULL, NULL, &buttons[10], (keynum_t)'m', NULL, 0, 0, 0, true); + VID_TouchscreenArea( 1,-100, 120, 100, 100, NULL , 0.0f, NULL, NULL, &buttons[11], (keynum_t)'b', NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[12], 'q', NULL, 0, 0, 0, true); + if (developer.integer) + VID_TouchscreenArea( 0, 0, 96, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true); + else + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, false); + VID_TouchscreenArea( 0, 0, 160, 64, 64, "gfx/gui/touch_menu_button.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true); + switch(cl.activeweapon) + { + case 14: + VID_TouchscreenArea( 2, 16*xscale,-320*yscale, 224*xscale, 64*yscale, "gfx/gui/touch_booster.tga" , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, true); + break; + case 12: + VID_TouchscreenArea( 2, 16*xscale,-320*yscale, 224*xscale, 64*yscale, "gfx/gui/touch_shockwave.tga" , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, true); + break; + default: + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], K_SPACE, NULL, 0, 0, 0, false); + } + } + break; + default: + if (!steelstorm_showing_mousecursor || !steelstorm_showing_mousecursor->integer) + { + Vid_ClearAllTouchscreenAreas(14); + // this way we can skip cutscenes + VID_TouchscreenArea( 0, 0, 0, vid_conwidth.value, vid_conheight.value, NULL , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, false); + } + else + { + // in_windowmouse_x* is in screen resolution coordinates, not console resolution + VID_TouchscreenCursor((float)in_windowmouse_x/vid_width.value*vid_conwidth.value, (float)in_windowmouse_y/vid_height.value*vid_conheight.value, 192*xscale, 192*yscale, &buttons[0], K_MOUSE1); + Vid_ClearAllTouchscreenAreas(0); + } + break; + } + + if (VID_ShowingKeyboard() && (float)in_windowmouse_y > vid_height.value / 2 - 10) + in_windowmouse_y = 128; + + cl.cmd.forwardmove -= move[1] * cl_forwardspeed.value; + cl.cmd.sidemove += move[0] * cl_sidespeed.value; + cl.viewangles[0] += aim[1] * cl_pitchspeed.value * cl.realframetime; + cl.viewangles[1] -= aim[0] * cl_yawspeed.value * cl.realframetime; +} + +static void IN_Move_TouchScreen_Quake(void) +{ + int x, y; + float move[3], aim[3], click[3]; + static qboolean oldbuttons[128]; + static qboolean buttons[128]; + keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest; + memcpy(oldbuttons, buttons, sizeof(oldbuttons)); + memset(multitouchs, 0, sizeof(multitouchs)); + + // simple quake controls + multitouch[MAXFINGERS-1][0] = SDL_GetMouseState(&x, &y); + multitouch[MAXFINGERS-1][1] = x * 32768 / vid.width; + multitouch[MAXFINGERS-1][2] = y * 32768 / vid.height; + + // top of screen is toggleconsole and K_ESCAPE + switch(keydest) + { + case key_console: + VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true); + if (!VID_ShowingKeyboard()) + { + // user entered a command, close the console now + Con_ToggleConsole_f(); + } + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[15], (keynum_t)0, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, aim, &buttons[1], K_MOUSE5, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, click,&buttons[2], K_MOUSE1, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[3], K_SPACE, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, true); + break; + case key_game: + VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 2, 0,-128, 128, 128, "gfx/touch_movebutton.tga" , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 3,-128,-128, 128, 128, "gfx/touch_aimbutton.tga" , 0.0f, NULL, aim, &buttons[1], K_MOUSE5, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 2, 0,-160, 64, 32, "gfx/touch_jumpbutton.tga" , 0.0f, NULL, NULL, &buttons[3], K_SPACE, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 3,-128,-160, 64, 32, "gfx/touch_attackbutton.tga" , 0.0f, NULL, NULL, &buttons[2], K_MOUSE1, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 3, -64,-160, 64, 32, "gfx/touch_attack2button.tga", 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, true); + buttons[15] = false; + break; + default: + VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , 0.0f, NULL, NULL, &buttons[13], (keynum_t)'`', NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , 0.0f, NULL, NULL, &buttons[14], K_ESCAPE, NULL, 0, 0, 0, true); + // in menus, an icon in the corner activates keyboard + VID_TouchscreenArea( 2, 0, -32, 32, 32, "gfx/touch_keyboard.tga" , 0.0f, NULL, NULL, &buttons[15], (keynum_t)0, NULL, 0, 0, 0, true); + if (buttons[15]) + VID_ShowKeyboard(true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, move, &buttons[0], K_MOUSE4, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, aim, &buttons[1], K_MOUSE5, NULL, 0, 0, 0, true); + VID_TouchscreenArea(16, -320,-480,640, 960, NULL , 0.0f, NULL, click,&buttons[2], K_MOUSE1, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[3], K_SPACE, NULL, 0, 0, 0, true); + VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , 0.0f, NULL, NULL, &buttons[4], K_MOUSE2, NULL, 0, 0, 0, true); + if (buttons[2]) + { + in_windowmouse_x = x; + in_windowmouse_y = y; + } + break; + } + + cl.cmd.forwardmove -= move[1] * cl_forwardspeed.value; + cl.cmd.sidemove += move[0] * cl_sidespeed.value; + cl.viewangles[0] += aim[1] * cl_pitchspeed.value * cl.realframetime; + cl.viewangles[1] -= aim[0] * cl_yawspeed.value * cl.realframetime; +} + void IN_Move( void ) { static int old_x = 0, old_y = 0; @@ -571,90 +985,18 @@ void IN_Move( void ) vid_joystate_t joystate; scr_numtouchscreenareas = 0; + if (vid_touchscreen.integer) { - float move[3], aim[3], click[3]; - static qboolean buttons[16]; - static keydest_t oldkeydest; - keydest_t keydest = (key_consoleactive & KEY_CONSOLEACTIVE_USER) ? key_console : key_dest; - multitouch[MAXFINGERS-1][0] = SDL_GetMouseState(&x, &y); - multitouch[MAXFINGERS-1][1] = x * 32768 / vid.width; - multitouch[MAXFINGERS-1][2] = y * 32768 / vid.height; - if (oldkeydest != keydest) - { - switch(keydest) - { - case key_game: VID_ShowKeyboard(false);break; - case key_console: VID_ShowKeyboard(true);break; - case key_message: VID_ShowKeyboard(true);break; - default: break; - } - } - oldkeydest = keydest; - // top of screen is toggleconsole and K_ESCAPE - switch(keydest) + switch(gamemode) { - case key_console: -#ifdef __IPHONEOS__ - VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , NULL, &buttons[13], (keynum_t)'`'); - VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , NULL, &buttons[14], K_ESCAPE); - if (!VID_ShowingKeyboard()) - { - // user entered a command, close the console now - Con_ToggleConsole_f(); - } -#endif - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[15], (keynum_t)0); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , move, &buttons[0], K_MOUSE4); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , aim, &buttons[1], K_MOUSE5); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , click,&buttons[2], K_MOUSE1); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[3], K_SPACE); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[4], K_MOUSE2); - break; - case key_game: -#ifdef __IPHONEOS__ - VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , NULL, &buttons[13], (keynum_t)'`'); - VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , NULL, &buttons[14], K_ESCAPE); -#endif - VID_TouchscreenArea( 2, 0,-128, 128, 128, "gfx/touch_movebutton.tga" , move, &buttons[0], K_MOUSE4); - VID_TouchscreenArea( 3,-128,-128, 128, 128, "gfx/touch_aimbutton.tga" , aim, &buttons[1], K_MOUSE5); - VID_TouchscreenArea( 2, 0,-160, 64, 32, "gfx/touch_jumpbutton.tga" , NULL, &buttons[3], K_SPACE); - VID_TouchscreenArea( 3,-128,-160, 64, 32, "gfx/touch_attackbutton.tga" , NULL, &buttons[2], K_MOUSE1); - VID_TouchscreenArea( 3, -64,-160, 64, 32, "gfx/touch_attack2button.tga", NULL, &buttons[4], K_MOUSE2); - buttons[15] = false; + case GAME_STEELSTORM: + IN_Move_TouchScreen_SteelStorm(); break; default: -#ifdef __IPHONEOS__ - VID_TouchscreenArea( 0, 0, 0, 64, 64, NULL , NULL, &buttons[13], (keynum_t)'`'); - VID_TouchscreenArea( 0, 64, 0, 64, 64, "gfx/touch_menu.tga" , NULL, &buttons[14], K_ESCAPE); - // in menus, an icon in the corner activates keyboard - VID_TouchscreenArea( 2, 0, -32, 32, 32, "gfx/touch_keyboard.tga" , NULL, &buttons[15], (keynum_t)0); - if (buttons[15]) - VID_ShowKeyboard(true); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , move, &buttons[0], K_MOUSE4); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , aim, &buttons[1], K_MOUSE5); - VID_TouchscreenArea(16, -320,-480,640, 960, NULL , click,&buttons[2], K_MOUSE1); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[3], K_SPACE); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[4], K_MOUSE2); - if (buttons[2]) - { - in_windowmouse_x = x; - in_windowmouse_y = y; - } -#else - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[15], (keynum_t)0); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , move, &buttons[0], K_MOUSE4); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , aim, &buttons[1], K_MOUSE5); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , click,&buttons[2], K_MOUSE1); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[3], K_SPACE); - VID_TouchscreenArea( 0, 0, 0, 0, 0, NULL , NULL, &buttons[4], K_MOUSE2); -#endif + IN_Move_TouchScreen_Quake(); break; } - cl.cmd.forwardmove -= move[1] * cl_forwardspeed.value; - cl.cmd.sidemove += move[0] * cl_sidespeed.value; - cl.viewangles[0] += aim[1] * cl_pitchspeed.value * cl.realframetime; - cl.viewangles[1] -= aim[0] * cl_yawspeed.value * cl.realframetime; } else { @@ -723,7 +1065,6 @@ static void sdl_newmap(void) } #endif -#ifndef __IPHONEOS__ static keynum_t buttonremap[18] = { K_MOUSE1, @@ -745,7 +1086,6 @@ static keynum_t buttonremap[18] = K_MOUSE15, K_MOUSE16, }; -#endif #if SDL_MAJOR_VERSION == 1 // SDL @@ -852,6 +1192,8 @@ void Sys_SendKeyEvents( void ) #else +//#define DEBUGSDLEVENTS + // SDL2 void Sys_SendKeyEvents( void ) { @@ -867,16 +1209,31 @@ void Sys_SendKeyEvents( void ) while( SDL_PollEvent( &event ) ) switch( event.type ) { case SDL_QUIT: +#ifdef DEBUGSDLEVENTS + Con_DPrintf("SDL_Event: SDL_QUIT\n"); +#endif Sys_Quit(0); break; case SDL_KEYDOWN: case SDL_KEYUP: +#ifdef DEBUGSDLEVENTS + if (event.type == SDL_KEYDOWN) + Con_DPrintf("SDL_Event: SDL_KEYDOWN %i unicode %i\n", event.key.keysym.sym, event.key.keysym.unicode); + else + Con_DPrintf("SDL_Event: SDL_KEYUP %i unicode %i\n", event.key.keysym.sym, event.key.keysym.unicode); +#endif keycode = MapKey(event.key.keysym.sym); if (!VID_JoyBlockEmulatedKeys(keycode)) Key_Event(keycode, 0, (event.key.state == SDL_PRESSED)); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: +#ifdef DEBUGSDLEVENTS + if (event.type == SDL_MOUSEBUTTONDOWN) + Con_DPrintf("SDL_Event: SDL_MOUSEBUTTONDOWN\n"); + else + Con_DPrintf("SDL_Event: SDL_MOUSEBUTTONUP\n"); +#endif if (!vid_touchscreen.integer) if (event.button.button <= 18) Key_Event( buttonremap[event.button.button - 1], 0, event.button.state == SDL_PRESSED ); @@ -886,8 +1243,14 @@ void Sys_SendKeyEvents( void ) case SDL_JOYAXISMOTION: case SDL_JOYBALLMOTION: case SDL_JOYHATMOTION: +#ifdef DEBUGSDLEVENTS + Con_DPrintf("SDL_Event: SDL_JOY*\n"); +#endif break; case SDL_WINDOWEVENT: +#ifdef DEBUGSDLEVENTS + Con_DPrintf("SDL_Event: SDL_WINDOWEVENT %i\n", (int)event.window.event); +#endif //if (event.window.windowID == window) // how to compare? { switch(event.window.event) @@ -899,6 +1262,9 @@ void Sys_SendKeyEvents( void ) vid_hidden = true; break; case SDL_WINDOWEVENT_EXPOSED: +#ifdef DEBUGSDLEVENTS + Con_DPrintf("SDL_Event: SDL_WINDOWEVENT_EXPOSED\n"); +#endif break; case SDL_WINDOWEVENT_MOVED: break; @@ -950,9 +1316,15 @@ void Sys_SendKeyEvents( void ) } break; case SDL_TEXTEDITING: +#ifdef DEBUGSDLEVENTS + Con_DPrintf("SDL_Event: SDL_TEXTEDITING - composition = %s, cursor = %d, selection lenght = %d\n", event.edit.text, event.edit.start, event.edit.length); +#endif // FIXME! this is where composition gets supported break; case SDL_TEXTINPUT: +#ifdef DEBUGSDLEVENTS + Con_DPrintf("SDL_Event: SDL_TEXTINPUT - text: %s\n", event.text.text); +#endif // we have some characters to parse { unicode = 0; @@ -972,6 +1344,7 @@ void Sys_SendKeyEvents( void ) unicode = '?'; // we could use 0xFFFD instead, the unicode substitute character } //Con_DPrintf("SDL_TEXTINPUT: K_TEXT %i \n", unicode); + Key_Event(K_TEXT, unicode, true); Key_Event(K_TEXT, unicode, false); } @@ -980,12 +1353,14 @@ void Sys_SendKeyEvents( void ) case SDL_MOUSEMOTION: break; case SDL_FINGERDOWN: +#ifdef DEBUGSDLEVENTS Con_DPrintf("SDL_FINGERDOWN for finger %i\n", (int)event.tfinger.fingerId); +#endif for (i = 0;i < MAXFINGERS-1;i++) { if (!multitouch[i][0]) { - multitouch[i][0] = event.tfinger.fingerId; + multitouch[i][0] = event.tfinger.fingerId + 1; multitouch[i][1] = event.tfinger.x; multitouch[i][2] = event.tfinger.y; // TODO: use event.tfinger.pressure? @@ -996,10 +1371,12 @@ void Sys_SendKeyEvents( void ) Con_DPrintf("Too many fingers at once!\n"); break; case SDL_FINGERUP: +#ifdef DEBUGSDLEVENTS Con_DPrintf("SDL_FINGERUP for finger %i\n", (int)event.tfinger.fingerId); +#endif for (i = 0;i < MAXFINGERS-1;i++) { - if (multitouch[i][0] == event.tfinger.fingerId) + if (multitouch[i][0] == event.tfinger.fingerId + 1) { multitouch[i][0] = 0; break; @@ -1009,10 +1386,12 @@ void Sys_SendKeyEvents( void ) Con_DPrintf("No SDL_FINGERDOWN event matches this SDL_FINGERMOTION event\n"); break; case SDL_FINGERMOTION: +#ifdef DEBUGSDLEVENTS Con_DPrintf("SDL_FINGERMOTION for finger %i\n", (int)event.tfinger.fingerId); +#endif for (i = 0;i < MAXFINGERS-1;i++) { - if (multitouch[i][0] == event.tfinger.fingerId) + if (multitouch[i][0] == event.tfinger.fingerId + 1) { multitouch[i][1] = event.tfinger.x; multitouch[i][2] = event.tfinger.y; @@ -1022,14 +1401,10 @@ void Sys_SendKeyEvents( void ) if (i == MAXFINGERS-1) Con_DPrintf("No SDL_FINGERDOWN event matches this SDL_FINGERMOTION event\n"); break; - case SDL_TOUCHBUTTONDOWN: - // not sure what to do with this... - break; - case SDL_TOUCHBUTTONUP: - // not sure what to do with this... - break; default: +#ifdef DEBUGSDLEVENTS Con_DPrintf("Received unrecognized SDL_Event type 0x%x\n", event.type); +#endif break; } @@ -1303,7 +1678,7 @@ void GLES_Init(void) // qglIsQueryARB = wrapglIsQuery; qglIsRenderbufferEXT = wrapglIsRenderbuffer; // qglUnmapBufferARB = wrapglUnmapBuffer; - qglCheckFramebufferStatusEXT = wrapglCheckFramebufferStatus; + qglCheckFramebufferStatus = wrapglCheckFramebufferStatus; qglGetError = wrapglGetError; qglCreateProgram = wrapglCreateProgram; qglCreateShader = wrapglCreateShader; @@ -1322,8 +1697,8 @@ void GLES_Init(void) qglBindAttribLocation = wrapglBindAttribLocation; // qglBindFragDataLocation = wrapglBindFragDataLocation; qglBindBufferARB = wrapglBindBuffer; - qglBindFramebufferEXT = wrapglBindFramebuffer; - qglBindRenderbufferEXT = wrapglBindRenderbuffer; + qglBindFramebuffer = wrapglBindFramebuffer; + qglBindRenderbuffer = wrapglBindRenderbuffer; qglBindTexture = wrapglBindTexture; qglBlendEquationEXT = wrapglBlendEquation; qglBlendFunc = wrapglBlendFunc; @@ -1348,11 +1723,11 @@ void GLES_Init(void) qglCopyTexSubImage3D = wrapglCopyTexSubImage3D; qglCullFace = wrapglCullFace; qglDeleteBuffersARB = wrapglDeleteBuffers; - qglDeleteFramebuffersEXT = wrapglDeleteFramebuffers; + qglDeleteFramebuffers = wrapglDeleteFramebuffers; qglDeleteProgram = wrapglDeleteProgram; qglDeleteShader = wrapglDeleteShader; // qglDeleteQueriesARB = wrapglDeleteQueries; - qglDeleteRenderbuffersEXT = wrapglDeleteRenderbuffers; + qglDeleteRenderbuffers = wrapglDeleteRenderbuffers; qglDeleteTextures = wrapglDeleteTextures; qglDepthFunc = wrapglDepthFunc; qglDepthMask = wrapglDepthMask; @@ -1377,9 +1752,9 @@ void GLES_Init(void) qglFramebufferTexture2DEXT = wrapglFramebufferTexture2D; qglFramebufferTexture3DEXT = wrapglFramebufferTexture3D; qglGenBuffersARB = wrapglGenBuffers; - qglGenFramebuffersEXT = wrapglGenFramebuffers; + qglGenFramebuffers = wrapglGenFramebuffers; // qglGenQueriesARB = wrapglGenQueries; - qglGenRenderbuffersEXT = wrapglGenRenderbuffers; + qglGenRenderbuffers = wrapglGenRenderbuffers; qglGenTextures = wrapglGenTextures; qglGenerateMipmapEXT = wrapglGenerateMipmap; qglGetActiveAttrib = wrapglGetActiveAttrib; @@ -1425,7 +1800,7 @@ void GLES_Init(void) // qglPolygonStipple = wrapglPolygonStipple; qglReadBuffer = wrapglReadBuffer; qglReadPixels = wrapglReadPixels; - qglRenderbufferStorageEXT = wrapglRenderbufferStorage; + qglRenderbufferStorage = wrapglRenderbufferStorage; qglScissor = wrapglScissor; qglShaderSource = wrapglShaderSource; qglStencilFunc = wrapglStencilFunc; @@ -1541,34 +1916,45 @@ void GLES_Init(void) vid.support.gl20shaders = true; vid.support.amd_texture_texture4 = false; - vid.support.arb_depth_texture = false; + vid.support.arb_depth_texture = SDL_GL_ExtensionSupported("GL_OES_depth_texture") != 0; // renderbuffer used anyway on gles2? vid.support.arb_draw_buffers = false; vid.support.arb_multitexture = false; vid.support.arb_occlusion_query = false; vid.support.arb_shadow = false; vid.support.arb_texture_compression = false; // different (vendor-specific) formats than on desktop OpenGL... - vid.support.arb_texture_cube_map = true; + vid.support.arb_texture_cube_map = SDL_GL_ExtensionSupported("GL_OES_texture_cube_map") != 0; vid.support.arb_texture_env_combine = false; vid.support.arb_texture_gather = false; vid.support.arb_texture_non_power_of_two = strstr(gl_extensions, "GL_OES_texture_npot") != NULL; - vid.support.arb_vertex_buffer_object = true; + vid.support.arb_vertex_buffer_object = true; // GLES2 core vid.support.ati_separate_stencil = false; vid.support.ext_blend_minmax = false; - vid.support.ext_blend_subtract = true; - vid.support.ext_draw_range_elements = true; + vid.support.ext_blend_subtract = true; // GLES2 core + vid.support.ext_blend_func_separate = true; // GLES2 core + vid.support.ext_draw_range_elements = false; + + /* ELUAN: + Note: "In OS 2.1, the functions in GL_OES_framebuffer_object were not usable from the Java API. + Calling them just threw an exception. Android developer relations confirmed that they forgot to implement these. (yeah...) + It's apparently been fixed in 2.2, though I haven't tested." + */ vid.support.ext_framebuffer_object = false;//true; vid.support.ext_packed_depth_stencil = false; vid.support.ext_stencil_two_side = false; - vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D"); - vid.support.ext_texture_compression_s3tc = SDL_GL_ExtensionSupported("GL_EXT_texture_compression_s3tc"); - vid.support.ext_texture_edge_clamp = true; + vid.support.ext_texture_3d = SDL_GL_ExtensionSupported("GL_OES_texture_3D") != 0; + vid.support.ext_texture_compression_s3tc = SDL_GL_ExtensionSupported("GL_EXT_texture_compression_s3tc") != 0; + vid.support.ext_texture_edge_clamp = true; // GLES2 core vid.support.ext_texture_filter_anisotropic = false; // probably don't want to use it... vid.support.ext_texture_srgb = false; + // NOTE: On some devices, a value of 512 gives better FPS than the maximum. qglGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_2d); + +#ifdef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT if (vid.support.ext_texture_filter_anisotropic) qglGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*)&vid.max_anisotropy); +#endif if (vid.support.arb_texture_cube_map) qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap); #ifdef GL_MAX_3D_TEXTURE_SIZE @@ -1608,6 +1994,9 @@ void GLES_Init(void) vid.texunits = 4; vid.teximageunits = 8; vid.texarrayunits = 5; + //qglGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*)&vid.texunits); + qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&vid.teximageunits);CHECKGLERROR + //qglGetIntegerv(GL_MAX_TEXTURE_COORDS, (GLint*)&vid.texarrayunits);CHECKGLERROR vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS); vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS); vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS); @@ -1647,7 +2036,7 @@ void VID_Init (void) Cvar_RegisterVariable(&apple_mouse_noaccel); #endif #endif -#ifdef __IPHONEOS__ +#ifdef DP_MOBILETOUCH Cvar_SetValueQuick(&vid_touchscreen, 1); #endif @@ -1695,7 +2084,14 @@ void VID_EnableJoystick(qboolean enable) { vid_sdljoystick = SDL_JoystickOpen(sdlindex); if (vid_sdljoystick) - Con_Printf("Joystick %i opened (SDL_Joystick %i is \"%s\" with %i axes, %i buttons, %i balls)\n", index, sdlindex, SDL_JoystickName(sdlindex), (int)SDL_JoystickNumAxes(vid_sdljoystick), (int)SDL_JoystickNumButtons(vid_sdljoystick), (int)SDL_JoystickNumBalls(vid_sdljoystick)); + { +#if SDL_MAJOR_VERSION == 1 + const char *joystickname = SDL_JoystickName(sdlindex); +#else + const char *joystickname = SDL_JoystickName(vid_sdljoystick); +#endif + Con_Printf("Joystick %i opened (SDL_Joystick %i is \"%s\" with %i axes, %i buttons, %i balls)\n", index, sdlindex, joystickname, (int)SDL_JoystickNumAxes(vid_sdljoystick), (int)SDL_JoystickNumButtons(vid_sdljoystick), (int)SDL_JoystickNumBalls(vid_sdljoystick)); + } else { Con_Printf("Joystick %i failed (SDL_JoystickOpen(%i) returned: %s)\n", index, sdlindex, SDL_GetError()); @@ -2010,14 +2406,16 @@ static void VID_OutputVersion(void) static qboolean VID_InitModeGL(viddef_mode_t *mode) { - int i; #if SDL_MAJOR_VERSION == 1 static int notfirstvideomode = false; int flags = SDL_OPENGL; #else int windowflags = SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL; #endif +#ifndef USE_GLES2 + int i; const char *drivername; +#endif win_half_width = mode->width>>1; win_half_height = mode->height>>1; @@ -2057,7 +2455,7 @@ static qboolean VID_InitModeGL(viddef_mode_t *mode) } #endif -#ifdef __IPHONEOS__ +#ifdef DP_MOBILETOUCH // mobile platforms are always fullscreen, we'll get the resolution after opening the window mode->fullscreen = true; // hide the menu with SDL_WINDOW_BORDERLESS @@ -2296,8 +2694,16 @@ static qboolean VID_InitModeSoft(viddef_mode_t *mode) qboolean VID_InitMode(viddef_mode_t *mode) { + // GAME_STEELSTORM specific + steelstorm_showing_map = Cvar_FindVar("steelstorm_showing_map"); + steelstorm_showing_mousecursor = Cvar_FindVar("steelstorm_showing_mousecursor"); + if (!SDL_WasInit(SDL_INIT_VIDEO) && SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) Sys_Error ("Failed to init SDL video subsystem: %s", SDL_GetError()); + +#if SDL_MAJOR_VERSION != 1 + Cvar_SetValueQuick(&vid_touchscreen_supportshowkeyboard, SDL_HasScreenKeyboardSupport() ? 1 : 0); +#endif #ifdef SSE_POSSIBLE if (vid_soft.integer) return VID_InitModeSoft(mode); @@ -2388,6 +2794,7 @@ void VID_Finish (void) CHECKGLERROR if (r_speeds.integer == 2 || gl_finish.integer) GL_Finish(); + #if SDL_MAJOR_VERSION != 1 { qboolean vid_usevsync; diff --git a/vid_shared.c b/vid_shared.c index b141908a..719d6299 100644 --- a/vid_shared.c +++ b/vid_shared.c @@ -164,6 +164,12 @@ cvar_t vid_samples = {CVAR_SAVE, "vid_samples", "1", "how many anti-aliasing sam cvar_t vid_refreshrate = {CVAR_SAVE, "vid_refreshrate", "60", "refresh rate to use, in hz (higher values flicker less, if supported by your monitor)"}; cvar_t vid_userefreshrate = {CVAR_SAVE, "vid_userefreshrate", "0", "set this to 1 to make vid_refreshrate used, or to 0 to let the engine choose a sane default"}; cvar_t vid_stereobuffer = {CVAR_SAVE, "vid_stereobuffer", "0", "enables 'quad-buffered' stereo rendering for stereo shutterglasses, HMD (head mounted display) devices, or polarized stereo LCDs, if supported by your drivers"}; +// the density cvars are completely optional, set and use when something needs to have a density-independent size. +// TODO: set them when changing resolution, setting them from the commandline will be independent from the resolution - use only if you have a native fixed resolution. +// values for the Samsung Galaxy SIII, Snapdragon version: 2.000000 density, 304.799988 xdpi, 303.850464 ydpi +cvar_t vid_touchscreen_density = {0, "vid_touchscreen_density", "2.0", "Standard quantized screen density multiplier (see Android documentation for DisplayMetrics), similar values are given on iPhoneOS"}; +cvar_t vid_touchscreen_xdpi = {0, "vid_touchscreen_xdpi", "300", "Horizontal DPI of the screen (only valid on Android currently)"}; +cvar_t vid_touchscreen_ydpi = {0, "vid_touchscreen_ydpi", "300", "Vertical DPI of the screen (only valid on Android currently)"}; cvar_t vid_vsync = {CVAR_SAVE, "vid_vsync", "0", "sync to vertical blank, prevents 'tearing' (seeing part of one frame and part of another on the screen at the same time), automatically disabled when doing timedemo benchmarks"}; cvar_t vid_mouse = {CVAR_SAVE, "vid_mouse", "1", "whether to use the mouse in windowed mode (fullscreen always does)"}; @@ -177,6 +183,8 @@ cvar_t vid_sRGB = {CVAR_SAVE, "vid_sRGB", "0", "if hardware is capable, modify r cvar_t vid_sRGB_fallback = {CVAR_SAVE, "vid_sRGB_fallback", "0", "do an approximate sRGB fallback if not properly supported by hardware (2: also use the fallback if framebuffer is 8bit, 3: always use the fallback even if sRGB is supported)"}; cvar_t vid_touchscreen = {0, "vid_touchscreen", "0", "Use touchscreen-style input (no mouse grab, track mouse motion only while button is down, screen areas for mimicing joystick axes and buttons"}; +cvar_t vid_touchscreen_showkeyboard = {0, "vid_touchscreen_showkeyboard", "0", "shows the platform's screen keyboard for text entry, can be set by csqc or menu qc if it wants to receive text input, does nothing if the platform has no screen keyboard"}; +cvar_t vid_touchscreen_supportshowkeyboard = {CVAR_READONLY, "vid_touchscreen_supportshowkeyboard", "0", "indicates if the platform supports a virtual keyboard"}; cvar_t vid_stick_mouse = {CVAR_SAVE, "vid_stick_mouse", "0", "have the mouse stuck in the center of the screen" }; cvar_t vid_resizable = {CVAR_SAVE, "vid_resizable", "0", "0: window not resizable, 1: resizable, 2: window can be resized but the framebuffer isn't adjusted" }; @@ -518,6 +526,8 @@ void (GLAPIENTRY *qglBindBufferRange)(GLenum target, GLuint index, GLuint buffer void (GLAPIENTRY *qglBindBufferBase)(GLenum target, GLuint index, GLuint buffer); void (GLAPIENTRY *qglGetIntegeri_v)(GLenum target, GLuint index, GLint* data); void (GLAPIENTRY *qglUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + +void (GLAPIENTRY *qglBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); #endif #if _MSC_VER >= 1400 @@ -974,6 +984,13 @@ static dllfunction_t multisamplefuncs[] = {"glSampleCoverageARB", (void **) &qglSampleCoverageARB}, {NULL, NULL} }; + +static dllfunction_t blendfuncseparatefuncs[] = +{ + {"glBlendFuncSeparateEXT", (void **) &qglBlendFuncSeparate}, + {NULL, NULL} +}; + #endif void VID_ClearExtensions(void) @@ -1059,6 +1076,7 @@ void VID_CheckExtensions(void) vid.support.ati_separate_stencil = GL_CheckExtension("separatestencil", gl2separatestencilfuncs, "-noseparatestencil", true) || GL_CheckExtension("GL_ATI_separate_stencil", atiseparatestencilfuncs, "-noseparatestencil", false); vid.support.ext_blend_minmax = GL_CheckExtension("GL_EXT_blend_minmax", blendequationfuncs, "-noblendminmax", false); vid.support.ext_blend_subtract = GL_CheckExtension("GL_EXT_blend_subtract", blendequationfuncs, "-noblendsubtract", false); + vid.support.ext_blend_func_separate = GL_CheckExtension("GL_EXT_blend_func_separate", blendfuncseparatefuncs, "-noblendfuncseparate", false); vid.support.ext_draw_range_elements = GL_CheckExtension("drawrangeelements", drawrangeelementsfuncs, "-nodrawrangeelements", true) || GL_CheckExtension("GL_EXT_draw_range_elements", drawrangeelementsextfuncs, "-nodrawrangeelements", false); vid.support.arb_framebuffer_object = GL_CheckExtension("GL_ARB_framebuffer_object", arbfbofuncs, "-nofbo", false); if (vid.support.arb_framebuffer_object) @@ -1739,10 +1757,15 @@ void VID_Shared_Init(void) Cvar_RegisterVariable(&vid_refreshrate); Cvar_RegisterVariable(&vid_userefreshrate); Cvar_RegisterVariable(&vid_stereobuffer); + Cvar_RegisterVariable(&vid_touchscreen_density); + Cvar_RegisterVariable(&vid_touchscreen_xdpi); + Cvar_RegisterVariable(&vid_touchscreen_ydpi); Cvar_RegisterVariable(&vid_vsync); Cvar_RegisterVariable(&vid_mouse); Cvar_RegisterVariable(&vid_grabkeyboard); Cvar_RegisterVariable(&vid_touchscreen); + Cvar_RegisterVariable(&vid_touchscreen_showkeyboard); + Cvar_RegisterVariable(&vid_touchscreen_supportshowkeyboard); Cvar_RegisterVariable(&vid_stick_mouse); Cvar_RegisterVariable(&vid_resizable); Cvar_RegisterVariable(&vid_minwidth); @@ -1845,11 +1868,13 @@ static int VID_Mode(int fullscreen, int width, int height, int bpp, float refres case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GL20: +#ifdef GL_STEREO { GLboolean stereo; qglGetBooleanv(GL_STEREO, &stereo); vid.stereobuffer = stereo != 0; } +#endif break; default: vid.stereobuffer = false; @@ -1878,6 +1903,12 @@ static int VID_Mode(int fullscreen, int width, int height, int bpp, float refres Cvar_SetValueQuick(&vid_refreshrate, vid.mode.refreshrate); Cvar_SetValueQuick(&vid_stereobuffer, vid.stereobuffer ? 1 : 0); + if (vid_touchscreen.integer) + { + in_windowmouse_x = vid_width.value / 2.f; + in_windowmouse_y = vid_height.value / 2.f; + } + return true; } else @@ -1971,6 +2002,15 @@ void VID_Start(void) // COMMANDLINEOPTION: Video: -bpp performs +vid_bitsperpixel (example -bpp 32 or -bpp 16) if ((i = COM_CheckParm("-bpp")) != 0) Cvar_SetQuick(&vid_bitsperpixel, com_argv[i+1]); +// COMMANDLINEOPTION: Video: -density performs +vid_touchscreen_density (example -density 1 or -density 1.5) + if ((i = COM_CheckParm("-density")) != 0) + Cvar_SetQuick(&vid_touchscreen_density, com_argv[i+1]); +// COMMANDLINEOPTION: Video: -xdpi performs +vid_touchscreen_xdpi (example -xdpi 160 or -xdpi 320) + if ((i = COM_CheckParm("-touchscreen_xdpi")) != 0) + Cvar_SetQuick(&vid_touchscreen_xdpi, com_argv[i+1]); +// COMMANDLINEOPTION: Video: -ydpi performs +vid_touchscreen_ydpi (example -ydpi 160 or -ydpi 320) + if ((i = COM_CheckParm("-touchscreen_ydpi")) != 0) + Cvar_SetQuick(&vid_touchscreen_ydpi, com_argv[i+1]); } success = VID_Mode(vid_fullscreen.integer, vid_width.integer, vid_height.integer, vid_bitsperpixel.integer, vid_refreshrate.value, vid_stereobuffer.integer, vid_samples.integer); -- 2.39.2