From e78c8448c9b01751bfe12b91fc6eefbc151e9ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20Jos=C3=A9=20Garc=C3=ADa=20Garc=C3=ADa?= Date: Sat, 14 Nov 2020 09:57:40 +0100 Subject: [PATCH] [VITA] Remove vitaGL and vitaShark from deps dir --- Makefile.common | 15 +- Makefile.vita | 13 +- deps/vitaGL/.clang-format | 99 - deps/vitaGL/.gitattributes | 17 - deps/vitaGL/.github/FUNDING.yml | 1 - deps/vitaGL/.gitignore | 57 - deps/vitaGL/COPYING | 674 ----- deps/vitaGL/COPYING.LESSER | 165 -- deps/vitaGL/Makefile | 83 - deps/vitaGL/README.md | 50 - deps/vitaGL/format.bat | 6 - deps/vitaGL/samples/sample1/Makefile | 40 - deps/vitaGL/samples/sample1/main.c | 67 - deps/vitaGL/samples/sample1/texture.bmp | Bin 1566774 -> 0 bytes deps/vitaGL/samples/sample2/Makefile | 42 - deps/vitaGL/samples/sample2/main.c | 39 - deps/vitaGL/samples/sample3/Makefile | 38 - deps/vitaGL/samples/sample3/main.c | 36 - deps/vitaGL/samples/sample4/Makefile | 37 - deps/vitaGL/samples/sample4/main.c | 38 - deps/vitaGL/samples/sample5/Makefile | 37 - deps/vitaGL/samples/sample5/main.c | 75 - deps/vitaGL/samples/sample6/Makefile | 37 - deps/vitaGL/samples/sample6/main.c | 89 - deps/vitaGL/samples/sample7/Makefile | 40 - deps/vitaGL/samples/sample7/main.c | 91 - deps/vitaGL/samples/sample7/texture.bmp | Bin 1566774 -> 0 bytes deps/vitaGL/samples/sample8/Makefile | 37 - deps/vitaGL/samples/sample8/main.c | 76 - deps/vitaGL/shaders/clear_f.cg | 4 - deps/vitaGL/shaders/clear_v.cg | 7 - deps/vitaGL/shaders/disable_color_buffer_f.cg | 5 - deps/vitaGL/shaders/rgb_v.cg | 11 - deps/vitaGL/shaders/rgba_f.cg | 4 - deps/vitaGL/shaders/rgba_v.cg | 11 - deps/vitaGL/shaders/texture2d_f.cg | 83 - deps/vitaGL/shaders/texture2d_rgba_f.cg | 83 - deps/vitaGL/shaders/texture2d_rgba_v.cg | 27 - deps/vitaGL/shaders/texture2d_v.cg | 24 - deps/vitaGL/source/custom_shaders.c | 788 ------ deps/vitaGL/source/framebuffers.c | 207 -- deps/vitaGL/source/get_info.c | 228 -- deps/vitaGL/source/gxm.c | 477 ---- deps/vitaGL/source/hacks/memcpy_neon.S | 140 - deps/vitaGL/source/hacks/sbrk.c | 114 - deps/vitaGL/source/legacy.c | 592 ----- deps/vitaGL/source/matrices.c | 228 -- deps/vitaGL/source/misc.c | 568 ----- deps/vitaGL/source/shaders.h | 105 - deps/vitaGL/source/shaders/clear_f.h | 23 - deps/vitaGL/source/shaders/clear_v.h | 32 - .../source/shaders/disable_color_buffer_f.h | 26 - deps/vitaGL/source/shaders/rgb_v.h | 36 - deps/vitaGL/source/shaders/rgba_f.h | 22 - deps/vitaGL/source/shaders/rgba_v.h | 36 - deps/vitaGL/source/shaders/texture2d_f.h | 89 - deps/vitaGL/source/shaders/texture2d_rgba_f.h | 91 - deps/vitaGL/source/shaders/texture2d_rgba_v.h | 50 - deps/vitaGL/source/shaders/texture2d_v.h | 48 - deps/vitaGL/source/shared.h | 211 -- deps/vitaGL/source/state.c | 71 - deps/vitaGL/source/state.h | 207 -- deps/vitaGL/source/tests.c | 510 ---- deps/vitaGL/source/texture_callbacks.c | 161 -- deps/vitaGL/source/texture_callbacks.h | 47 - deps/vitaGL/source/textures.c | 980 ------- deps/vitaGL/source/utils/gpu_utils.c | 542 ---- deps/vitaGL/source/utils/gpu_utils.h | 108 - deps/vitaGL/source/utils/math_utils.c | 252 -- deps/vitaGL/source/utils/math_utils.h | 92 - deps/vitaGL/source/utils/mem_utils.c | 321 --- deps/vitaGL/source/utils/mem_utils.h | 33 - deps/vitaGL/source/utils/stb_dxt.h | 748 ------ deps/vitaGL/source/vitaGL.c | 2245 ----------------- deps/vitaGL/source/vitaGL.h | 478 ---- deps/vitaShaRK/.gitattributes | 2 - deps/vitaShaRK/.github/FUNDING.yml | 1 - deps/vitaShaRK/.gitignore | 59 - deps/vitaShaRK/LICENSE | 165 -- deps/vitaShaRK/Makefile | 37 - deps/vitaShaRK/README.md | 18 - deps/vitaShaRK/SceShaccCg.yml | 43 - deps/vitaShaRK/SceShaccCg/Makefile | 47 - deps/vitaShaRK/include/shacccg.h | 185 -- deps/vitaShaRK/samples/sample1/Makefile | 37 - deps/vitaShaRK/samples/sample1/main.c | 59 - deps/vitaShaRK/samples/sample2/Makefile | 37 - deps/vitaShaRK/samples/sample2/main.c | 85 - deps/vitaShaRK/source/vitashark.c | 124 - deps/vitaShaRK/source/vitashark.h | 75 - 90 files changed, 4 insertions(+), 14134 deletions(-) delete mode 100644 deps/vitaGL/.clang-format delete mode 100644 deps/vitaGL/.gitattributes delete mode 100644 deps/vitaGL/.github/FUNDING.yml delete mode 100644 deps/vitaGL/.gitignore delete mode 100644 deps/vitaGL/COPYING delete mode 100644 deps/vitaGL/COPYING.LESSER delete mode 100644 deps/vitaGL/Makefile delete mode 100644 deps/vitaGL/README.md delete mode 100644 deps/vitaGL/format.bat delete mode 100644 deps/vitaGL/samples/sample1/Makefile delete mode 100644 deps/vitaGL/samples/sample1/main.c delete mode 100644 deps/vitaGL/samples/sample1/texture.bmp delete mode 100644 deps/vitaGL/samples/sample2/Makefile delete mode 100644 deps/vitaGL/samples/sample2/main.c delete mode 100644 deps/vitaGL/samples/sample3/Makefile delete mode 100644 deps/vitaGL/samples/sample3/main.c delete mode 100644 deps/vitaGL/samples/sample4/Makefile delete mode 100644 deps/vitaGL/samples/sample4/main.c delete mode 100644 deps/vitaGL/samples/sample5/Makefile delete mode 100644 deps/vitaGL/samples/sample5/main.c delete mode 100644 deps/vitaGL/samples/sample6/Makefile delete mode 100644 deps/vitaGL/samples/sample6/main.c delete mode 100644 deps/vitaGL/samples/sample7/Makefile delete mode 100644 deps/vitaGL/samples/sample7/main.c delete mode 100644 deps/vitaGL/samples/sample7/texture.bmp delete mode 100644 deps/vitaGL/samples/sample8/Makefile delete mode 100644 deps/vitaGL/samples/sample8/main.c delete mode 100644 deps/vitaGL/shaders/clear_f.cg delete mode 100644 deps/vitaGL/shaders/clear_v.cg delete mode 100644 deps/vitaGL/shaders/disable_color_buffer_f.cg delete mode 100644 deps/vitaGL/shaders/rgb_v.cg delete mode 100644 deps/vitaGL/shaders/rgba_f.cg delete mode 100644 deps/vitaGL/shaders/rgba_v.cg delete mode 100644 deps/vitaGL/shaders/texture2d_f.cg delete mode 100644 deps/vitaGL/shaders/texture2d_rgba_f.cg delete mode 100644 deps/vitaGL/shaders/texture2d_rgba_v.cg delete mode 100644 deps/vitaGL/shaders/texture2d_v.cg delete mode 100644 deps/vitaGL/source/custom_shaders.c delete mode 100644 deps/vitaGL/source/framebuffers.c delete mode 100644 deps/vitaGL/source/get_info.c delete mode 100644 deps/vitaGL/source/gxm.c delete mode 100644 deps/vitaGL/source/hacks/memcpy_neon.S delete mode 100644 deps/vitaGL/source/hacks/sbrk.c delete mode 100644 deps/vitaGL/source/legacy.c delete mode 100644 deps/vitaGL/source/matrices.c delete mode 100644 deps/vitaGL/source/misc.c delete mode 100644 deps/vitaGL/source/shaders.h delete mode 100644 deps/vitaGL/source/shaders/clear_f.h delete mode 100644 deps/vitaGL/source/shaders/clear_v.h delete mode 100644 deps/vitaGL/source/shaders/disable_color_buffer_f.h delete mode 100644 deps/vitaGL/source/shaders/rgb_v.h delete mode 100644 deps/vitaGL/source/shaders/rgba_f.h delete mode 100644 deps/vitaGL/source/shaders/rgba_v.h delete mode 100644 deps/vitaGL/source/shaders/texture2d_f.h delete mode 100644 deps/vitaGL/source/shaders/texture2d_rgba_f.h delete mode 100644 deps/vitaGL/source/shaders/texture2d_rgba_v.h delete mode 100644 deps/vitaGL/source/shaders/texture2d_v.h delete mode 100644 deps/vitaGL/source/shared.h delete mode 100644 deps/vitaGL/source/state.c delete mode 100644 deps/vitaGL/source/state.h delete mode 100644 deps/vitaGL/source/tests.c delete mode 100644 deps/vitaGL/source/texture_callbacks.c delete mode 100644 deps/vitaGL/source/texture_callbacks.h delete mode 100644 deps/vitaGL/source/textures.c delete mode 100644 deps/vitaGL/source/utils/gpu_utils.c delete mode 100644 deps/vitaGL/source/utils/gpu_utils.h delete mode 100644 deps/vitaGL/source/utils/math_utils.c delete mode 100644 deps/vitaGL/source/utils/math_utils.h delete mode 100644 deps/vitaGL/source/utils/mem_utils.c delete mode 100644 deps/vitaGL/source/utils/mem_utils.h delete mode 100644 deps/vitaGL/source/utils/stb_dxt.h delete mode 100644 deps/vitaGL/source/vitaGL.c delete mode 100644 deps/vitaGL/source/vitaGL.h delete mode 100644 deps/vitaShaRK/.gitattributes delete mode 100644 deps/vitaShaRK/.github/FUNDING.yml delete mode 100644 deps/vitaShaRK/.gitignore delete mode 100644 deps/vitaShaRK/LICENSE delete mode 100644 deps/vitaShaRK/Makefile delete mode 100644 deps/vitaShaRK/README.md delete mode 100644 deps/vitaShaRK/SceShaccCg.yml delete mode 100644 deps/vitaShaRK/SceShaccCg/Makefile delete mode 100644 deps/vitaShaRK/include/shacccg.h delete mode 100644 deps/vitaShaRK/samples/sample1/Makefile delete mode 100644 deps/vitaShaRK/samples/sample1/main.c delete mode 100644 deps/vitaShaRK/samples/sample2/Makefile delete mode 100644 deps/vitaShaRK/samples/sample2/main.c delete mode 100644 deps/vitaShaRK/source/vitashark.c delete mode 100644 deps/vitaShaRK/source/vitashark.h diff --git a/Makefile.common b/Makefile.common index fe1b5eb13f..235ee2a893 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1389,7 +1389,7 @@ ifeq ($(HAVE_PLAIN_DRM), 1) endif ifeq ($(HAVE_VITAGL), 1) - DEFINES += -DHAVE_OPENGL1 + DEFINES += -DHAVE_OPENGL1 -DHAVE_VITAGL OBJ += gfx/drivers/gl1.o \ gfx/drivers_font/gl1_raster_font.o \ gfx/drivers_context/vita_ctx.o \ @@ -2320,19 +2320,6 @@ ifeq ($(HAVE_MATH_NEON), 1) OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c))) endif -ifeq ($(HAVE_VITAGL), 1) - INCLUDE_DIRS += -I$(DEPS_DIR)/vitaShaRK/source - SOURCES := $(DEPS_DIR)/vitaShaRK/source - OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c))) -endif - -ifeq ($(HAVE_VITAGL), 1) - DEFINES += -DHAVE_VITAGL -DSTB_DXT_IMPLEMENTATION -DSKIP_ERROR_HANDLING -DHAVE_SHARK - INCLUDE_DIRS += -I$(DEPS_DIR)/vitaGL/source -I$(DEPS_DIR)/vitaShaRK/include - SOURCES := $(DEPS_DIR)/vitaGL/source $(DEPS_DIR)/vitaGL/source/utils - OBJ += $(patsubst %.c,%.o,$(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c))) -endif - ##################################### ### Android Play Feature Delivery ### ### (Play Store build core ### diff --git a/Makefile.vita b/Makefile.vita index d4aa224d52..dd94ba0282 100644 --- a/Makefile.vita +++ b/Makefile.vita @@ -132,7 +132,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions VITA_LIBS := -lSceDisplay_stub -lSceGxm_stub -lSceNet_stub -lSceNetCtl_stub -lSceAppUtil_stub \ -lSceSysmodule_stub -lSceCtrl_stub -lSceHid_stub -lSceTouch_stub -lSceAudio_stub \ -lScePower_stub -lSceRtc_stub -lSceCommonDialog_stub -lScePgf_stub -lSceMotion_stub \ - -lSceFiber_stub -lSceMotion_stub -lSceAppMgr_stub -lstdc++ -lpthread -lpng -lz -lSceShaccCg_stub + -lSceFiber_stub -lSceMotion_stub -lSceAppMgr_stub -lstdc++ -lpthread -lpng -lz -lvitaGL -lvitashark -lSceShaccCg_stub LIBS := $(WHOLE_START) -lretro_vita $(WHOLE_END) $(VITA_LIBS) -lm -lc @@ -165,13 +165,7 @@ all: $(TARGETS) %.depend: ; -libSceShaccCg_stub.a: - mkdir -p deps/vitaShaRK/SceShaccCg - vita-libs-gen deps/vitaShaRK/SceShaccCg.yml deps/vitaShaRK/SceShaccCg - make -C deps/vitaShaRK/SceShaccCg ARCH=arm-vita-eabi - cp deps/vitaShaRK/SceShaccCg/libSceShaccCg_stub.a . - -$(TARGET).elf: $(OBJ) libretro_vita.a libSceShaccCg_stub.a +$(TARGET).elf: $(OBJ) libretro_vita.a $(LD) $(OBJ) $(LDFLAGS) $(LIBDIRS) $(LIBS) -o $@ %.velf: %.elf @@ -187,8 +181,7 @@ $(TARGET).elf: $(OBJ) libretro_vita.a libSceShaccCg_stub.a vita-pack-vpk -s param.sfo -b $< $@ clean: - rm -f $(OBJ) $(TARGET).elf $(TARGET).elf.unstripped.elf $(TARGET).velf $(TARGET).self param.sfo $(TARGET).vpk libSceShaccCg_stub.a - rm -rf deps/vitaShaRK/SceShaccCg + rm -f $(OBJ) $(TARGET).elf $(TARGET).elf.unstripped.elf $(TARGET).velf $(TARGET).self param.sfo $(TARGET).vpk rm -f $(OBJ:.o=.depend) # Useful for developers diff --git a/deps/vitaGL/.clang-format b/deps/vitaGL/.clang-format deleted file mode 100644 index 466a0cff41..0000000000 --- a/deps/vitaGL/.clang-format +++ /dev/null @@ -1,99 +0,0 @@ ---- -Language: Cpp -# BasedOnStyle: WebKit -AccessModifierOffset: -4 -AlignAfterOpenBracket: DontAlign -AlignConsecutiveAssignments: false -AlignConsecutiveDeclarations: false -AlignEscapedNewlines: Right -AlignOperands: false -AlignTrailingComments: false -AllowAllParametersOfDeclarationOnNextLine: true -AllowShortBlocksOnASingleLine: false -AllowShortCaseLabelsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: false -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: false -BinPackArguments: true -BinPackParameters: true -BraceWrapping: - AfterClass: false - AfterControlStatement: false - AfterEnum: false - AfterFunction: true - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - IndentBraces: false -BreakBeforeBinaryOperators: All -BreakBeforeBraces: Attach -BreakBeforeInheritanceComma: false -BreakBeforeTernaryOperators: true -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeComma -BreakAfterJavaFieldAnnotations: false -BreakStringLiterals: true -ColumnLimit: 0 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerAllOnOneLineOrOnePerLine: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: false -DerivePointerAlignment: false -DisableFormat: false -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: true -ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] -IncludeCategories: - - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - Priority: 2 - - Regex: '^(<|"(gtest|isl|json)/)' - Priority: 3 - - Regex: '.*' - Priority: 1 -IncludeIsMainRegex: '$' -IndentCaseLabels: false -IndentWidth: 4 -IndentWrappedFunctionNames: false -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: false -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBlockIndentWidth: 4 -ObjCSpaceAfterProperty: true -ObjCSpaceBeforeProtocolList: true -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakString: 1000 -PenaltyExcessCharacter: 1000000 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -ReflowComments: true -SortIncludes: true -SpaceAfterCStyleCast: false -SpaceAfterTemplateKeyword: true -SpaceBeforeAssignmentOperators: true -SpaceBeforeParens: ControlStatements -SpaceInEmptyParentheses: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: false -SpacesInContainerLiterals: true -SpacesInCStyleCastParentheses: false -SpacesInParentheses: false -SpacesInSquareBrackets: false -TabWidth: 4 -UseTab: Always -... diff --git a/deps/vitaGL/.gitattributes b/deps/vitaGL/.gitattributes deleted file mode 100644 index bdb0cabc87..0000000000 --- a/deps/vitaGL/.gitattributes +++ /dev/null @@ -1,17 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.cs diff=csharp - -# Standard to msysgit -*.doc diff=astextplain -*.DOC diff=astextplain -*.docx diff=astextplain -*.DOCX diff=astextplain -*.dot diff=astextplain -*.DOT diff=astextplain -*.pdf diff=astextplain -*.PDF diff=astextplain -*.rtf diff=astextplain -*.RTF diff=astextplain diff --git a/deps/vitaGL/.github/FUNDING.yml b/deps/vitaGL/.github/FUNDING.yml deleted file mode 100644 index dbd470e946..0000000000 --- a/deps/vitaGL/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -patreon: Rinnegatamante diff --git a/deps/vitaGL/.gitignore b/deps/vitaGL/.gitignore deleted file mode 100644 index 23410e348b..0000000000 --- a/deps/vitaGL/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -*.vpk -*.elf -*.velf -*.bin -*.sfo - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Vita build stuffs -*.a -*.o diff --git a/deps/vitaGL/COPYING b/deps/vitaGL/COPYING deleted file mode 100644 index f288702d2f..0000000000 --- a/deps/vitaGL/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/deps/vitaGL/COPYING.LESSER b/deps/vitaGL/COPYING.LESSER deleted file mode 100644 index 0a041280bd..0000000000 --- a/deps/vitaGL/COPYING.LESSER +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/deps/vitaGL/Makefile b/deps/vitaGL/Makefile deleted file mode 100644 index fc0f21bfca..0000000000 --- a/deps/vitaGL/Makefile +++ /dev/null @@ -1,83 +0,0 @@ -TARGET := libvitaGL -SOURCES := source source/utils -SHADERS := shaders - -ifeq ($(HAVE_SBRK),1) -SOURCES += source/hacks -endif - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -ASMFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.S)) -CGFILES := $(foreach dir,$(SHADERS), $(wildcard $(dir)/*.cg)) -HEADERS := $(CGFILES:.cg=.h) -OBJS := $(CFILES:.c=.o) $(ASMFILES:.S=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -AR = $(PREFIX)-gcc-ar -CFLAGS = -g -Wl,-q -O2 -ffast-math -mtune=cortex-a9 -mfpu=neon -ftree-vectorize -DSTB_DXT_IMPLEMENTATION -ASFLAGS = $(CFLAGS) - -ifeq ($(NO_DEBUG),1) -CFLAGS += -DSKIP_ERROR_HANDLING -endif - -ifeq ($(HAVE_SHARK),1) -CFLAGS += -DHAVE_SHARK -endif - -ifeq ($(HAVE_SHARK),2) -CFLAGS += -DHAVE_SHARK -DHAVE_SHARK_LOG -endif - -all: $(TARGET).a - -$(TARGET).a: $(OBJS) - $(AR) -rc $@ $^ - -%_f.h: - psp2cgc -profile sce_fp_psp2 $(@:_f.h=_f.cg) -Wperf -o $(@:_f.h=_f.gxp) - bin2c $(@:_f.h=_f.gxp) source/shaders/$(notdir $(@)) $(notdir $(@:_f.h=_f)) - @rm -rf $(@:_f.h=_f.gxp) - -%_v.h: - psp2cgc -profile sce_vp_psp2 $(@:_v.h=_v.cg) -Wperf -o $(@:_v.h=_v.gxp) - bin2c $(@:_v.h=_v.gxp) source/shaders/$(notdir $(@:_v.h=_v.h)) $(notdir $(@:_v.h=_v)) - @rm -rf $(@:_v.h=_v.gxp) - -shaders: $(HEADERS) - -clean: - @rm -rf $(TARGET).a $(TARGET).elf $(OBJS) - @make -C samples/sample1 clean - @make -C samples/sample2 clean - @make -C samples/sample3 clean - @make -C samples/sample4 clean - @make -C samples/sample5 clean - @make -C samples/sample6 clean - @make -C samples/sample7 clean - @make -C samples/sample8 clean - -install: $(TARGET).a - @mkdir -p $(VITASDK)/$(PREFIX)/lib/ - cp $(TARGET).a $(VITASDK)/$(PREFIX)/lib/ - @mkdir -p $(VITASDK)/$(PREFIX)/include/ - cp source/vitaGL.h $(VITASDK)/$(PREFIX)/include/ - -samples: $(TARGET).a - @make -C samples/sample1 - cp "samples/sample1/vitaGL-Sample001.vpk" . - @make -C samples/sample2 - cp "samples/sample2/vitaGL-Sample002.vpk" . - @make -C samples/sample3 - cp "samples/sample3/vitaGL-Sample003.vpk" . - @make -C samples/sample4 - cp "samples/sample4/vitaGL-Sample004.vpk" . - @make -C samples/sample5 - cp "samples/sample5/vitaGL-Sample005.vpk" . - @make -C samples/sample6 - cp "samples/sample6/vitaGL-Sample006.vpk" . - @make -C samples/sample7 - cp "samples/sample7/vitaGL-Sample007.vpk" . - @make -C samples/sample8 - cp "samples/sample8/vitaGL-Sample008.vpk" . diff --git a/deps/vitaGL/README.md b/deps/vitaGL/README.md deleted file mode 100644 index 98ab65c04a..0000000000 --- a/deps/vitaGL/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# vitaGL -vitaGL is a wrapper between openGL and sceGxm. It allows to use a subset of openGL functions with fully hardware acceleration by translating the code to sceGxm equivalent. - -# Build Instructions -In order to build vitaGL use the following command: `make HAVE_SBRK=1 install`. -If you already have a newlib sbrk replacement in your app (eg. RetroArch), use instead this command: `make install`. - -# Samples - -You can find samples in the *samples* folder in this repository. - -# Help and Troubleshooting - -If you plan to use vitaGL for one of your projects, you can find an official channel to get help with it on Vita Nuova discord server: https://discord.gg/PyCaBx9 - -# Projects actually using vitaGL - -Here you can find a list of projects using vitaGL: - -Direct OpenGL Usage:
-[vitaQuake](https://vitadb.rinnegatamante.it/#/info/10) - Port of Quake I and mission packs
-[vitaQuakeII](https://vitadb.rinnegatamante.it/#/info/278) -Port of Quake II and mission packs
-[vitaQuakeIII](https://vitadb.rinnegatamante.it/#/info/375) - Port of ioquake3 (Quake III: Arena, Quake III: Team Arena, OpenArena, Urban Terror)
-[vitaRTCW](https://vitadb.rinnegatamante.it/#/info/459) - Port of iortcw (Return to Castle Wolfenstein)
-[vitaHexenII](https://vitadb.rinnegatamante.it/#/info/196) - Port of Hexen II
-[vitaXash3D](https://vitadb.rinnegatamante.it/#/info/365) - Port of Xash3D (Half Life, Counter Strike 1.6)
-[Fade to Black](https://vitadb.rinnegatamante.it/#/info/367) - Port of Fade to Black
-[vitaVoyager](https://vitadb.rinnegatamante.it/#/info/367) - Port of lilium-voyager (Star Trek Voyager: Elite Force)
-[Daedalus X64](https://github.com/Rinnegatamante/daedalusx64-vitagl) - Port of Daedalus X64 (N64 Emulator)
-[RetroArch](https://github.com/libretro/RetroArch) - Vita's GL1 video driver of RetroArch
-[vitaET](https://github.com/Rinnegatamante/vitaET) - Port of ET: Legacy (Wolfenstein: Enemy Territory)
-[flycast](https://github.com/Rinnegatamante/flycast) - Port of flycast (Dreamcast Emulator)
-[AvP Gold](https://github.com/Rinnegatamante/AvP-Gold-Vita) - Port of Aliens versus Predator: Gold Edition
-[re3-vita](https://vitadb.rinnegatamante.it/#/info/589) - Port of Grand Theft Auto III
-[prboom-plus](https://vitadb.rinnegatamante.it/#/info/591) - Port of PrBoom Plus (Doom engine sourceport)
-[VITAlbum](https://vitadb.rinnegatamante.it/#/info/566) - Filebrowser and image viewer app
-[sm64-vita](https://github.com/bythos14/sm64-vita) - Port of Super Mario 64
- -Libraries:
-[sdl12_gl](https://github.com/Rinnegatamante/SDL-Vita/tree/sdl12_gl/src) - SDL 1.2 Vita port adapted to work with vitaGL as renderer
-[imgui_vita](https://github.com/Rinnegatamante/imgui-vita) - Port of dear imGui
- -sdl12_gl Apps:
-[SuperMarioWar](https://vitadb.rinnegatamante.it/#/info/422) - Port of Super Mario War
-[ZeldaOLB](https://vitadb.rinnegatamante.it/#/info/265) - Port of Zelda: Oni Link Begins
-[ZeldaROTH](https://vitadb.rinnegatamante.it/#/info/109) - Port of Zelda: Return of the Hylian
-[Zelda3T](https://vitadb.rinnegatamante.it/#/info/334) - Port of Zelda: Time to Triumph
-[ZeldaNSQ](https://vitadb.rinnegatamante.it/#/info/350) - Port of Zelda: Navi's Quest
-[vitaWolfen](https://vitadb.rinnegatamante.it/#/info/31) - Port of Wolf4SDL (Wolfenstein 3D)
-[meritous](https://vitadb.rinnegatamante.it/#/info/411) - Port of meritous
diff --git a/deps/vitaGL/format.bat b/deps/vitaGL/format.bat deleted file mode 100644 index dab6c9f4a1..0000000000 --- a/deps/vitaGL/format.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off -cd source -for /f %%f in ('dir *.c *.h /b/s') do ( - echo.%%f | findstr /C:"\\shaders\\">nul || (clang-format -i %%f) -) -cd .. diff --git a/deps/vitaGL/samples/sample1/Makefile b/deps/vitaGL/samples/sample1/Makefile deleted file mode 100644 index 006a1677b1..0000000000 --- a/deps/vitaGL/samples/sample1/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -SAMPLE_NUM := 001 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lSceLibKernel_stub -lScePvf_stub -lmathneon \ - -lSceAppMgr_stub -lSceAppUtil_stub -lScePgf_stub \ - -ljpeg -lfreetype -lc -lSceCommonDialog_stub -lpng16 -lm -lz \ - -lSceGxm_stub -lSceDisplay_stub -lSceSysmodule_stub \ - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin -a texture.bmp=texture.bmp $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample1/main.c b/deps/vitaGL/samples/sample1/main.c deleted file mode 100644 index 45898dd51f..0000000000 --- a/deps/vitaGL/samples/sample1/main.c +++ /dev/null @@ -1,67 +0,0 @@ -// Drawing a fullscreen image on screen with glBegin/glEnd - -#include -#include -#include - -GLenum texture_format = GL_RGB; -GLuint texture = 0; - -int main(){ - - // Initializing graphics device - vglInit(0x800000); - - // Loading BMP image to use as texture - SceUID fd = sceIoOpen("app0:texture.bmp", SCE_O_RDONLY, 0777); - uint16_t w, h; - sceIoLseek(fd, 0x12, SCE_SEEK_SET); - sceIoRead(fd, &w, sizeof(uint16_t)); - sceIoLseek(fd, 0x16, SCE_SEEK_SET); - sceIoRead(fd, &h, sizeof(uint16_t)); - sceIoLseek(fd, 0x26, SCE_SEEK_SET); - uint8_t *buffer = (uint8_t*)malloc(w * h * 3); - sceIoRead(fd, buffer, w * h * 3); - sceIoClose(fd); - - glClearColor(0.50, 0, 0, 0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 960, 544, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // Initializing openGL texture - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - - glTexImage2D(GL_TEXTURE_2D, 0, texture_format, w, h, 0, texture_format, GL_UNSIGNED_BYTE, buffer); - - glEnable(GL_TEXTURE_2D); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBegin(GL_QUADS); - - // Note: BMP images are vertically flipped - glTexCoord2i(0, 1); - glVertex3f(0, 0, 0); - glTexCoord2i(1, 1); - glVertex3f(960, 0, 0); - glTexCoord2i(1, 0); - glVertex3f(960, 544, 0); - glTexCoord2i(0, 0); - glVertex3f(0, 544, 0); - - glEnd(); - vglStopRendering(); - glLoadIdentity(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/samples/sample1/texture.bmp b/deps/vitaGL/samples/sample1/texture.bmp deleted file mode 100644 index cfcc30313b0d18cabd6bc85ec2d78c7c39ce21ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1566774 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

fk71ZTJ@RCw7|rF@=rm*0&*Hv-)V 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

  • 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 zAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F z6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^ zKp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t z2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$P zg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>! zPzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu z0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}n zAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F z6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^ ZKp{{F6as}nAy5bu0);>!up%Px{{sk#eft0a diff --git a/deps/vitaGL/samples/sample2/Makefile b/deps/vitaGL/samples/sample2/Makefile deleted file mode 100644 index 9a385a0fda..0000000000 --- a/deps/vitaGL/samples/sample2/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -SAMPLE_NUM := 002 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lc -lSceCommonDialog_stub -lm -lSceGxm_stub -lSceDisplay_stub -lmathneon -lSceAppMgr_stub - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -debug: CFLAGS += -DDEBUG_BUILD -debug: all - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - cp $< $<.unstripped.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin - diff --git a/deps/vitaGL/samples/sample2/main.c b/deps/vitaGL/samples/sample2/main.c deleted file mode 100644 index 79b2746f44..0000000000 --- a/deps/vitaGL/samples/sample2/main.c +++ /dev/null @@ -1,39 +0,0 @@ -// Drawing a triangle on screen with vertex array - -#include - -float colors[] = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0}; -float vertices[] = {100, 100, 0, 150, 100, 0, 100, 150, 0}; - -int main(){ - - // Initializing graphics device - vglInit(0x800000); - - glClearColor (0.50f, 0.0f, 0.0f, 1.0f); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 960, 544, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertices); - glColorPointer(3, GL_FLOAT, 0, colors); - glDrawArrays(GL_TRIANGLES, 0, 3); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - vglStopRendering(); - - glLoadIdentity(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/samples/sample3/Makefile b/deps/vitaGL/samples/sample3/Makefile deleted file mode 100644 index 887e53b8b7..0000000000 --- a/deps/vitaGL/samples/sample3/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -SAMPLE_NUM := 003 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lSceLibKernel_stub -lSceAppMgr_stub -lSceAppUtil_stub -lmathneon \ - -lc -lSceCommonDialog_stub -lm -lSceGxm_stub -lSceDisplay_stub -lSceSysmodule_stub \ - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample3/main.c b/deps/vitaGL/samples/sample3/main.c deleted file mode 100644 index 97cb9f186e..0000000000 --- a/deps/vitaGL/samples/sample3/main.c +++ /dev/null @@ -1,36 +0,0 @@ -// Drawing a colored quad with glBegin/glEnd - -#include - -int main(){ - - // Initializing graphics device - vglInit(0x800000); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 960, 544, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT); - glBegin(GL_QUADS); - glColor3f(1.0, 0.0, 0.0); - glVertex3f(400, 0, 0); - glColor3f(1.0, 1.0, 0.0); - glVertex3f(800, 0, 0); - glColor3f(0.0, 1.0, 0.0); - glVertex3f(800, 400, 0); - glColor3f(1.0, 0.0, 1.0); - glVertex3f(400, 400, 0); - glEnd(); - vglStopRendering(); - glLoadIdentity(); - } - - vglEnd(); - -} diff --git a/deps/vitaGL/samples/sample4/Makefile b/deps/vitaGL/samples/sample4/Makefile deleted file mode 100644 index 16fdc27ac7..0000000000 --- a/deps/vitaGL/samples/sample4/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -SAMPLE_NUM := 004 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lc -lSceCommonDialog_stub -lm -lSceGxm_stub -lSceDisplay_stub -lmathneon -lSceAppMgr_stub - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample4/main.c b/deps/vitaGL/samples/sample4/main.c deleted file mode 100644 index c1ff0fda96..0000000000 --- a/deps/vitaGL/samples/sample4/main.c +++ /dev/null @@ -1,38 +0,0 @@ -// Drawing a quad on screen with glDrawElements - -#include - -float colors[] = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0}; -float vertices[] = {100, 100, 0, 150, 100, 0, 100, 150, 0, 150, 150, 0}; -uint16_t indices[] = {0, 1, 2, 1, 2, 3}; - -int main(){ - - // Initializing graphics device - vglInit(0x800000); - - glClearColor (0.50f, 0.0f, 0.0f, 1.0f); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 960, 544, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertices); - glColorPointer(3, GL_FLOAT, 0, colors); - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - vglStopRendering(); - glLoadIdentity(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/samples/sample5/Makefile b/deps/vitaGL/samples/sample5/Makefile deleted file mode 100644 index 964bd24cce..0000000000 --- a/deps/vitaGL/samples/sample5/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -SAMPLE_NUM := 005 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lc -lSceCommonDialog_stub -lm -lSceGxm_stub -lSceDisplay_stub -lSceAppMgr_stub -lmathneon - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample5/main.c b/deps/vitaGL/samples/sample5/main.c deleted file mode 100644 index 6b4389c403..0000000000 --- a/deps/vitaGL/samples/sample5/main.c +++ /dev/null @@ -1,75 +0,0 @@ -// Drawing a rotating cube - -#include -#include - -float colors[] = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0}; // Colors for a face - -float vertices_front[] = {-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f}; // Front Face -float vertices_back[] = {-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Back Face -float vertices_left[] = {-0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f}; // Left Face -float vertices_right[] = {0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Right Face -float vertices_top[] = {-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f}; // Top Face -float vertices_bottom[] = {-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Bottom Face - -uint16_t indices[] = { - 0, 1, 2, 1, 2, 3, // Front - 4, 5, 6, 5, 6, 7, // Back - 8, 9,10, 9,10,11, // Left - 12,13,14,13,14,15, // Right - 16,17,18,17,18,19, // Top - 20,21,22,21,22,23 // Bottom -}; - -int main(){ - - // Initializing graphics device - vglInit(0x800000); - vglWaitVblankStart(GL_TRUE); - - // Creating colors array - float color_array[12*6]; - int i; - for (i=0;i<12*6;i++){ - color_array[i] = colors[i % 12]; - } - - // Creating vertices array - float vertex_array[12*6]; - memcpy(&vertex_array[12*0], &vertices_front[0], sizeof(float) * 12); - memcpy(&vertex_array[12*1], &vertices_back[0], sizeof(float) * 12); - memcpy(&vertex_array[12*2], &vertices_left[0], sizeof(float) * 12); - memcpy(&vertex_array[12*3], &vertices_right[0], sizeof(float) * 12); - memcpy(&vertex_array[12*4], &vertices_top[0], sizeof(float) * 12); - memcpy(&vertex_array[12*5], &vertices_bottom[0], sizeof(float) * 12); - - glClearColor (0.0f, 0.0f, 0.0f, 0.0f); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(90.0f, 960.f/544.0f, 0.01f, 100.0f); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, -3.0f); // Centering the cube - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertex_array); - glColorPointer(3, GL_FLOAT, 0, color_array); - glRotatef(1.0f, 0.0f, 0.0f, 1.0f); - glRotatef(0.5f, 0.0f, 1.0f, 0.0f); - glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_SHORT, indices); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - vglStopRendering(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/samples/sample6/Makefile b/deps/vitaGL/samples/sample6/Makefile deleted file mode 100644 index eaf8e9f488..0000000000 --- a/deps/vitaGL/samples/sample6/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -SAMPLE_NUM := 006 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lc -lSceCommonDialog_stub -lm -lSceGxm_stub -lSceDisplay_stub -lmathneon -lSceAppMgr_stub - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample6/main.c b/deps/vitaGL/samples/sample6/main.c deleted file mode 100644 index 817eeecf05..0000000000 --- a/deps/vitaGL/samples/sample6/main.c +++ /dev/null @@ -1,89 +0,0 @@ -// Drawing a rotating cube with VBO - -#include -#include - -#define BUF_OFFS(i) ((void*)(i)) - -float colors[] = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0}; // Colors for a face - -float vertices_front[] = {-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f}; // Front Face -float vertices_back[] = {-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Back Face -float vertices_left[] = {-0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f}; // Left Face -float vertices_right[] = {0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Right Face -float vertices_top[] = {-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f}; // Top Face -float vertices_bottom[] = {-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Bottom Face - -GLuint buffers[2]; - -uint16_t indices[] = { - 0, 1, 2, 1, 2, 3, // Front - 4, 5, 6, 5, 6, 7, // Back - 8, 9,10, 9,10,11, // Left - 12,13,14,13,14,15, // Right - 16,17,18,17,18,19, // Top - 20,21,22,21,22,23 // Bottom -}; - -int main(){ - - // Initializing graphics device - vglInit(0x80000); - vglWaitVblankStart(GL_TRUE); - - // Creating VBO data with vertices + colors - float vbo[12*12]; - memcpy(&vbo[12*0], &vertices_front[0], sizeof(float) * 12); - memcpy(&vbo[12*1], &vertices_back[0], sizeof(float) * 12); - memcpy(&vbo[12*2], &vertices_left[0], sizeof(float) * 12); - memcpy(&vbo[12*3], &vertices_right[0], sizeof(float) * 12); - memcpy(&vbo[12*4], &vertices_top[0], sizeof(float) * 12); - memcpy(&vbo[12*5], &vertices_bottom[0], sizeof(float) * 12); - memcpy(&vbo[12*6], &colors[0], sizeof(float) * 12); - memcpy(&vbo[12*7], &colors[0], sizeof(float) * 12); - memcpy(&vbo[12*8], &colors[0], sizeof(float) * 12); - memcpy(&vbo[12*9], &colors[0], sizeof(float) * 12); - memcpy(&vbo[12*10], &colors[0], sizeof(float) * 12); - memcpy(&vbo[12*11], &colors[0], sizeof(float) * 12); - - // Creating two buffers for colors, vertices and indices - glGenBuffers(2, buffers); - - // Setting up VBO - glBindBuffer(GL_ARRAY_BUFFER, buffers[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 12 * 12, vbo, GL_STATIC_DRAW); - - // Setting up indices array - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t) * 6 * 6, indices, GL_STATIC_DRAW); - - glClearColor (0.0f, 0.0f, 0.0f, 0.0f); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(90.0f, 960.f/544.0f, 0.01f, 100.0f); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, -3.0f); // Centering the cube - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, BUF_OFFS(0)); - glColorPointer(3, GL_FLOAT, 0, BUF_OFFS(12*6*sizeof(float))); - glRotatef(1.0f, 0.0f, 0.0f, 1.0f); - glRotatef(0.5f, 1.0f, 0.0f, 0.0f); - glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_SHORT, BUF_OFFS(0)); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - vglStopRendering(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/samples/sample7/Makefile b/deps/vitaGL/samples/sample7/Makefile deleted file mode 100644 index 8b33dfa4f8..0000000000 --- a/deps/vitaGL/samples/sample7/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -SAMPLE_NUM := 007 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lSceLibKernel_stub -lScePvf_stub \ - -lSceAppMgr_stub -lSceAppUtil_stub -lScePgf_stub \ - -ljpeg -lfreetype -lc -lSceCommonDialog_stub -lpng16 -lm -lz \ - -lSceGxm_stub -lSceDisplay_stub -lSceSysmodule_stub -lmathneon - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin -a texture.bmp=texture.bmp $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample7/main.c b/deps/vitaGL/samples/sample7/main.c deleted file mode 100644 index 556bdad738..0000000000 --- a/deps/vitaGL/samples/sample7/main.c +++ /dev/null @@ -1,91 +0,0 @@ -// Drawing a fullscreen image on screen with glBegin/glEnd - -#include -#include -#include - -GLenum texture_format = GL_RGB; -GLuint texture = 0; - -float colors[] = {0.4, 0.1, 0.3, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0}; -float vertices[] = {100, 100, 0, 150, 100, 0, 100, 150, 0}; - -int main(){ - - // Initializing graphics device - vglInit(0x800000); - - // Loading BMP image to use as texture - SceUID fd = sceIoOpen("app0:texture.bmp", SCE_O_RDONLY, 0777); - uint16_t w, h; - sceIoLseek(fd, 0x12, SCE_SEEK_SET); - sceIoRead(fd, &w, sizeof(uint16_t)); - sceIoLseek(fd, 0x16, SCE_SEEK_SET); - sceIoRead(fd, &h, sizeof(uint16_t)); - sceIoLseek(fd, 0x26, SCE_SEEK_SET); - uint8_t *buffer = (uint8_t*)malloc(w * h * 3); - sceIoRead(fd, buffer, w * h * 3); - sceIoClose(fd); - - glClearColor(0.50, 0, 0, 0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, 960, 544, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // Initializing openGL texture - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, texture_format, w, h, 0, texture_format, GL_UNSIGNED_BYTE, buffer); - glEnable(GL_TEXTURE_2D); - - // Initializing framebuffer - GLuint fb; - glGenFramebuffers(1, &fb); - glBindFramebuffer(GL_FRAMEBUFFER, fb); - - // Binding texture to framebuffer - glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0); - - // Drawing on texture - vglStartRendering(); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertices); - glColorPointer(3, GL_FLOAT, 0, colors); - glDrawArrays(GL_TRIANGLES, 0, 3); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - vglStopRendering(); - glFinish(); - glLoadIdentity(); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glBegin(GL_QUADS); - - // Note: BMP images are vertically flipped - glTexCoord2i(0, 1); - glVertex3f(0, 0, 0); - glTexCoord2i(1, 1); - glVertex3f(960, 0, 0); - glTexCoord2i(1, 0); - glVertex3f(960, 544, 0); - glTexCoord2i(0, 0); - glVertex3f(0, 544, 0); - - glEnd(); - vglStopRendering(); - glLoadIdentity(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/samples/sample7/texture.bmp b/deps/vitaGL/samples/sample7/texture.bmp deleted file mode 100644 index cfcc30313b0d18cabd6bc85ec2d78c7c39ce21ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1566774 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

    fk71ZTJ@RCw7|rF@=rm*0&*Hv-)V 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

  • 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 zAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F z6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^ zKp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t z2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$P zg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>! zPzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu z0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}n zAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F z6as}nAy5bu0);>!PzV$Pg+L)t2owT^Kp{{F6as}nAy5bu0);>!PzV$Pg+L)t2owT^ ZKp{{F6as}nAy5bu0);>!up%Px{{sk#eft0a diff --git a/deps/vitaGL/samples/sample8/Makefile b/deps/vitaGL/samples/sample8/Makefile deleted file mode 100644 index 68a1481bd6..0000000000 --- a/deps/vitaGL/samples/sample8/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -SAMPLE_NUM := 008 -TARGET := vitaGL-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitaGL -lc -lSceCommonDialog_stub -lm -lSceGxm_stub -lSceDisplay_stub -lSceAppMgr_stub -lmathneon - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VITAGL$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -at 0x0E -m 0x10000 $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaGL/samples/sample8/main.c b/deps/vitaGL/samples/sample8/main.c deleted file mode 100644 index 9a7feee685..0000000000 --- a/deps/vitaGL/samples/sample8/main.c +++ /dev/null @@ -1,76 +0,0 @@ -// Drawing a rotating cube - -#include -#include - -float colors[] = {1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0}; // Colors for a face - -float vertices_front[] = {-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f}; // Front Face -float vertices_back[] = {-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Back Face -float vertices_left[] = {-0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f}; // Left Face -float vertices_right[] = {0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Right Face -float vertices_top[] = {-0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f}; // Top Face -float vertices_bottom[] = {-0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f}; // Bottom Face - -uint16_t indices[] = { - 0, 1, 2, 1, 2, 3, // Front - 4, 5, 6, 5, 6, 7, // Back - 8, 9,10, 9,10,11, // Left - 12,13,14,13,14,15, // Right - 16,17,18,17,18,19, // Top - 20,21,22,21,22,23 // Bottom -}; - -int main(){ - - // Initializing graphics device - vglSetParamBufferSize(2 * 1024 * 1024); - vglInitWithCustomSizes(0x1000, 960, 544, 16 * 1024 * 1024, 0, 0, SCE_GXM_MULTISAMPLE_4X); - vglWaitVblankStart(GL_TRUE); - - // Creating colors array - float color_array[12*6]; - int i; - for (i=0;i<12*6;i++){ - color_array[i] = colors[i % 12]; - } - - // Creating vertices array - float vertex_array[12*6]; - memcpy(&vertex_array[12*0], &vertices_front[0], sizeof(float) * 12); - memcpy(&vertex_array[12*1], &vertices_back[0], sizeof(float) * 12); - memcpy(&vertex_array[12*2], &vertices_left[0], sizeof(float) * 12); - memcpy(&vertex_array[12*3], &vertices_right[0], sizeof(float) * 12); - memcpy(&vertex_array[12*4], &vertices_top[0], sizeof(float) * 12); - memcpy(&vertex_array[12*5], &vertices_bottom[0], sizeof(float) * 12); - - glClearColor (0.0f, 0.0f, 0.0f, 0.0f); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - gluPerspective(90.0f, 960.f/544.0f, 0.01f, 100.0f); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, -3.0f); // Centering the cube - - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - - for (;;){ - vglStartRendering(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, vertex_array); - glColorPointer(3, GL_FLOAT, 0, color_array); - glRotatef(1.0f, 0.0f, 0.0f, 1.0f); - glRotatef(0.5f, 0.0f, 1.0f, 0.0f); - glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_SHORT, indices); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - vglStopRendering(); - } - - vglEnd(); - -} \ No newline at end of file diff --git a/deps/vitaGL/shaders/clear_f.cg b/deps/vitaGL/shaders/clear_f.cg deleted file mode 100644 index aa28edf821..0000000000 --- a/deps/vitaGL/shaders/clear_f.cg +++ /dev/null @@ -1,4 +0,0 @@ -float4 main(uniform float4 u_clear_color) : COLOR -{ - return u_clear_color; -} diff --git a/deps/vitaGL/shaders/clear_v.cg b/deps/vitaGL/shaders/clear_v.cg deleted file mode 100644 index 95a138108a..0000000000 --- a/deps/vitaGL/shaders/clear_v.cg +++ /dev/null @@ -1,7 +0,0 @@ -float4 main(unsigned int idx : INDEX, uniform float4 position) : POSITION -{ - float x = (idx == 1 || idx == 2) ? position[1] : position[0]; - float y = (idx == 2 || idx == 3) ? position[3] : position[2]; - - return float4(x, y, 1.f, 1.f); -} diff --git a/deps/vitaGL/shaders/disable_color_buffer_f.cg b/deps/vitaGL/shaders/disable_color_buffer_f.cg deleted file mode 100644 index 0202ff51c2..0000000000 --- a/deps/vitaGL/shaders/disable_color_buffer_f.cg +++ /dev/null @@ -1,5 +0,0 @@ -float main( - uniform float depth_clear) : DEPTH -{ - return depth_clear; -} diff --git a/deps/vitaGL/shaders/rgb_v.cg b/deps/vitaGL/shaders/rgb_v.cg deleted file mode 100644 index e4f62b03e6..0000000000 --- a/deps/vitaGL/shaders/rgb_v.cg +++ /dev/null @@ -1,11 +0,0 @@ -void main( - float3 aPosition, - float3 aColor, - column_major uniform float4x4 wvp, - float4 out vPosition: POSITION, - float4 out vColor: COLOR) -{ - vPosition = mul(float4(aPosition, 1.f), wvp); - vColor = float4(aColor, 1.f); -} - diff --git a/deps/vitaGL/shaders/rgba_f.cg b/deps/vitaGL/shaders/rgba_f.cg deleted file mode 100644 index 39ef1af00c..0000000000 --- a/deps/vitaGL/shaders/rgba_f.cg +++ /dev/null @@ -1,4 +0,0 @@ -float4 main(float4 vColor : COLOR) : COLOR -{ - return vColor; -} diff --git a/deps/vitaGL/shaders/rgba_v.cg b/deps/vitaGL/shaders/rgba_v.cg deleted file mode 100644 index 93786fd01e..0000000000 --- a/deps/vitaGL/shaders/rgba_v.cg +++ /dev/null @@ -1,11 +0,0 @@ -void main( - float3 aPosition, - float4 aColor, - column_major uniform float4x4 wvp, - float4 out vPosition: POSITION, - float4 out vColor: COLOR) -{ - vPosition = mul(float4(aPosition, 1.f), wvp); - vColor = aColor; -} - diff --git a/deps/vitaGL/shaders/texture2d_f.cg b/deps/vitaGL/shaders/texture2d_f.cg deleted file mode 100644 index 2d202f7a9d..0000000000 --- a/deps/vitaGL/shaders/texture2d_f.cg +++ /dev/null @@ -1,83 +0,0 @@ -float4 main( - float2 vTexcoord : TEXCOORD0, - float4 coords: WPOS, - uniform sampler2D tex, - uniform float alphaCut, - uniform int alphaOp, - uniform float4 tintColor, - uniform int texEnv, - uniform int fog_mode, - uniform float4 fogColor, - uniform float4 texEnvColor, - uniform float fog_near, - uniform float fog_far, - uniform float fog_density - ) -{ - float4 texColor = tex2D(tex, vTexcoord); - - // Texture Environment - if (texEnv < 4){ - if (texEnv == 0){ // GL_MODULATE - texColor = texColor * tintColor; - }else if (texEnv == 1){ // GL_DECAL - texColor.rgb = lerp(tintColor.rgb, texColor.rgb, texColor.a); - texColor.a = tintColor.a; - }else if (texEnv == 2){ // GL_BLEND - texColor.rgb = lerp(tintColor.rgb, texEnvColor.rgb, texColor.rgb); - texColor.a = texColor.a * tintColor.a; - }else{ // GL_ADD - texColor.rgb = clamp(texColor.rgb + tintColor.rgb, 0.0, 1.0); - texColor.a = texColor.a * tintColor.a; - } - } - - // Alpha Test - if (alphaOp < 7){ - if (alphaOp == 0){ - if (texColor.a < alphaCut){ - discard; - } - }else if (alphaOp == 1){ - if (texColor.a <= alphaCut){ - discard; - } - }else if (alphaOp == 2){ - if (texColor.a == alphaCut){ - discard; - } - }else if (alphaOp == 3){ - if (texColor.a != alphaCut){ - discard; - } - }else if (alphaOp == 4){ - if (texColor.a > alphaCut){ - discard; - } - }else if (alphaOp == 5){ - if (texColor.a >= alphaCut){ - discard; - } - }else{ - discard; - } - } - - // Fogging - if (fog_mode < 3){ - float vFog; - if (fog_mode == 0){ // GL_LINEAR - vFog = (fog_far - coords.z) / (fog_far - fog_near); - }else if (fog_mode == 1){ // GL_EXP - vFog = exp(-fog_density * coords.z); - }else{ // GL_EXP2 - const float LOG2 = -1.442695; - float d = fog_density * coords.z; - vFog = exp(d * d * LOG2); - } - vFog = clamp(vFog, 0.0, 1.0); - texColor.rgb = lerp(fogColor.rgb, texColor.rgb, vFog); - } - - return texColor; -} diff --git a/deps/vitaGL/shaders/texture2d_rgba_f.cg b/deps/vitaGL/shaders/texture2d_rgba_f.cg deleted file mode 100644 index f76328fdf9..0000000000 --- a/deps/vitaGL/shaders/texture2d_rgba_f.cg +++ /dev/null @@ -1,83 +0,0 @@ -float4 main( - float2 vTexcoord : TEXCOORD0, - float4 vColor : COLOR, - float4 coords: WPOS, - uniform sampler2D tex, - uniform float alphaCut, - uniform int alphaOp, - uniform int texEnv, - uniform int fog_mode, - uniform float4 fogColor, - uniform float4 texEnvColor, - uniform float fog_near, - uniform float fog_far, - uniform float fog_density - ) -{ - float4 texColor = tex2D(tex, vTexcoord); - - // Texture Environment - if (texEnv < 4){ - if (texEnv == 0){ // GL_MODULATE - texColor = texColor * vColor; - }else if (texEnv == 1){ // GL_DECAL - texColor.rgb = lerp(vColor.rgb, texColor.rgb, texColor.a); - texColor.a = vColor.a; - }else if (texEnv == 2){ // GL_BLEND - texColor.rgb = lerp(vColor.rgb, texEnvColor.rgb, texColor.rgb); - texColor.a = texColor.a * vColor.a; - }else{ // GL_ADD - texColor.rgb = clamp(texColor.rgb + vColor.rgb, 0.0, 1.0); - texColor.a = texColor.a * vColor.a; - } - } - - // Alpha Test - if (alphaOp < 7){ - if (alphaOp == 0){ - if (texColor.a < alphaCut){ - discard; - } - }else if (alphaOp == 1){ - if (texColor.a <= alphaCut){ - discard; - } - }else if (alphaOp == 2){ - if (texColor.a == alphaCut){ - discard; - } - }else if (alphaOp == 3){ - if (texColor.a != alphaCut){ - discard; - } - }else if (alphaOp == 4){ - if (texColor.a > alphaCut){ - discard; - } - }else if (alphaOp == 5){ - if (texColor.a >= alphaCut){ - discard; - } - }else{ - discard; - } - } - - // Fogging - if (fog_mode < 3){ - float vFog; - if (fog_mode == 0){ // GL_LINEAR - vFog = (fog_far - coords.z) / (fog_far - fog_near); - }else if (fog_mode == 1){ // GL_EXP - vFog = exp(-fog_density * coords.z); - }else{ // GL_EXP2 - const float LOG2 = -1.442695; - float d = fog_density * coords.z; - vFog = exp(d * d * LOG2); - } - vFog = clamp(vFog, 0.0, 1.0); - texColor.rgb = lerp(fogColor.rgb, texColor.rgb, vFog); - } - - return texColor; -} diff --git a/deps/vitaGL/shaders/texture2d_rgba_v.cg b/deps/vitaGL/shaders/texture2d_rgba_v.cg deleted file mode 100644 index a1bf531855..0000000000 --- a/deps/vitaGL/shaders/texture2d_rgba_v.cg +++ /dev/null @@ -1,27 +0,0 @@ -void main( - float3 position, - float2 texcoord, - float4 color, - column_major uniform float4x4 wvp, - uniform int clip_plane0, // In the future this can turn into an array to support other planes - uniform float4 clip_plane0_eq, // In the future this can turn into an array to support other planes - uniform float4x4 modelview, - float4 out vPosition : POSITION, - float2 out vTexcoord : TEXCOORD0, - float4 out vColor : COLOR, - float out vClip : CLP0) -{ - float4 pos4 = float4(position, 1.f); - - // User clip planes - if (clip_plane0 < 1) { - vClip = 1.f; - } else { - float4 modelpos = mul(modelview, pos4); - vClip = dot(modelpos, clip_plane0_eq); - } - - vPosition = mul(pos4, wvp); - vTexcoord = texcoord; - vColor = color; -} diff --git a/deps/vitaGL/shaders/texture2d_v.cg b/deps/vitaGL/shaders/texture2d_v.cg deleted file mode 100644 index 5111a38ab3..0000000000 --- a/deps/vitaGL/shaders/texture2d_v.cg +++ /dev/null @@ -1,24 +0,0 @@ -void main( - float3 position, - float2 texcoord, - column_major uniform float4x4 wvp, - uniform int clip_plane0, // In the future this can turn into an array to support other planes - uniform float4 clip_plane0_eq, // In the future this can turn into an array to support other planes - uniform float4x4 modelview, - float4 out vPosition : POSITION, - float2 out vTexcoord : TEXCOORD0, - float out vClip : CLP0) -{ - float4 pos4 = float4(position, 1.f); - - // User clip planes - if (clip_plane0 < 1) { - vClip = 1.f; - } else { - float4 modelpos = mul(modelview, pos4); - vClip = dot(modelpos, clip_plane0_eq); - } - - vPosition = mul(pos4, wvp); - vTexcoord = texcoord; -} diff --git a/deps/vitaGL/source/custom_shaders.c b/deps/vitaGL/source/custom_shaders.c deleted file mode 100644 index 398cb2a8c3..0000000000 --- a/deps/vitaGL/source/custom_shaders.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * custom_shaders.c: - * Implementation for custom shaders feature - */ - -#include "shared.h" - -#define MAX_CUSTOM_SHADERS 128 // Maximum number of linkable custom shaders -#define MAX_SHADER_PARAMS 8 // Maximum number of parameters per custom shader - -// Internal stuffs -void *frag_uniforms = NULL; -void *vert_uniforms = NULL; -uint8_t use_shark = 1; // Flag to check if vitaShaRK should be initialized at vitaGL boot -uint8_t is_shark_online = 0; // Current vitaShaRK status - -#ifdef HAVE_SHARK -// Internal runtime shader compiler settings -static int32_t compiler_fastmath = 0; -static int32_t compiler_fastprecision = 0; -static int32_t compiler_fastint = 0; -static shark_opt compiler_opts = SHARK_OPT_DEFAULT; -#endif - -GLuint cur_program = 0; // Current in use custom program (0 = No custom program) - -// Uniform struct -typedef struct uniform { - GLboolean isVertex; - const SceGxmProgramParameter *ptr; - void *chain; -} uniform; - -// Generic shader struct -typedef struct shader { - GLenum type; - GLboolean valid; - SceGxmShaderPatcherId id; - const SceGxmProgram *prog; - uint32_t size; - char *log; -} shader; - -// Program struct holding vertex/fragment shader info -typedef struct program { - shader *vshader; - shader *fshader; - GLboolean valid; - SceGxmVertexAttribute attr[MAX_SHADER_PARAMS]; - SceGxmVertexStream stream[MAX_SHADER_PARAMS]; - SceGxmVertexProgram *vprog; - SceGxmFragmentProgram *fprog; - GLuint attr_num; - GLuint stream_num; - const SceGxmProgramParameter *wvp; - uniform *uniforms; - uniform *last_uniform; -} program; - -// Internal shaders array -static shader shaders[MAX_CUSTOM_SHADERS]; - -// Internal programs array -static program progs[MAX_CUSTOM_SHADERS / 2]; - -void resetCustomShaders(void) { - // Init custom shaders - int i; - for (i = 0; i < MAX_CUSTOM_SHADERS; i++) { - shaders[i].valid = 0; - shaders[i].log = NULL; - progs[i >> 1].valid = 0; - } -} - -void changeCustomShadersBlend(SceGxmBlendInfo *blend_info) { - int j; - for (j = 0; j < MAX_CUSTOM_SHADERS / 2; j++) { - program *p = &progs[j]; - if (p->valid) { - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - p->fshader->id, - SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa_mode, - blend_info, - p->vshader->prog, - &p->fprog); - } - } -} - -void reloadCustomShader(void) { - if (cur_program == 0) - return; - program *p = &progs[cur_program - 1]; - sceGxmSetVertexProgram(gxm_context, p->vprog); - sceGxmSetFragmentProgram(gxm_context, p->fprog); - vert_uniforms = NULL; - frag_uniforms = NULL; -} - -void _vglDrawObjects_CustomShadersIMPL(GLenum mode, GLsizei count, GLboolean implicit_wvp) { - if (implicit_wvp) { - program *p = &progs[cur_program - 1]; - if (mvp_modified) { - matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix); - mvp_modified = GL_FALSE; - } - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - if (p->wvp == NULL) - p->wvp = sceGxmProgramFindParameterByName(p->vshader->prog, "wvp"); - sceGxmSetUniformDataF(vert_uniforms, p->wvp, 0, 16, (const float *)mvp_matrix); - } -} - -#if defined(HAVE_SHARK) && defined(HAVE_SHARK_LOG) -static char *shark_log = NULL; -void shark_log_cb(const char *msg, shark_log_level msg_level, int line) { - uint8_t append = shark_log != NULL; - char newline[1024]; - switch (msg_level) { - case SHARK_LOG_INFO: - sprintf(newline, "%sI] %s on line %d", append ? "\n" : "", msg, line); - break; - case SHARK_LOG_WARNING: - sprintf(newline, "%sW] %s on line %d", append ? "\n" : "", msg, line); - break; - case SHARK_LOG_ERROR: - sprintf(newline, "%sE] %s on line %d", append ? "\n" : "", msg, line); - break; - } - uint32_t size = (append ? strlen(shark_log) : 0) + strlen(newline); - shark_log = realloc(shark_log, size + 1); - if (append) - sprintf(shark_log, "%s%s", shark_log, newline); - else - strcpy(shark_log, newline); -} -#endif - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ -void vglSetupRuntimeShaderCompiler(shark_opt opt_level, int32_t use_fastmath, int32_t use_fastprecision, int32_t use_fastint) { -#ifdef HAVE_SHARK - compiler_opts = opt_level; - compiler_fastmath = use_fastmath; - compiler_fastprecision = use_fastprecision; - compiler_fastint = use_fastint; -#endif -} - -void vglEnableRuntimeShaderCompiler(GLboolean usage) { - use_shark = usage; -} - -GLuint glCreateShader(GLenum shaderType) { - // Looking for a free shader slot - GLuint i, res = 0; - for (i = 1; i < MAX_CUSTOM_SHADERS; i++) { - if (!(shaders[i - 1].valid)) { - res = i; - break; - } - } - - // All shader slots are busy, exiting call - if (res == 0) - return res; - - // Reserving and initializing shader slot - switch (shaderType) { - case GL_FRAGMENT_SHADER: - shaders[res - 1].type = GL_FRAGMENT_SHADER; - break; - case GL_VERTEX_SHADER: - shaders[res - 1].type = GL_VERTEX_SHADER; - break; - default: - vgl_error = GL_INVALID_ENUM; - return 0; - break; - } - shaders[res - 1].valid = GL_TRUE; - - return res; -} - -void glGetShaderiv(GLuint handle, GLenum pname, GLint *params) { - // Grabbing passed shader - shader *s = &shaders[handle - 1]; - - switch (pname) { - case GL_SHADER_TYPE: - *params = s->type; - break; - case GL_COMPILE_STATUS: - *params = s->prog ? GL_TRUE : GL_FALSE; - break; - case GL_INFO_LOG_LENGTH: - *params = s->log ? strlen(s->log) : 0; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glGetShaderInfoLog(GLuint handle, GLsizei maxLength, GLsizei *length, GLchar *infoLog) { -#ifndef SKIP_ERROR_HANDLING - if (maxLength < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Grabbing passed shader - shader *s = &shaders[handle - 1]; - - if (s->log) { - *length = min(strlen(s->log), maxLength); - memcpy_neon(infoLog, s->log, *length); - } -} - -void glShaderSource(GLuint handle, GLsizei count, const GLchar *const *string, const GLint *length) { -#ifndef SKIP_ERROR_HANDLING - if (count < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - if (!is_shark_online) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } - - // Grabbing passed shader - shader *s = &shaders[handle - 1]; - - // Temporarily setting prog to point to the shader source - s->prog = (SceGxmProgram *)*string; - s->size = length ? *length : strlen(*string); -} - -void glShaderBinary(GLsizei count, const GLuint *handles, GLenum binaryFormat, const void *binary, GLsizei length) { - // Grabbing passed shader - shader *s = &shaders[handles[0] - 1]; - - // Allocating compiled shader on RAM and registering it into sceGxmShaderPatcher - s->prog = (SceGxmProgram *)malloc(length); - memcpy_neon((void *)s->prog, binary, length); - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, s->prog, &s->id); - s->prog = sceGxmShaderPatcherGetProgramFromId(s->id); -} - -uint8_t shader_idxs = 0; -void glCompileShader(GLuint handle) { - // If vitaShaRK is not enabled, we just error out - if (!is_shark_online) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#ifdef HAVE_SHARK - // Grabbing passed shader - shader *s = &shaders[handle - 1]; - - // Compiling shader source - s->prog = shark_compile_shader_extended((const char *)s->prog, &s->size, s->type == GL_FRAGMENT_SHADER ? SHARK_FRAGMENT_SHADER : SHARK_VERTEX_SHADER, compiler_opts, compiler_fastmath, compiler_fastprecision, compiler_fastint); - if (s->prog) { - SceGxmProgram *res = (SceGxmProgram *)malloc(s->size); - memcpy_neon((void *)res, (void *)s->prog, s->size); - s->prog = res; - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, s->prog, &s->id); - s->prog = sceGxmShaderPatcherGetProgramFromId(s->id); - } -#ifdef HAVE_SHARK_LOG - s->log = shark_log; - shark_log = NULL; -#endif - shark_clear_output(); -#endif -} - -void glDeleteShader(GLuint shad) { - // Grabbing passed shader - shader *s = &shaders[shad - 1]; - - // Deallocating shader and unregistering it from sceGxmShaderPatcher - if (s->valid) { - sceGxmShaderPatcherForceUnregisterProgram(gxm_shader_patcher, s->id); - free((void *)s->prog); - if (s->log) - free(s->log); - } - s->log = NULL; - s->valid = GL_FALSE; -} - -void glAttachShader(GLuint prog, GLuint shad) { - // Grabbing passed shader and program - shader *s = &shaders[shad - 1]; - program *p = &progs[prog - 1]; - - // Attaching shader to desired program - if (p->valid && s->valid) { - switch (s->type) { - case GL_VERTEX_SHADER: - p->vshader = s; - break; - case GL_FRAGMENT_SHADER: - p->fshader = s; - break; - default: - break; - } - } else { - SET_GL_ERROR(GL_INVALID_VALUE) - } -} - -GLuint glCreateProgram(void) { - // Looking for a free program slot - GLuint i, res = 0; - for (i = 1; i < (MAX_CUSTOM_SHADERS / 2); i++) { - // Program slot found, reserving and initializing it - if (!(progs[i - 1].valid)) { - res = i; - progs[i - 1].valid = GL_TRUE; - progs[i - 1].attr_num = 0; - progs[i - 1].wvp = NULL; - progs[i - 1].uniforms = NULL; - progs[i - 1].last_uniform = NULL; - break; - } - } - return res; -} - -void glDeleteProgram(GLuint prog) { - // Grabbing passed program - program *p = &progs[prog - 1]; - - // Releasing both vertex and fragment programs from sceGxmShaderPatcher - if (p->valid) { - unsigned int count, i; - sceGxmShaderPatcherGetFragmentProgramRefCount(gxm_shader_patcher, p->fprog, &count); - for (i = 0; i < count; i++) { - sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, p->fprog); - sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, p->vprog); - } - while (p->uniforms != NULL) { - uniform *old = p->uniforms; - p->uniforms = (uniform *)p->uniforms->chain; - free(old); - } - } - p->valid = GL_FALSE; -} - -void glLinkProgram(GLuint progr) { - // Grabbing passed program - program *p = &progs[progr - 1]; - - // Creating fragment and vertex program via sceGxmShaderPatcher - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - p->vshader->id, p->attr, p->attr_num, - p->stream, p->stream_num, &p->vprog); - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - p->fshader->id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa_mode, NULL, p->vshader->prog, - &p->fprog); -} - -void glUseProgram(GLuint prog) { - // Setting current custom program to passed program - cur_program = prog; - - // Setting in-use vertex and fragment program in sceGxm - reloadCustomShader(); -} - -GLint glGetUniformLocation(GLuint prog, const GLchar *name) { - // Grabbing passed program - program *p = &progs[prog - 1]; - - uniform *res = (uniform *)malloc(sizeof(uniform)); - res->chain = NULL; - - // Checking if parameter is a vertex or fragment related one - res->ptr = sceGxmProgramFindParameterByName(p->vshader->prog, name); - res->isVertex = GL_TRUE; - if (res->ptr == NULL) { - res->ptr = sceGxmProgramFindParameterByName(p->fshader->prog, name); - res->isVertex = GL_FALSE; - } - - if (res->ptr == NULL) { - free(res); - return -1; - } - - if (p->last_uniform != NULL) - p->last_uniform->chain = (void *)res; - p->last_uniform = res; - - return (GLint)res; -} - -void glUniform1i(GLint location, GLint v0) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - float v0_f = (float)v0; - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 1, &v0_f); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - float v0_f = (float)v0; - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 1, &v0_f); - } -} - -void glUniform2i(GLint location, GLint v0, GLint v1) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - float v0_f[2]; - v0_f[0] = (float)v0; - v0_f[1] = (float)v1; - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 2, v0_f); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - float v0_f[2]; - v0_f[0] = (float)v0; - v0_f[1] = (float)v1; - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 2, v0_f); - } -} - -void glUniform1f(GLint location, GLfloat v0) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 1, &v0); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 1, &v0); - } -} - -void glUniform2f(GLint location, GLfloat v0, GLfloat v1) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - float v0_f[2]; - v0_f[0] = v0; - v0_f[1] = v1; - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 2, v0_f); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - float v0_f[2]; - v0_f[0] = v0; - v0_f[1] = v1; - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 2, v0_f); - } -} - -void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 2 * count, value); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 2 * count, value); - } -} - -void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 3 * count, value); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 3 * count, value); - } -} - -void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - float v[4] = { v0, v1, v2, v3 }; - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 4, v); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 4, v); - } -} - -void glUniform4fv(GLint location, GLsizei count, const GLfloat *value) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 4 * count, value); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 4 * count, value); - } -} - -void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { - // Checking if the uniform does exist - if (location == -1) - return; - - // Grabbing passed uniform - uniform *u = (uniform *)location; - if (u->ptr == NULL) - return; - - // Setting passed value to desired uniform - if (u->isVertex) { - if (vert_uniforms == NULL) - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vert_uniforms); - sceGxmSetUniformDataF(vert_uniforms, u->ptr, 0, 16 * count, value); - } else { - if (frag_uniforms == NULL) - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &frag_uniforms); - sceGxmSetUniformDataF(frag_uniforms, u->ptr, 0, 16 * count, value); - } -} - -/* - * ------------------------------ - * - VGL_EXT_gxp_shaders - - * ------------------------------ - */ - -// Equivalent of glBindAttribLocation but for sceGxm architecture -void vglBindAttribLocation(GLuint prog, GLuint index, const GLchar *name, const GLuint num, const GLenum type) { - // Grabbing passed program - program *p = &progs[prog - 1]; - SceGxmVertexAttribute *attributes = &p->attr[index]; - SceGxmVertexStream *streams = &p->stream[index]; - - // Looking for desired parameter in requested program - const SceGxmProgramParameter *param = sceGxmProgramFindParameterByName(p->vshader->prog, name); - if (param == NULL) - return; - - // Setting stream index and offset values - attributes->streamIndex = index; - attributes->offset = 0; - - // Detecting attribute format and size - int bpe; - switch (type) { - case GL_FLOAT: - attributes->format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - bpe = sizeof(float); - break; - case GL_SHORT: - attributes->format = SCE_GXM_ATTRIBUTE_FORMAT_S16N; - bpe = sizeof(int16_t); - break; - case GL_UNSIGNED_BYTE: - attributes->format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; - bpe = sizeof(uint8_t); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Setting various info about the stream - attributes->componentCount = num; - attributes->regIndex = sceGxmProgramParameterGetResourceIndex(param); - streams->stride = bpe * num; - streams->indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - if (index >= p->attr_num) { - p->attr_num = index + 1; - p->stream_num = index + 1; - } -} - -// Equivalent of glBindAttribLocation but for sceGxm architecture when packed attributes are used -GLint vglBindPackedAttribLocation(GLuint prog, const GLchar *name, const GLuint num, const GLenum type, GLuint offset, GLint stride) { - // Grabbing passed program - program *p = &progs[prog - 1]; - SceGxmVertexAttribute *attributes = &p->attr[p->attr_num]; - SceGxmVertexStream *streams = &p->stream[0]; - - // Looking for desired parameter in requested program - const SceGxmProgramParameter *param = sceGxmProgramFindParameterByName(p->vshader->prog, name); - if (param == NULL) - return GL_FALSE; - - // Setting stream index and offset values - attributes->streamIndex = 0; - attributes->offset = offset; - - // Detecting attribute format and size - int bpe; - switch (type) { - case GL_FLOAT: - attributes->format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - bpe = sizeof(float); - break; - case GL_SHORT: - attributes->format = SCE_GXM_ATTRIBUTE_FORMAT_S16N; - bpe = sizeof(int16_t); - break; - case GL_UNSIGNED_BYTE: - attributes->format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; - bpe = sizeof(uint8_t); - break; - default: - vgl_error = GL_INVALID_ENUM; - return GL_FALSE; - break; - } - - // Setting various info about the stream - attributes->componentCount = num; - attributes->regIndex = sceGxmProgramParameterGetResourceIndex(param); - streams->stride = stride ? stride : bpe * num; - streams->indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - p->stream_num = 1; - p->attr_num++; - - return GL_TRUE; -} - -// Equivalent of glVertexAttribPointer but for sceGxm architecture -void vglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint count, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (stride < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Detecting type size - int bpe; - switch (type) { - case GL_FLOAT: - bpe = sizeof(GLfloat); - break; - case GL_SHORT: - bpe = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Allocating enough memory on vitaGL mempool - void *ptr = gpu_pool_memalign(count * bpe * size, bpe * size); - - // Copying passed data to vitaGL mempool - if (stride == 0) - memcpy_neon(ptr, pointer, count * bpe * size); // Faster if stride == 0 - else { - int i; - uint8_t *dst = (uint8_t *)ptr; - uint8_t *src = (uint8_t *)pointer; - for (i = 0; i < count; i++) { - memcpy_neon(dst, src, bpe * size); - dst += (bpe * size); - src += stride; - } - } - - // Setting vertex stream to passed index in sceGxm - sceGxmSetVertexStream(gxm_context, index, ptr); -} - -void vglVertexAttribPointerMapped(GLuint index, const GLvoid *pointer) { - // Setting vertex stream to passed index in sceGxm - sceGxmSetVertexStream(gxm_context, index, pointer); -} diff --git a/deps/vitaGL/source/framebuffers.c b/deps/vitaGL/source/framebuffers.c deleted file mode 100644 index a93ad24148..0000000000 --- a/deps/vitaGL/source/framebuffers.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * framebuffers.c: - * Implementation for framebuffers related functions - */ - -#include "shared.h" - -static framebuffer framebuffers[BUFFERS_NUM]; // Framebuffers array - -framebuffer *active_read_fb = NULL; // Current readback framebuffer in use -framebuffer *active_write_fb = NULL; // Current write framebuffer in use - -uint32_t get_color_from_texture(uint32_t type) { - uint32_t res = 0; - switch (type) { - case GL_RGB: - res = SCE_GXM_COLOR_FORMAT_U8U8U8_BGR; - break; - case GL_RGBA: - res = SCE_GXM_COLOR_FORMAT_U8U8U8U8_ABGR; - break; - case GL_LUMINANCE: - res = SCE_GXM_COLOR_FORMAT_U8_R; - break; - case GL_LUMINANCE_ALPHA: - res = SCE_GXM_COLOR_FORMAT_U8U8_GR; - break; - case GL_INTENSITY: - res = SCE_GXM_COLOR_FORMAT_U8_R; - break; - case GL_ALPHA: - res = SCE_GXM_COLOR_FORMAT_U8_A; - break; - default: - vgl_error = GL_INVALID_ENUM; - break; - } - return res; -} - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void glGenFramebuffers(GLsizei n, GLuint *ids) { - int i = 0, j = 0; -#ifndef SKIP_ERROR_HANDLING - if (n < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - for (i = 0; i < BUFFERS_NUM; i++) { - if (!framebuffers[i].active) { - ids[j++] = (GLuint)&framebuffers[i]; - framebuffers[i].active = 1; - framebuffers[i].depth_buffer_addr = NULL; - framebuffers[i].stencil_buffer_addr = NULL; - } - if (j >= n) - break; - } -} - -void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers) { -#ifndef SKIP_ERROR_HANDLING - if (n < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - while (n > 0) { - framebuffer *fb = (framebuffer *)framebuffers[n--]; - if (fb) { - fb->active = 0; - if (fb->target) { - sceGxmDestroyRenderTarget(fb->target); - fb->target = NULL; - } - if (fb->depth_buffer_addr) { - vgl_mem_free(fb->depth_buffer_addr, fb->depth_buffer_mem_type); - vgl_mem_free(fb->stencil_buffer_addr, fb->stencil_buffer_mem_type); - fb->depth_buffer_addr = NULL; - fb->stencil_buffer_addr = NULL; - } - } - } -} - -void glBindFramebuffer(GLenum target, GLuint fb) { - switch (target) { - case GL_DRAW_FRAMEBUFFER: - active_write_fb = (framebuffer *)fb; - break; - case GL_READ_FRAMEBUFFER: - active_read_fb = (framebuffer *)fb; - break; - case GL_FRAMEBUFFER: - active_write_fb = active_read_fb = (framebuffer *)fb; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glFramebufferTexture(GLenum target, GLenum attachment, GLuint tex_id, GLint level) { - // Detecting requested framebuffer - framebuffer *fb = NULL; - switch (target) { - case GL_DRAW_FRAMEBUFFER: - case GL_FRAMEBUFFER: - fb = active_write_fb; - break; - case GL_READ_FRAMEBUFFER: - fb = active_read_fb; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Aliasing to make code more readable - texture *tex = &vgl_textures[tex_id]; - - // Extracting texture sizes - fb->width = sceGxmTextureGetWidth(&tex->gxm_tex); - fb->height = sceGxmTextureGetHeight(&tex->gxm_tex); - - // Detecting requested attachment - switch (attachment) { - case GL_COLOR_ATTACHMENT0: - - // Allocating colorbuffer - sceGxmColorSurfaceInit( - &fb->colorbuffer, - get_color_from_texture(tex->type), - SCE_GXM_COLOR_SURFACE_LINEAR, - msaa_mode == SCE_GXM_MULTISAMPLE_NONE ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE, - SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, - fb->width, - fb->height, - fb->width, - sceGxmTextureGetData(&tex->gxm_tex)); - - // Allocating depth and stencil buffer (FIXME: This probably shouldn't be here) - initDepthStencilBuffer(fb->width, fb->height, &fb->depthbuffer, &fb->depth_buffer_addr, &fb->stencil_buffer_addr, &fb->depth_buffer_mem_type, &fb->stencil_buffer_mem_type); - - // Creating rendertarget - SceGxmRenderTargetParams renderTargetParams; - memset(&renderTargetParams, 0, sizeof(SceGxmRenderTargetParams)); - renderTargetParams.flags = 0; - renderTargetParams.width = sceGxmTextureGetWidth(&tex->gxm_tex); - renderTargetParams.height = sceGxmTextureGetHeight(&tex->gxm_tex); - renderTargetParams.scenesPerFrame = 1; - renderTargetParams.multisampleMode = msaa_mode; - renderTargetParams.multisampleLocations = 0; - renderTargetParams.driverMemBlock = -1; - sceGxmCreateRenderTarget(&renderTargetParams, &fb->target); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -/* vgl* */ - -void vglTexImageDepthBuffer(GLenum target) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - switch (target) { - case GL_TEXTURE_2D: - { - if (active_read_fb) - sceGxmTextureInitLinear(&tex->gxm_tex, active_read_fb->depth_buffer_addr, SCE_GXM_TEXTURE_FORMAT_DF32M, active_read_fb->width, active_read_fb->height, 0); - else - sceGxmTextureInitLinear(&tex->gxm_tex, gxm_depth_surface_addr, SCE_GXM_TEXTURE_FORMAT_DF32M, DISPLAY_WIDTH, DISPLAY_HEIGHT, 0); - tex->valid = 1; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} diff --git a/deps/vitaGL/source/get_info.c b/deps/vitaGL/source/get_info.c deleted file mode 100644 index 1ad8a4a1ae..0000000000 --- a/deps/vitaGL/source/get_info.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * get_info.c: - * Implementation for functions returning info to end user - */ - -#include "shared.h" - -// Constants returned by glGetString -static const GLubyte *vendor = "Rinnegatamante"; -static const GLubyte *renderer = "SGX543MP4+"; -static const GLubyte *version = "VitaGL 1.0"; -static const GLubyte *extensions = "VGL_EXT_gpu_objects_array VGL_EXT_gxp_shaders"; - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -const GLubyte *glGetString(GLenum name) { - switch (name) { - case GL_VENDOR: // Vendor - return vendor; - break; - case GL_RENDERER: // Renderer - return renderer; - break; - case GL_VERSION: // openGL Version - return version; - break; - case GL_EXTENSIONS: // Supported extensions - return extensions; - break; - default: - vgl_error = GL_INVALID_ENUM; - return NULL; - break; - } -} - -void glGetBooleanv(GLenum pname, GLboolean *params) { - switch (pname) { - case GL_BLEND: // Blending feature state - *params = blend_state; - break; - case GL_BLEND_DST_ALPHA: // Blend Alpha Factor for Destination - *params = (blend_dfactor_a == SCE_GXM_BLEND_FACTOR_ZERO) ? GL_FALSE : GL_TRUE; - break; - case GL_BLEND_DST_RGB: // Blend RGB Factor for Destination - *params = (blend_dfactor_rgb == SCE_GXM_BLEND_FACTOR_ZERO) ? GL_FALSE : GL_TRUE; - break; - case GL_BLEND_SRC_ALPHA: // Blend Alpha Factor for Source - *params = (blend_sfactor_a == SCE_GXM_BLEND_FACTOR_ZERO) ? GL_FALSE : GL_TRUE; - break; - case GL_BLEND_SRC_RGB: // Blend RGB Factor for Source - *params = (blend_sfactor_rgb == SCE_GXM_BLEND_FACTOR_ZERO) ? GL_FALSE : GL_TRUE; - break; - case GL_DEPTH_TEST: // Depth test state - *params = depth_test_state; - break; - case GL_ACTIVE_TEXTURE: // Active texture - *params = GL_FALSE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glGetFloatv(GLenum pname, GLfloat *data) { - int i, j; - switch (pname) { - case GL_POLYGON_OFFSET_FACTOR: // Polygon offset factor - *data = pol_factor; - break; - case GL_POLYGON_OFFSET_UNITS: // Polygon offset units - *data = pol_units; - break; - case GL_MODELVIEW_MATRIX: // Modelview matrix - // Since we use column-major matrices internally, wee need to transpose it before returning it to the application - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - data[i * 4 + j] = modelview_matrix[j][i]; - } - } - break; - case GL_PROJECTION_MATRIX: // Projection matrix - // Since we use column-major matrices internally, wee need to transpose it before returning it to the application - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - data[i * 4 + j] = projection_matrix[j][i]; - } - } - break; - case GL_ACTIVE_TEXTURE: // Active texture - *data = (1.0f * (server_texture_unit + GL_TEXTURE0)); - break; - case GL_MAX_MODELVIEW_STACK_DEPTH: // Max modelview stack depth - *data = MODELVIEW_STACK_DEPTH; - break; - case GL_MAX_PROJECTION_STACK_DEPTH: // Max projection stack depth - *data = GENERIC_STACK_DEPTH; - break; - case GL_MAX_TEXTURE_STACK_DEPTH: // Max texture stack depth - *data = GENERIC_STACK_DEPTH; - break; - case GL_DEPTH_BITS: - *data = 32; - break; - case GL_STENCIL_BITS: - *data = 8; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glGetIntegerv(GLenum pname, GLint *data) { - // Aliasing to make code more readable - texture_unit *server_tex_unit = &texture_units[server_texture_unit]; - - switch (pname) { - case GL_POLYGON_MODE: - data[0] = gl_polygon_mode_front; - data[1] = gl_polygon_mode_back; - break; - case GL_SCISSOR_BOX: - data[0] = region.x; - data[1] = region.y; - data[2] = region.w; - data[3] = region.h; - break; - case GL_TEXTURE_BINDING_2D: - *data = server_tex_unit->tex_id; - break; - case GL_MAX_TEXTURE_SIZE: - *data = 1024; - break; - case GL_VIEWPORT: - data[0] = gl_viewport.x; - data[1] = gl_viewport.y; - data[2] = gl_viewport.w; - data[3] = gl_viewport.h; - break; - case GL_DEPTH_BITS: - data[0] = 32; - break; - case GL_STENCIL_BITS: - data[0] = 8; - break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: - *data = COMPRESSED_TEXTURE_FORMATS_NUM; - break; - case GL_COMPRESSED_TEXTURE_FORMATS: - data[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - data[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - data[2] = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - data[3] = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG; - data[4] = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG; - data[5] = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; - data[6] = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; - data[7] = GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG; - data[8] = GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -GLboolean glIsEnabled(GLenum cap) { - GLboolean ret = GL_FALSE; - switch (cap) { - case GL_DEPTH_TEST: - ret = depth_test_state; - break; - case GL_STENCIL_TEST: - ret = stencil_test_state; - break; - case GL_BLEND: - ret = blend_state; - break; - case GL_SCISSOR_TEST: - ret = scissor_test_state; - break; - case GL_CULL_FACE: - ret = cull_face_state; - break; - case GL_POLYGON_OFFSET_FILL: - ret = pol_offset_fill; - break; - case GL_POLYGON_OFFSET_LINE: - ret = pol_offset_line; - break; - case GL_POLYGON_OFFSET_POINT: - ret = pol_offset_point; - break; - default: - vgl_error = GL_INVALID_ENUM; - break; - } - return ret; -} - -GLenum glGetError(void) { - GLenum ret = vgl_error; - vgl_error = GL_NO_ERROR; - return ret; -} diff --git a/deps/vitaGL/source/gxm.c b/deps/vitaGL/source/gxm.c deleted file mode 100644 index 3851c9e27d..0000000000 --- a/deps/vitaGL/source/gxm.c +++ /dev/null @@ -1,477 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * gxm.c: - * Implementation for setup and cleanup for sceGxm specific stuffs - */ - -#include "shared.h" - -static uint32_t gxm_param_buf_size = SCE_GXM_DEFAULT_PARAMETER_BUFFER_SIZE; // Param buffer size for sceGxm - -static void *vdm_ring_buffer_addr; // VDM ring buffer memblock starting address -static void *vertex_ring_buffer_addr; // vertex ring buffer memblock starting address -static void *fragment_ring_buffer_addr; // fragment ring buffer memblock starting address -static void *fragment_usse_ring_buffer_addr; // fragment USSE ring buffer memblock starting address - -static SceGxmRenderTarget *gxm_render_target; // Display render target -static SceGxmColorSurface gxm_color_surfaces[DISPLAY_BUFFER_COUNT]; // Display color surfaces -void *gxm_color_surfaces_addr[DISPLAY_BUFFER_COUNT]; // Display color surfaces memblock starting addresses -static SceGxmSyncObject *gxm_sync_objects[DISPLAY_BUFFER_COUNT]; // Display sync objects -unsigned int gxm_front_buffer_index; // Display front buffer id -unsigned int gxm_back_buffer_index; // Display back buffer id -static unsigned int gxm_scene_flags = 0; // Current gxm scene flags - -static void *gxm_shader_patcher_buffer_addr; // Shader PAtcher buffer memblock starting address -static void *gxm_shader_patcher_vertex_usse_addr; // Shader Patcher vertex USSE memblock starting address -static void *gxm_shader_patcher_fragment_usse_addr; // Shader Patcher fragment USSE memblock starting address - -void *gxm_depth_surface_addr; // Depth surface memblock starting address -static void *gxm_stencil_surface_addr; // Stencil surface memblock starting address -static SceGxmDepthStencilSurface gxm_depth_stencil_surface; // Depth/Stencil surfaces setup for sceGxm - -static SceUID shared_fb; // In-use hared framebuffer identifier -static SceSharedFbInfo shared_fb_info; // In-use shared framebuffer info struct - -SceGxmContext *gxm_context; // sceGxm context instance -GLenum vgl_error = GL_NO_ERROR; // Error returned by glGetError -SceGxmShaderPatcher *gxm_shader_patcher; // sceGxmShaderPatcher shader patcher instance - -matrix4x4 mvp_matrix; // ModelViewProjection Matrix -matrix4x4 projection_matrix; // Projection Matrix -matrix4x4 modelview_matrix; // ModelView Matrix - -int DISPLAY_WIDTH; // Display width in pixels -int DISPLAY_HEIGHT; // Display height in pixels -int DISPLAY_STRIDE; // Display stride in pixels -float DISPLAY_WIDTH_FLOAT; // Display width in pixels (float) -float DISPLAY_HEIGHT_FLOAT; // Display height in pixels (float) - -uint8_t system_app_mode = 0; // Flag for system app mode usage -static uint8_t gxm_initialized = 0; // Current sceGxm state - -// sceDisplay callback data -struct display_queue_callback_data { - void *addr; -}; - -// sceGxmShaderPatcher custom allocator -static void *shader_patcher_host_alloc_cb(void *user_data, unsigned int size) { - return malloc(size); -} - -// sceGxmShaderPatcher custom deallocator -static void shader_patcher_host_free_cb(void *user_data, void *mem) { - free(mem); -} - -// sceDisplay callback -static void display_queue_callback(const void *callbackData) { - // Populating sceDisplay framebuffer parameters - SceDisplayFrameBuf display_fb; - const struct display_queue_callback_data *cb_data = callbackData; - memset(&display_fb, 0, sizeof(SceDisplayFrameBuf)); - display_fb.size = sizeof(SceDisplayFrameBuf); - display_fb.base = cb_data->addr; - display_fb.pitch = DISPLAY_STRIDE; - display_fb.pixelformat = SCE_DISPLAY_PIXELFORMAT_A8B8G8R8; - display_fb.width = DISPLAY_WIDTH; - display_fb.height = DISPLAY_HEIGHT; - - // Setting sceDisplay framebuffer - sceDisplaySetFrameBuf(&display_fb, SCE_DISPLAY_SETBUF_NEXTFRAME); - - // Performing VSync if enabled - if (vblank) - sceDisplayWaitVblankStart(); -} - -void initGxm(void) { - if (gxm_initialized) - return; - - // Initializing runtime shader compiler - if (use_shark) { -#ifdef HAVE_SHARK - if (shark_init(NULL) >= 0) { - is_shark_online = 1; -#ifdef HAVE_SHARK_LOG - shark_install_log_cb(shark_log_cb); - shark_set_warnings_level(SHARK_WARN_MAX); -#endif - } else -#endif - is_shark_online = 0; - } - - // Checking if the running application is a system one - SceAppMgrBudgetInfo info; - info.size = sizeof(SceAppMgrBudgetInfo); - if (!sceAppMgrGetBudgetInfo(&info)) - system_app_mode = 1; - - // Initializing sceGxm init parameters - SceGxmInitializeParams gxm_init_params; - memset(&gxm_init_params, 0, sizeof(SceGxmInitializeParams)); - gxm_init_params.flags = system_app_mode ? 0x0A : 0; - gxm_init_params.displayQueueMaxPendingCount = DISPLAY_BUFFER_COUNT - 1; - gxm_init_params.displayQueueCallback = display_queue_callback; - gxm_init_params.displayQueueCallbackDataSize = sizeof(struct display_queue_callback_data); - gxm_init_params.parameterBufferSize = gxm_param_buf_size; - - // Initializing sceGxm - if (system_app_mode) - sceGxmVshInitialize(&gxm_init_params); - else - sceGxmInitialize(&gxm_init_params); - gxm_initialized = 1; -} - -void initGxmContext(void) { - vglMemType type = VGL_MEM_VRAM; - - // Allocating VDM ring buffer - vdm_ring_buffer_addr = gpu_alloc_mapped(SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE, &type); - - // Allocating vertex ring buffer - vertex_ring_buffer_addr = gpu_alloc_mapped(SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE, &type); - - // Allocating fragment ring buffer - fragment_ring_buffer_addr = gpu_alloc_mapped(SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE, &type); - - // Allocating fragment USSE ring buffer - unsigned int fragment_usse_offset; - fragment_usse_ring_buffer_addr = gpu_fragment_usse_alloc_mapped( - SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE, &fragment_usse_offset); - - // Setting sceGxm context parameters - SceGxmContextParams gxm_context_params; - memset(&gxm_context_params, 0, sizeof(SceGxmContextParams)); - gxm_context_params.hostMem = malloc(SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE); - gxm_context_params.hostMemSize = SCE_GXM_MINIMUM_CONTEXT_HOST_MEM_SIZE; - gxm_context_params.vdmRingBufferMem = vdm_ring_buffer_addr; - gxm_context_params.vdmRingBufferMemSize = SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE; - gxm_context_params.vertexRingBufferMem = vertex_ring_buffer_addr; - gxm_context_params.vertexRingBufferMemSize = SCE_GXM_DEFAULT_VERTEX_RING_BUFFER_SIZE; - gxm_context_params.fragmentRingBufferMem = fragment_ring_buffer_addr; - gxm_context_params.fragmentRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_RING_BUFFER_SIZE; - gxm_context_params.fragmentUsseRingBufferMem = fragment_usse_ring_buffer_addr; - gxm_context_params.fragmentUsseRingBufferMemSize = SCE_GXM_DEFAULT_FRAGMENT_USSE_RING_BUFFER_SIZE; - gxm_context_params.fragmentUsseRingBufferOffset = fragment_usse_offset; - - // Initializing sceGxm context - sceGxmCreateContext(&gxm_context_params, &gxm_context); -} - -void termGxmContext(void) { - // Deallocating ring buffers - vgl_mem_free(vdm_ring_buffer_addr, VGL_MEM_VRAM); - vgl_mem_free(vertex_ring_buffer_addr, VGL_MEM_VRAM); - vgl_mem_free(fragment_ring_buffer_addr, VGL_MEM_VRAM); - gpu_fragment_usse_free_mapped(fragment_usse_ring_buffer_addr); - - // Destroying sceGxm context - sceGxmDestroyContext(gxm_context); - - if (system_app_mode) { - sceSharedFbBegin(shared_fb, &shared_fb_info); - sceGxmUnmapMemory(shared_fb_info.fb_base); - sceSharedFbEnd(shared_fb); - sceSharedFbClose(shared_fb); - } -#ifdef HAVE_SHARK - // Shutting down runtime shader compiler - if (is_shark_online) - shark_end(); -#endif -} - -void createDisplayRenderTarget(void) { - // Populating sceGxmRenderTarget parameters - SceGxmRenderTargetParams render_target_params; - memset(&render_target_params, 0, sizeof(SceGxmRenderTargetParams)); - render_target_params.flags = 0; - render_target_params.width = DISPLAY_WIDTH; - render_target_params.height = DISPLAY_HEIGHT; - render_target_params.scenesPerFrame = 1; - render_target_params.multisampleMode = msaa_mode; - render_target_params.multisampleLocations = 0; - render_target_params.driverMemBlock = -1; - - // Creating render target for the display - sceGxmCreateRenderTarget(&render_target_params, &gxm_render_target); -} - -void destroyDisplayRenderTarget(void) { - // Destroying render target for the display - sceGxmDestroyRenderTarget(gxm_render_target); -} - -void initDisplayColorSurfaces(void) { - // Getting access to the shared framebuffer on system app mode - while (system_app_mode) { - shared_fb = sceSharedFbOpen(1); - memset(&shared_fb_info, 0, sizeof(SceSharedFbInfo)); - sceSharedFbGetInfo(shared_fb, &shared_fb_info); - if (shared_fb_info.index == 1) - sceSharedFbClose(shared_fb); - else { - sceGxmMapMemory(shared_fb_info.fb_base, shared_fb_info.fb_size, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE); - gxm_color_surfaces_addr[0] = shared_fb_info.fb_base; - gxm_color_surfaces_addr[1] = shared_fb_info.fb_base2; - memset(&shared_fb_info, 0, sizeof(SceSharedFbInfo)); - break; - } - } - - vglMemType type = VGL_MEM_VRAM; - int i; - for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) { - // Allocating color surface memblock - if (!system_app_mode) { - gxm_color_surfaces_addr[i] = gpu_alloc_mapped( - ALIGN(4 * DISPLAY_STRIDE * DISPLAY_HEIGHT, 1 * 1024 * 1024), - &type); - memset(gxm_color_surfaces_addr[i], 0, DISPLAY_STRIDE * DISPLAY_HEIGHT); - } - - // Initializing allocated color surface - sceGxmColorSurfaceInit(&gxm_color_surfaces[i], - SCE_GXM_COLOR_FORMAT_A8B8G8R8, - SCE_GXM_COLOR_SURFACE_LINEAR, - msaa_mode == SCE_GXM_MULTISAMPLE_NONE ? SCE_GXM_COLOR_SURFACE_SCALE_NONE : SCE_GXM_COLOR_SURFACE_SCALE_MSAA_DOWNSCALE, - SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, - DISPLAY_WIDTH, - DISPLAY_HEIGHT, - DISPLAY_STRIDE, - gxm_color_surfaces_addr[i]); - - // Creating a display sync object for the allocated color surface - sceGxmSyncObjectCreate(&gxm_sync_objects[i]); - } -} - -void termDisplayColorSurfaces(void) { - // Deallocating display's color surfaces and destroying sync objects - int i; - for (i = 0; i < DISPLAY_BUFFER_COUNT; i++) { - if (!system_app_mode) - vgl_mem_free(gxm_color_surfaces_addr[i], VGL_MEM_VRAM); - sceGxmSyncObjectDestroy(gxm_sync_objects[i]); - } -} - -void initDepthStencilBuffer(uint32_t w, uint32_t h, SceGxmDepthStencilSurface *surface, void **depth_buffer, void **stencil_buffer, vglMemType *depth_type, vglMemType *stencil_type) { - // Calculating sizes for depth and stencil surfaces - unsigned int depth_stencil_width = ALIGN(w, SCE_GXM_TILE_SIZEX); - unsigned int depth_stencil_height = ALIGN(h, SCE_GXM_TILE_SIZEY); - unsigned int depth_stencil_samples = depth_stencil_width * depth_stencil_height; - if (msaa_mode == SCE_GXM_MULTISAMPLE_2X) - depth_stencil_samples = depth_stencil_samples * 2; - else if (msaa_mode == SCE_GXM_MULTISAMPLE_4X) - depth_stencil_samples = depth_stencil_samples * 4; - - // Allocating depth surface - *depth_type = VGL_MEM_VRAM; - *depth_buffer = gpu_alloc_mapped(4 * depth_stencil_samples, depth_type); - - // Allocating stencil surface - *stencil_type = VGL_MEM_VRAM; - *stencil_buffer = gpu_alloc_mapped(1 * depth_stencil_samples, stencil_type); - - // Initializing depth and stencil surfaces - sceGxmDepthStencilSurfaceInit(surface, - SCE_GXM_DEPTH_STENCIL_FORMAT_DF32M_S8, - SCE_GXM_DEPTH_STENCIL_SURFACE_LINEAR, - msaa_mode == SCE_GXM_MULTISAMPLE_4X ? depth_stencil_width * 2 : depth_stencil_width, - *depth_buffer, - *stencil_buffer); -} - -void initDepthStencilSurfaces(void) { - vglMemType t1, t2; - initDepthStencilBuffer(DISPLAY_WIDTH, DISPLAY_HEIGHT, &gxm_depth_stencil_surface, &gxm_depth_surface_addr, &gxm_stencil_surface_addr, &t1, &t2); -} - -void termDepthStencilSurfaces(void) { - // Deallocating depth and stencil surfaces memblocks - vgl_mem_free(gxm_depth_surface_addr, VGL_MEM_VRAM); - vgl_mem_free(gxm_stencil_surface_addr, VGL_MEM_VRAM); -} - -void startShaderPatcher(void) { - // Constants for shader patcher buffers - static const unsigned int shader_patcher_buffer_size = 1024 * 1024; - static const unsigned int shader_patcher_vertex_usse_size = 1024 * 1024; - static const unsigned int shader_patcher_fragment_usse_size = 1024 * 1024; - vglMemType type = VGL_MEM_VRAM; - - // Allocating Shader Patcher buffer - gxm_shader_patcher_buffer_addr = gpu_alloc_mapped( - shader_patcher_buffer_size, &type); - - // Allocating Shader Patcher vertex USSE buffer - unsigned int shader_patcher_vertex_usse_offset; - gxm_shader_patcher_vertex_usse_addr = gpu_vertex_usse_alloc_mapped( - shader_patcher_vertex_usse_size, &shader_patcher_vertex_usse_offset); - - // Allocating Shader Patcher fragment USSE buffer - unsigned int shader_patcher_fragment_usse_offset; - gxm_shader_patcher_fragment_usse_addr = gpu_fragment_usse_alloc_mapped( - shader_patcher_fragment_usse_size, &shader_patcher_fragment_usse_offset); - - // Populating shader patcher parameters - SceGxmShaderPatcherParams shader_patcher_params; - memset(&shader_patcher_params, 0, sizeof(SceGxmShaderPatcherParams)); - shader_patcher_params.userData = NULL; - shader_patcher_params.hostAllocCallback = shader_patcher_host_alloc_cb; - shader_patcher_params.hostFreeCallback = shader_patcher_host_free_cb; - shader_patcher_params.bufferAllocCallback = NULL; - shader_patcher_params.bufferFreeCallback = NULL; - shader_patcher_params.bufferMem = gxm_shader_patcher_buffer_addr; - shader_patcher_params.bufferMemSize = shader_patcher_buffer_size; - shader_patcher_params.vertexUsseAllocCallback = NULL; - shader_patcher_params.vertexUsseFreeCallback = NULL; - shader_patcher_params.vertexUsseMem = gxm_shader_patcher_vertex_usse_addr; - shader_patcher_params.vertexUsseMemSize = shader_patcher_vertex_usse_size; - shader_patcher_params.vertexUsseOffset = shader_patcher_vertex_usse_offset; - shader_patcher_params.fragmentUsseAllocCallback = NULL; - shader_patcher_params.fragmentUsseFreeCallback = NULL; - shader_patcher_params.fragmentUsseMem = gxm_shader_patcher_fragment_usse_addr; - shader_patcher_params.fragmentUsseMemSize = shader_patcher_fragment_usse_size; - shader_patcher_params.fragmentUsseOffset = shader_patcher_fragment_usse_offset; - - // Creating shader patcher instance - sceGxmShaderPatcherCreate(&shader_patcher_params, &gxm_shader_patcher); -} - -void stopShaderPatcher(void) { - // Destroying shader patcher instance - sceGxmShaderPatcherDestroy(gxm_shader_patcher); - - // Freeing shader patcher buffers - vgl_mem_free(gxm_shader_patcher_buffer_addr, VGL_MEM_VRAM); - gpu_vertex_usse_free_mapped(gxm_shader_patcher_vertex_usse_addr); - gpu_fragment_usse_free_mapped(gxm_shader_patcher_fragment_usse_addr); -} - -void waitRenderingDone(void) { - // Wait for rendering to be finished - sceGxmDisplayQueueFinish(); - sceGxmFinish(gxm_context); -} - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void vglSetParamBufferSize(uint32_t size) { - gxm_param_buf_size = size; -} - -void vglStartRendering(void) { - // Starting drawing scene - if (active_write_fb == NULL) { // Default framebuffer is used - if (system_app_mode) { - sceSharedFbBegin(shared_fb, &shared_fb_info); - shared_fb_info.vsync = vblank; - gxm_back_buffer_index = (shared_fb_info.index + 1) % 2; - } - sceGxmBeginScene(gxm_context, gxm_scene_flags, gxm_render_target, - NULL, NULL, - gxm_sync_objects[gxm_back_buffer_index], - &gxm_color_surfaces[gxm_back_buffer_index], - &gxm_depth_stencil_surface); - gxm_scene_flags &= ~SCE_GXM_SCENE_VERTEX_WAIT_FOR_DEPENDENCY; - } else { - gxm_scene_flags |= SCE_GXM_SCENE_FRAGMENT_SET_DEPENDENCY; - sceGxmBeginScene(gxm_context, gxm_scene_flags, active_write_fb->target, - NULL, NULL, NULL, - &active_write_fb->colorbuffer, - &active_write_fb->depthbuffer); - gxm_scene_flags |= SCE_GXM_SCENE_VERTEX_WAIT_FOR_DEPENDENCY; - gxm_scene_flags &= ~SCE_GXM_SCENE_FRAGMENT_SET_DEPENDENCY; - } - - // Setting back current viewport if enabled cause sceGxm will reset it at sceGxmEndScene call - sceGxmSetViewport(gxm_context, x_port, x_scale, y_port, y_scale, z_port, z_scale); - - if (scissor_test_state) - sceGxmSetRegionClip(gxm_context, SCE_GXM_REGION_CLIP_OUTSIDE, region.x, region.y, region.x + region.w - 1, region.y + region.h - 1); - else - sceGxmSetRegionClip(gxm_context, SCE_GXM_REGION_CLIP_OUTSIDE, 0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1); -} - -void vglStopRenderingInit(void) { - // Ending drawing scene - sceGxmEndScene(gxm_context, NULL, NULL); - if (system_app_mode && vblank) - sceDisplayWaitVblankStart(); -} - -void vglStopRenderingTerm(void) { - if (active_write_fb == NULL) { // Default framebuffer is used - // Properly requesting a display update - if (system_app_mode) - sceSharedFbEnd(shared_fb); - else { - struct display_queue_callback_data queue_cb_data; - queue_cb_data.addr = gxm_color_surfaces_addr[gxm_back_buffer_index]; - sceGxmDisplayQueueAddEntry(gxm_sync_objects[gxm_front_buffer_index], - gxm_sync_objects[gxm_back_buffer_index], &queue_cb_data); - gxm_front_buffer_index = gxm_back_buffer_index; - gxm_back_buffer_index = (gxm_back_buffer_index + 1) % DISPLAY_BUFFER_COUNT; - } - } - - // Resetting vitaGL mempool - gpu_pool_reset(); -} - -void vglStopRendering() { - // Ending drawing scene - vglStopRenderingInit(); - - // Updating display and resetting vitaGL mempool - vglStopRenderingTerm(); -} - -void vglUpdateCommonDialog() { - // Populating SceCommonDialog parameters - SceCommonDialogUpdateParam updateParam; - memset(&updateParam, 0, sizeof(updateParam)); - updateParam.renderTarget.colorFormat = SCE_GXM_COLOR_FORMAT_A8B8G8R8; - updateParam.renderTarget.surfaceType = SCE_GXM_COLOR_SURFACE_LINEAR; - updateParam.renderTarget.width = DISPLAY_WIDTH; - updateParam.renderTarget.height = DISPLAY_HEIGHT; - updateParam.renderTarget.strideInPixels = DISPLAY_STRIDE; - updateParam.renderTarget.colorSurfaceData = gxm_color_surfaces_addr[gxm_back_buffer_index]; - updateParam.renderTarget.depthSurfaceData = gxm_depth_surface_addr; - updateParam.displaySyncObject = gxm_sync_objects[gxm_back_buffer_index]; - - // Updating sceCommonDialog - sceCommonDialogUpdate(&updateParam); -} - -void glFinish(void) { - // Waiting for GPU to finish drawing jobs - sceGxmFinish(gxm_context); -} diff --git a/deps/vitaGL/source/hacks/memcpy_neon.S b/deps/vitaGL/source/hacks/memcpy_neon.S deleted file mode 100644 index 2f1d33ebb7..0000000000 --- a/deps/vitaGL/source/hacks/memcpy_neon.S +++ /dev/null @@ -1,140 +0,0 @@ -/* - * NEON code contributed by Siarhei Siamashka . - * Origin: http://sourceware.org/ml/libc-ports/2009-07/msg00003.html - * - * The GNU C Library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License. - * - * Tweaked for Android by Jim Huang - */ - -.arm -.fpu neon - -@ void* memcpy_n(void *destination, const void *source, size_t num) -.global memcpy_neon -.type memcpy_neon, %function -/* - * ENABLE_UNALIGNED_MEM_ACCESSES macro can be defined to permit the use - * of unaligned load/store memory accesses supported since ARMv6. This - * will further improve performance, but can purely theoretically cause - * problems if somebody decides to set SCTLR.A bit in the OS kernel - * (to trap each unaligned memory access) or somehow mess with strongly - * ordered/device memory. - */ -#define ENABLE_UNALIGNED_MEM_ACCESSES 1 - -#define NEON_MAX_PREFETCH_DISTANCE 320 - -.align 4 -memcpy_neon: - .fnstart - mov ip, r0 - cmp r2, #16 - blt 4f @ Have less than 16 bytes to copy - - @ First ensure 16 byte alignment for the destination buffer - tst r0, #0xF - beq 2f - tst r0, #1 - ldrneb r3, [r1], #1 - strneb r3, [ip], #1 - subne r2, r2, #1 - tst ip, #2 -#ifdef ENABLE_UNALIGNED_MEM_ACCESSES - ldrneh r3, [r1], #2 - strneh r3, [ip], #2 -#else - ldrneb r3, [r1], #1 - strneb r3, [ip], #1 - ldrneb r3, [r1], #1 - strneb r3, [ip], #1 -#endif - subne r2, r2, #2 - - tst ip, #4 - beq 1f - vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]! - vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [ip, :32]! - sub r2, r2, #4 -1: - tst ip, #8 - beq 2f - vld1.8 {d0}, [r1]! - vst1.8 {d0}, [ip, :64]! - sub r2, r2, #8 -2: - subs r2, r2, #32 - blt 3f - mov r3, #32 - - @ Main copy loop, 32 bytes are processed per iteration. - @ ARM instructions are used for doing fine-grained prefetch, - @ increasing prefetch distance progressively up to - @ NEON_MAX_PREFETCH_DISTANCE at runtime -1: - vld1.8 {d0-d3}, [r1]! - cmp r3, #(NEON_MAX_PREFETCH_DISTANCE - 32) - pld [r1, r3] - addle r3, r3, #32 - vst1.8 {d0-d3}, [ip, :128]! - sub r2, r2, #32 - cmp r2, r3 - bge 1b - cmp r2, #0 - blt 3f -1: @ Copy the remaining part of the buffer (already prefetched) - vld1.8 {d0-d3}, [r1]! - subs r2, r2, #32 - vst1.8 {d0-d3}, [ip, :128]! - bge 1b -3: @ Copy up to 31 remaining bytes - tst r2, #16 - beq 4f - vld1.8 {d0, d1}, [r1]! - vst1.8 {d0, d1}, [ip, :128]! -4: - @ Use ARM instructions exclusively for the final trailing part - @ not fully fitting into full 16 byte aligned block in order - @ to avoid "ARM store after NEON store" hazard. Also NEON - @ pipeline will be (mostly) flushed by the time when the - @ control returns to the caller, making the use of NEON mostly - @ transparent (and avoiding hazards in the caller code) - -#ifdef ENABLE_UNALIGNED_MEM_ACCESSES - movs r3, r2, lsl #29 - ldrcs r3, [r1], #4 - strcs r3, [ip], #4 - ldrcs r3, [r1], #4 - strcs r3, [ip], #4 - ldrmi r3, [r1], #4 - strmi r3, [ip], #4 - movs r2, r2, lsl #31 - ldrcsh r3, [r1], #2 - strcsh r3, [ip], #2 - ldrmib r3, [r1], #1 - strmib r3, [ip], #1 -#else - movs r3, r2, lsl #29 - bcc 1f - .rept 8 - ldrcsb r3, [r1], #1 - strcsb r3, [ip], #1 - .endr -1: - bpl 1f - .rept 4 - ldrmib r3, [r1], #1 - strmib r3, [ip], #1 - .endr -1: - movs r2, r2, lsl #31 - ldrcsb r3, [r1], #1 - strcsb r3, [ip], #1 - ldrcsb r3, [r1], #1 - strcsb r3, [ip], #1 - ldrmib r3, [r1], #1 - strmib r3, [ip], #1 -#endif - bx lr - .fnend diff --git a/deps/vitaGL/source/hacks/sbrk.c b/deps/vitaGL/source/hacks/sbrk.c deleted file mode 100644 index 828ce3ca39..0000000000 --- a/deps/vitaGL/source/hacks/sbrk.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * Copyright (c) 2016, 2017, 2018 vitasdk - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include - -extern unsigned int _newlib_heap_size_user __attribute__((weak)); - -int _newlib_heap_memblock; -unsigned _newlib_heap_size; -static char *_newlib_heap_base, *_newlib_heap_end, *_newlib_heap_cur; -static char _newlib_sbrk_mutex[32] __attribute__((aligned(8))); - -void *_sbrk_r(struct _reent *reent, ptrdiff_t incr) { - if (sceKernelLockLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, 1, 0) < 0) - goto fail; - if (!_newlib_heap_base || _newlib_heap_cur + incr >= _newlib_heap_end) { - sceKernelUnlockLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, 1); - fail: - reent->_errno = ENOMEM; - return (void *)-1; - } - - char *prev_heap_end = _newlib_heap_cur; - _newlib_heap_cur += incr; - - sceKernelUnlockLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, 1); - return (void *)prev_heap_end; -} - -void _init_vita_heap(void) { - // Create a mutex to use inside _sbrk_r - if (sceKernelCreateLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex, "sbrk mutex", 0, 0, 0) < 0) { - goto failure; - } - if (&_newlib_heap_size_user != NULL) { - _newlib_heap_size = _newlib_heap_size_user; - } else { - // Create a memblock for the heap memory, 32MB - _newlib_heap_size = 32 * 1024 * 1024; - } - _newlib_heap_memblock = sceKernelAllocMemBlock("Newlib heap", 0x0c20d060, _newlib_heap_size, 0); - if (_newlib_heap_memblock < 0) { - goto failure; - } - if (sceKernelGetMemBlockBase(_newlib_heap_memblock, (void *)&_newlib_heap_base) < 0) { - goto failure; - } - _newlib_heap_end = _newlib_heap_base + _newlib_heap_size; - _newlib_heap_cur = _newlib_heap_base; - - return; -failure: - _newlib_heap_memblock = 0; - _newlib_heap_base = 0; - _newlib_heap_cur = 0; -} - -void _free_vita_heap(void) { - // Destroy the sbrk mutex - sceKernelDeleteLwMutex((SceKernelLwMutexWork *)_newlib_sbrk_mutex); - - // Free the heap memblock to avoid memory leakage. - sceKernelFreeMemBlock(_newlib_heap_memblock); - - _newlib_heap_memblock = 0; - _newlib_heap_base = 0; - _newlib_heap_cur = 0; -} diff --git a/deps/vitaGL/source/legacy.c b/deps/vitaGL/source/legacy.c deleted file mode 100644 index 081cad03aa..0000000000 --- a/deps/vitaGL/source/legacy.c +++ /dev/null @@ -1,592 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * legacy.c: - * Implementation for legacy openGL 1.0 rendering method - */ - -#include "shared.h" - -// Vertex list struct -typedef struct vertexList { - vector3f v; - void *next; -} vertexList; - -// Color vertex list struct -typedef struct rgbaList { - vector4f v; - void *next; -} rgbaList; - -// Texture coord list struct -typedef struct uvList { - vector2f v; - void *next; -} uvList; - -static vertexList *model_vertices = NULL; // Pointer to vertex list -static vertexList *last_vert = NULL; // Pointer to last element in vertex list -static rgbaList *model_color = NULL; // Pointer to color vertex list -static rgbaList *last_clr = NULL; // Pointer to last element in color vertex list -static uvList *model_uv = NULL; // Pointer to texcoord list -static uvList *last_uv = NULL; // Pointer to last element in texcoord list -static uint64_t vertex_count = 0; // Vertex counter for vertex list -static SceGxmPrimitiveType prim; // Current in use primitive for rendering -static SceGxmPrimitiveTypeExtra prim_extra = SCE_GXM_PRIMITIVE_NONE; // Current in use non native primitive for rendering -static uint8_t np = 0xFF; // Number of expected vertices per element for current in use primitive - -vector4f current_color = { 1.0f, 1.0f, 1.0f, 1.0f }; // Current in use color - -static void purge_vertex_list() { - vertexList *old; - rgbaList *old2; - uvList *old3; - - // Purging color and vertex lists - while (model_vertices != NULL) { - old = model_vertices; - old2 = model_color; - model_vertices = model_vertices->next; - model_color = model_color->next; - free(old); - free(old2); - } - - // Purging texcoord list - while (model_uv != NULL) { - old3 = model_uv; - model_uv = model_uv->next; - free(old3); - } -} - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void glVertex3f(GLfloat x, GLfloat y, GLfloat z) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase != MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Adding a new element to color and vertex lists - if (model_vertices == NULL) { - model_vertices = last_vert = (vertexList *)malloc(sizeof(vertexList)); - model_color = last_clr = (rgbaList *)malloc(sizeof(rgbaList)); - } else { - last_vert->next = (vertexList *)malloc(sizeof(vertexList)); - last_clr->next = (rgbaList *)malloc(sizeof(rgbaList)); - last_vert = last_vert->next; - last_clr = last_clr->next; - } - - // Properly populating the new element - last_vert->v.x = x; - last_vert->v.y = y; - last_vert->v.z = z; - memcpy_neon(&last_clr->v, ¤t_color.r, sizeof(vector4f)); - last_clr->next = last_vert->next = NULL; - - // Increasing vertex counter - vertex_count++; -} - -void glVertex3fv(const GLfloat *v) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase != MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Adding a new element to color and vertex lists - if (model_vertices == NULL) { - model_vertices = last_vert = (vertexList *)malloc(sizeof(vertexList)); - model_color = last_clr = (rgbaList *)malloc(sizeof(rgbaList)); - } else { - last_vert->next = (vertexList *)malloc(sizeof(vertexList)); - last_clr->next = (rgbaList *)malloc(sizeof(rgbaList)); - last_vert = last_vert->next; - last_clr = last_clr->next; - } - - // Properly populating the new element - memcpy_neon(&last_vert->v, v, sizeof(vector3f)); - memcpy_neon(&last_clr->v, ¤t_color.r, sizeof(vector4f)); - last_clr->next = last_vert->next = NULL; - - // Increasing vertex counter - vertex_count++; -} - -void glVertex2f(GLfloat x, GLfloat y) { - glVertex3f(x, y, 0.0f); -} - -void glColor3f(GLfloat red, GLfloat green, GLfloat blue) { - // Setting current color value - current_color.r = red; - current_color.g = green; - current_color.b = blue; - current_color.a = 1.0f; -} - -void glColor3fv(const GLfloat *v) { - // Setting current color value - memcpy_neon(¤t_color.r, v, sizeof(vector3f)); - current_color.a = 1.0f; -} - -void glColor3ub(GLubyte red, GLubyte green, GLubyte blue) { - // Setting current color value - current_color.r = (1.0f * red) / 255.0f; - current_color.g = (1.0f * green) / 255.0f; - current_color.b = (1.0f * blue) / 255.0f; - current_color.a = 1.0f; -} - -void glColor3ubv(const GLubyte *c) { - // Setting current color value - current_color.r = (1.0f * c[0]) / 255.0f; - current_color.g = (1.0f * c[1]) / 255.0f; - current_color.b = (1.0f * c[2]) / 255.0f; - current_color.a = 1.0f; -} - -void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - // Setting current color value - current_color.r = red; - current_color.g = green; - current_color.b = blue; - current_color.a = alpha; -} - -void glColor4fv(const GLfloat *v) { - // Setting current color value - memcpy_neon(¤t_color.r, v, sizeof(vector4f)); -} - -void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) { - current_color.r = (1.0f * red) / 255.0f; - current_color.g = (1.0f * green) / 255.0f; - current_color.b = (1.0f * blue) / 255.0f; - current_color.a = (1.0f * alpha) / 255.0f; -} - -void glColor4ubv(const GLubyte *c) { - // Setting current color value - current_color.r = (1.0f * c[0]) / 255.0f; - current_color.g = (1.0f * c[1]) / 255.0f; - current_color.b = (1.0f * c[2]) / 255.0f; - current_color.a = (1.0f * c[3]) / 255.0f; -} - -void glTexCoord2fv(GLfloat *f) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase != MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Adding a new element to texcoord list - if (model_uv == NULL) { - model_uv = last_uv = (uvList *)malloc(sizeof(uvList)); - } else { - last_uv->next = (uvList *)malloc(sizeof(uvList)); - last_uv = last_uv->next; - } - - // Properly populating the new element - last_uv->v.x = f[0]; - last_uv->v.y = f[1]; - last_uv->next = NULL; -} - -void glTexCoord2f(GLfloat s, GLfloat t) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase != MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Adding a new element to texcoord list - if (model_uv == NULL) { - model_uv = last_uv = (uvList *)malloc(sizeof(uvList)); - } else { - last_uv->next = (uvList *)malloc(sizeof(uvList)); - last_uv = last_uv->next; - } - - // Properly populating the new element - last_uv->v.x = s; - last_uv->v.y = t; - last_uv->next = NULL; -} - -void glTexCoord2i(GLint s, GLint t) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase != MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Adding a new element to texcoord list - if (model_uv == NULL) { - model_uv = last_uv = (uvList *)malloc(sizeof(uvList)); - } else { - last_uv->next = (uvList *)malloc(sizeof(uvList)); - last_uv = last_uv->next; - } - - // Properly populating the new element - last_uv->v.x = s; - last_uv->v.y = t; - last_uv->next = NULL; -} - -void glArrayElement(GLint i) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (i < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Aliasing client texture unit for better code readability - texture_unit *tex_unit = &texture_units[client_texture_unit]; - - // Checking if current texture unit has GL_VERTEX_ARRAY enabled - if (tex_unit->vertex_array_state) { - // Calculating offset of requested element - uint8_t *ptr; - if (tex_unit->vertex_array.stride == 0) - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (i * (tex_unit->vertex_array.num * tex_unit->vertex_array.size)); - else - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (i * tex_unit->vertex_array.stride); - - // Adding a new element to vertex and color lists - if (model_vertices == NULL) { - model_vertices = last_vert = (vertexList *)malloc(sizeof(vertexList)); - model_color = last_clr = (rgbaList *)malloc(sizeof(rgbaList)); - } else { - last_vert->next = (vertexList *)malloc(sizeof(vertexList)); - last_clr->next = (rgbaList *)malloc(sizeof(rgbaList)); - last_vert = last_vert->next; - last_clr = last_clr->next; - } - last_vert->next = NULL; - last_clr->next = NULL; - - // Populating new vertex element - memcpy_neon(&last_vert->v, ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - - // Checking if current texture unit has GL_COLOR_ARRAY enabled - if (tex_unit->color_array_state) { - // Calculating offset of requested element - uint8_t *ptr_clr; - if (tex_unit->color_array.stride == 0) - ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (i * (tex_unit->color_array.num * tex_unit->color_array.size)); - else - ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (i * tex_unit->color_array.stride); - - // Populating new color element - last_clr->v.a = 1.0f; - memcpy_neon(&last_clr->v, ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num); - - } else { - // Populating new color element with current color - memcpy_neon(&last_clr->v, ¤t_color.r, sizeof(vector4f)); - } - - // Checking if current texture unit has GL_TEXTURE_COORD_ARRAY enabled - if (tex_unit->texture_array_state) { - // Calculating offset of requested element - uint8_t *ptr_tex; - if (tex_unit->texture_array.stride == 0) - ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (i * (tex_unit->texture_array.num * tex_unit->texture_array.size)); - else - ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (i * tex_unit->texture_array.stride); - - // Adding a new element to texcoord list - if (model_uv == NULL) { - model_uv = last_uv = (uvList *)malloc(sizeof(uvList)); - } else { - last_uv->next = (uvList *)malloc(sizeof(uvList)); - last_uv = last_uv->next; - } - - // Populating new texcoord element - memcpy_neon(&last_uv->v, ptr_tex, tex_unit->vertex_array.size * 2); - last_uv->next = NULL; - } - } -} - -void glBegin(GLenum mode) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Changing current openGL machine state - phase = MODEL_CREATION; - - // Translating primitive to sceGxm one - prim_extra = SCE_GXM_PRIMITIVE_NONE; - switch (mode) { - case GL_POINTS: - prim = SCE_GXM_PRIMITIVE_POINTS; - np = 1; - break; - case GL_LINES: - prim = SCE_GXM_PRIMITIVE_LINES; - np = 2; - break; - case GL_TRIANGLES: - prim = SCE_GXM_PRIMITIVE_TRIANGLES; - np = 3; - break; - case GL_TRIANGLE_STRIP: - prim = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP; - np = 1; - break; - case GL_TRIANGLE_FAN: - prim = SCE_GXM_PRIMITIVE_TRIANGLE_FAN; - np = 1; - break; - case GL_QUADS: - prim = SCE_GXM_PRIMITIVE_TRIANGLES; - prim_extra = SCE_GXM_PRIMITIVE_QUADS; - np = 4; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Resetting vertex count - vertex_count = 0; -} - -void glEnd(void) { -#ifndef SKIP_ERROR_HANDLING - // Integrity checks - if (vertex_count == 0 || ((vertex_count % np) != 0)) - return; - - // Error handling - if (phase != MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - return; - } -#endif - - // Changing current openGL machine state - phase = NONE; - - // Checking if we can totally skip drawing cause of culling mode - if (no_polygons_mode && ((prim == SCE_GXM_PRIMITIVE_TRIANGLES) || (prim >= SCE_GXM_PRIMITIVE_TRIANGLE_STRIP))) { - purge_vertex_list(); - vertex_count = 0; - return; - } - - // Aliasing server texture unit and texture id for better code readability - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - - // Calculating mvp matrix - if (mvp_modified) { - matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix); - mvp_modified = GL_FALSE; - } - - // Checking if we have to write a texture - if ((server_texture_unit >= 0) && (tex_unit->enabled) && (model_uv != NULL) && (vgl_textures[texture2d_idx].valid)) { - // Setting proper vertex and fragment programs - sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched); - - // Setting fragment uniforms for alpha test and texture environment - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_op, 0, 1, &alpha_operation); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tint_color, 0, 4, ¤t_color.r); - float tex_env = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &tex_env); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_density, 0, 1, (const float *)&fog_density); - - } else { - // Setting proper vertex and fragment programs - sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } - - // Reserving default uniform buffer for wvp - int i, j; - void *vertex_wvp_buffer; - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer); - - // Checking if we have to write a texture - if (model_uv != NULL) { - // Setting wvp matrix - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix); - - // Setting fogging uniforms - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_mv, 0, 16, (const float *)modelview_matrix); - - // Setting in use texture - sceGxmSetFragmentTexture(gxm_context, 0, &vgl_textures[texture2d_idx].gxm_tex); - - // Properly generating vertices, uv map and indices buffers - vector3f *vertices; - vector2f *uv_map; - uint16_t *indices; - int n = 0, quad_n = 0; - vertexList *object = model_vertices; - uvList *object_uv = model_uv; - uint64_t idx_count = vertex_count; - switch (prim_extra) { - case SCE_GXM_PRIMITIVE_NONE: - vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f)); - uv_map = (vector2f *)gpu_pool_memalign(vertex_count * sizeof(vector2f), sizeof(vector2f)); - memset(vertices, 0, (vertex_count * sizeof(vector3f))); - indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t)); - for (i = 0; i < vertex_count; i++) { - memcpy_neon(&vertices[n], &object->v, sizeof(vector3f)); - memcpy_neon(&uv_map[n], &object_uv->v, sizeof(vector2f)); - indices[n] = n; - object = object->next; - object_uv = object_uv->next; - n++; - } - break; - case SCE_GXM_PRIMITIVE_QUADS: - quad_n = vertex_count >> 2; - idx_count = quad_n * 6; - vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f)); - uv_map = (vector2f *)gpu_pool_memalign(vertex_count * sizeof(vector2f), sizeof(vector2f)); - memset(vertices, 0, (vertex_count * sizeof(vector3f))); - indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t)); - for (i = 0; i < quad_n; i++) { - indices[i * 6] = i * 4; - indices[i * 6 + 1] = i * 4 + 1; - indices[i * 6 + 2] = i * 4 + 3; - indices[i * 6 + 3] = i * 4 + 1; - indices[i * 6 + 4] = i * 4 + 2; - indices[i * 6 + 5] = i * 4 + 3; - } - for (j = 0; j < vertex_count; j++) { - memcpy_neon(&vertices[j], &object->v, sizeof(vector3f)); - memcpy_neon(&uv_map[j], &object_uv->v, sizeof(vector2f)); - object = object->next; - object_uv = object_uv->next; - } - break; - } - - // Performing the requested draw call - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, uv_map); - sceGxmDraw(gxm_context, prim, SCE_GXM_INDEX_FORMAT_U16, indices, idx_count); - - } else { - // Setting wvp matrix - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - - // Properly generating vertices, colors and indices buffers - vector3f *vertices; - vector4f *colors; - uint16_t *indices; - int n = 0, quad_n = 0; - vertexList *object = model_vertices; - rgbaList *object_clr = model_color; - uint64_t idx_count = vertex_count; - switch (prim_extra) { - case SCE_GXM_PRIMITIVE_NONE: - vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f)); - colors = (vector4f *)gpu_pool_memalign(vertex_count * sizeof(vector4f), sizeof(vector4f)); - memset(vertices, 0, (vertex_count * sizeof(vector3f))); - indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t)); - for (i = 0; i < vertex_count; i++) { - memcpy_neon(&vertices[n], &object->v, sizeof(vector3f)); - memcpy_neon(&colors[n], &object_clr->v, sizeof(vector4f)); - indices[n] = n; - object = object->next; - object_clr = object_clr->next; - n++; - } - break; - case SCE_GXM_PRIMITIVE_QUADS: - quad_n = vertex_count >> 2; - idx_count = quad_n * 6; - vertices = (vector3f *)gpu_pool_memalign(vertex_count * sizeof(vector3f), sizeof(vector3f)); - colors = (vector4f *)gpu_pool_memalign(vertex_count * sizeof(vector4f), sizeof(vector4f)); - memset(vertices, 0, (vertex_count * sizeof(vector3f))); - indices = (uint16_t *)gpu_pool_memalign(idx_count * sizeof(uint16_t), sizeof(uint16_t)); - int i, j; - for (i = 0; i < quad_n; i++) { - indices[i * 6] = i * 4; - indices[i * 6 + 1] = i * 4 + 1; - indices[i * 6 + 2] = i * 4 + 3; - indices[i * 6 + 3] = i * 4 + 1; - indices[i * 6 + 4] = i * 4 + 2; - indices[i * 6 + 5] = i * 4 + 3; - } - for (j = 0; j < vertex_count; j++) { - memcpy_neon(&vertices[j], &object->v, sizeof(vector3f)); - memcpy_neon(&colors[j], &object_clr->v, sizeof(vector4f)); - object = object->next; - object_clr = object_clr->next; - } - break; - } - - // Performing the requested draw call - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, colors); - sceGxmDraw(gxm_context, prim, SCE_GXM_INDEX_FORMAT_U16, indices, idx_count); - } - - // Purging vertex, colors and texcoord lists - purge_vertex_list(); - vertex_count = 0; -} diff --git a/deps/vitaGL/source/matrices.c b/deps/vitaGL/source/matrices.c deleted file mode 100644 index 50a65e536f..0000000000 --- a/deps/vitaGL/source/matrices.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * matrices.c: - * Implementation for matrices related functions - */ - -#include "shared.h" - -matrix4x4 *matrix = NULL; // Current in-use matrix mode -static matrix4x4 modelview_matrix_stack[MODELVIEW_STACK_DEPTH]; // Modelview matrices stack -static uint8_t modelview_stack_counter = 0; // Modelview matrices stack counter -static matrix4x4 projection_matrix_stack[GENERIC_STACK_DEPTH]; // Projection matrices stack -static uint8_t projection_stack_counter = 0; // Projection matrices stack counter -GLboolean mvp_modified = GL_TRUE; // Check if ModelViewProjection matrix needs to be recreated - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void glMatrixMode(GLenum mode) { - // Changing current in use matrix - switch (mode) { - case GL_MODELVIEW: // Modelview matrix - matrix = &modelview_matrix; - break; - case GL_PROJECTION: // Projection matrix - matrix = &projection_matrix; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } else if ((left == right) || (bottom == top) || (nearVal == farVal)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Initializing ortho matrix with requested parameters - matrix4x4_init_orthographic(*matrix, left, right, bottom, top, nearVal, farVal); - mvp_modified = GL_TRUE; -} - -void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } else if ((left == right) || (bottom == top) || (nearVal < 0) || (farVal < 0)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Initializing frustum matrix with requested parameters - matrix4x4_init_frustum(*matrix, left, right, bottom, top, nearVal, farVal); - mvp_modified = GL_TRUE; -} - -void glLoadIdentity(void) { - // Set current in use matrix to identity one - matrix4x4_identity(*matrix); - mvp_modified = GL_TRUE; -} - -void glMultMatrixf(const GLfloat *m) { - matrix4x4 res; - - // Properly ordering matrix to perform multiplication - matrix4x4 tmp; - int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - tmp[i][j] = m[j * 4 + i]; - } - } - - // Multiplicating passed matrix with in use one - matrix4x4_multiply(res, *matrix, tmp); - - // Copying result to in use matrix - matrix4x4_copy(*matrix, res); - mvp_modified = GL_TRUE; -} - -void glLoadMatrixf(const GLfloat *m) { - // Properly ordering matrix - int i, j; - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - (*matrix)[i][j] = m[j * 4 + i]; - } - } - - mvp_modified = GL_TRUE; -} - -void glTranslatef(GLfloat x, GLfloat y, GLfloat z) { - // Translating in use matrix - matrix4x4_translate(*matrix, x, y, z); - mvp_modified = GL_TRUE; -} - -void glScalef(GLfloat x, GLfloat y, GLfloat z) { - // Scaling in use matrix - matrix4x4_scale(*matrix, x, y, z); - mvp_modified = GL_TRUE; -} - -void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Performing rotation on in use matrix depending on user call - float rad = DEG_TO_RAD(angle); - if (x == 1.0f) { - matrix4x4_rotate_x(*matrix, rad); - } - if (y == 1.0f) { - matrix4x4_rotate_y(*matrix, rad); - } - if (z == 1.0f) { - matrix4x4_rotate_z(*matrix, rad); - } - mvp_modified = GL_TRUE; -} - -void glPushMatrix(void) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - if (matrix == &modelview_matrix) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (modelview_stack_counter >= MODELVIEW_STACK_DEPTH) { - SET_GL_ERROR(GL_STACK_OVERFLOW) - } else -#endif - // Copying current matrix into the matrix stack and increasing stack counter - matrix4x4_copy(modelview_matrix_stack[modelview_stack_counter++], *matrix); - - } else if (matrix == &projection_matrix) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (projection_stack_counter >= GENERIC_STACK_DEPTH) { - SET_GL_ERROR(GL_STACK_OVERFLOW) - } else -#endif - // Copying current matrix into the matrix stack and increasing stack counter - matrix4x4_copy(projection_matrix_stack[projection_stack_counter++], *matrix); - } -} - -void glPopMatrix(void) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - if (matrix == &modelview_matrix) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (modelview_stack_counter == 0) { - SET_GL_ERROR(GL_STACK_UNDERFLOW) - } else -#endif - // Copying last matrix on stack into current matrix and decreasing stack counter - matrix4x4_copy(*matrix, modelview_matrix_stack[--modelview_stack_counter]); - - } else if (matrix == &projection_matrix) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (projection_stack_counter == 0) { - SET_GL_ERROR(GL_STACK_UNDERFLOW) - } else -#endif - // Copying last matrix on stack into current matrix and decreasing stack counter - matrix4x4_copy(*matrix, projection_matrix_stack[--projection_stack_counter]); - } - mvp_modified = GL_TRUE; -} - -void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Initializing frustum matrix with requested parameters - matrix4x4_init_perspective(*matrix, fovy, aspect, zNear, zFar); - mvp_modified = GL_TRUE; -} diff --git a/deps/vitaGL/source/misc.c b/deps/vitaGL/source/misc.c deleted file mode 100644 index 3c1d41d50b..0000000000 --- a/deps/vitaGL/source/misc.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * misc.c: - * Implementation for miscellaneous functions - */ - -#include "shared.h" -GLboolean fast_texture_compression = GL_FALSE; // Hints for texture compression - -static void update_fogging_state() { - if (fogging) { - switch (fog_mode) { - case GL_LINEAR: - internal_fog_mode = LINEAR; - break; - case GL_EXP: - internal_fog_mode = EXP; - break; - default: - internal_fog_mode = EXP2; - break; - } - } else - internal_fog_mode = DISABLED; -} - -static void update_polygon_offset() { - switch (polygon_mode_front) { - case SCE_GXM_POLYGON_MODE_TRIANGLE_LINE: - if (pol_offset_line) - sceGxmSetFrontDepthBias(gxm_context, (int)pol_factor, (int)pol_units); - else - sceGxmSetFrontDepthBias(gxm_context, 0, 0); - break; - case SCE_GXM_POLYGON_MODE_TRIANGLE_POINT: - if (pol_offset_point) - sceGxmSetFrontDepthBias(gxm_context, (int)pol_factor, (int)pol_units); - else - sceGxmSetFrontDepthBias(gxm_context, 0, 0); - break; - case SCE_GXM_POLYGON_MODE_TRIANGLE_FILL: - if (pol_offset_fill) - sceGxmSetFrontDepthBias(gxm_context, (int)pol_factor, (int)pol_units); - else - sceGxmSetFrontDepthBias(gxm_context, 0, 0); - break; - } - switch (polygon_mode_back) { - case SCE_GXM_POLYGON_MODE_TRIANGLE_LINE: - if (pol_offset_line) - sceGxmSetBackDepthBias(gxm_context, (int)pol_factor, (int)pol_units); - else - sceGxmSetBackDepthBias(gxm_context, 0, 0); - break; - case SCE_GXM_POLYGON_MODE_TRIANGLE_POINT: - if (pol_offset_point) - sceGxmSetBackDepthBias(gxm_context, (int)pol_factor, (int)pol_units); - else - sceGxmSetBackDepthBias(gxm_context, 0, 0); - break; - case SCE_GXM_POLYGON_MODE_TRIANGLE_FILL: - if (pol_offset_fill) - sceGxmSetBackDepthBias(gxm_context, (int)pol_factor, (int)pol_units); - else - sceGxmSetBackDepthBias(gxm_context, 0, 0); - break; - } -} - -static void change_cull_mode() { - // Setting proper cull mode in sceGxm depending to current openGL machine state - if (cull_face_state) { - if ((gl_front_face == GL_CW) && (gl_cull_mode == GL_BACK)) - sceGxmSetCullMode(gxm_context, SCE_GXM_CULL_CCW); - else if ((gl_front_face == GL_CCW) && (gl_cull_mode == GL_BACK)) - sceGxmSetCullMode(gxm_context, SCE_GXM_CULL_CW); - else if ((gl_front_face == GL_CCW) && (gl_cull_mode == GL_FRONT)) - sceGxmSetCullMode(gxm_context, SCE_GXM_CULL_CCW); - else if ((gl_front_face == GL_CW) && (gl_cull_mode == GL_FRONT)) - sceGxmSetCullMode(gxm_context, SCE_GXM_CULL_CW); - else if (gl_cull_mode == GL_FRONT_AND_BACK) - no_polygons_mode = GL_TRUE; - } else - sceGxmSetCullMode(gxm_context, SCE_GXM_CULL_NONE); -} - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void glPolygonMode(GLenum face, GLenum mode) { - SceGxmPolygonMode new_mode; - switch (mode) { - case GL_POINT: - new_mode = SCE_GXM_POLYGON_MODE_TRIANGLE_POINT; - break; - case GL_LINE: - new_mode = SCE_GXM_POLYGON_MODE_TRIANGLE_LINE; - break; - case GL_FILL: - new_mode = SCE_GXM_POLYGON_MODE_TRIANGLE_FILL; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - switch (face) { - case GL_FRONT: - polygon_mode_front = new_mode; - gl_polygon_mode_front = mode; - sceGxmSetFrontPolygonMode(gxm_context, new_mode); - break; - case GL_BACK: - polygon_mode_back = new_mode; - gl_polygon_mode_back = mode; - sceGxmSetBackPolygonMode(gxm_context, new_mode); - break; - case GL_FRONT_AND_BACK: - polygon_mode_front = polygon_mode_back = new_mode; - gl_polygon_mode_front = gl_polygon_mode_back = mode; - sceGxmSetFrontPolygonMode(gxm_context, new_mode); - sceGxmSetBackPolygonMode(gxm_context, new_mode); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - return; - } - update_polygon_offset(); -} - -void glPolygonOffset(GLfloat factor, GLfloat units) { - pol_factor = factor; - pol_units = units; - update_polygon_offset(); -} - -void glCullFace(GLenum mode) { - gl_cull_mode = mode; - if (cull_face_state) - change_cull_mode(); -} - -void glFrontFace(GLenum mode) { - gl_front_face = mode; - if (cull_face_state) - change_cull_mode(); -} - -void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { -#ifndef SKIP_ERROR_HANDLING - if ((width < 0) || (height < 0)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - x_scale = width >> 1; - x_port = x + x_scale; - y_scale = -(height >> 1); - y_port = DISPLAY_HEIGHT - y + y_scale; - sceGxmSetViewport(gxm_context, x_port, x_scale, y_port, y_scale, z_port, z_scale); - gl_viewport.x = x; - gl_viewport.y = y; - gl_viewport.w = width; - gl_viewport.h = height; -} - -void glDepthRange(GLdouble nearVal, GLdouble farVal) { - z_port = (farVal + nearVal) / 2.0f; - z_scale = (farVal - nearVal) / 2.0f; - sceGxmSetViewport(gxm_context, x_port, x_scale, y_port, y_scale, z_port, z_scale); -} - -void glDepthRangef(GLfloat nearVal, GLfloat farVal) { - z_port = (farVal + nearVal) / 2.0f; - z_scale = (farVal - nearVal) / 2.0f; - sceGxmSetViewport(gxm_context, x_port, x_scale, y_port, y_scale, z_port, z_scale); -} - -void glEnable(GLenum cap) { -#ifndef SKIP_ERROR_HANDLING - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - switch (cap) { - case GL_DEPTH_TEST: - depth_test_state = GL_TRUE; - change_depth_func(); - break; - case GL_STENCIL_TEST: - stencil_test_state = GL_TRUE; - change_stencil_settings(); - break; - case GL_BLEND: - if (!blend_state) - change_blend_factor(); - blend_state = GL_TRUE; - break; - case GL_SCISSOR_TEST: - scissor_test_state = GL_TRUE; - update_scissor_test(); - break; - case GL_CULL_FACE: - cull_face_state = GL_TRUE; - change_cull_mode(); - break; - case GL_POLYGON_OFFSET_FILL: - pol_offset_fill = GL_TRUE; - update_polygon_offset(); - break; - case GL_POLYGON_OFFSET_LINE: - pol_offset_line = GL_TRUE; - update_polygon_offset(); - break; - case GL_POLYGON_OFFSET_POINT: - pol_offset_point = GL_TRUE; - update_polygon_offset(); - break; - case GL_TEXTURE_2D: - texture_units[server_texture_unit].enabled = GL_TRUE; - break; - case GL_ALPHA_TEST: - alpha_test_state = GL_TRUE; - update_alpha_test_settings(); - break; - case GL_FOG: - fogging = GL_TRUE; - update_fogging_state(); - break; - case GL_CLIP_PLANE0: - clip_plane0 = GL_TRUE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glDisable(GLenum cap) { -#ifndef SKIP_ERROR_HANDLING - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - switch (cap) { - case GL_DEPTH_TEST: - depth_test_state = GL_FALSE; - change_depth_func(); - break; - case GL_STENCIL_TEST: - stencil_test_state = GL_FALSE; - change_stencil_settings(); - break; - case GL_BLEND: - if (blend_state) - disable_blend(); - blend_state = GL_FALSE; - break; - case GL_SCISSOR_TEST: - scissor_test_state = GL_FALSE; - update_scissor_test(); - break; - case GL_CULL_FACE: - cull_face_state = GL_FALSE; - change_cull_mode(); - break; - case GL_POLYGON_OFFSET_FILL: - pol_offset_fill = GL_FALSE; - update_polygon_offset(); - break; - case GL_POLYGON_OFFSET_LINE: - pol_offset_line = GL_FALSE; - update_polygon_offset(); - break; - case GL_POLYGON_OFFSET_POINT: - pol_offset_point = GL_FALSE; - update_polygon_offset(); - break; - case GL_TEXTURE_2D: - texture_units[server_texture_unit].enabled = GL_FALSE; - break; - case GL_ALPHA_TEST: - alpha_test_state = GL_FALSE; - update_alpha_test_settings(); - break; - case GL_FOG: - fogging = GL_FALSE; - update_fogging_state(); - break; - case GL_CLIP_PLANE0: - clip_plane0 = GL_FALSE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glClear(GLbitfield mask) { - GLenum orig_depth_test = depth_test_state; - if ((mask & GL_COLOR_BUFFER_BIT) == GL_COLOR_BUFFER_BIT) { - invalidate_depth_test(); - change_depth_write(SCE_GXM_DEPTH_WRITE_DISABLED); - sceGxmSetFrontPolygonMode(gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); - sceGxmSetBackPolygonMode(gxm_context, SCE_GXM_POLYGON_MODE_TRIANGLE_FILL); - sceGxmSetVertexProgram(gxm_context, clear_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, clear_fragment_program_patched); - void *color_buffer, *vertex_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &color_buffer); - sceGxmSetUniformDataF(color_buffer, clear_color, 0, 4, &clear_rgba_val.r); - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_buffer); - sceGxmSetUniformDataF(vertex_buffer, clear_position, 0, 4, &clear_vertices->x); - sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_FAN, SCE_GXM_INDEX_FORMAT_U16, depth_clear_indices, 4); - validate_depth_test(); - change_depth_write(depth_mask_state ? SCE_GXM_DEPTH_WRITE_ENABLED : SCE_GXM_DEPTH_WRITE_DISABLED); - sceGxmSetFrontPolygonMode(gxm_context, polygon_mode_front); - sceGxmSetBackPolygonMode(gxm_context, polygon_mode_back); - } - if ((mask & GL_DEPTH_BUFFER_BIT) == GL_DEPTH_BUFFER_BIT) { - invalidate_depth_test(); - change_depth_write(SCE_GXM_DEPTH_WRITE_ENABLED); - sceGxmSetVertexProgram(gxm_context, clear_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, disable_color_buffer_fragment_program_patched); - void *depth_buffer, *vertex_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &depth_buffer); - float temp = depth_value; - sceGxmSetUniformDataF(depth_buffer, clear_depth, 0, 1, &temp); - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_buffer); - sceGxmSetUniformDataF(vertex_buffer, clear_position, 0, 4, &clear_vertices->x); - sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_FAN, SCE_GXM_INDEX_FORMAT_U16, depth_clear_indices, 4); - validate_depth_test(); - change_depth_write(depth_mask_state ? SCE_GXM_DEPTH_WRITE_ENABLED : SCE_GXM_DEPTH_WRITE_DISABLED); - } - if ((mask & GL_STENCIL_BUFFER_BIT) == GL_STENCIL_BUFFER_BIT) { - invalidate_depth_test(); - change_depth_write(SCE_GXM_DEPTH_WRITE_DISABLED); - sceGxmSetVertexProgram(gxm_context, clear_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, disable_color_buffer_fragment_program_patched); - sceGxmSetFrontStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_NEVER, - SCE_GXM_STENCIL_OP_REPLACE, - SCE_GXM_STENCIL_OP_REPLACE, - SCE_GXM_STENCIL_OP_REPLACE, - 0, stencil_value * 0xFF); - sceGxmSetBackStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_NEVER, - SCE_GXM_STENCIL_OP_REPLACE, - SCE_GXM_STENCIL_OP_REPLACE, - SCE_GXM_STENCIL_OP_REPLACE, - 0, stencil_value * 0xFF); - void *depth_buffer, *vertex_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &depth_buffer); - float temp = 1.0f; - sceGxmSetUniformDataF(depth_buffer, clear_depth, 0, 1, &temp); - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_buffer); - sceGxmSetUniformDataF(vertex_buffer, clear_position, 0, 4, &clear_vertices->x); - sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_FAN, SCE_GXM_INDEX_FORMAT_U16, depth_clear_indices, 4); - validate_depth_test(); - change_depth_write(depth_mask_state ? SCE_GXM_DEPTH_WRITE_ENABLED : SCE_GXM_DEPTH_WRITE_DISABLED); - change_stencil_settings(); - } -} - -void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) { - clear_rgba_val.r = red; - clear_rgba_val.g = green; - clear_rgba_val.b = blue; - clear_rgba_val.a = alpha; -} - -void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data) { - SceDisplayFrameBuf pParam; - pParam.size = sizeof(SceDisplayFrameBuf); - sceDisplayGetFrameBuf(&pParam, SCE_DISPLAY_SETBUF_NEXTFRAME); - y = DISPLAY_HEIGHT - (height + y); - int i, j; - uint8_t *out8 = (uint8_t *)data; - uint8_t *in8 = (uint8_t *)pParam.base; - uint32_t *out32 = (uint32_t *)data; - uint32_t *in32 = (uint32_t *)pParam.base; - switch (format) { - case GL_RGBA: - switch (type) { - case GL_UNSIGNED_BYTE: - in32 += (x + y * pParam.pitch); - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - out32[(height - (i + 1)) * width + j] = in32[j]; - } - in32 += pParam.pitch; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RGB: - switch (type) { - case GL_UNSIGNED_BYTE: - in8 += (x * 4 + y * pParam.pitch * 4); - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - out8[((height - (i + 1)) * width + j) * 3] = in8[j * 4]; - out8[((height - (i + 1)) * width + j) * 3 + 1] = in8[j * 4 + 1]; - out8[((height - (i + 1)) * width + j) * 3 + 2] = in8[j * 4 + 2]; - } - in8 += pParam.pitch * 4; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glLineWidth(GLfloat width) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (width <= 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Changing line and point width as requested - sceGxmSetFrontPointLineWidth(gxm_context, width); - sceGxmSetBackPointLineWidth(gxm_context, width); -} - -void glPointSize(GLfloat size) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (size <= 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Changing line and point width as requested - sceGxmSetFrontPointLineWidth(gxm_context, size); - sceGxmSetBackPointLineWidth(gxm_context, size); -} - -void glFogf(GLenum pname, GLfloat param) { - switch (pname) { - case GL_FOG_MODE: - fog_mode = param; - update_fogging_state(); - break; - case GL_FOG_DENSITY: - fog_density = param; - break; - case GL_FOG_START: - fog_near = param; - break; - case GL_FOG_END: - fog_far = param; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glFogfv(GLenum pname, const GLfloat *params) { - switch (pname) { - case GL_FOG_MODE: - fog_mode = params[0]; - update_fogging_state(); - break; - case GL_FOG_DENSITY: - fog_density = params[0]; - break; - case GL_FOG_START: - fog_near = params[0]; - break; - case GL_FOG_END: - fog_far = params[0]; - break; - case GL_FOG_COLOR: - memcpy_neon(&fog_color.r, params, sizeof(vector4f)); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glFogi(GLenum pname, const GLint param) { - switch (pname) { - case GL_FOG_MODE: - fog_mode = param; - update_fogging_state(); - break; - case GL_FOG_DENSITY: - fog_density = param; - break; - case GL_FOG_START: - fog_near = param; - break; - case GL_FOG_END: - fog_far = param; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glClipPlane(GLenum plane, const GLdouble *equation) { - switch (plane) { - case GL_CLIP_PLANE0: - clip_plane0_eq.x = equation[0]; - clip_plane0_eq.y = equation[1]; - clip_plane0_eq.z = equation[2]; - clip_plane0_eq.w = equation[3]; - matrix4x4 inverted, inverted_transposed; - matrix4x4_invert(inverted, modelview_matrix); - matrix4x4_transpose(inverted_transposed, inverted); - vector4f temp; - vector4f_matrix4x4_mult(&temp, inverted_transposed, &clip_plane0_eq); - memcpy_neon(&clip_plane0_eq.x, &temp.x, sizeof(vector4f)); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glHint(GLenum target, GLenum mode) { - switch (target) { - case GL_TEXTURE_COMPRESSION_HINT: - switch (mode) { - case GL_FASTEST: - fast_texture_compression = GL_TRUE; - break; - default: - fast_texture_compression = GL_FALSE; - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} diff --git a/deps/vitaGL/source/shaders.h b/deps/vitaGL/source/shaders.h deleted file mode 100644 index 705ec6f04d..0000000000 --- a/deps/vitaGL/source/shaders.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - *shaders.h: - *Header file for default shaders related stuffs - */ - -#ifndef _SHADERS_H_ -#define _SHADERS_H_ - -// Disable color buffer shader -extern SceGxmShaderPatcherId disable_color_buffer_fragment_id; -extern const SceGxmProgramParameter *disable_color_buffer_position; -extern SceGxmFragmentProgram *disable_color_buffer_fragment_program_patched; -extern const SceGxmProgramParameter *clear_depth; - -// Clear shader -extern SceGxmShaderPatcherId clear_vertex_id; -extern SceGxmShaderPatcherId clear_fragment_id; -extern const SceGxmProgramParameter *clear_position; -extern const SceGxmProgramParameter *clear_color; -extern SceGxmVertexProgram *clear_vertex_program_patched; -extern SceGxmFragmentProgram *clear_fragment_program_patched; - -// Color (RGBA/RGB) shader -extern SceGxmShaderPatcherId rgba_vertex_id; -extern SceGxmShaderPatcherId rgb_vertex_id; -extern SceGxmShaderPatcherId rgba_fragment_id; -extern const SceGxmProgramParameter *rgba_position; -extern const SceGxmProgramParameter *rgba_color; -extern const SceGxmProgramParameter *rgba_wvp; -extern const SceGxmProgramParameter *rgb_position; -extern const SceGxmProgramParameter *rgb_color; -extern const SceGxmProgramParameter *rgb_wvp; -extern SceGxmVertexProgram *rgba_vertex_program_patched; -extern SceGxmVertexProgram *rgba_u8n_vertex_program_patched; -extern SceGxmVertexProgram *rgb_vertex_program_patched; -extern SceGxmVertexProgram *rgb_u8n_vertex_program_patched; -extern SceGxmFragmentProgram *rgba_fragment_program_patched; -extern const SceGxmProgram *rgba_fragment_program; - -// Texture2D shader -extern SceGxmShaderPatcherId texture2d_vertex_id; -extern SceGxmShaderPatcherId texture2d_fragment_id; -extern const SceGxmProgramParameter *texture2d_position; -extern const SceGxmProgramParameter *texture2d_texcoord; -extern const SceGxmProgramParameter *texture2d_wvp; -extern const SceGxmProgramParameter *texture2d_alpha_cut; -extern const SceGxmProgramParameter *texture2d_alpha_op; -extern const SceGxmProgramParameter *texture2d_tint_color; -extern const SceGxmProgramParameter *texture2d_tex_env; -extern const SceGxmProgramParameter *texture2d_clip_plane0; -extern const SceGxmProgramParameter *texture2d_clip_plane0_eq; -extern const SceGxmProgramParameter *texture2d_mv; -extern const SceGxmProgramParameter *texture2d_fog_mode; -extern const SceGxmProgramParameter *texture2d_fog_near; -extern const SceGxmProgramParameter *texture2d_fog_far; -extern const SceGxmProgramParameter *texture2d_fog_density; -extern const SceGxmProgramParameter *texture2d_fog_color; -extern const SceGxmProgramParameter *texture2d_tex_env_color; -extern SceGxmVertexProgram *texture2d_vertex_program_patched; -extern SceGxmFragmentProgram *texture2d_fragment_program_patched; -extern const SceGxmProgram *texture2d_fragment_program; - -// Texture2D+RGBA shader -extern SceGxmShaderPatcherId texture2d_rgba_vertex_id; -extern SceGxmShaderPatcherId texture2d_rgba_fragment_id; -extern const SceGxmProgramParameter *texture2d_rgba_position; -extern const SceGxmProgramParameter *texture2d_rgba_texcoord; -extern const SceGxmProgramParameter *texture2d_rgba_wvp; -extern const SceGxmProgramParameter *texture2d_rgba_alpha_cut; -extern const SceGxmProgramParameter *texture2d_rgba_alpha_op; -extern const SceGxmProgramParameter *texture2d_rgba_color; -extern const SceGxmProgramParameter *texture2d_rgba_tex_env; -extern const SceGxmProgramParameter *texture2d_rgba_clip_plane0; -extern const SceGxmProgramParameter *texture2d_rgba_clip_plane0_eq; -extern const SceGxmProgramParameter *texture2d_rgba_mv; -extern const SceGxmProgramParameter *texture2d_rgba_fog_mode; -extern const SceGxmProgramParameter *texture2d_rgba_fog_near; -extern const SceGxmProgramParameter *texture2d_rgba_fog_far; -extern const SceGxmProgramParameter *texture2d_rgba_fog_density; -extern const SceGxmProgramParameter *texture2d_rgba_fog_color; -extern const SceGxmProgramParameter *texture2d_rgba_tex_env_color; -extern SceGxmVertexProgram *texture2d_rgba_vertex_program_patched; -extern SceGxmVertexProgram *texture2d_rgba_u8n_vertex_program_patched; -extern SceGxmFragmentProgram *texture2d_rgba_fragment_program_patched; -extern const SceGxmProgram *texture2d_rgba_fragment_program; - -#endif diff --git a/deps/vitaGL/source/shaders/clear_f.h b/deps/vitaGL/source/shaders/clear_f.h deleted file mode 100644 index 3efceae539..0000000000 --- a/deps/vitaGL/source/shaders/clear_f.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __clear_f__ -#define __clear_f__ - -static unsigned int size_clear_f = 236; -static unsigned char clear_f[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0xea, 0x00, 0x00, 0x00, 0x31, 0xc7, 0xbe, 0x93, - 0x4c, 0xc3, 0x26, 0xba, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x02, 0x80, 0x19, 0xf0, - 0x7e, 0x0d, 0x80, 0x40, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, 0x63, 0x6c, - 0x65, 0x61, 0x72, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/clear_v.h b/deps/vitaGL/source/shaders/clear_v.h deleted file mode 100644 index 1b55545922..0000000000 --- a/deps/vitaGL/source/shaders/clear_v.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __clear_v__ -#define __clear_v__ - -static unsigned int size_clear_v = 372; -static unsigned char clear_v[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0x71, 0x01, 0x00, 0x00, 0xf3, 0x7d, 0x64, 0x50, - 0xb9, 0x22, 0xc8, 0x0c, 0x04, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x30, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, - 0x88, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x03, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x10, 0x81, - 0x0a, 0x05, 0x84, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, - 0x04, 0xc0, 0x07, 0xb0, 0x85, 0x01, 0x88, 0x48, 0x06, 0xc0, 0x07, 0xb0, 0x81, 0x01, 0x88, 0x48, - 0x04, 0xc0, 0x07, 0xb0, 0x81, 0x01, 0x88, 0x4d, 0x00, 0x04, 0x40, 0xe0, 0x09, 0x00, 0x81, 0x50, - 0x40, 0x00, 0x04, 0xc1, 0x01, 0x05, 0x80, 0x3d, 0x05, 0xc0, 0x07, 0xb0, 0x85, 0x01, 0x88, 0x4e, - 0x00, 0x00, 0x00, 0xe0, 0x09, 0x00, 0x81, 0x50, 0x00, 0x00, 0x00, 0xc1, 0x09, 0x05, 0x80, 0x3a, - 0x40, 0x00, 0x00, 0x42, 0x01, 0x05, 0x80, 0x38, 0x01, 0x00, 0x04, 0x50, 0x85, 0x11, 0xa5, 0x08, - 0x01, 0x80, 0x56, 0x90, 0x81, 0x11, 0x83, 0x08, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x04, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x00, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/disable_color_buffer_f.h b/deps/vitaGL/source/shaders/disable_color_buffer_f.h deleted file mode 100644 index 397bdc35c9..0000000000 --- a/deps/vitaGL/source/shaders/disable_color_buffer_f.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __disable_color_buffer_f__ -#define __disable_color_buffer_f__ - -static unsigned int size_disable_color_buffer_f = 276; -static unsigned char disable_color_buffer_f[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0x14, 0x01, 0x00, 0x00, 0x4d, 0x94, 0xc7, 0x39, - 0x5b, 0xce, 0x5e, 0x9b, 0x15, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0xfa, - 0x00, 0x00, 0x00, 0xe0, 0x08, 0x00, 0x81, 0x50, 0x02, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x30, 0xfb, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x70, 0x74, 0x68, 0x5f, 0x63, 0x6c, - 0x65, 0x61, 0x72, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/rgb_v.h b/deps/vitaGL/source/shaders/rgb_v.h deleted file mode 100644 index bc5caf32a9..0000000000 --- a/deps/vitaGL/source/shaders/rgb_v.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __rgb_v__ -#define __rgb_v__ - -static unsigned int size_rgb_v = 448; -static unsigned char rgb_v[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0xbd, 0x01, 0x00, 0x00, 0xcf, 0x61, 0x92, 0x9a, - 0x71, 0x82, 0x84, 0xfc, 0x04, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0xa2, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x00, 0x2c, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x05, 0x00, 0xa3, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x01, 0x30, 0x82, 0x02, 0x05, 0x80, 0x38, 0x07, 0x01, 0x43, 0xa2, - 0x8e, 0x0d, 0x80, 0x40, 0x0f, 0x05, 0x83, 0xa2, 0x8e, 0x0d, 0x80, 0x40, 0x05, 0x00, 0xc3, 0xa1, - 0x8e, 0x0d, 0x80, 0x40, 0x0d, 0x04, 0x03, 0xa2, 0x8e, 0x0d, 0x80, 0x40, 0x00, 0x00, 0x40, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x00, 0x04, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x04, 0x00, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x01, 0x00, 0x82, 0x02, 0x05, 0x84, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x81, 0x00, 0x84, 0x90, 0x85, 0x19, 0xa5, 0x08, - 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 0x14, 0x89, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, - 0x0b, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 0x07, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, - 0x01, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, 0x00, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, - 0xc1, 0x00, 0xd4, 0x90, 0x89, 0x11, 0xc1, 0x08, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x00, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/rgba_f.h b/deps/vitaGL/source/shaders/rgba_f.h deleted file mode 100644 index f89c9ae975..0000000000 --- a/deps/vitaGL/source/shaders/rgba_f.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __rgba_f__ -#define __rgba_f__ - -static unsigned int size_rgba_f = 212; -static unsigned char rgba_f[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0xd4, 0x00, 0x00, 0x00, 0x9c, 0xd6, 0x9b, 0xf7, - 0x94, 0x1a, 0xc4, 0x74, 0x01, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x0f, 0xa0, 0xd0, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x02, 0x80, 0x19, 0xa0, - 0x7e, 0x0d, 0x80, 0x40, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/rgba_v.h b/deps/vitaGL/source/shaders/rgba_v.h deleted file mode 100644 index f72aaa45a4..0000000000 --- a/deps/vitaGL/source/shaders/rgba_v.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __rgba_v__ -#define __rgba_v__ - -static unsigned int size_rgba_v = 440; -static unsigned char rgba_v[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0xb5, 0x01, 0x00, 0x00, 0x24, 0xdc, 0x9e, 0xbb, - 0xe8, 0xbd, 0x34, 0xb5, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, - 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0xa2, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x00, 0x2c, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x05, 0x00, 0xa3, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x01, 0x30, 0x82, 0x02, 0x05, 0x80, 0x38, 0x07, 0x01, 0x43, 0xa2, - 0x8e, 0x0d, 0x80, 0x40, 0x0f, 0x05, 0x83, 0xa2, 0x8e, 0x0d, 0x80, 0x40, 0x05, 0x00, 0xc3, 0xa1, - 0x8e, 0x0d, 0x80, 0x40, 0x0d, 0x04, 0x03, 0xa2, 0x8e, 0x0d, 0x80, 0x40, 0x00, 0x00, 0x40, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x00, 0x04, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x04, 0x00, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x01, 0x00, 0x82, 0x02, 0x05, 0x84, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x80, 0x00, 0x08, 0x83, 0x21, 0x1d, 0x80, 0x38, - 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 0x14, 0x89, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, - 0x0b, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 0x07, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, - 0x01, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, 0x00, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, - 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, - 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x2a, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x21, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x61, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x61, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x00, 0x77, 0x76, 0x70, 0x00, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/texture2d_f.h b/deps/vitaGL/source/shaders/texture2d_f.h deleted file mode 100644 index e5017a4c37..0000000000 --- a/deps/vitaGL/source/shaders/texture2d_f.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef __texture2d_f__ -#define __texture2d_f__ - -static unsigned int size_texture2d_f = 1284; -static unsigned char texture2d_f[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0x01, 0x05, 0x00, 0x00, 0xa0, 0xad, 0x6e, 0x36, - 0x32, 0x6a, 0xc9, 0x2c, 0x09, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0xa8, 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x24, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x4d, 0x00, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0xf4, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x2c, 0x03, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0xd9, 0xc0, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x47, 0x10, 0x44, 0xa4, 0xa6, 0x41, 0xa4, 0x08, 0x88, 0x10, 0x04, 0xa4, 0xaa, 0x00, 0xc0, 0x08, - 0xcf, 0x00, 0x04, 0xa2, 0xa6, 0x08, 0xa4, 0x08, 0x49, 0x12, 0x04, 0xaf, 0xa4, 0x10, 0xa4, 0x08, - 0x02, 0x3e, 0x00, 0x00, 0x02, 0x00, 0x80, 0x30, 0x40, 0x82, 0xe4, 0xa1, 0x82, 0x10, 0x84, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0xfa, 0x17, 0x84, 0x07, 0xf0, 0x81, 0x06, 0xa8, 0x48, - 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x04, 0x02, 0x03, 0xa0, 0x8c, 0x0d, 0x80, 0x40, - 0x06, 0x03, 0x43, 0xa0, 0x8c, 0x0d, 0x80, 0x40, 0x1a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x15, 0x84, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x81, 0x00, 0x04, 0xb0, 0x84, 0x41, 0xa4, 0x08, - 0xc2, 0x00, 0x44, 0xb0, 0x88, 0x41, 0xc0, 0x08, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x16, 0x84, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x0f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x18, 0x84, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, 0x04, 0x81, 0x99, 0xff, 0xbc, 0x0d, 0xc0, 0x40, - 0x02, 0x01, 0x5d, 0x8f, 0x84, 0x8b, 0xa1, 0x18, 0x41, 0x5f, 0x44, 0x1f, 0x84, 0x1b, 0xa5, 0x08, - 0x40, 0x6f, 0x04, 0x10, 0x84, 0x09, 0xa5, 0x08, 0x40, 0x6f, 0x4d, 0x10, 0x80, 0x00, 0x81, 0x08, - 0x03, 0x0f, 0x4c, 0x20, 0x00, 0x11, 0x80, 0x08, 0x0a, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x41, 0x24, 0x00, 0xf0, 0x84, 0x91, 0xa0, 0x00, 0x02, 0x34, 0x40, 0xf0, 0x84, 0x00, 0x80, 0x00, - 0x83, 0x00, 0x46, 0xe0, 0x08, 0x11, 0xc0, 0x08, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x80, 0x02, 0x60, 0xe0, 0x08, 0x00, 0xc1, 0x50, 0x04, 0x81, 0x81, 0xff, 0x9c, 0x0d, 0xc0, 0x40, - 0x43, 0x00, 0x11, 0x8f, 0xc0, 0x8b, 0xb1, 0x18, 0xbc, 0x30, 0x04, 0x80, 0x84, 0x91, 0x80, 0x00, - 0xfc, 0x30, 0x50, 0x80, 0x84, 0x40, 0x80, 0x00, 0x9a, 0x83, 0x07, 0xf0, 0x81, 0x06, 0xa8, 0x48, - 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x0c, 0xa0, 0x85, 0x01, 0x8b, 0x48, - 0x12, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, 0x95, 0x83, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x80, 0x80, 0x03, 0x30, 0x15, 0xc9, 0x88, 0x48, 0x0f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x96, 0x83, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x80, 0x80, 0x03, 0x30, 0x95, 0xca, 0x88, 0x48, - 0x0c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x98, 0x83, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x80, 0x80, 0x03, 0x30, 0x95, 0xc2, 0x88, 0x48, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x99, 0x83, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x80, 0x80, 0x03, 0x30, 0x95, 0xc1, 0x88, 0x48, - 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x97, 0x83, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x80, 0x80, 0x03, 0x30, 0x15, 0xc5, 0x88, 0x48, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x9b, 0x83, 0x07, 0xf0, 0x85, 0x01, 0x88, 0x48, 0x80, 0x80, 0x03, 0x30, 0x95, 0xc6, 0x88, 0x4a, - 0x14, 0x0a, 0x00, 0xf0, 0x06, 0x04, 0x30, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x04, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x99, 0x84, 0x07, 0xf0, 0x81, 0x06, 0xa8, 0x48, - 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xfd, 0x95, 0x84, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x0b, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x96, 0x84, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0xc1, 0x00, 0x00, 0xe0, 0x82, 0x08, 0x80, 0x08, - 0x00, 0x00, 0x00, 0xaf, 0x80, 0x08, 0x80, 0x08, 0x4e, 0x80, 0x01, 0xcf, 0x80, 0x80, 0xe1, 0x18, - 0x01, 0x3e, 0x00, 0x00, 0x02, 0x06, 0x80, 0x30, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x01, 0x02, 0x00, 0xe0, 0x82, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x80, 0x02, 0x06, 0x80, 0x30, - 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, 0x07, 0x10, 0x10, 0xf0, 0xa6, 0x00, 0x80, 0x00, - 0x0e, 0x50, 0x04, 0xb0, 0x86, 0x08, 0xa4, 0x08, 0x00, 0x60, 0x00, 0x9f, 0x80, 0x08, 0xa5, 0x08, - 0x0c, 0x85, 0xa1, 0xff, 0x9c, 0x0d, 0xc0, 0x40, 0x3d, 0x11, 0x41, 0x0f, 0xc0, 0x8b, 0xb1, 0x18, - 0x00, 0x11, 0x01, 0x00, 0x80, 0x81, 0xb1, 0x18, 0x01, 0x90, 0x40, 0x00, 0x80, 0x80, 0xb1, 0x18, - 0x02, 0x80, 0x19, 0x00, 0x7e, 0x0d, 0x80, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x09, 0x00, 0x00, 0x00, 0x26, 0x35, 0x05, 0xc0, - 0x0a, 0x00, 0x00, 0x00, 0x3b, 0xaa, 0xb8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x0b, 0x00, - 0xd0, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xc9, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, - 0xc1, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xbb, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, - 0xb2, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, - 0xab, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0xa4, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0xa0, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, - 0x99, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x91, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x8d, 0x00, 0x00, 0x00, 0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x43, 0x75, 0x74, 0x00, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x4f, 0x70, - 0x00, 0x74, 0x69, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x74, 0x65, 0x78, 0x45, 0x6e, - 0x76, 0x00, 0x66, 0x6f, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x00, 0x66, 0x6f, 0x67, 0x43, 0x6f, - 0x6c, 0x6f, 0x72, 0x00, 0x74, 0x65, 0x78, 0x45, 0x6e, 0x76, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, - 0x66, 0x6f, 0x67, 0x5f, 0x6e, 0x65, 0x61, 0x72, 0x00, 0x66, 0x6f, 0x67, 0x5f, 0x66, 0x61, 0x72, - 0x00, 0x66, 0x6f, 0x67, 0x5f, 0x64, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x00, 0x74, 0x65, 0x78, - 0x00, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/texture2d_rgba_f.h b/deps/vitaGL/source/shaders/texture2d_rgba_f.h deleted file mode 100644 index 494bce1638..0000000000 --- a/deps/vitaGL/source/shaders/texture2d_rgba_f.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef __texture2d_rgba_f__ -#define __texture2d_rgba_f__ - -static unsigned int size_texture2d_rgba_f = 1320; -static unsigned char texture2d_rgba_f[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0x27, 0x05, 0x00, 0x00, 0xf0, 0x40, 0x0f, 0xe9, - 0x85, 0x99, 0xb7, 0x4d, 0x09, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x1b, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x55, 0x00, 0x00, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x98, 0x03, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x0b, 0x00, 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x03, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x6c, 0x03, 0x00, 0x00, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x00, 0xa9, 0xd0, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, - 0x0f, 0xd0, 0xc0, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0d, 0x80, 0x68, 0xa3, 0xa6, 0x08, 0xc0, 0x08, 0xc7, 0x11, 0x04, 0xaf, 0xa4, 0x10, 0xa4, 0x08, - 0x02, 0x3e, 0x40, 0x00, 0x02, 0x00, 0x80, 0x30, 0xc2, 0x81, 0xe4, 0xa1, 0x82, 0x10, 0x84, 0x08, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x04, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x44, 0xfa, 0x93, 0x81, 0x07, 0xf0, 0x81, 0x06, 0xa8, 0x48, - 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x04, 0x02, 0x03, 0xa0, 0x8c, 0x0d, 0x80, 0x40, - 0x06, 0x03, 0x43, 0xa0, 0x8e, 0x0d, 0x80, 0x40, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x91, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x80, 0x00, 0x04, 0xa0, 0x84, 0x41, 0xa4, 0x08, - 0xc1, 0x00, 0x04, 0xa1, 0x8a, 0x41, 0xc0, 0x08, 0x1b, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x92, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x13, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x94, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xaf, 0xbc, 0x0d, 0xc0, 0x40, - 0x02, 0x01, 0x5d, 0x8f, 0x84, 0x8b, 0xa1, 0x18, 0x41, 0x5f, 0x44, 0x1f, 0x84, 0x1b, 0xa5, 0x08, - 0x40, 0x6f, 0x04, 0x10, 0x84, 0x09, 0xa5, 0x08, 0x40, 0x6f, 0x4d, 0x10, 0x82, 0x00, 0x81, 0x08, - 0x03, 0x0f, 0x4c, 0x20, 0x02, 0x11, 0x80, 0x08, 0x10, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x99, 0xaf, 0xbc, 0x0d, 0xc0, 0x40, - 0x06, 0x82, 0xa1, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 0x05, 0x01, 0x91, 0xdf, 0x80, 0x8b, 0xb1, 0x18, - 0x3d, 0x21, 0x11, 0x00, 0xc0, 0x89, 0xb1, 0x18, 0xbd, 0xa0, 0x48, 0x00, 0xc2, 0x80, 0xb1, 0x18, - 0x03, 0x0f, 0x4c, 0x20, 0x02, 0x11, 0x80, 0x08, 0x08, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, 0x06, 0x82, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, - 0x00, 0x01, 0x1d, 0x8f, 0xc4, 0x8b, 0xa1, 0x18, 0xc0, 0xc0, 0x13, 0xa0, 0x80, 0x81, 0xa0, 0x00, - 0xc1, 0xc0, 0x5b, 0xa0, 0x82, 0x00, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x08, 0x04, 0x43, 0xa0, 0x8e, 0x0d, 0x80, 0x40, 0x16, 0x81, 0x07, 0xf0, 0x81, 0x06, 0xa8, 0x48, - 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x0c, 0xa0, 0x85, 0x01, 0x8b, 0x48, - 0x12, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, 0x11, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x80, 0x80, 0x03, 0xb0, 0x15, 0xc9, 0x88, 0x48, 0x0f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x12, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x80, 0x80, 0x03, 0xb0, 0x95, 0xca, 0x88, 0x48, - 0x0c, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x14, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x80, 0x80, 0x03, 0xb0, 0x95, 0xc2, 0x88, 0x48, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x15, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, 0x80, 0x80, 0x03, 0xb0, 0x95, 0xc1, 0x88, 0x48, - 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x13, 0x81, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x80, 0x80, 0x03, 0xb0, 0x15, 0xc5, 0x88, 0x48, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x17, 0x81, 0x07, 0xf0, 0x85, 0x01, 0x88, 0x48, 0x80, 0x80, 0x03, 0xb0, 0x95, 0xc6, 0x88, 0x4a, - 0x10, 0x08, 0x00, 0xf0, 0x06, 0x04, 0x30, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x04, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x15, 0x82, 0x07, 0xf0, 0x81, 0x06, 0xa8, 0x48, - 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x03, 0x00, 0x8e, 0x0d, 0x80, 0x40, - 0x14, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, 0x11, 0x82, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x0b, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x12, 0x82, 0x07, 0xf0, 0x81, 0x01, 0xa8, 0x48, - 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, 0x05, 0x80, 0x24, 0xe0, 0x82, 0x08, 0x84, 0x08, - 0x00, 0x00, 0x00, 0xaf, 0x80, 0x08, 0x80, 0x08, 0x4c, 0x80, 0x01, 0xcf, 0x80, 0x80, 0xe1, 0x18, - 0x01, 0x3e, 0x00, 0x00, 0x02, 0x06, 0x80, 0x30, 0x05, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, - 0x45, 0x03, 0x00, 0xe0, 0x82, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x80, 0x02, 0x06, 0x80, 0x30, - 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf8, 0x87, 0x50, 0x10, 0xf0, 0xa6, 0x00, 0x80, 0x00, - 0x0c, 0x50, 0x04, 0xb0, 0x86, 0x08, 0xa4, 0x08, 0x00, 0x60, 0x00, 0x9f, 0x80, 0x08, 0xa5, 0x08, - 0x08, 0x83, 0xa1, 0xff, 0x9c, 0x0d, 0xc0, 0x40, 0x3d, 0x11, 0x41, 0x0f, 0xc0, 0x8b, 0xb1, 0x18, - 0x00, 0x11, 0x01, 0x00, 0x82, 0x81, 0xb1, 0x18, 0x01, 0x90, 0x40, 0x80, 0x82, 0x80, 0xb1, 0x18, - 0x02, 0x80, 0x19, 0xa0, 0x7e, 0x0d, 0x80, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x09, 0x00, 0x00, 0x00, 0x26, 0x35, 0x05, 0xc0, - 0x0a, 0x00, 0x00, 0x00, 0x3b, 0xaa, 0xb8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, - 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x13, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0b, 0x00, - 0xc0, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb9, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0xb1, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, - 0xa8, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, - 0xa1, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, - 0x9a, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, - 0x96, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x8f, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, - 0x87, 0x00, 0x00, 0x00, 0x01, 0xe1, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x83, 0x00, 0x00, 0x00, 0x02, 0x04, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x43, 0x75, 0x74, 0x00, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x4f, 0x70, - 0x00, 0x74, 0x65, 0x78, 0x45, 0x6e, 0x76, 0x00, 0x66, 0x6f, 0x67, 0x5f, 0x6d, 0x6f, 0x64, 0x65, - 0x00, 0x66, 0x6f, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x74, 0x65, 0x78, 0x45, 0x6e, 0x76, - 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x66, 0x6f, 0x67, 0x5f, 0x6e, 0x65, 0x61, 0x72, 0x00, 0x66, - 0x6f, 0x67, 0x5f, 0x66, 0x61, 0x72, 0x00, 0x66, 0x6f, 0x67, 0x5f, 0x64, 0x65, 0x6e, 0x73, 0x69, - 0x74, 0x79, 0x00, 0x74, 0x65, 0x78, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/texture2d_rgba_v.h b/deps/vitaGL/source/shaders/texture2d_rgba_v.h deleted file mode 100644 index a233deec22..0000000000 --- a/deps/vitaGL/source/shaders/texture2d_rgba_v.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __texture2d_rgba_v__ -#define __texture2d_rgba_v__ - -static unsigned int size_texture2d_rgba_v = 668; -static unsigned char texture2d_rgba_v[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0x99, 0x02, 0x00, 0x00, 0x03, 0x54, 0x4f, 0xaa, - 0x6e, 0x7a, 0x89, 0x04, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x0c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00, 0x00, 0x00, - 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x18, 0x00, 0x0b, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa6, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x00, 0x60, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x05, 0x40, 0xa6, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x01, 0x64, 0x82, 0x02, 0x05, 0x80, 0x38, 0x07, 0x01, 0x83, 0xa5, - 0x8e, 0x0d, 0x80, 0x40, 0x0f, 0x05, 0xc3, 0xa5, 0x8e, 0x0d, 0x80, 0x40, 0x05, 0x00, 0x03, 0xa5, - 0x8e, 0x0d, 0x80, 0x40, 0x0d, 0x04, 0x43, 0xa5, 0x8e, 0x0d, 0x80, 0x40, 0x00, 0x00, 0x40, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x00, 0x04, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x04, 0x00, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x01, 0x00, 0x82, 0x02, 0x05, 0x84, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x01, 0x0e, 0x01, 0x01, 0x02, 0x00, 0x10, 0xfa, - 0x80, 0x00, 0x08, 0x83, 0x21, 0x25, 0x80, 0x38, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x10, 0xfa, - 0x27, 0x90, 0x07, 0xf0, 0x81, 0x06, 0xc8, 0x48, 0xc0, 0x04, 0xf0, 0xc1, 0x00, 0x05, 0x80, 0x38, - 0x41, 0x92, 0x40, 0x41, 0x81, 0x80, 0xd3, 0x18, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0x80, 0x40, - 0x08, 0xa2, 0xbd, 0xc0, 0x82, 0x38, 0x90, 0x18, 0x24, 0x91, 0x99, 0xff, 0xbc, 0x0d, 0x80, 0x40, - 0x02, 0xa2, 0x51, 0x81, 0x81, 0x80, 0xd1, 0x18, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, - 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 0x2e, 0x96, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, - 0x18, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 0x14, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, - 0x01, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, 0x00, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, - 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x26, 0x00, 0x02, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x00, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x00, - 0x77, 0x76, 0x70, 0x00, 0x63, 0x6c, 0x69, 0x70, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x30, 0x00, - 0x63, 0x6c, 0x69, 0x70, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x30, 0x5f, 0x65, 0x71, 0x00, 0x6d, - 0x6f, 0x64, 0x65, 0x6c, 0x76, 0x69, 0x65, 0x77, 0x00, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shaders/texture2d_v.h b/deps/vitaGL/source/shaders/texture2d_v.h deleted file mode 100644 index 276c3abf17..0000000000 --- a/deps/vitaGL/source/shaders/texture2d_v.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef __texture2d_v__ -#define __texture2d_v__ - -static unsigned int size_texture2d_v = 628; -static unsigned char texture2d_v[] __attribute__((aligned(16))) = { - 0x47, 0x58, 0x50, 0x00, 0x01, 0x05, 0x50, 0x03, 0x73, 0x02, 0x00, 0x00, 0xd5, 0xed, 0x20, 0x1e, - 0xe4, 0x17, 0x9c, 0x83, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, - 0x08, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x13, 0x00, 0x00, 0x00, - 0xe0, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, 0xd0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0xc0, 0x3d, 0x03, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x44, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x01, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x34, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x07, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xa6, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x00, 0x60, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x05, 0x40, 0xa6, - 0x0a, 0x00, 0x81, 0x50, 0xc0, 0x01, 0x64, 0x82, 0x02, 0x05, 0x80, 0x38, 0x07, 0x01, 0x83, 0xa5, - 0x8e, 0x0d, 0x80, 0x40, 0x0f, 0x05, 0xc3, 0xa5, 0x8e, 0x0d, 0x80, 0x40, 0x05, 0x00, 0x03, 0xa5, - 0x8e, 0x0d, 0x80, 0x40, 0x0d, 0x04, 0x43, 0xa5, 0x8e, 0x0d, 0x80, 0x40, 0x00, 0x00, 0x40, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x00, 0x04, 0x82, 0x02, 0x05, 0x80, 0x38, 0x00, 0x04, 0x00, 0xa0, - 0x0a, 0x00, 0x81, 0x50, 0x80, 0x01, 0x00, 0x82, 0x02, 0x05, 0x84, 0x38, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x44, 0xfa, 0x80, 0x00, 0x08, 0x83, 0x21, 0x05, 0x80, 0x38, - 0x27, 0x90, 0x07, 0xf0, 0x81, 0x06, 0xc8, 0x48, 0xc0, 0x04, 0xf0, 0xc1, 0x00, 0x05, 0x80, 0x38, - 0x41, 0x92, 0xc0, 0x40, 0x81, 0x80, 0xd3, 0x18, 0x06, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xf9, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0x80, 0x40, - 0x08, 0xa2, 0x3d, 0xc0, 0x81, 0x38, 0x90, 0x18, 0x24, 0x91, 0x99, 0xff, 0xbc, 0x0d, 0x80, 0x40, - 0x00, 0xa2, 0xd1, 0x40, 0x81, 0x80, 0xd1, 0x18, 0x00, 0x00, 0x00, 0x00, 0x40, 0x09, 0x00, 0xf8, - 0x02, 0x80, 0x81, 0xaf, 0x9c, 0x0d, 0xc0, 0x40, 0x2e, 0x96, 0xb9, 0xff, 0xbc, 0x0d, 0xc0, 0x40, - 0x18, 0x11, 0x49, 0xcf, 0x80, 0x8f, 0xb1, 0x18, 0x14, 0x11, 0x45, 0xcf, 0x80, 0x8f, 0xb1, 0x18, - 0x01, 0x11, 0x01, 0xc0, 0x81, 0x81, 0xb1, 0x18, 0x00, 0xd1, 0x42, 0xc0, 0x81, 0x81, 0xb1, 0x18, - 0x00, 0x00, 0x20, 0xa0, 0x00, 0x50, 0x27, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x00, - 0x13, 0x00, 0x00, 0x00, 0x26, 0x00, 0x02, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x41, 0xe1, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x01, 0xe4, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x00, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x00, 0x77, 0x76, 0x70, 0x00, 0x63, 0x6c, - 0x69, 0x70, 0x5f, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x30, 0x00, 0x63, 0x6c, 0x69, 0x70, 0x5f, 0x70, - 0x6c, 0x61, 0x6e, 0x65, 0x30, 0x5f, 0x65, 0x71, 0x00, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x76, 0x69, - 0x65, 0x77, 0x00, 0x00, -}; - -#endif diff --git a/deps/vitaGL/source/shared.h b/deps/vitaGL/source/shared.h deleted file mode 100644 index 5a1f41f11e..0000000000 --- a/deps/vitaGL/source/shared.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * shared.h: - * All functions/definitions that shouldn't be exposed to - * end users but are used in multiple source files must be here - */ - -#ifndef _SHARED_H_ -#define _SHARED_H_ - -// Internal constants -#define TEXTURES_NUM 16384 // Available textures -#define COMPRESSED_TEXTURE_FORMATS_NUM 9 // The number of supported texture formats. -#define MODELVIEW_STACK_DEPTH 32 // Depth of modelview matrix stack -#define GENERIC_STACK_DEPTH 2 // Depth of generic matrix stack -#define DISPLAY_WIDTH_DEF 960 // Default display width in pixels -#define DISPLAY_HEIGHT_DEF 544 // Default display height in pixels -#define DISPLAY_BUFFER_COUNT 2 // Display buffers to use -#define GXM_TEX_MAX_SIZE 4096 // Maximum width/height in pixels per texture -#define BUFFERS_ADDR 0xA000 // Starting address for buffers indexing -#define BUFFERS_NUM 128 // Maximum number of allocatable buffers - -// Internal constants set in bootup phase -extern int DISPLAY_WIDTH; // Display width in pixels -extern int DISPLAY_HEIGHT; // Display height in pixels -extern int DISPLAY_STRIDE; // Display stride in pixels -extern float DISPLAY_WIDTH_FLOAT; // Display width in pixels (float) -extern float DISPLAY_HEIGHT_FLOAT; // Display height in pixels (float) - -#include -#include -#include - -#include "vitaGL.h" - -#include "utils/gpu_utils.h" -#include "utils/math_utils.h" -#include "utils/mem_utils.h" - -#include "state.h" -#include "texture_callbacks.h" - -#define SET_GL_ERROR(x) \ - vgl_error = x; \ - return; - -// Texture environment mode -typedef enum texEnvMode { - MODULATE = 0, - DECAL = 1, - BLEND = 2, - ADD = 3, - REPLACE = 4 -} texEnvMode; - -// 3D vertex for position + 4D vertex for RGBA color struct -typedef struct rgba_vertex { - vector3f position; - vector4f color; -} rgba_vertex; - -// 3D vertex for position + 3D vertex for RGB color struct -typedef struct rgb_vertex { - vector3f position; - vector3f color; -} rgb_vertex; - -// 3D vertex for position + 2D vertex for UV map struct -typedef struct texture2d_vertex { - vector3f position; - vector2f texcoord; -} texture2d_vertex; - -// Non native primitives implemented -typedef enum SceGxmPrimitiveTypeExtra { - SCE_GXM_PRIMITIVE_NONE = 0, - SCE_GXM_PRIMITIVE_QUADS = 1 -} SceGxmPrimitiveTypeExtra; - -#include "shaders.h" - -// Internal stuffs -extern void *frag_uniforms; -extern void *vert_uniforms; -extern SceGxmMultisampleMode msaa_mode; -extern GLboolean use_extra_mem; - -// Debugging tool -#ifdef ENABLE_LOG -void LOG(const char *format, ...); -#endif - -// Logging callback for vitaShaRK -#if defined(HAVE_SHARK) && defined(HAVE_SHARK_LOG) -void shark_log_cb(const char *msg, shark_log_level msg_level, int line); -#endif - -// Depending on SDK, these could be or not defined -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef min -#define min(a, b) ((a) < (b) ? (a) : (b)) -#endif - -extern uint8_t use_shark; // Flag to check if vitaShaRK should be initialized at vitaGL boot -extern uint8_t is_shark_online; // Current vitaShaRK status - -// sceGxm viewport setup (NOTE: origin is on center screen) -extern float x_port; -extern float y_port; -extern float z_port; -extern float x_scale; -extern float y_scale; -extern float z_scale; - -// Fullscreen sceGxm viewport (NOTE: origin is on center screen) -extern float fullscreen_x_port; -extern float fullscreen_y_port; -extern float fullscreen_z_port; -extern float fullscreen_x_scale; -extern float fullscreen_y_scale; -extern float fullscreen_z_scale; - -extern SceGxmContext *gxm_context; // sceGxm context instance -extern GLenum vgl_error; // Error returned by glGetError -extern SceGxmShaderPatcher *gxm_shader_patcher; // sceGxmShaderPatcher shader patcher instance -extern void *gxm_depth_surface_addr; // Depth surface memblock starting address -extern uint8_t system_app_mode; // Flag for system app mode usage - -extern matrix4x4 mvp_matrix; // ModelViewProjection Matrix -extern matrix4x4 projection_matrix; // Projection Matrix -extern matrix4x4 modelview_matrix; // ModelView Matrix -extern GLboolean mvp_modified; // Check if ModelViewProjection matrix needs to be recreated - -extern GLuint cur_program; // Current in use custom program (0 = No custom program) -extern GLboolean vblank; // Current setting for VSync - -extern GLenum orig_depth_test; // Original depth test state (used for depth test invalidation) - -// Scissor test shaders -extern SceGxmFragmentProgram *scissor_test_fragment_program; // Scissor test fragment program -extern vector4f *scissor_test_vertices; // Scissor test region vertices -extern SceUID scissor_test_vertices_uid; // Scissor test vertices memblock id - -extern uint16_t *depth_clear_indices; // Memblock starting address for clear screen indices - -// Clear screen shaders -extern SceGxmVertexProgram *clear_vertex_program_patched; // Patched vertex program for clearing screen -extern vector4f *clear_vertices; // Memblock starting address for clear screen vertices - -extern GLboolean fast_texture_compression; // Hints for texture compression - -/* gxm.c */ -void initGxm(void); // Inits sceGxm -void initGxmContext(void); // Inits sceGxm context -void termGxmContext(void); // Terms sceGxm context -void createDisplayRenderTarget(void); // Creates render target for the display -void destroyDisplayRenderTarget(void); // Destroys render target for the display -void initDisplayColorSurfaces(void); // Creates color surfaces for the display -void termDisplayColorSurfaces(void); // Destroys color surfaces for the display -void initDepthStencilBuffer(uint32_t w, uint32_t h, SceGxmDepthStencilSurface *surface, void **depth_buffer, void **stencil_buffer, vglMemType *depth_type, vglMemType *stencil_type); // Creates depth and stencil surfaces -void initDepthStencilSurfaces(void); // Creates depth and stencil surfaces for the display -void termDepthStencilSurfaces(void); // Destroys depth and stencil surfaces for the display -void startShaderPatcher(void); // Creates a shader patcher instance -void stopShaderPatcher(void); // Destroys a shader patcher instance -void waitRenderingDone(void); // Waits for rendering to be finished - -/* tests.c */ -void change_depth_write(SceGxmDepthWriteMode mode); // Changes current in use depth write mode -void change_depth_func(void); // Changes current in use depth test function -void invalidate_depth_test(void); // Invalidates depth test state -void validate_depth_test(void); // Resets original depth test state after invalidation -void change_stencil_settings(void); // Changes current in use stencil test parameters -GLboolean change_stencil_config(SceGxmStencilOp *cfg, GLenum new); // Changes current in use stencil test operation value -GLboolean change_stencil_func_config(SceGxmStencilFunc *cfg, GLenum new); // Changes current in use stencil test function value -void update_alpha_test_settings(void); // Changes current in use alpha test operation value -void update_scissor_test(void); // Changes current in use scissor test region -void resetScissorTestRegion(void); // Resets scissor test region to default values - -/* blending.c */ -void change_blend_factor(void); // Changes current blending settings for all used shaders -void disable_blend(void); // Disables blending for all used shaders - -/* custom_shaders.c */ -void resetCustomShaders(void); // Resets custom shaders -void changeCustomShadersBlend(SceGxmBlendInfo *blend_info); // Change SceGxmBlendInfo value to all custom shaders -void reloadCustomShader(void); // Reloads in use custom shader inside sceGxm -void _vglDrawObjects_CustomShadersIMPL(GLenum mode, GLsizei count, GLboolean implicit_wvp); // vglDrawObjects implementation for rendering with custom shaders - -/* misc functions */ -void vector4f_convert_to_local_space(vector4f *out, int x, int y, int width, int height); // Converts screen coords to local space - -#endif diff --git a/deps/vitaGL/source/state.c b/deps/vitaGL/source/state.c deleted file mode 100644 index 2f7d928be5..0000000000 --- a/deps/vitaGL/source/state.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * state.c: - * Initial config of the openGL machine state - */ - -#include "shared.h" - -// Blending -GLboolean blend_state = GL_FALSE; // Current state for GL_BLEND -SceGxmBlendFactor blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE; // Current in use RGB source blend factor -SceGxmBlendFactor blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ZERO; // Current in use RGB dest blend factor -SceGxmBlendFactor blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE; // Current in use A source blend factor -SceGxmBlendFactor blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ZERO; // Current in use A dest blend factor - -// Polygon Mode -GLfloat pol_factor = 0.0f; // Current factor for glPolygonOffset -GLfloat pol_units = 0.0f; // Current units for glPolygonOffset - -// Texture Units -int8_t client_texture_unit = 0; // Current in use client side texture unit - -// Miscellaneous -glPhase phase = NONE; // Current drawing phase for legacy openGL -vector4f clear_rgba_val; // Current clear color for glClear - -// Fogging -GLboolean fogging = GL_FALSE; // Current fogging processor state -GLint fog_mode = GL_EXP; // Current fogging mode (openGL) -fogType internal_fog_mode = DISABLED; // Current fogging mode (sceGxm) -GLfloat fog_density = 1.0f; // Current fogging density -GLfloat fog_near = 0.0f; // Current fogging near distance -GLfloat fog_far = 1.0f; // Current fogging far distance -vector4f fog_color = { 0.0f, 0.0f, 0.0f, 0.0f }; // Current fogging color - -// Clipping Planes -GLint clip_plane0 = GL_FALSE; // Current status of clip plane 0 -vector4f clip_plane0_eq = { 0.0f, 0.0f, 0.0f, 0.0f }; // Current equation of clip plane 0 - -// Cullling -GLboolean cull_face_state = GL_FALSE; // Current state for GL_CULL_FACE -GLenum gl_cull_mode = GL_BACK; // Current in use openGL cull mode -GLenum gl_front_face = GL_CCW; // Current in use openGL setting for front facing primitives -GLboolean no_polygons_mode = GL_FALSE; // GL_TRUE when cull mode is set to GL_FRONT_AND_BACK - -// Polygon Offset -GLboolean pol_offset_fill = GL_FALSE; // Current state for GL_POLYGON_OFFSET_FILL -GLboolean pol_offset_line = GL_FALSE; // Current state for GL_POLYGON_OFFSET_LINE -GLboolean pol_offset_point = GL_FALSE; // Current state for GL_POLYGON_OFFSET_POINT -SceGxmPolygonMode polygon_mode_front = SCE_GXM_POLYGON_MODE_TRIANGLE_FILL; // Current in use polygon mode for front -SceGxmPolygonMode polygon_mode_back = SCE_GXM_POLYGON_MODE_TRIANGLE_FILL; // Current in use polygon mode for back -GLenum gl_polygon_mode_front = GL_FILL; // Current in use polygon mode for front -GLenum gl_polygon_mode_back = GL_FILL; // Current in use polygon mode for back -viewport gl_viewport; // Current viewport state diff --git a/deps/vitaGL/source/state.h b/deps/vitaGL/source/state.h deleted file mode 100644 index 2ff6e91e05..0000000000 --- a/deps/vitaGL/source/state.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * state.h: - * Header file managing state of openGL machine - */ - -#ifndef _STATE_H_ -#define _STATE_H_ - -// Drawing phases constants for legacy openGL -typedef enum glPhase { - NONE = 0, - MODEL_CREATION = 1 -} glPhase; - -// Vertex array attributes struct -typedef struct vertexArray { - GLint size; - GLint num; - GLsizei stride; - const GLvoid *pointer; -} vertexArray; - -// Scissor test region struct -typedef struct scissor_region { - int x; - int y; - int w; - int h; -} scissor_region; - -// Viewport struct -typedef struct viewport { - int x; - int y; - int w; - int h; -} viewport; - -// Alpha operations for alpha testing -typedef enum alphaOp { - GREATER_EQUAL = 0, - GREATER = 1, - NOT_EQUAL = 2, - EQUAL = 3, - LESS_EQUAL = 4, - LESS = 5, - NEVER = 6, - ALWAYS = 7 -} alphaOp; - -// Fog modes -typedef enum fogType { - LINEAR = 0, - EXP = 1, - EXP2 = 2, - DISABLED = 3 -} fogType; - -// Texture unit struct -typedef struct texture_unit { - GLboolean enabled; - GLboolean vertex_array_state; - GLboolean color_array_state; - GLboolean texture_array_state; - matrix4x4 stack[GENERIC_STACK_DEPTH]; - vertexArray vertex_array; - vertexArray color_array; - vertexArray texture_array; - GLenum color_object_type; - void *vertex_object; - void *color_object; - void *texture_object; - void *index_object; - int env_mode; - int tex_id; -} texture_unit; - -// Framebuffer struct -typedef struct framebuffer { - uint8_t active; - SceGxmRenderTarget *target; - SceGxmColorSurface colorbuffer; - SceGxmDepthStencilSurface depthbuffer; - void *depth_buffer_addr; - vglMemType depth_buffer_mem_type; - void *stencil_buffer_addr; - vglMemType stencil_buffer_mem_type; - int width; - int height; -} framebuffer; - -// Blending -extern GLboolean blend_state; // Current state for GL_BLEND -extern SceGxmBlendFactor blend_sfactor_rgb; // Current in use RGB source blend factor -extern SceGxmBlendFactor blend_dfactor_rgb; // Current in use RGB dest blend factor -extern SceGxmBlendFactor blend_sfactor_a; // Current in use A source blend factor -extern SceGxmBlendFactor blend_dfactor_a; // Current in use A dest blend factor - -// Depth Test -extern GLboolean depth_test_state; // Current state for GL_DEPTH_TEST -extern SceGxmDepthFunc gxm_depth; // Current in-use depth test func -extern GLenum orig_depth_test; // Original depth test state (used for depth test invalidation) -extern GLdouble depth_value; // Current depth test clear value -extern GLboolean depth_mask_state; // Current state for glDepthMask - -// Scissor Test -extern scissor_region region; // Current scissor test region setup -extern GLboolean scissor_test_state; // Current state for GL_SCISSOR_TEST - -// Stencil Test -extern uint8_t stencil_mask_front; // Current in use mask for stencil test on front -extern uint8_t stencil_mask_back; // Current in use mask for stencil test on back -extern uint8_t stencil_mask_front_write; // Current in use mask for write stencil test on front -extern uint8_t stencil_mask_back_write; // Current in use mask for write stencil test on back -extern uint8_t stencil_ref_front; // Current in use reference for stencil test on front -extern uint8_t stencil_ref_back; // Current in use reference for stencil test on back -extern SceGxmStencilOp stencil_fail_front; // Current in use stencil operation when stencil test fails for front -extern SceGxmStencilOp depth_fail_front; // Current in use stencil operation when depth test fails for front -extern SceGxmStencilOp depth_pass_front; // Current in use stencil operation when depth test passes for front -extern SceGxmStencilOp stencil_fail_back; // Current in use stencil operation when stencil test fails for back -extern SceGxmStencilOp depth_fail_back; // Current in use stencil operation when depth test fails for back -extern SceGxmStencilOp depth_pass_back; // Current in use stencil operation when depth test passes for back -extern SceGxmStencilFunc stencil_func_front; // Current in use stencil function on front -extern SceGxmStencilFunc stencil_func_back; // Current in use stencil function on back -extern GLboolean stencil_test_state; // Current state for GL_STENCIL_TEST -extern GLint stencil_value; // Current stencil test clear value - -// Alpha Test -extern GLenum alpha_func; // Current in use alpha test mode -extern GLfloat alpha_ref; // Current in use alpha test reference value -extern int alpha_op; // Current in use alpha test operation -extern GLboolean alpha_test_state; // Current state for GL_ALPHA_TEST - -// Polygon Mode -extern GLfloat pol_factor; // Current factor for glPolygonOffset -extern GLfloat pol_units; // Current units for glPolygonOffset - -// Texture Units -extern texture_unit texture_units[GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; // Available texture units -extern texture vgl_textures[TEXTURES_NUM]; // Available texture slots -extern int8_t server_texture_unit; // Current in use server side texture unit -extern int8_t client_texture_unit; // Current in use client side texture unit -extern palette *color_table; // Current in-use color table - -// Matrices -extern matrix4x4 *matrix; // Current in-use matrix mode - -// Miscellaneous -extern glPhase phase; // Current drawing phase for legacy openGL -extern vector4f current_color; // Current in use color -extern vector4f clear_rgba_val; // Current clear color for glClear -extern viewport gl_viewport; // Current viewport state - -// Culling -extern GLboolean no_polygons_mode; // GL_TRUE when cull mode is set to GL_FRONT_AND_BACK -extern GLboolean cull_face_state; // Current state for GL_CULL_FACE -extern GLenum gl_cull_mode; // Current in use openGL cull mode -extern GLenum gl_front_face; // Current in use openGL setting for front facing primitives - -// Polygon Offset -extern GLboolean pol_offset_fill; // Current state for GL_POLYGON_OFFSET_FILL -extern GLboolean pol_offset_line; // Current state for GL_POLYGON_OFFSET_LINE -extern GLboolean pol_offset_point; // Current state for GL_POLYGON_OFFSET_POINT -extern SceGxmPolygonMode polygon_mode_front; // Current in use polygon mode for front -extern SceGxmPolygonMode polygon_mode_back; // Current in use polygon mode for back -extern GLenum gl_polygon_mode_front; // Current in use polygon mode for front -extern GLenum gl_polygon_mode_back; // Current in use polygon mode for back - -// Texture Environment -extern vector4f texenv_color; // Current in use texture environment color - -// Fogging -extern GLboolean fogging; // Current fogging processor state -extern GLint fog_mode; // Current fogging mode (openGL) -extern fogType internal_fog_mode; // Current fogging mode (sceGxm) -extern GLfloat fog_density; // Current fogging density -extern GLfloat fog_near; // Current fogging near distance -extern GLfloat fog_far; // Current fogging far distance -extern vector4f fog_color; // Current fogging color - -// Clipping Planes -extern GLint clip_plane0; // Current status of clip plane 0 -extern vector4f clip_plane0_eq; // Current equation of clip plane 0 - -// Framebuffers -extern framebuffer *active_read_fb; // Current readback framebuffer in use -extern framebuffer *active_write_fb; // Current write framebuffer in use - -#endif diff --git a/deps/vitaGL/source/tests.c b/deps/vitaGL/source/tests.c deleted file mode 100644 index 8e0251412a..0000000000 --- a/deps/vitaGL/source/tests.c +++ /dev/null @@ -1,510 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * tests.c: - * Implementation for all drawing tests functions - */ - -#include "shared.h" - -// Depth Test -GLboolean depth_test_state = GL_FALSE; // Current state for GL_DEPTH_TEST -SceGxmDepthFunc gxm_depth = SCE_GXM_DEPTH_FUNC_LESS; // Current in-use depth test func -GLenum orig_depth_test; // Original depth test state (used for depth test invalidation) -GLdouble depth_value = 1.0f; // Current depth test clear value -GLboolean depth_mask_state = GL_TRUE; // Current state for glDepthMask - -// Scissor Test -scissor_region region; // Current scissor test region setup -GLboolean scissor_test_state = GL_FALSE; // Current state for GL_SCISSOR_TEST -SceGxmFragmentProgram *scissor_test_fragment_program; // Scissor test fragment program -vector4f *scissor_test_vertices = NULL; // Scissor test region vertices -SceUID scissor_test_vertices_uid; // Scissor test vertices memblock id - -// Stencil Test -uint8_t stencil_mask_front = 0xFF; // Current in use mask for stencil test on front -uint8_t stencil_mask_back = 0xFF; // Current in use mask for stencil test on back -uint8_t stencil_mask_front_write = 0xFF; // Current in use mask for write stencil test on front -uint8_t stencil_mask_back_write = 0xFF; // Current in use mask for write stencil test on back -uint8_t stencil_ref_front = 0; // Current in use reference for stencil test on front -uint8_t stencil_ref_back = 0; // Current in use reference for stencil test on back -SceGxmStencilOp stencil_fail_front = SCE_GXM_STENCIL_OP_KEEP; // Current in use stencil operation when stencil test fails for front -SceGxmStencilOp depth_fail_front = SCE_GXM_STENCIL_OP_KEEP; // Current in use stencil operation when depth test fails for front -SceGxmStencilOp depth_pass_front = SCE_GXM_STENCIL_OP_KEEP; // Current in use stencil operation when depth test passes for front -SceGxmStencilOp stencil_fail_back = SCE_GXM_STENCIL_OP_KEEP; // Current in use stencil operation when stencil test fails for back -SceGxmStencilOp depth_fail_back = SCE_GXM_STENCIL_OP_KEEP; // Current in use stencil operation when depth test fails for back -SceGxmStencilOp depth_pass_back = SCE_GXM_STENCIL_OP_KEEP; // Current in use stencil operation when depth test passes for back -SceGxmStencilFunc stencil_func_front = SCE_GXM_STENCIL_FUNC_ALWAYS; // Current in use stencil function on front -SceGxmStencilFunc stencil_func_back = SCE_GXM_STENCIL_FUNC_ALWAYS; // Current in use stencil function on back -GLboolean stencil_test_state = GL_FALSE; // Current state for GL_STENCIL_TEST -GLint stencil_value = 0; // Current stencil test clear value - -// Alpha Test -GLenum alpha_func = GL_ALWAYS; // Current in-use alpha test mode -GLfloat alpha_ref = 0.0f; // Current in use alpha test reference value -int alpha_op = ALWAYS; // Current in use alpha test operation -GLboolean alpha_test_state = GL_FALSE; // Current state for GL_ALPHA_TEST - -void change_depth_write(SceGxmDepthWriteMode mode) { - // Change depth write mode for both front and back primitives - sceGxmSetFrontDepthWriteEnable(gxm_context, mode); - sceGxmSetBackDepthWriteEnable(gxm_context, mode); -} - -void change_depth_func() { - // Setting depth function for both front and back primitives - sceGxmSetFrontDepthFunc(gxm_context, depth_test_state ? gxm_depth : SCE_GXM_DEPTH_FUNC_ALWAYS); - sceGxmSetBackDepthFunc(gxm_context, depth_test_state ? gxm_depth : SCE_GXM_DEPTH_FUNC_ALWAYS); - - // Calling an update for the depth write mode - change_depth_write(depth_mask_state ? SCE_GXM_DEPTH_WRITE_ENABLED : SCE_GXM_DEPTH_WRITE_DISABLED); -} - -void invalidate_depth_test() { - // Invalidating current depth test state - orig_depth_test = depth_test_state; - depth_test_state = GL_FALSE; - - // Invoking a depth function update - change_depth_func(); -} - -void validate_depth_test() { - // Restoring original depth test state - depth_test_state = orig_depth_test; - - // Invoking a depth function update - change_depth_func(); -} - -void invalidate_viewport() { - // Invalidating current viewport - sceGxmSetViewport(gxm_context, fullscreen_x_port, fullscreen_x_scale, fullscreen_y_port, fullscreen_y_scale, fullscreen_z_port, fullscreen_z_scale); -} - -void validate_viewport() { - // Restoring original viewport - sceGxmSetViewport(gxm_context, x_port, x_scale, y_port, y_scale, z_port, z_scale); -} - -void change_stencil_settings() { - if (stencil_test_state) { - // Setting stencil function for both front and back primitives - sceGxmSetFrontStencilFunc(gxm_context, - stencil_func_front, - stencil_fail_front, - depth_fail_front, - depth_pass_front, - stencil_mask_front, stencil_mask_front_write); - sceGxmSetBackStencilFunc(gxm_context, - stencil_func_back, - stencil_fail_back, - depth_fail_back, - depth_pass_back, - stencil_mask_back, stencil_mask_back_write); - - // Setting stencil ref for both front and back primitives - sceGxmSetFrontStencilRef(gxm_context, stencil_ref_front); - sceGxmSetBackStencilRef(gxm_context, stencil_ref_back); - - } else { - sceGxmSetFrontStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_ALWAYS, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - 0, 0); - sceGxmSetBackStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_ALWAYS, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - 0, 0); - } -} - -GLboolean change_stencil_config(SceGxmStencilOp *cfg, GLenum new) { - // Translating openGL stencil operation value to sceGxm one - GLboolean ret = GL_TRUE; - switch (new) { - case GL_KEEP: - *cfg = SCE_GXM_STENCIL_OP_KEEP; - break; - case GL_ZERO: - *cfg = SCE_GXM_STENCIL_OP_ZERO; - break; - case GL_REPLACE: - *cfg = SCE_GXM_STENCIL_OP_REPLACE; - break; - case GL_INCR: - *cfg = SCE_GXM_STENCIL_OP_INCR; - break; - case GL_INCR_WRAP: - *cfg = SCE_GXM_STENCIL_OP_INCR_WRAP; - break; - case GL_DECR: - *cfg = SCE_GXM_STENCIL_OP_DECR; - break; - case GL_DECR_WRAP: - *cfg = SCE_GXM_STENCIL_OP_DECR_WRAP; - break; - case GL_INVERT: - *cfg = SCE_GXM_STENCIL_OP_INVERT; - break; - default: - ret = GL_FALSE; - break; - } - return ret; -} - -GLboolean change_stencil_func_config(SceGxmStencilFunc *cfg, GLenum new) { - // Translating openGL stencil function to sceGxm one - GLboolean ret = GL_TRUE; - switch (new) { - case GL_NEVER: - *cfg = SCE_GXM_STENCIL_FUNC_NEVER; - break; - case GL_LESS: - *cfg = SCE_GXM_STENCIL_FUNC_LESS; - break; - case GL_LEQUAL: - *cfg = SCE_GXM_STENCIL_FUNC_LESS_EQUAL; - break; - case GL_GREATER: - *cfg = SCE_GXM_STENCIL_FUNC_GREATER; - break; - case GL_GEQUAL: - *cfg = SCE_GXM_STENCIL_FUNC_GREATER_EQUAL; - break; - case GL_EQUAL: - *cfg = SCE_GXM_STENCIL_FUNC_EQUAL; - break; - case GL_NOTEQUAL: - *cfg = SCE_GXM_STENCIL_FUNC_NOT_EQUAL; - break; - case GL_ALWAYS: - *cfg = SCE_GXM_STENCIL_FUNC_ALWAYS; - break; - default: - ret = GL_FALSE; - break; - } - return ret; -} - -void update_alpha_test_settings() { - // Translating openGL alpha test operation to internal one - if (alpha_test_state) { - switch (alpha_func) { - case GL_EQUAL: - alpha_op = EQUAL; - break; - case GL_LEQUAL: - alpha_op = LESS_EQUAL; - break; - case GL_GEQUAL: - alpha_op = GREATER_EQUAL; - break; - case GL_LESS: - alpha_op = LESS; - break; - case GL_GREATER: - alpha_op = GREATER; - break; - case GL_NOTEQUAL: - alpha_op = NOT_EQUAL; - break; - case GL_NEVER: - alpha_op = NEVER; - break; - default: - alpha_op = ALWAYS; - break; - } - } else - alpha_op = ALWAYS; -} - -void update_scissor_test() { - // Setting current vertex program to clear screen one and fragment program to scissor test one - sceGxmSetVertexProgram(gxm_context, clear_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, scissor_test_fragment_program); - - // Invalidating viewport - invalidate_viewport(); - - // Invalidating internal tile based region clip - sceGxmSetRegionClip(gxm_context, SCE_GXM_REGION_CLIP_OUTSIDE, 0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1); - - if (scissor_test_state) { - // Calculating scissor test region vertices - vector4f_convert_to_local_space(scissor_test_vertices, region.x, region.y, region.w, region.h); - - void *vertex_buffer; - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_buffer); - sceGxmSetUniformDataF(vertex_buffer, clear_position, 0, 4, &clear_vertices->x); - - // Cleaning stencil surface mask update bit on the whole screen - sceGxmSetFrontStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_NEVER, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - 0, 0); - sceGxmSetBackStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_NEVER, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - 0, 0); - sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_FAN, SCE_GXM_INDEX_FORMAT_U16, depth_clear_indices, 4); - } - - // Setting stencil surface mask update bit on the scissor test region - sceGxmSetFrontStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_ALWAYS, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - 0, 0); - sceGxmSetBackStencilFunc(gxm_context, - SCE_GXM_STENCIL_FUNC_ALWAYS, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - SCE_GXM_STENCIL_OP_KEEP, - 0, 0); - - void *vertex_buffer; - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_buffer); - if (scissor_test_state) - sceGxmSetUniformDataF(vertex_buffer, clear_position, 0, 4, &scissor_test_vertices->x); - else - sceGxmSetUniformDataF(vertex_buffer, clear_position, 0, 4, &clear_vertices->x); - sceGxmDraw(gxm_context, SCE_GXM_PRIMITIVE_TRIANGLE_FAN, SCE_GXM_INDEX_FORMAT_U16, depth_clear_indices, 4); - - // Restoring viewport - validate_viewport(); - - // Reducing GPU workload by performing tile granularity clipping - if (scissor_test_state) - sceGxmSetRegionClip(gxm_context, SCE_GXM_REGION_CLIP_OUTSIDE, region.x, region.y, region.x + region.w - 1, region.y + region.h - 1); - - // Restoring original stencil test settings - change_stencil_settings(); -} - -void resetScissorTestRegion(void) { - // Setting scissor test region to default values - region.x = region.y = 0; - region.w = DISPLAY_WIDTH; - region.h = DISPLAY_HEIGHT; -} - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if ((width < 0) || (height < 0)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Converting openGL scissor test region to sceGxm one - region.x = x; - region.y = DISPLAY_HEIGHT - y - height; - region.w = width; - region.h = height; - - // Updating in use scissor test parameters if GL_SCISSOR_TEST is enabled - if (scissor_test_state) - update_scissor_test(); -} - -void glDepthFunc(GLenum func) { - // Properly translating openGL function to sceGxm one - switch (func) { - case GL_NEVER: - gxm_depth = SCE_GXM_DEPTH_FUNC_NEVER; - break; - case GL_LESS: - gxm_depth = SCE_GXM_DEPTH_FUNC_LESS; - break; - case GL_EQUAL: - gxm_depth = SCE_GXM_DEPTH_FUNC_EQUAL; - break; - case GL_LEQUAL: - gxm_depth = SCE_GXM_DEPTH_FUNC_LESS_EQUAL; - break; - case GL_GREATER: - gxm_depth = SCE_GXM_DEPTH_FUNC_GREATER; - break; - case GL_NOTEQUAL: - gxm_depth = SCE_GXM_DEPTH_FUNC_NOT_EQUAL; - break; - case GL_GEQUAL: - gxm_depth = SCE_GXM_DEPTH_FUNC_GREATER_EQUAL; - break; - case GL_ALWAYS: - gxm_depth = SCE_GXM_DEPTH_FUNC_ALWAYS; - break; - } - - // Updating in use depth function - change_depth_func(); -} - -void glClearDepth(GLdouble depth) { - // Set current in use depth test depth value - depth_value = depth; -} - -void glDepthMask(GLboolean flag) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - // Set current in use depth mask and invoking a depth write mode update - depth_mask_state = flag; - change_depth_write(depth_mask_state ? SCE_GXM_DEPTH_WRITE_ENABLED : SCE_GXM_DEPTH_WRITE_DISABLED); -} - -void glAlphaFunc(GLenum func, GLfloat ref) { - // Updating in use alpha test parameters - alpha_func = func; - alpha_ref = ref; - update_alpha_test_settings(); -} - -void glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) { - // Properly updating stencil operation settings - switch (face) { - case GL_FRONT: - if (!change_stencil_config(&stencil_fail_front, sfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_fail_front, dpfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_pass_front, dppass)) - SET_GL_ERROR(GL_INVALID_ENUM) - break; - case GL_BACK: - if (!change_stencil_config(&stencil_fail_back, sfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_fail_back, dpfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_pass_front, dppass)) - SET_GL_ERROR(GL_INVALID_ENUM) - break; - case GL_FRONT_AND_BACK: - if (!change_stencil_config(&stencil_fail_front, sfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&stencil_fail_back, sfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_fail_front, dpfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_fail_back, dpfail)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_pass_front, dppass)) - SET_GL_ERROR(GL_INVALID_ENUM) - if (!change_stencil_config(&depth_pass_back, dppass)) - SET_GL_ERROR(GL_INVALID_ENUM) - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - change_stencil_settings(); -} - -void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass) { - glStencilOpSeparate(GL_FRONT_AND_BACK, sfail, dpfail, dppass); -} - -void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) { - // Properly updating stencil test function settings - switch (face) { - case GL_FRONT: - if (!change_stencil_func_config(&stencil_func_front, func)) { - SET_GL_ERROR(GL_INVALID_ENUM) - } - stencil_mask_front = mask; - stencil_ref_front = ref; - break; - case GL_BACK: - if (!change_stencil_func_config(&stencil_func_back, func)) { - SET_GL_ERROR(GL_INVALID_ENUM) - } - stencil_mask_back = mask; - stencil_ref_back = ref; - break; - case GL_FRONT_AND_BACK: - if (!change_stencil_func_config(&stencil_func_front, func)) { - SET_GL_ERROR(GL_INVALID_ENUM) - } - if (!change_stencil_func_config(&stencil_func_back, func)) { - SET_GL_ERROR(GL_INVALID_ENUM) - } - stencil_mask_front = stencil_mask_back = mask; - stencil_ref_front = stencil_ref_back = ref; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - change_stencil_settings(); -} - -void glStencilFunc(GLenum func, GLint ref, GLuint mask) { - glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask); -} - -void glStencilMaskSeparate(GLenum face, GLuint mask) { - // Properly updating stencil test mask settings - switch (face) { - case GL_FRONT: - stencil_mask_front_write = mask; - break; - case GL_BACK: - stencil_mask_back_write = mask; - break; - case GL_FRONT_AND_BACK: - stencil_mask_front_write = stencil_mask_back_write = mask; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - return; - } - change_stencil_settings(); -} - -void glStencilMask(GLuint mask) { - glStencilMaskSeparate(GL_FRONT_AND_BACK, mask); -} - -void glClearStencil(GLint s) { - stencil_value = s; -} diff --git a/deps/vitaGL/source/texture_callbacks.c b/deps/vitaGL/source/texture_callbacks.c deleted file mode 100644 index d23cc227a8..0000000000 --- a/deps/vitaGL/source/texture_callbacks.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * texture_callbacks.c: - * Implementation for texture data reading/writing callbacks - */ - -#include -#include - -#include "vitaGL.h" -#include "texture_callbacks.h" - -#define convert_u16_to_u32_cspace(color, lshift, rshift, mask) ((((color << lshift) >> rshift) & mask) * 0xFF) / mask - -// Read callback for 32bpp unsigned ABGR format -uint32_t readBGRA(void *data) { - uint32_t res; - memcpy_neon(&res, data, 4); - uint8_t *p = (uint8_t *)&res; - uint8_t tmp = p[0]; - p[0] = p[2]; - p[2] = tmp; - return res; -} - -// Read callback for 32bpp unsigned RGBA format -uint32_t readRGBA(void *data) { - uint32_t res; - memcpy_neon(&res, data, 4); - return res; -} - -// Read callback for 16bpp unsigned RGBA5551 format -uint32_t readRGBA5551(void *data) { - uint16_t clr; - uint32_t r, g, b, a; - memcpy_neon(&clr, data, 2); - r = convert_u16_to_u32_cspace(clr, 0, 11, 0x1F); - g = convert_u16_to_u32_cspace(clr, 5, 11, 0x1F); - b = convert_u16_to_u32_cspace(clr, 10, 11, 0x1F); - a = convert_u16_to_u32_cspace(clr, 15, 15, 0x01); - return ((a << 24) | (b << 16) | (g << 8) | r); -} - -// Read callback for 16bpp unsigned RGBA4444 format -uint32_t readRGBA4444(void *data) { - uint16_t clr; - uint32_t r, g, b, a; - memcpy_neon(&clr, data, 2); - r = convert_u16_to_u32_cspace(clr, 0, 12, 0x0F); - g = convert_u16_to_u32_cspace(clr, 4, 12, 0x0F); - b = convert_u16_to_u32_cspace(clr, 8, 12, 0x0F); - a = convert_u16_to_u32_cspace(clr, 12, 12, 0x0F); - return ((a << 24) | (b << 16) | (g << 8) | r); -} - -// Read callback for 16bpp unsigned RGB565 format -uint32_t readRGB565(void *data) { - uint16_t clr; - uint32_t r, g, b; - memcpy_neon(&clr, data, 2); - r = convert_u16_to_u32_cspace(clr, 0, 11, 0x1F); - g = convert_u16_to_u32_cspace(clr, 5, 10, 0x3F); - b = convert_u16_to_u32_cspace(clr, 11, 11, 0x1F); - return ((0xFF << 24) | (b << 16) | (g << 8) | r); -} - -// Read callback for 24bpp unsigned BGR format -uint32_t readBGR(void *data) { - uint32_t res = 0xFFFFFFFF; - uint8_t *src = (uint8_t *)data; - uint8_t *dst = (uint8_t *)res; - dst[0] = src[2]; - dst[1] = src[1]; - dst[2] = src[0]; - return res; -} - -// Read callback for 24bpp unsigned RGB format -uint32_t readRGB(void *data) { - uint32_t res = 0xFFFFFFFF; - memcpy_neon(&res, data, 3); - return res; -} - -// Read callback for 16bpp unsigned RG format -uint32_t readRG(void *data) { - uint32_t res = 0xFFFFFFFF; - memcpy_neon(&res, data, 2); - return res; -} - -// Read callback for 8bpp unsigned R format -uint32_t readR(void *data) { - uint32_t res = 0xFFFFFFFF; - memcpy_neon(&res, data, 1); - return res; -} - -// Write callback for 32bpp unsigned RGBA format -void writeRGBA(void *data, uint32_t color) { - memcpy_neon(data, &color, 4); -} - -// Write callback for 32bpp unsigned BGRA format -void writeBGRA(void *data, uint32_t color) { - memcpy_neon(data, &color, 4); - uint8_t *p = (uint8_t *)data; - uint8_t tmp = p[0]; - p[0] = p[2]; - p[2] = tmp; -} - -// Write callback for 24bpp unsigned RGB format -void writeRGB(void *data, uint32_t color) { - memcpy_neon(data, &color, 3); -} - -// Write callback for 24bpp unsigned BGR format -void writeBGR(void *data, uint32_t color) { - uint8_t *src = (uint8_t *)&color; - uint8_t *dst = (uint8_t *)data; - dst[0] = src[2]; - dst[1] = src[1]; - dst[2] = src[0]; -} - -// Write callback for 16bpp unsigned RG format -void writeRG(void *data, uint32_t color) { - memcpy_neon(data, &color, 2); -} - -// Write callback for 16bpp unsigned RA format -void writeRA(void *data, uint32_t color) { - uint8_t *dst = (uint8_t *)data; - uint8_t *src = (uint8_t *)&color; - dst[0] = src[0]; - dst[1] = src[3]; -} - -// Write callback for 8bpp unsigned R format -void writeR(void *data, uint32_t color) { - memcpy_neon(data, &color, 1); -} \ No newline at end of file diff --git a/deps/vitaGL/source/texture_callbacks.h b/deps/vitaGL/source/texture_callbacks.h deleted file mode 100644 index bff9541963..0000000000 --- a/deps/vitaGL/source/texture_callbacks.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * texture_callbacks.h: - * Header file for texture data reading/writing callbacks exposed by texture_callbacks.c - */ - -#ifndef _TEXTURE_CALLBACKS_H_ -#define _TEXTURE_CALLBACKS_H_ - -// Read callbacks -uint32_t readR(void *data); -uint32_t readRG(void *data); -uint32_t readRGB(void *data); -uint32_t readBGR(void *data); -uint32_t readRGB565(void *data); -uint32_t readRGBA(void *data); -uint32_t readBGRA(void *data); -uint32_t readRGBA5551(void *data); -uint32_t readRGBA4444(void *data); - -// Write callbacks -void writeR(void *data, uint32_t color); -void writeRG(void *data, uint32_t color); -void writeRA(void *data, uint32_t color); -void writeRGB(void *data, uint32_t color); -void writeBGR(void *data, uint32_t color); -void writeRGBA(void *data, uint32_t color); -void writeBGRA(void *data, uint32_t color); - -#endif diff --git a/deps/vitaGL/source/textures.c b/deps/vitaGL/source/textures.c deleted file mode 100644 index 9f6b3c350a..0000000000 --- a/deps/vitaGL/source/textures.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * textures.c: - * Implementation for textures related functions - */ - -#include "shared.h" - -texture_unit texture_units[GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; // Available texture units -texture vgl_textures[TEXTURES_NUM]; // Available texture slots -palette *color_table = NULL; // Current in-use color table -int8_t server_texture_unit = 0; // Current in use server side texture unit - -/* - * ------------------------------ - * - IMPLEMENTATION STARTS HERE - - * ------------------------------ - */ - -void glGenTextures(GLsizei n, GLuint *res) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (n < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Aliasing to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - - // Reserving a texture and returning its id if available - int i, j = 0; - for (i = 1; i < TEXTURES_NUM; i++) { - if (!(vgl_textures[i].used)) { - res[j++] = i; - vgl_textures[i].used = 1; - - // Resetting texture parameters to their default values - vgl_textures[i].min_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - vgl_textures[i].mag_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - vgl_textures[i].mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - vgl_textures[i].u_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; - vgl_textures[i].v_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; - vgl_textures[i].lod_bias = GL_MAX_TEXTURE_LOD_BIAS; // sceGxm range is 0 - (GL_MAX_TEXTURE_LOD_BIAS*2 + 1) - } - if (j >= n) - break; - } -} - -void glBindTexture(GLenum target, GLuint texture) { - // Aliasing to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - - // Setting current in use texture id for the in use server texture unit - switch (target) { - case GL_TEXTURE_2D: - tex_unit->tex_id = texture; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glDeleteTextures(GLsizei n, const GLuint *gl_textures) { -#ifndef SKIP_ERROR_HANDLING - // Error handling - if (n < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Aliasing to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - - // Deallocating given vgl_textures and invalidating used texture ids - int j; - for (j = 0; j < n; j++) { - GLuint i = gl_textures[j]; - if (i > 0) { - vgl_textures[i].used = 0; - - // Resetting texture parameters to their default values - vgl_textures[i].min_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - vgl_textures[i].mag_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - vgl_textures[i].mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - vgl_textures[i].u_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; - vgl_textures[i].v_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; - vgl_textures[i].lod_bias = GL_MAX_TEXTURE_LOD_BIAS; // sceGxm range is 0 - (GL_MAX_TEXTURE_LOD_BIAS*2 + 1) - - gpu_free_texture(&vgl_textures[i]); - if (i == tex_unit->tex_id) - tex_unit->tex_id = 0; - } - } -} - -void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - SceGxmTextureFormat tex_format; - uint8_t data_bpp = 0; - uint8_t fast_store = GL_FALSE; - - // Support for legacy GL1.0 internalFormat - switch (internalFormat) { - case 1: - internalFormat = GL_RED; - break; - case 2: - internalFormat = GL_RG; - break; - case 3: - internalFormat = GL_RGB; - break; - case 4: - internalFormat = GL_RGBA; - break; - } - - /* - * Callbacks are actually used to just perform down/up-sampling - * between U8 texture formats. Reads are expected to give as result - * a RGBA sample that will be wrote depending on texture format - * by the write callback - */ - void (*write_cb)(void *, uint32_t) = NULL; - uint32_t (*read_cb)(void *) = NULL; - - // Detecting proper read callaback and source bpp - switch (format) { - case GL_RED: - case GL_ALPHA: - switch (type) { - case GL_UNSIGNED_BYTE: - read_cb = readR; - data_bpp = 1; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RG: - case GL_LUMINANCE_ALPHA: - switch (type) { - case GL_UNSIGNED_BYTE: - read_cb = readRG; - data_bpp = 2; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_BGR: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 3; - if (internalFormat == GL_BGR) - fast_store = GL_TRUE; - else - read_cb = readBGR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RGB: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 3; - if (internalFormat == GL_RGB) - fast_store = GL_TRUE; - else - read_cb = readRGB; - break; - case GL_UNSIGNED_SHORT_5_6_5: - data_bpp = 2; - read_cb = readRGB565; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_BGRA: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 4; - if (internalFormat == GL_BGRA) - fast_store = GL_TRUE; - else - read_cb = readBGRA; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RGBA: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 4; - if (internalFormat == GL_RGBA) - fast_store = GL_TRUE; - else - read_cb = readRGBA; - break; - case GL_UNSIGNED_SHORT_5_5_5_1: - data_bpp = 2; - read_cb = readRGBA5551; - break; - case GL_UNSIGNED_SHORT_4_4_4_4: - data_bpp = 2; - read_cb = readRGBA4444; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - } - - switch (target) { - case GL_TEXTURE_2D: - - // Detecting proper write callback and texture format - switch (internalFormat) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - tex_format = SCE_GXM_TEXTURE_FORMAT_UBC1_ABGR; - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - tex_format = SCE_GXM_TEXTURE_FORMAT_UBC3_ABGR; - break; - case GL_RGB: - write_cb = writeRGB; - tex_format = SCE_GXM_TEXTURE_FORMAT_U8U8U8_BGR; - break; - case GL_BGR: - write_cb = writeBGR; - tex_format = SCE_GXM_TEXTURE_FORMAT_U8U8U8_RGB; - break; - case GL_RGBA: - write_cb = writeRGBA; - tex_format = SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR; - break; - case GL_BGRA: - write_cb = writeBGRA; - tex_format = SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB; - break; - case GL_LUMINANCE: - write_cb = writeR; - tex_format = SCE_GXM_TEXTURE_FORMAT_L8; - break; - case GL_LUMINANCE_ALPHA: - write_cb = writeRG; - tex_format = SCE_GXM_TEXTURE_FORMAT_A8L8; - break; - case GL_INTENSITY: - write_cb = writeR; - tex_format = SCE_GXM_TEXTURE_FORMAT_U8_RRRR; - break; - case GL_ALPHA: - write_cb = writeR; - tex_format = SCE_GXM_TEXTURE_FORMAT_A8; - break; - case GL_COLOR_INDEX8_EXT: - write_cb = writeR; // TODO: This is a hack - tex_format = SCE_GXM_TEXTURE_FORMAT_P8_ABGR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Checking if texture is too big for sceGxm - if (width > GXM_TEX_MAX_SIZE || height > GXM_TEX_MAX_SIZE) { - SET_GL_ERROR(GL_INVALID_VALUE) - } - - // Allocating texture/mipmaps depending on user call - tex->type = internalFormat; - tex->write_cb = write_cb; - if (level == 0) - if (tex->write_cb) - gpu_alloc_texture(width, height, tex_format, data, tex, data_bpp, read_cb, write_cb, fast_store); - else - gpu_alloc_compressed_texture(width, height, tex_format, 0, data, tex, data_bpp, read_cb); - else - gpu_alloc_mipmaps(level, tex); - - // Setting texture parameters - sceGxmTextureSetUAddrMode(&tex->gxm_tex, tex->u_mode); - sceGxmTextureSetVAddrMode(&tex->gxm_tex, tex->v_mode); - sceGxmTextureSetMinFilter(&tex->gxm_tex, tex->min_filter); - sceGxmTextureSetMagFilter(&tex->gxm_tex, tex->mag_filter); - sceGxmTextureSetMipFilter(&tex->gxm_tex, tex->mip_filter); - sceGxmTextureSetLodBias(&tex->gxm_tex, tex->lod_bias); - - // Setting palette if the format requests one - if (tex->valid && tex->palette_UID) - sceGxmTextureSetPalette(&tex->gxm_tex, color_table->data); - - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *target_texture = &vgl_textures[texture2d_idx]; - - // Calculating implicit texture stride and start address of requested texture modification - uint32_t orig_w = sceGxmTextureGetWidth(&target_texture->gxm_tex); - uint32_t orig_h = sceGxmTextureGetHeight(&target_texture->gxm_tex); - SceGxmTextureFormat tex_format = sceGxmTextureGetFormat(&target_texture->gxm_tex); - uint8_t bpp = tex_format_to_bytespp(tex_format); - uint32_t stride = ALIGN(orig_w, 8) * bpp; - uint8_t *ptr = (uint8_t *)sceGxmTextureGetData(&target_texture->gxm_tex) + xoffset * bpp + yoffset * stride; - uint8_t *ptr_line = ptr; - uint8_t data_bpp = 0; - int i, j; - - if (xoffset + width > orig_w) { - SET_GL_ERROR(GL_INVALID_VALUE) - } else if (yoffset + height > orig_h) { - SET_GL_ERROR(GL_INVALID_VALUE) - } - - // Support for legacy GL1.0 format - switch (format) { - case 1: - format = GL_RED; - break; - case 2: - format = GL_RG; - break; - case 3: - format = GL_RGB; - break; - case 4: - format = GL_RGBA; - break; - } - - /* - * Callbacks are actually used to just perform down/up-sampling - * between U8 texture formats. Reads are expected to give as result - * a RGBA sample that will be wrote depending on texture format - * by the write callback - */ - void (*write_cb)(void *, uint32_t) = NULL; - uint32_t (*read_cb)(void *) = NULL; - - // Detecting proper read callback and source bpp - switch (format) { - case GL_RED: - case GL_ALPHA: - switch (type) { - case GL_UNSIGNED_BYTE: - read_cb = readR; - data_bpp = 1; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RG: - switch (type) { - case GL_UNSIGNED_BYTE: - read_cb = readRG; - data_bpp = 2; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RGB: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 3; - read_cb = readRGB; - break; - case GL_UNSIGNED_SHORT_5_6_5: - data_bpp = 2; - read_cb = readRGB565; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_BGR: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 3; - read_cb = readBGR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_RGBA: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 4; - read_cb = readRGBA; - break; - case GL_UNSIGNED_SHORT_5_5_5_1: - data_bpp = 2; - read_cb = readRGBA5551; - break; - case GL_UNSIGNED_SHORT_4_4_4_4: - data_bpp = 2; - read_cb = readRGBA4444; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - case GL_BGRA: - switch (type) { - case GL_UNSIGNED_BYTE: - data_bpp = 4; - read_cb = readBGRA; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - } - - switch (target) { - case GL_TEXTURE_2D: - - // Detecting proper write callback - switch (target_texture->type) { - case GL_RGB: - write_cb = writeRGB; - break; - case GL_BGR: - write_cb = writeBGR; - break; - case GL_RGBA: - write_cb = writeRGBA; - break; - case GL_BGRA: - write_cb = writeBGRA; - break; - case GL_LUMINANCE: - write_cb = writeR; - break; - case GL_LUMINANCE_ALPHA: - write_cb = writeRG; - break; - case GL_INTENSITY: - write_cb = writeR; - break; - case GL_ALPHA: - write_cb = writeR; - break; - } - - // Executing texture modification via callbacks - uint8_t *data = (uint8_t *)pixels; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j++) { - uint32_t clr = read_cb((uint8_t *)data); - write_cb(ptr, clr); - data += data_bpp; - ptr += bpp; - } - ptr = ptr_line + stride; - ptr_line = ptr; - } - - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - SceGxmTextureFormat tex_format; - -#ifndef SKIP_ERROR_HANDLING - // Checking if texture is too big for sceGxm - if (width > GXM_TEX_MAX_SIZE || height > GXM_TEX_MAX_SIZE) { - SET_GL_ERROR(GL_INVALID_VALUE) - } - - // Checking if texture dimensions are not a power of two - if (((width & (width - 1)) != 0) || ((height & (height - 1)) != 0)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } - - // Ensure imageSize isn't zero. - if (imageSize == 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - switch (target) { - case GL_TEXTURE_2D: - // Detecting proper write callback and texture format - switch (internalFormat) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - tex_format = SCE_GXM_TEXTURE_FORMAT_UBC1_ABGR; - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - tex_format = SCE_GXM_TEXTURE_FORMAT_UBC3_ABGR; - break; - case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG: - tex_format = SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_1BGR; - break; - case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: - tex_format = SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_ABGR; - break; - case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG: - tex_format = SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_1BGR; - break; - case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: - tex_format = SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_ABGR; - break; - case GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG: - tex_format = SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP_ABGR; - break; - case GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG: - tex_format = SCE_GXM_TEXTURE_FORMAT_PVRTII4BPP_ABGR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Allocating texture/mipmaps depending on user call - tex->type = internalFormat; - gpu_alloc_compressed_texture(width, height, tex_format, imageSize, data, tex, 0, NULL); - - // Setting texture parameters - sceGxmTextureSetUAddrMode(&tex->gxm_tex, tex->u_mode); - sceGxmTextureSetVAddrMode(&tex->gxm_tex, tex->v_mode); - sceGxmTextureSetMinFilter(&tex->gxm_tex, tex->min_filter); - sceGxmTextureSetMagFilter(&tex->gxm_tex, tex->mag_filter); - sceGxmTextureSetMipFilter(&tex->gxm_tex, tex->mip_filter); - sceGxmTextureSetLodBias(&tex->gxm_tex, tex->lod_bias); - - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glColorTable(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *data) { - // Checking if a color table is already enabled, if so, deallocating it - if (color_table != NULL) { - gpu_free_palette(color_table); - color_table = NULL; - } - - // Calculating color table bpp - uint8_t bpp = 0; - switch (target) { - case GL_COLOR_TABLE: - switch (format) { - case GL_RGBA: - bpp = 4; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - // Allocating and initializing color table - color_table = gpu_alloc_palette(data, width, bpp); -} - -void glTexParameteri(GLenum target, GLenum pname, GLint param) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - switch (target) { - case GL_TEXTURE_2D: - switch (pname) { - case GL_TEXTURE_MIN_FILTER: // Min filter - switch (param) { - case GL_NEAREST: // Point - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_POINT; - break; - case GL_LINEAR: // Linear - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - break; - case GL_NEAREST_MIPMAP_NEAREST: - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_POINT; - break; - case GL_LINEAR_MIPMAP_NEAREST: - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_ENABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_ENABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_LINEAR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - sceGxmTextureSetMinFilter(&tex->gxm_tex, tex->min_filter); - break; - case GL_TEXTURE_MAG_FILTER: // Mag Filter - switch (param) { - case GL_NEAREST: - tex->mag_filter = SCE_GXM_TEXTURE_FILTER_POINT; - break; - case GL_LINEAR: - tex->mag_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - sceGxmTextureSetMagFilter(&tex->gxm_tex, tex->mag_filter); - break; - case GL_TEXTURE_WRAP_S: // U Mode - switch (param) { - case GL_CLAMP_TO_EDGE: // Clamp - tex->u_mode = SCE_GXM_TEXTURE_ADDR_CLAMP; - break; - case GL_REPEAT: // Repeat - tex->u_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; - break; - case GL_MIRRORED_REPEAT: // Mirror - tex->u_mode = SCE_GXM_TEXTURE_ADDR_MIRROR; - break; - case GL_MIRROR_CLAMP_EXT: // Mirror Clamp - tex->u_mode = SCE_GXM_TEXTURE_ADDR_MIRROR_CLAMP; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - sceGxmTextureSetUAddrMode(&tex->gxm_tex, tex->u_mode); - break; - case GL_TEXTURE_WRAP_T: // V Mode - switch (param) { - case GL_CLAMP_TO_EDGE: // Clamp - tex->v_mode = SCE_GXM_TEXTURE_ADDR_CLAMP; - break; - case GL_REPEAT: // Repeat - tex->v_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; - break; - case GL_MIRRORED_REPEAT: // Mirror - tex->v_mode = SCE_GXM_TEXTURE_ADDR_MIRROR; - break; - case GL_MIRROR_CLAMP_EXT: // Mirror Clamp - tex->v_mode = SCE_GXM_TEXTURE_ADDR_MIRROR_CLAMP; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - sceGxmTextureSetVAddrMode(&tex->gxm_tex, tex->v_mode); - break; - case GL_TEXTURE_LOD_BIAS: // Distant LOD bias - tex->lod_bias = (uint32_t)(param + GL_MAX_TEXTURE_LOD_BIAS); - sceGxmTextureSetLodBias(&tex->gxm_tex, tex->lod_bias); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glTexParameterf(GLenum target, GLenum pname, GLfloat param) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - switch (target) { - case GL_TEXTURE_2D: - switch (pname) { - case GL_TEXTURE_MIN_FILTER: // Min Filter - if (param == GL_NEAREST) { - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_POINT; - } - if (param == GL_LINEAR) { - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - } - if (param == GL_NEAREST_MIPMAP_NEAREST) { - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_POINT; - } - if (param == GL_LINEAR_MIPMAP_NEAREST) { - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_ENABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_POINT; - } - if (param == GL_NEAREST_MIPMAP_LINEAR) { - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_DISABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_LINEAR; - } - if (param == GL_LINEAR_MIPMAP_LINEAR) { - tex->mip_filter = SCE_GXM_TEXTURE_MIP_FILTER_ENABLED; - tex->min_filter = SCE_GXM_TEXTURE_FILTER_MIPMAP_LINEAR; - } - sceGxmTextureSetMinFilter(&tex->gxm_tex, tex->min_filter); - sceGxmTextureSetMipFilter(&tex->gxm_tex, tex->mip_filter); - break; - case GL_TEXTURE_MAG_FILTER: // Mag filter - if (param == GL_NEAREST) - tex->mag_filter = SCE_GXM_TEXTURE_FILTER_POINT; - else if (param == GL_LINEAR) - tex->mag_filter = SCE_GXM_TEXTURE_FILTER_LINEAR; - sceGxmTextureSetMagFilter(&tex->gxm_tex, tex->mag_filter); - break; - case GL_TEXTURE_WRAP_S: // U Mode - if (param == GL_CLAMP_TO_EDGE) - tex->u_mode = SCE_GXM_TEXTURE_ADDR_CLAMP; // Clamp - else if (param == GL_REPEAT) - tex->u_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; // Repeat - else if (param == GL_MIRRORED_REPEAT) - tex->u_mode = SCE_GXM_TEXTURE_ADDR_MIRROR; // Mirror - else if (param == GL_MIRROR_CLAMP_EXT) - tex->u_mode = SCE_GXM_TEXTURE_ADDR_MIRROR_CLAMP; // Mirror Clamp - sceGxmTextureSetUAddrMode(&tex->gxm_tex, tex->u_mode); - break; - case GL_TEXTURE_WRAP_T: // V Mode - if (param == GL_CLAMP_TO_EDGE) - tex->v_mode = SCE_GXM_TEXTURE_ADDR_CLAMP; // Clamp - else if (param == GL_REPEAT) - tex->v_mode = SCE_GXM_TEXTURE_ADDR_REPEAT; // Repeat - else if (param == GL_MIRRORED_REPEAT) - tex->v_mode = SCE_GXM_TEXTURE_ADDR_MIRROR; // Mirror - else if (param == GL_MIRROR_CLAMP_EXT) - tex->v_mode = SCE_GXM_TEXTURE_ADDR_MIRROR_CLAMP; // Mirror Clamp - sceGxmTextureSetVAddrMode(&tex->gxm_tex, tex->v_mode); - break; - case GL_TEXTURE_LOD_BIAS: // Distant LOD bias - tex->lod_bias = (uint32_t)(param + GL_MAX_TEXTURE_LOD_BIAS); - sceGxmTextureSetLodBias(&tex->gxm_tex, tex->lod_bias); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glActiveTexture(GLenum texture) { - // Changing current in use server texture unit -#ifndef SKIP_ERROR_HANDLING - if ((texture < GL_TEXTURE0) && (texture > GL_TEXTURE31)) { - SET_GL_ERROR(GL_INVALID_ENUM) - } else -#endif - server_texture_unit = texture - GL_TEXTURE0; -} - -void glGenerateMipmap(GLenum target) { - // Setting some aliases to make code more readable - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - -#ifndef SKIP_ERROR_HANDLING - // Checking if current texture is valid - if (!tex->valid) - return; -#endif - - switch (target) { - case GL_TEXTURE_2D: - - // Generating mipmaps to the max possible level - gpu_alloc_mipmaps(-1, tex); - - // Setting texture parameters - sceGxmTextureSetUAddrMode(&tex->gxm_tex, tex->u_mode); - sceGxmTextureSetVAddrMode(&tex->gxm_tex, tex->v_mode); - sceGxmTextureSetMinFilter(&tex->gxm_tex, tex->min_filter); - sceGxmTextureSetMagFilter(&tex->gxm_tex, tex->mag_filter); - sceGxmTextureSetMipFilter(&tex->gxm_tex, tex->mip_filter); - sceGxmTextureSetLodBias(&tex->gxm_tex, tex->lod_bias); - - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glTexEnvf(GLenum target, GLenum pname, GLfloat param) { - // Aliasing texture unit for cleaner code - texture_unit *tex_unit = &texture_units[server_texture_unit]; - - // Properly changing texture environment settings as per request - switch (target) { - case GL_TEXTURE_ENV: - switch (pname) { - case GL_TEXTURE_ENV_MODE: - if (param == GL_MODULATE) - tex_unit->env_mode = MODULATE; - else if (param == GL_DECAL) - tex_unit->env_mode = DECAL; - else if (param == GL_REPLACE) - tex_unit->env_mode = REPLACE; - else if (param == GL_BLEND) - tex_unit->env_mode = BLEND; - else if (param == GL_ADD) - tex_unit->env_mode = ADD; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glTexEnvfv(GLenum target, GLenum pname, GLfloat *param) { - // Properly changing texture environment settings as per request - switch (target) { - case GL_TEXTURE_ENV: - switch (pname) { - case GL_TEXTURE_ENV_COLOR: - memcpy_neon(&texenv_color.r, param, sizeof(GLfloat) * 4); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glTexEnvi(GLenum target, GLenum pname, GLint param) { - // Aliasing texture unit for cleaner code - texture_unit *tex_unit = &texture_units[server_texture_unit]; - - // Properly changing texture environment settings as per request - switch (target) { - case GL_TEXTURE_ENV: - switch (pname) { - case GL_TEXTURE_ENV_MODE: - switch (param) { - case GL_MODULATE: - tex_unit->env_mode = MODULATE; - break; - case GL_DECAL: - tex_unit->env_mode = DECAL; - break; - case GL_REPLACE: - tex_unit->env_mode = REPLACE; - break; - case GL_BLEND: - tex_unit->env_mode = BLEND; - break; - case GL_ADD: - tex_unit->env_mode = ADD; - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void *vglGetTexDataPointer(GLenum target) { - // Aliasing texture unit for cleaner code - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - switch (target) { - case GL_TEXTURE_2D: - return tex->data; - break; - default: - vgl_error = GL_INVALID_ENUM; - break; - } - - return NULL; -} - -SceGxmTexture *vglGetGxmTexture(GLenum target) { - // Aliasing texture unit for cleaner code - texture_unit *tex_unit = &texture_units[server_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - texture *tex = &vgl_textures[texture2d_idx]; - - switch (target) { - case GL_TEXTURE_2D: - return &tex->gxm_tex; - break; - default: - vgl_error = GL_INVALID_ENUM; - break; - } - - return NULL; -} diff --git a/deps/vitaGL/source/utils/gpu_utils.c b/deps/vitaGL/source/utils/gpu_utils.c deleted file mode 100644 index a8159849f2..0000000000 --- a/deps/vitaGL/source/utils/gpu_utils.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * gpu_utils.c: - * Utilities for GPU usage - */ - -#include "../shared.h" -#include "stb_dxt.h" - -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(a, b) (((a) < (b)) ? (b) : (a)) -#define CEIL(a) ((a - (int)a) == 0 ? (int)a : (int)a + 1) -#endif - -// VRAM usage setting -uint8_t use_vram = 0; -uint8_t use_vram_for_usse = 0; - -// Newlib mempool usage setting -GLboolean use_extra_mem = GL_TRUE; - -// vitaGL memory pool setup -static void *pool_addr = NULL; -static unsigned int pool_index = 0; -static unsigned int pool_size = 0; - -// USSE memory settings -vglMemType frag_usse_type; -vglMemType vert_usse_type; - -uint64_t morton_1(uint64_t x) { - x = x & 0x5555555555555555; - x = (x | (x >> 1)) & 0x3333333333333333; - x = (x | (x >> 2)) & 0x0F0F0F0F0F0F0F0F; - x = (x | (x >> 4)) & 0x00FF00FF00FF00FF; - x = (x | (x >> 8)) & 0x0000FFFF0000FFFF; - x = (x | (x >> 16)) & 0xFFFFFFFFFFFFFFFF; - return x; -} - -void d2xy_morton(uint64_t d, uint64_t *x, uint64_t *y) { - *x = morton_1(d); - *y = morton_1(d >> 1); -} - -void extract_block(const uint8_t *src, int width, uint8_t *block) { - int j; - for (j = 0; j < 4; j++) { - memcpy_neon(&block[j * 4 * 4], src, 16); - src += width * 4; - } -} - -void dxt_compress(uint8_t *dst, uint8_t *src, int w, int h, int isdxt5) { - uint8_t block[64]; - int s = MAX(w, h); - uint32_t num_blocks = (s * s) / 16; - uint64_t d, offs_x, offs_y; - for (d = 0; d < num_blocks; d++) { - d2xy_morton(d, &offs_x, &offs_y); - if (offs_x * 4 >= h) - continue; - if (offs_y * 4 >= w) - continue; - extract_block(src + offs_y * 16 + offs_x * w * 16, w, block); - stb_compress_dxt_block(dst, block, isdxt5, fast_texture_compression ? STB_DXT_NORMAL : STB_DXT_HIGHQUAL); - dst += isdxt5 ? 16 : 8; - } -} - -void swizzle_compressed_texture(uint8_t *dst, uint8_t *src, int w, int h, int isdxt5, int ispvrt2bpp) { - int blocksize = isdxt5 ? 16 : 8; - - int s = MAX(w, h); - uint32_t num_blocks = (s * s) / 16; - uint64_t d, offs_x, offs_y; - for (d = 0; d < num_blocks; d++) { - d2xy_morton(d, &offs_x, &offs_y); - if (offs_x * 4 >= h) - continue; - if (offs_y * (ispvrt2bpp ? 8 : 4) >= w) - continue; - memcpy(dst, src + offs_y * blocksize + offs_x * (w / (ispvrt2bpp ? 8 : 4)) * blocksize, blocksize); - dst += isdxt5 ? 16 : 8; - } -} - -void *gpu_alloc_mapped(size_t size, vglMemType *type) { - // Allocating requested memblock - void *res = vgl_mempool_alloc(size, *type); - - // Requested memory type finished, using other one - if (res == NULL) { - *type = *type == VGL_MEM_VRAM ? VGL_MEM_RAM : VGL_MEM_VRAM; - res = vgl_mempool_alloc(size, *type); - } - - // Even the other one failed, using our last resort - if (res == NULL) { - *type = VGL_MEM_SLOW; - res = vgl_mempool_alloc(size, *type); - } - - if (res == NULL && use_extra_mem) { - *type = VGL_MEM_EXTERNAL; - res = malloc(size); - } - - return res; -} - -void *gpu_vertex_usse_alloc_mapped(size_t size, unsigned int *usse_offset) { - // Allocating memblock - vert_usse_type = use_vram_for_usse ? VGL_MEM_VRAM : VGL_MEM_RAM; - void *addr = gpu_alloc_mapped(size, &vert_usse_type); - - // Mapping memblock into sceGxm as vertex USSE memory - sceGxmMapVertexUsseMemory(addr, size, usse_offset); - - // Returning memblock starting address - return addr; -} - -void gpu_vertex_usse_free_mapped(void *addr) { - // Unmapping memblock from sceGxm as vertex USSE memory - sceGxmUnmapVertexUsseMemory(addr); - - // Deallocating memblock - vgl_mem_free(addr, vert_usse_type); -} - -void *gpu_fragment_usse_alloc_mapped(size_t size, unsigned int *usse_offset) { - // Allocating memblock - frag_usse_type = use_vram_for_usse ? VGL_MEM_VRAM : VGL_MEM_RAM; - void *addr = gpu_alloc_mapped(size, &frag_usse_type); - - // Mapping memblock into sceGxm as fragment USSE memory - sceGxmMapFragmentUsseMemory(addr, size, usse_offset); - - // Returning memblock starting address - return addr; -} - -void gpu_fragment_usse_free_mapped(void *addr) { - // Unmapping memblock from sceGxm as fragment USSE memory - sceGxmUnmapFragmentUsseMemory(addr); - - // Deallocating memblock - vgl_mem_free(addr, frag_usse_type); -} - -void *gpu_pool_malloc(unsigned int size) { - // Reserving vitaGL mempool space - if ((pool_index + size) < pool_size) { - void *addr = (void *)((unsigned int)pool_addr + pool_index); - pool_index += size; - return addr; - } - - return NULL; -} - -void *gpu_pool_memalign(unsigned int size, unsigned int alignment) { - // Aligning requested memory size - unsigned int new_index = ALIGN(pool_index, alignment); - - // Reserving vitaGL mempool space - if ((new_index + size) < pool_size) { - void *addr = (void *)((unsigned int)pool_addr + new_index); - pool_index = new_index + size; - return addr; - } - return NULL; -} - -unsigned int gpu_pool_free_space() { - // Returning vitaGL available mempool space - return pool_size - pool_index; -} - -void gpu_pool_reset() { - // Resetting vitaGL available mempool space - pool_index = 0; -} - -void gpu_pool_init(uint32_t temp_pool_size) { - // Allocating vitaGL mempool - pool_size = temp_pool_size; - vglMemType type = VGL_MEM_RAM; - pool_addr = gpu_alloc_mapped(temp_pool_size, &type); -} - -int tex_format_to_bytespp(SceGxmTextureFormat format) { - // Calculating bpp for the requested texture format - switch (format & 0x9f000000U) { - case SCE_GXM_TEXTURE_BASE_FORMAT_U8: - case SCE_GXM_TEXTURE_BASE_FORMAT_S8: - case SCE_GXM_TEXTURE_BASE_FORMAT_P8: - return 1; - case SCE_GXM_TEXTURE_BASE_FORMAT_U4U4U4U4: - case SCE_GXM_TEXTURE_BASE_FORMAT_U8U3U3U2: - case SCE_GXM_TEXTURE_BASE_FORMAT_U1U5U5U5: - case SCE_GXM_TEXTURE_BASE_FORMAT_U5U6U5: - case SCE_GXM_TEXTURE_BASE_FORMAT_S5S5U6: - case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8: - case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8: - return 2; - case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8: - case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8: - return 3; - case SCE_GXM_TEXTURE_BASE_FORMAT_U8U8U8U8: - case SCE_GXM_TEXTURE_BASE_FORMAT_S8S8S8S8: - case SCE_GXM_TEXTURE_BASE_FORMAT_F32: - case SCE_GXM_TEXTURE_BASE_FORMAT_U32: - case SCE_GXM_TEXTURE_BASE_FORMAT_S32: - default: - return 4; - } -} - -int tex_format_to_alignment(SceGxmTextureFormat format) { - switch (format & 0x9f000000U) { - case SCE_GXM_TEXTURE_BASE_FORMAT_UBC3: - return 16; - default: - return 8; - } -} - -palette *gpu_alloc_palette(const void *data, uint32_t w, uint32_t bpe) { - // Allocating a palette object - palette *res = (palette *)malloc(sizeof(palette)); - res->type = use_vram ? VGL_MEM_VRAM : VGL_MEM_RAM; - - // Allocating palette data buffer - void *texture_palette = gpu_alloc_mapped(256 * sizeof(uint32_t), &res->type); - - // Initializing palette - if (data == NULL) - memset(texture_palette, 0, 256 * sizeof(uint32_t)); - else if (bpe == 4) - memcpy_neon(texture_palette, data, w * sizeof(uint32_t)); - res->data = texture_palette; - - // Returning palette - return res; -} - -void gpu_free_texture(texture *tex) { - // Deallocating texture - if (tex->data != NULL) - vgl_mem_free(tex->data, tex->mtype); - - // Invalidating texture object - tex->valid = 0; -} - -void gpu_alloc_texture(uint32_t w, uint32_t h, SceGxmTextureFormat format, const void *data, texture *tex, uint8_t src_bpp, uint32_t (*read_cb)(void *), void (*write_cb)(void *, uint32_t), uint8_t fast_store) { - // If there's already a texture in passed texture object we first dealloc it - if (tex->valid) - gpu_free_texture(tex); - - // Getting texture format bpp - uint8_t bpp = tex_format_to_bytespp(format); - - // Allocating texture data buffer - tex->mtype = use_vram ? VGL_MEM_VRAM : VGL_MEM_RAM; - const int tex_size = ALIGN(w, 8) * h * bpp; - void *texture_data = gpu_alloc_mapped(tex_size, &tex->mtype); - - if (texture_data != NULL) { - // Initializing texture data buffer - if (data != NULL) { - int i, j; - uint8_t *src = (uint8_t *)data; - uint8_t *dst; - if (fast_store) { // Internal Format and Data Format are the same, we can just use memcpy_neon for better performance - uint32_t line_size = w * bpp; - for (i = 0; i < h; i++) { - dst = ((uint8_t *)texture_data) + (ALIGN(w, 8) * bpp) * i; - memcpy_neon(dst, src, line_size); - src += line_size; - } - } else { // Different internal and data formats, we need to go with slower callbacks system - for (i = 0; i < h; i++) { - dst = ((uint8_t *)texture_data) + (ALIGN(w, 8) * bpp) * i; - for (j = 0; j < w; j++) { - uint32_t clr = read_cb(src); - write_cb(dst, clr); - src += src_bpp; - dst += bpp; - } - } - } - } else - memset(texture_data, 0, tex_size); - - // Initializing texture and validating it - sceGxmTextureInitLinear(&tex->gxm_tex, texture_data, format, w, h, 0); - if ((format & 0x9f000000U) == SCE_GXM_TEXTURE_BASE_FORMAT_P8) - tex->palette_UID = 1; - else - tex->palette_UID = 0; - tex->valid = 1; - tex->data = texture_data; - } -} - -void gpu_alloc_compressed_texture(uint32_t w, uint32_t h, SceGxmTextureFormat format, uint32_t image_size, const void *data, texture *tex, uint8_t src_bpp, uint32_t (*read_cb)(void *)) { - // If there's already a texture in passed texture object we first dealloc it - if (tex->valid) - gpu_free_texture(tex); - - // Getting texture format alignment - uint8_t alignment = tex_format_to_alignment(format); - - // Calculating swizzled compressed texture size on memory - tex->mtype = use_vram ? VGL_MEM_VRAM : VGL_MEM_RAM; - - int tex_size = 0; - switch (format) { - case SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_1BGR: - case SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_ABGR: - tex_size = (MAX(w, 8) * MAX(h, 8) * 2 + 7) / 8; - break; - case SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_1BGR: - case SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_ABGR: - tex_size = (MAX(w, 8) * MAX(h, 8) * 4 + 7) / 8; - break; - case SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP_ABGR: - tex_size = CEIL(w / 8.0) * CEIL(h / 4.0) * 8.0; - break; - case SCE_GXM_TEXTURE_FORMAT_PVRTII4BPP_ABGR: - tex_size = CEIL(w / 4.0) * CEIL(h / 4.0) * 8.0; - break; - case SCE_GXM_TEXTURE_FORMAT_UBC1_ABGR: - tex_size = (w * h) / 2; - break; - case SCE_GXM_TEXTURE_FORMAT_UBC3_ABGR: - tex_size = w * h; - break; - } - -#ifndef SKIP_ERROR_HANDLING - // Check the given texture data size. - if (image_size != 0 && image_size != tex_size) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - - // Allocating texture data buffer - void *texture_data = gpu_alloc_mapped(tex_size, &tex->mtype); - - // Initializing texture data buffer - if (texture_data != NULL) { - if (data != NULL) { - if (read_cb != NULL) { - void *temp = (void *)data; - - // stb_dxt expects input as RGBA8888, so we convert input texture if necessary - if (read_cb != readRGBA) { - temp = malloc(w * h * 4); - uint8_t *src = (uint8_t *)data; - uint32_t *dst = (uint32_t *)temp; - int i; - for (i = 0; i < w * h; i++) { - uint32_t clr = read_cb(src); - writeRGBA(dst++, clr); - src += src_bpp; - } - } - - // Performing swizzling and DXT compression - dxt_compress(texture_data, temp, w, h, alignment == 16); - - // Freeing temporary data if necessary - if (read_cb != readRGBA) - free(temp); - } else { - // Perform swizzling if necessary. - switch (format) { - case SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_1BGR: - case SCE_GXM_TEXTURE_FORMAT_PVRT2BPP_ABGR: - case SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_1BGR: - case SCE_GXM_TEXTURE_FORMAT_PVRT4BPP_ABGR: - memcpy_neon(texture_data, data, tex_size); - break; - case SCE_GXM_TEXTURE_FORMAT_UBC3_ABGR: - swizzle_compressed_texture(texture_data, (void *)data, w, h, 1, 0); - break; - case SCE_GXM_TEXTURE_FORMAT_PVRTII2BPP_ABGR: - swizzle_compressed_texture(texture_data, (void *)data, w, h, 0, 1); - break; - default: - swizzle_compressed_texture(texture_data, (void *)data, w, h, 0, 0); - break; - } - } - - } else - memset(texture_data, 0, tex_size); - - // Initializing texture and validating it - sceGxmTextureInitSwizzled(&tex->gxm_tex, texture_data, format, w, h, 0); - tex->palette_UID = 0; - tex->valid = 1; - tex->data = texture_data; - } -} - -void gpu_alloc_mipmaps(int level, texture *tex) { - // Getting current mipmap count in passed texture - uint32_t count = sceGxmTextureGetMipmapCount(&tex->gxm_tex); - - // Getting textures info and calculating bpp - uint32_t w, h, stride; - uint32_t orig_w = sceGxmTextureGetWidth(&tex->gxm_tex); - uint32_t orig_h = sceGxmTextureGetHeight(&tex->gxm_tex); - SceGxmTextureFormat format = sceGxmTextureGetFormat(&tex->gxm_tex); - uint32_t bpp = tex_format_to_bytespp(format); - - // Checking if we need at least one more new mipmap level - if ((level > count) || (level < 0)) { // Note: level < 0 means we will use max possible mipmaps level - - uint32_t jumps[10]; - for (w = 1; w < orig_w; w <<= 1) { - } - for (h = 1; h < orig_h; h <<= 1) { - } - - // Calculating new texture data buffer size - uint32_t size = 0; - int j; - if (level > 0) { - for (j = 0; j < level; j++) { - jumps[j] = max(w, 8) * h * bpp; - size += jumps[j]; - w /= 2; - h /= 2; - } - } else { - level = 0; - while ((w > 1) && (h > 1)) { - jumps[level] = max(w, 8) * h * bpp; - size += jumps[level]; - w /= 2; - h /= 2; - level++; - } - } - - // Calculating needed sceGxmTransfer format for the downscale process - SceGxmTransferFormat fmt; - switch (tex->type) { - case GL_RGBA: - fmt = SCE_GXM_TRANSFER_FORMAT_U8U8U8U8_ABGR; - break; - case GL_RGB: - fmt = SCE_GXM_TRANSFER_FORMAT_U8U8U8_BGR; - default: - break; - } - - // Moving texture data to heap and deallocating texture memblock - GLboolean has_temp_buffer = GL_TRUE; - stride = ALIGN(orig_w, 8); - void *temp = (void *)malloc(stride * orig_h * bpp); - if (temp == NULL) { // If we finished newlib heap, we delay texture free - has_temp_buffer = GL_FALSE; - temp = sceGxmTextureGetData(&tex->gxm_tex); - } else { - memcpy_neon(temp, sceGxmTextureGetData(&tex->gxm_tex), stride * orig_h * bpp); - gpu_free_texture(tex); - } - - // Allocating the new texture data buffer - tex->mtype = use_vram ? VGL_MEM_VRAM : VGL_MEM_RAM; - void *texture_data = gpu_alloc_mapped(size, &tex->mtype); - - // Moving back old texture data from heap to texture memblock - memcpy_neon(texture_data, temp, stride * orig_h * bpp); - if (has_temp_buffer) - free(temp); - else - gpu_free_texture(tex); - tex->valid = 1; - - // Performing a chain downscale process to generate requested mipmaps - uint8_t *curPtr = (uint8_t *)texture_data; - uint32_t curWidth = orig_w; - uint32_t curHeight = orig_h; - if (curWidth % 2) - curWidth--; - if (curHeight % 2) - curHeight--; - for (j = 0; j < level - 1; j++) { - uint32_t curSrcStride = ALIGN(curWidth, 8); - uint32_t curDstStride = ALIGN(curWidth >> 1, 8); - uint8_t *dstPtr = curPtr + jumps[j]; - sceGxmTransferDownscale( - fmt, curPtr, 0, 0, - curWidth, curHeight, - curSrcStride * bpp, - fmt, dstPtr, 0, 0, - curDstStride * bpp, - NULL, SCE_GXM_TRANSFER_FRAGMENT_SYNC, NULL); - curPtr = dstPtr; - curWidth /= 2; - curHeight /= 2; - } - - // Initializing texture in sceGxm - sceGxmTextureInitLinear(&tex->gxm_tex, texture_data, format, orig_w, orig_h, level); - tex->data = texture_data; - } -} - -void gpu_free_palette(palette *pal) { - // Deallocating palette memblock and object - if (pal == NULL) - return; - vgl_mem_free(pal->data, pal->type); - free(pal); -} \ No newline at end of file diff --git a/deps/vitaGL/source/utils/gpu_utils.h b/deps/vitaGL/source/utils/gpu_utils.h deleted file mode 100644 index 33d9a965ed..0000000000 --- a/deps/vitaGL/source/utils/gpu_utils.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * gpu_utils.h: - * Header file for the GPU utilities exposed by gpu_utils.c - */ - -#ifndef _GPU_UTILS_H_ -#define _GPU_UTILS_H_ - -#include "mem_utils.h" - -// Align a value to the requested alignment -#define ALIGN(x, a) (((x) + ((a)-1)) & ~((a)-1)) - -// Texture object struct -typedef struct texture { - SceGxmTexture gxm_tex; - void *data; - vglMemType mtype; - SceUID palette_UID; - SceUID depth_UID; - uint8_t used; - uint8_t valid; - uint32_t type; - void (*write_cb)(void *, uint32_t); - SceGxmTextureFilter min_filter; - SceGxmTextureFilter mag_filter; - SceGxmTextureAddrMode u_mode; - SceGxmTextureAddrMode v_mode; - SceGxmTextureMipFilter mip_filter; - uint32_t lod_bias; -} texture; - -// Palette object struct -typedef struct palette { - void *data; - vglMemType type; -} palette; - -// Alloc a generic memblock into sceGxm mapped memory -void *gpu_alloc_mapped(size_t size, vglMemType *type); - -// Alloc into sceGxm mapped memory a vertex USSE memblock -void *gpu_vertex_usse_alloc_mapped(size_t size, unsigned int *usse_offset); - -// Dealloc from sceGxm mapped memory a vertex USSE memblock -void gpu_vertex_usse_free_mapped(void *addr); - -// Alloc into sceGxm mapped memory a fragment USSE memblock -void *gpu_fragment_usse_alloc_mapped(size_t size, unsigned int *usse_offset); - -// Dealloc from sceGxm mapped memory a fragment USSE memblock -void gpu_fragment_usse_free_mapped(void *addr); - -// Reserve a memory space from vitaGL mempool -void *gpu_pool_malloc(unsigned int size); - -// Reserve an aligned memory space from vitaGL mempool -void *gpu_pool_memalign(unsigned int size, unsigned int alignment); - -// Returns available free space on vitaGL mempool -unsigned int gpu_pool_free_space(); - -// Resets vitaGL mempool -void gpu_pool_reset(); - -// Alloc vitaGL mempool -void gpu_pool_init(uint32_t temp_pool_size); - -// Calculate bpp for a requested texture format -int tex_format_to_bytespp(SceGxmTextureFormat format); - -// Alloc a texture -void gpu_alloc_texture(uint32_t w, uint32_t h, SceGxmTextureFormat format, const void *data, texture *tex, uint8_t src_bpp, uint32_t (*read_cb)(void *), void (*write_cb)(void *, uint32_t), uint8_t fast_store); - -// Alloc a compresseed texture -void gpu_alloc_compressed_texture(uint32_t w, uint32_t h, SceGxmTextureFormat format, uint32_t image_size, const void *data, texture *tex, uint8_t src_bpp, uint32_t (*read_cb)(void *)); - -// Dealloc a texture -void gpu_free_texture(texture *tex); - -// Alloc a palette -palette *gpu_alloc_palette(const void *data, uint32_t w, uint32_t bpe); - -// Dealloc a palette -void gpu_free_palette(palette *pal); - -// Generate mipmaps for a given texture -void gpu_alloc_mipmaps(int level, texture *tex); - -#endif diff --git a/deps/vitaGL/source/utils/math_utils.c b/deps/vitaGL/source/utils/math_utils.c deleted file mode 100644 index ef9390781e..0000000000 --- a/deps/vitaGL/source/utils/math_utils.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * math_utils.c: - * Utilities for math operations - */ - -#include "../shared.h" -#include -#include - -// NOTE: matrices are row-major. - -void matrix4x4_identity(matrix4x4 m) { - m[0][1] = m[0][2] = m[0][3] = 0.0f; - m[1][0] = m[1][2] = m[1][3] = 0.0f; - m[2][0] = m[2][1] = m[2][3] = 0.0f; - m[3][0] = m[3][1] = m[3][2] = 0.0f; - m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f; -} - -void matrix4x4_copy(matrix4x4 dst, const matrix4x4 src) { - memcpy_neon(dst, src, sizeof(matrix4x4)); -} - -void matrix4x4_multiply(matrix4x4 dst, const matrix4x4 src1, const matrix4x4 src2) { - matmul4_neon((float *)src2, (float *)src1, (float *)dst); -} - -void matrix4x4_init_rotation_x(matrix4x4 m, float rad) { - float cs[2]; - sincosf_c(rad, cs); - - matrix4x4_identity(m); - - m[1][1] = cs[1]; - m[1][2] = -cs[0]; - m[2][1] = cs[0]; - m[2][2] = cs[1]; -} - -void matrix4x4_init_rotation_y(matrix4x4 m, float rad) { - float cs[2]; - sincosf_c(rad, cs); - - matrix4x4_identity(m); - - m[0][0] = cs[1]; - m[0][2] = cs[0]; - m[2][0] = -cs[0]; - m[2][2] = cs[1]; -} - -void matrix4x4_init_rotation_z(matrix4x4 m, float rad) { - float cs[2]; - sincosf_c(rad, cs); - - matrix4x4_identity(m); - - m[0][0] = cs[1]; - m[0][1] = -cs[0]; - m[1][0] = cs[0]; - m[1][1] = cs[1]; -} - -void matrix4x4_rotate_x(matrix4x4 m, float rad) { - matrix4x4 m1, m2; - - matrix4x4_init_rotation_x(m1, rad); - matrix4x4_multiply(m2, m, m1); - matrix4x4_copy(m, m2); -} - -void matrix4x4_rotate_y(matrix4x4 m, float rad) { - matrix4x4 m1, m2; - - matrix4x4_init_rotation_y(m1, rad); - matrix4x4_multiply(m2, m, m1); - matrix4x4_copy(m, m2); -} - -void matrix4x4_rotate_z(matrix4x4 m, float rad) { - matrix4x4 m1, m2; - - matrix4x4_init_rotation_z(m1, rad); - matrix4x4_multiply(m2, m, m1); - matrix4x4_copy(m, m2); -} - -void matrix4x4_init_translation(matrix4x4 m, float x, float y, float z) { - matrix4x4_identity(m); - - m[0][3] = x; - m[1][3] = y; - m[2][3] = z; -} - -void matrix4x4_translate(matrix4x4 m, float x, float y, float z) { - matrix4x4 m1, m2; - - matrix4x4_init_translation(m1, x, y, z); - matrix4x4_multiply(m2, m, m1); - matrix4x4_copy(m, m2); -} - -void matrix4x4_init_scaling(matrix4x4 m, float scale_x, float scale_y, float scale_z) { - matrix4x4_identity(m); - - m[0][0] = scale_x; - m[1][1] = scale_y; - m[2][2] = scale_z; -} - -void matrix4x4_scale(matrix4x4 m, float scale_x, float scale_y, float scale_z) { - matrix4x4 m1, m2; - - matrix4x4_init_scaling(m1, scale_x, scale_y, scale_z); - matrix4x4_multiply(m2, m, m1); - matrix4x4_copy(m, m2); -} - -void matrix4x4_transpose(matrix4x4 out, const matrix4x4 m) { - int i, j; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) - out[i][j] = m[j][i]; - } -} - -void matrix4x4_init_orthographic(matrix4x4 m, float left, float right, float bottom, float top, float near, float far) { - m[0][0] = 2.0f / (right - left); - m[0][1] = 0.0f; - m[0][2] = 0.0f; - m[0][3] = -(right + left) / (right - left); - - m[1][0] = 0.0f; - m[1][1] = 2.0f / (top - bottom); - m[1][2] = 0.0f; - m[1][3] = -(top + bottom) / (top - bottom); - - m[2][0] = 0.0f; - m[2][1] = 0.0f; - m[2][2] = -2.0f / (far - near); - m[2][3] = -(far + near) / (far - near); - - m[3][0] = 0.0f; - m[3][1] = 0.0f; - m[3][2] = 0.0f; - m[3][3] = 1.0f; -} - -void matrix4x4_init_frustum(matrix4x4 m, float left, float right, float bottom, float top, float near, float far) { - m[0][0] = (2.0f * near) / (right - left); - m[0][1] = 0.0f; - m[0][2] = (right + left) / (right - left); - m[0][3] = 0.0f; - - m[1][0] = 0.0f; - m[1][1] = (2.0f * near) / (top - bottom); - m[1][2] = (top + bottom) / (top - bottom); - m[1][3] = 0.0f; - - m[2][0] = 0.0f; - m[2][1] = 0.0f; - m[2][2] = -(far + near) / (far - near); - m[2][3] = (-2.0f * far * near) / (far - near); - - m[3][0] = 0.0f; - m[3][1] = 0.0f; - m[3][2] = -1.0f; - m[3][3] = 0.0f; -} - -void matrix4x4_init_perspective(matrix4x4 m, float fov, float aspect, float near, float far) { - float half_height = near * tanf_neon(DEG_TO_RAD(fov) * 0.5f); - float half_width = half_height * aspect; - - matrix4x4_init_frustum(m, -half_width, half_width, -half_height, half_height, near, far); -} - -int matrix4x4_invert(matrix4x4 out, const matrix4x4 m) { - int i, j; - - const float a0 = m[0][0] * m[1][1] - m[0][1] * m[1][0]; - const float a1 = m[0][0] * m[1][2] - m[0][2] * m[1][0]; - const float a2 = m[0][0] * m[1][3] - m[0][3] * m[1][0]; - const float a3 = m[0][1] * m[1][2] - m[0][2] * m[1][1]; - const float a4 = m[0][1] * m[1][3] - m[0][3] * m[1][1]; - const float a5 = m[0][2] * m[1][3] - m[0][3] * m[1][2]; - const float b0 = m[2][0] * m[3][1] - m[2][1] * m[3][0]; - const float b1 = m[2][0] * m[3][2] - m[2][2] * m[3][0]; - const float b2 = m[2][0] * m[3][3] - m[2][3] * m[3][0]; - const float b3 = m[2][1] * m[3][2] - m[2][2] * m[3][1]; - const float b4 = m[2][1] * m[3][3] - m[2][3] * m[3][1]; - const float b5 = m[2][2] * m[3][3] - m[2][3] * m[3][2]; - - float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0; - - if (fabsf(det) > 0.0001f) { - out[0][0] = m[0][1] * b5 - m[1][2] * b4 + m[1][3] * b3; - out[1][0] = -m[1][0] * b5 + m[1][2] * b2 - m[1][3] * b1; - out[2][0] = m[1][0] * b4 - m[1][1] * b2 + m[1][3] * b0; - out[3][0] = -m[1][0] * b3 + m[1][1] * b1 - m[1][2] * b0; - out[0][1] = -m[0][1] * b5 + m[0][2] * b4 - m[0][3] * b3; - out[1][1] = m[0][0] * b5 - m[0][2] * b2 + m[0][3] * b1; - out[2][1] = -m[0][0] * b4 + m[0][1] * b2 - m[0][3] * b0; - out[3][1] = m[0][0] * b3 - m[0][1] * b1 + m[0][2] * b0; - out[0][2] = m[3][1] * a5 - m[3][2] * a4 + m[3][3] * a3; - out[1][2] = -m[3][0] * a5 + m[3][2] * a2 - m[3][3] * a1; - out[2][2] = m[3][0] * a4 - m[3][1] * a2 + m[3][3] * a0; - out[3][2] = -m[3][0] * a3 + m[3][1] * a1 - m[3][2] * a0; - out[0][3] = -m[2][1] * a5 + m[2][2] * a4 - m[2][3] * a3; - out[1][3] = m[2][0] * a5 - m[2][2] * a2 + m[2][3] * a1; - out[2][3] = -m[2][0] * a4 + m[2][1] * a2 - m[2][3] * a0; - out[3][3] = m[2][0] * a3 - m[2][1] * a1 + m[2][2] * a0; - - det = 1.0f / det; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) - out[i][j] *= det; - } - - return 1; - } - - return 0; -} - -void vector4f_matrix4x4_mult(vector4f *u, const matrix4x4 m, const vector4f *v) { - u->x = m[0][0] * v->x + m[0][1] * v->y + m[0][2] * v->z + m[0][3] * v->w; - u->y = m[1][0] * v->x + m[1][1] * v->y + m[1][2] * v->z + m[1][3] * v->w; - u->z = m[2][0] * v->x + m[2][1] * v->y + m[2][2] * v->z + m[2][3] * v->w; - u->w = m[3][0] * v->x + m[3][1] * v->y + m[3][2] * v->z + m[3][3] * v->w; -} diff --git a/deps/vitaGL/source/utils/math_utils.h b/deps/vitaGL/source/utils/math_utils.h deleted file mode 100644 index 1d51ad6795..0000000000 --- a/deps/vitaGL/source/utils/math_utils.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * math_utils.h: - * Header file for the math utilities exposed by math_utils.c - */ - -#ifndef _MATH_UTILS_H_ -#define _MATH_UTILS_H_ - -#include - -#ifndef DEG_TO_RAD -#define DEG_TO_RAD(x) ((x)*M_PI / 180.0) -#endif - -// clang-format off -// vector of 2 floats struct -typedef struct { - float x, y; -} vector2f; - -// vector of 3 floats struct -typedef struct { - union { float x; float r; }; - union { float y; float g; }; - union { float z; float b; }; -} vector3f; - -// vector of 4 floats struct -typedef struct { - union { float x; float r; }; - union { float y; float g; }; - union { float z; float b; }; - union { float w; float a; }; -} vector4f; -// clang-format on - -// 4x4 matrix -typedef float matrix4x4[4][4]; - -// Creates an identity matrix -void matrix4x4_identity(matrix4x4 m); - -// Copy a matrix to another one -void matrix4x4_copy(matrix4x4 dst, const matrix4x4 src); - -// Perform a matrix per matrix moltiplication -void matrix4x4_multiply(matrix4x4 dst, const matrix4x4 src1, const matrix4x4 src2); - -// Rotate a matrix on x,y,z axis -void matrix4x4_rotate_x(matrix4x4 m, float rad); -void matrix4x4_rotate_y(matrix4x4 m, float rad); -void matrix4x4_rotate_z(matrix4x4 m, float rad); - -// Translate a matrix -void matrix4x4_translate(matrix4x4 m, float x, float y, float z); - -// Scale a matrix -void matrix4x4_scale(matrix4x4 m, float scale_x, float scale_y, float scale_z); - -// Transpose a matrix -void matrix4x4_transpose(matrix4x4 out, const matrix4x4 m); - -// Init a matrix with different settings (ortho, frustum, perspective) -void matrix4x4_init_orthographic(matrix4x4 m, float left, float right, float bottom, float top, float near, float far); -void matrix4x4_init_frustum(matrix4x4 m, float left, float right, float bottom, float top, float near, float far); -void matrix4x4_init_perspective(matrix4x4 m, float fov, float aspect, float near, float far); - -// Invert a matrix -int matrix4x4_invert(matrix4x4 out, const matrix4x4 m); - -// Perform a matrix per vector moltiplication -void vector4f_matrix4x4_mult(vector4f *u, const matrix4x4 m, const vector4f *v); - -#endif diff --git a/deps/vitaGL/source/utils/mem_utils.c b/deps/vitaGL/source/utils/mem_utils.c deleted file mode 100644 index b4d4c98a8a..0000000000 --- a/deps/vitaGL/source/utils/mem_utils.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * mem_utils.c: - * Utilities for memory management - */ - -#include "../shared.h" - -#define MEM_ALIGNMENT 16 - -typedef struct tm_block_s { - struct tm_block_s *next; // next block in list (either free or allocated) - int32_t type; // one of vglMemType (VGL_MEM_ALL when unused) - uintptr_t base; // block start address - uint32_t offset; // offset for USSE stuff (unused) - uint32_t size; // block size -} tm_block_t; - -static void *mempool_addr[3] = { NULL, NULL, NULL }; // addresses of heap memblocks (VRAM, RAM, PHYCONT RAM) -static SceUID mempool_id[3] = { 0, 0, 0 }; // UIDs of heap memblocks (VRAM, RAM, PHYCONT RAM) -static size_t mempool_size[3] = { 0, 0, 0 }; // sizes of heap memlbocks (VRAM, RAM, PHYCONT RAM) - -static int tm_initialized; - -static tm_block_t *tm_alloclist; // list of allocated blocks -static tm_block_t *tm_freelist; // list of free blocks - -static uint32_t tm_free[VGL_MEM_TYPE_COUNT]; // see enum vglMemType - -// heap funcs // - -// get new block header -static inline tm_block_t *heap_blk_new(void) { - return calloc(1, sizeof(tm_block_t)); -} - -// release block header -static inline void heap_blk_release(tm_block_t *block) { - free(block); -} - -// determine if two blocks can be merged into one -// blocks of different types can't be merged, -// blocks of same type can only be merged if they're next to each other -// in memory and have matching offsets -static inline int heap_blk_mergeable(tm_block_t *a, tm_block_t *b) { - return a->type == b->type - && a->base + a->size == b->base - && a->offset + a->size == b->offset; -} - -// inserts a block into the free list and merges with neighboring -// free blocks if possible -static void heap_blk_insert_free(tm_block_t *block) { - tm_block_t *curblk = tm_freelist; - tm_block_t *prevblk = NULL; - while (curblk && curblk->base < block->base) { - prevblk = curblk; - curblk = curblk->next; - } - - if (prevblk) - prevblk->next = block; - else - tm_freelist = block; - - block->next = curblk; - tm_free[block->type] += block->size; - tm_free[0] += block->size; - - if (curblk && heap_blk_mergeable(block, curblk)) { - block->size += curblk->size; - block->next = curblk->next; - heap_blk_release(curblk); - } - - if (prevblk && heap_blk_mergeable(prevblk, block)) { - prevblk->size += block->size; - prevblk->next = block->next; - heap_blk_release(block); - } -} - -// allocates a block from the heap -// (removes it from free list and adds to alloc list) -static tm_block_t *heap_blk_alloc(int32_t type, uint32_t size, uint32_t alignment) { - tm_block_t *curblk = tm_freelist; - tm_block_t *prevblk = NULL; - - while (curblk) { - const uint32_t skip = ALIGN(curblk->base, alignment) - curblk->base; - - if (curblk->type == type && skip + size <= curblk->size) { - tm_block_t *skipblk = NULL; - tm_block_t *unusedblk = NULL; - - if (skip != 0) { - skipblk = heap_blk_new(); - if (!skipblk) - return NULL; - } - - if (skip + size != curblk->size) { - unusedblk = heap_blk_new(); - if (!unusedblk) { - if (skipblk) - heap_blk_release(skipblk); - return NULL; - } - } - - if (skip != 0) { - if (prevblk) - prevblk->next = skipblk; - else - tm_freelist = skipblk; - - skipblk->next = curblk; - skipblk->type = curblk->type; - skipblk->base = curblk->base; - skipblk->offset = curblk->offset; - skipblk->size = skip; - - curblk->base += skip; - curblk->offset += skip; - curblk->size -= skip; - - prevblk = skipblk; - } - - if (size != curblk->size) { - unusedblk->next = curblk->next; - curblk->next = unusedblk; - unusedblk->type = curblk->type; - unusedblk->base = curblk->base + size; - unusedblk->offset = curblk->offset + size; - unusedblk->size = curblk->size - size; - curblk->size = size; - } - - if (prevblk) - prevblk->next = curblk->next; - else - tm_freelist = curblk->next; - - curblk->next = tm_alloclist; - tm_alloclist = curblk; - tm_free[type] -= size; - tm_free[0] -= size; - return curblk; - } - - prevblk = curblk; - curblk = curblk->next; - } - - return NULL; -} - -// frees a previously allocated heap block -// (removes from alloc list and inserts into free list) -static void heap_blk_free(uintptr_t base) { - tm_block_t *curblk = tm_alloclist; - tm_block_t *prevblk = NULL; - - while (curblk && curblk->base != base) { - prevblk = curblk; - curblk = curblk->next; - } - - if (!curblk) - return; - - if (prevblk) - prevblk->next = curblk->next; - else - tm_alloclist = curblk->next; - - curblk->next = NULL; - - heap_blk_insert_free(curblk); -} - -// initializes heap variables and blockpool -static void heap_init(void) { - tm_alloclist = NULL; - tm_freelist = NULL; - - for (int i = 0; i < VGL_MEM_TYPE_COUNT; ++i) - tm_free[i] = 0; - - tm_initialized = 1; -} - -// resets heap state and frees allocated block headers -static void heap_destroy(void) { - tm_block_t *n; - - tm_block_t *p = tm_alloclist; - while (p) { - n = p->next; - heap_blk_release(p); - p = n; - } - - p = tm_freelist; - while (p) { - n = p->next; - heap_blk_release(p); - p = n; - } - - tm_initialized = 0; -} - -// adds a memblock to the heap -static void heap_extend(int32_t type, void *base, uint32_t size) { - tm_block_t *block = heap_blk_new(); - block->next = NULL; - block->type = type; - block->base = (uintptr_t)base; - block->offset = 0; - block->size = size; - heap_blk_insert_free(block); -} - -// allocates memory from the heap (basically malloc()) -static void *heap_alloc(int32_t type, uint32_t size, uint32_t alignment) { - tm_block_t *block = heap_blk_alloc(type, size, alignment); - - if (!block) - return NULL; - - return (void *)block->base; -} - -// frees previously allocated heap memory (basically free()) -static void heap_free(void *addr) { - heap_blk_free((uintptr_t)addr); -} - -void vgl_mem_term(void) { - heap_destroy(); - if (mempool_addr[0] != NULL) { - sceKernelFreeMemBlock(mempool_id[0]); - sceKernelFreeMemBlock(mempool_id[1]); - mempool_addr[0] = NULL; - mempool_addr[1] = NULL; - mempool_id[0] = 0; - mempool_id[1] = 0; - } -} - -int vgl_mem_init(size_t size_ram, size_t size_cdram, size_t size_phycont) { - if (mempool_addr[0] != NULL) - vgl_mem_term(); - - mempool_size[VGL_MEM_VRAM - 1] = ALIGN(size_cdram, 256 * 1024); - mempool_size[VGL_MEM_RAM - 1] = ALIGN(size_ram, 4 * 1024); - mempool_size[VGL_MEM_SLOW - 1] = ALIGN(size_phycont, 256 * 1024); - if (size_cdram) - mempool_id[VGL_MEM_VRAM - 1] = sceKernelAllocMemBlock("cdram_mempool", SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, mempool_size[VGL_MEM_VRAM - 1], NULL); - mempool_id[VGL_MEM_RAM - 1] = sceKernelAllocMemBlock("ram_mempool", SCE_KERNEL_MEMBLOCK_TYPE_USER_RW, mempool_size[VGL_MEM_RAM - 1], NULL); - if (size_phycont) - mempool_id[VGL_MEM_SLOW - 1] = sceKernelAllocMemBlock("phycont_mempool", SCE_KERNEL_MEMBLOCK_TYPE_USER_MAIN_PHYCONT_RW, mempool_size[VGL_MEM_SLOW - 1], NULL); - - for (int i = 0; i < VGL_MEM_TYPE_COUNT - 2; i++) { - if (mempool_size[i]) { - sceKernelGetMemBlockBase(mempool_id[i], &mempool_addr[i]); - sceGxmMapMemory(mempool_addr[i], mempool_size[i], SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE); - } - } - - // Initialize heap - heap_init(); - - // Add memblocks to heap - if (size_cdram) - heap_extend(VGL_MEM_VRAM, mempool_addr[0], mempool_size[0]); - heap_extend(VGL_MEM_RAM, mempool_addr[1], mempool_size[1]); - if (size_phycont) - heap_extend(VGL_MEM_SLOW, mempool_addr[2], mempool_size[2]); - - return 1; -} - -void vgl_mem_free(void *ptr, vglMemType type) { - if (type == VGL_MEM_EXTERNAL) - free(ptr); - else - heap_free(ptr); // type is already stored in heap for alloc'd blocks -} - -void *vgl_mempool_alloc(size_t size, vglMemType type) { - void *res = NULL; - if (size <= tm_free[type]) - res = heap_alloc(type, size, MEM_ALIGNMENT); - return res; -} - -// Returns currently free space on mempool -size_t vgl_mempool_get_free_space(vglMemType type) { - return tm_free[type]; -} diff --git a/deps/vitaGL/source/utils/mem_utils.h b/deps/vitaGL/source/utils/mem_utils.h deleted file mode 100644 index c54f46f89b..0000000000 --- a/deps/vitaGL/source/utils/mem_utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * mem_utils.h: - * Header file for the memory management utilities exposed by mem_utils.c - */ - -#ifndef _MEM_UTILS_H_ -#define _MEM_UTILS_H_ - -int vgl_mem_init(size_t size_ram, size_t size_cdram, size_t size_phycont); // Initialize mempools -void vgl_mem_term(void); // Terminate both CDRAM and RAM mempools -size_t vgl_mempool_get_free_space(vglMemType type); // Return free space in bytes for a mempool -void *vgl_mempool_alloc(size_t size, vglMemType type); // Allocate a memory block on a mempool -void vgl_mem_free(void *ptr, vglMemType type); // Free a memory block on a mempool - -#endif \ No newline at end of file diff --git a/deps/vitaGL/source/utils/stb_dxt.h b/deps/vitaGL/source/utils/stb_dxt.h deleted file mode 100644 index 7441bede63..0000000000 --- a/deps/vitaGL/source/utils/stb_dxt.h +++ /dev/null @@ -1,748 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// stb_dxt.h - v1.09 - DXT1/DXT5 compressor - public domain -// original by fabian "ryg" giesen - ported to C by stb -// use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation -// -// USAGE: -// call stb_compress_dxt_block() for every block (you must pad) -// source should be a 4x4 block of RGBA data in row-major order; -// Alpha channel is not stored if you specify alpha=0 (but you -// must supply some constant alpha in the alpha channel). -// You can turn on dithering and "high quality" using mode. -// -// version history: -// v1.09 - (stb) update documentation re: surprising alpha channel requirement -// v1.08 - (stb) fix bug in dxt-with-alpha block -// v1.07 - (stb) bc4; allow not using libc; add STB_DXT_STATIC -// v1.06 - (stb) fix to known-broken 1.05 -// v1.05 - (stb) support bc5/3dc (Arvids Kokins), use extern "C" in C++ (Pavel Krajcevski) -// v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec); -// single color match fix (allow for inexact color interpolation); -// optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps. -// v1.03 - (stb) endianness support -// v1.02 - (stb) fix alpha encoding bug -// v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom -// v1.00 - (stb) first release -// -// contributors: -// Kevin Schmidt (#defines for "freestanding" compilation) -// github:ppiastucki (BC4 support) -// -// LICENSE -// -// See end of file for license information. - -#ifndef STB_INCLUDE_STB_DXT_H -#define STB_INCLUDE_STB_DXT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef STB_DXT_STATIC -#define STBDDEF static -#else -#define STBDDEF extern -#endif - -// compression mode (bitflags) -#define STB_DXT_NORMAL 0 -#define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like! -#define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower. - -STBDDEF void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src_rgba_four_bytes_per_pixel, int alpha, int mode); -STBDDEF void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src_r_one_byte_per_pixel); -STBDDEF void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src_rg_two_byte_per_pixel); - -#define STB_COMPRESS_DXT_BLOCK - -#ifdef __cplusplus -} -#endif -#endif // STB_INCLUDE_STB_DXT_H - -#ifdef STB_DXT_IMPLEMENTATION - -// configuration options for DXT encoder. set them in the project/makefile or just define -// them at the top. - -// STB_DXT_USE_ROUNDING_BIAS -// use a rounding bias during color interpolation. this is closer to what "ideal" -// interpolation would do but doesn't match the S3TC/DX10 spec. old versions (pre-1.03) -// implicitly had this turned on. -// -// in case you're targeting a specific type of hardware (e.g. console programmers): -// NVidia and Intel GPUs (as of 2010) as well as DX9 ref use DXT decoders that are closer -// to STB_DXT_USE_ROUNDING_BIAS. AMD/ATI, S3 and DX10 ref are closer to rounding with no bias. -// you also see "(a*5 + b*3) / 8" on some old GPU designs. -// #define STB_DXT_USE_ROUNDING_BIAS - -#include - -#if !defined(STBD_ABS) || !defined(STBI_FABS) -#include -#endif - -#ifndef STBD_ABS -#define STBD_ABS(i) abs(i) -#endif - -#ifndef STBD_FABS -#define STBD_FABS(x) fabs(x) -#endif - -#ifndef STBD_MEMSET -#include -#define STBD_MEMSET memset -#endif - -static unsigned char stb__Expand5[32]; -static unsigned char stb__Expand6[64]; -static unsigned char stb__OMatch5[256][2]; -static unsigned char stb__OMatch6[256][2]; -static unsigned char stb__QuantRBTab[256+16]; -static unsigned char stb__QuantGTab[256+16]; - -static int stb__Mul8Bit(int a, int b) -{ - int t = a*b + 128; - return (t + (t >> 8)) >> 8; -} - -static void stb__From16Bit(unsigned char *out, unsigned short v) -{ - int rv = (v & 0xf800) >> 11; - int gv = (v & 0x07e0) >> 5; - int bv = (v & 0x001f) >> 0; - - out[0] = stb__Expand5[rv]; - out[1] = stb__Expand6[gv]; - out[2] = stb__Expand5[bv]; - out[3] = 0; -} - -static unsigned short stb__As16Bit(int r, int g, int b) -{ - return (unsigned short)((stb__Mul8Bit(r,31) << 11) + (stb__Mul8Bit(g,63) << 5) + stb__Mul8Bit(b,31)); -} - -// linear interpolation at 1/3 point between a and b, using desired rounding type -static int stb__Lerp13(int a, int b) -{ -#ifdef STB_DXT_USE_ROUNDING_BIAS - // with rounding bias - return a + stb__Mul8Bit(b-a, 0x55); -#else - // without rounding bias - // replace "/ 3" by "* 0xaaab) >> 17" if your compiler sucks or you really need every ounce of speed. - return (2*a + b) / 3; -#endif -} - -// lerp RGB color -static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char *p2) -{ - out[0] = (unsigned char)stb__Lerp13(p1[0], p2[0]); - out[1] = (unsigned char)stb__Lerp13(p1[1], p2[1]); - out[2] = (unsigned char)stb__Lerp13(p1[2], p2[2]); -} - -/****************************************************************************/ - -// compute table to reproduce constant colors as accurately as possible -static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size) -{ - int i,mn,mx; - for (i=0;i<256;i++) { - int bestErr = 256; - for (mn=0;mn> 4)]; - ep1[0] = bp[ 0] - dp[ 0]; - dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)]; - ep1[1] = bp[ 4] - dp[ 4]; - dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)]; - ep1[2] = bp[ 8] - dp[ 8]; - dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)]; - ep1[3] = bp[12] - dp[12]; - bp += 16; - dp += 16; - et = ep1, ep1 = ep2, ep2 = et; // swap - } - } -} - -// The color matching function -static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color,int dither) -{ - unsigned int mask = 0; - int dirr = color[0*4+0] - color[1*4+0]; - int dirg = color[0*4+1] - color[1*4+1]; - int dirb = color[0*4+2] - color[1*4+2]; - int dots[16]; - int stops[4]; - int i; - int c0Point, halfPoint, c3Point; - - for(i=0;i<16;i++) - dots[i] = block[i*4+0]*dirr + block[i*4+1]*dirg + block[i*4+2]*dirb; - - for(i=0;i<4;i++) - stops[i] = color[i*4+0]*dirr + color[i*4+1]*dirg + color[i*4+2]*dirb; - - // think of the colors as arranged on a line; project point onto that line, then choose - // next color out of available ones. we compute the crossover points for "best color in top - // half"/"best in bottom half" and then the same inside that subinterval. - // - // relying on this 1d approximation isn't always optimal in terms of euclidean distance, - // but it's very close and a lot faster. - // http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html - - c0Point = (stops[1] + stops[3]) >> 1; - halfPoint = (stops[3] + stops[2]) >> 1; - c3Point = (stops[2] + stops[0]) >> 1; - - if(!dither) { - // the version without dithering is straightforward - for (i=15;i>=0;i--) { - int dot = dots[i]; - mask <<= 2; - - if(dot < halfPoint) - mask |= (dot < c0Point) ? 1 : 3; - else - mask |= (dot < c3Point) ? 2 : 0; - } - } else { - // with floyd-steinberg dithering - int err[8],*ep1 = err,*ep2 = err+4; - int *dp = dots, y; - - c0Point <<= 4; - halfPoint <<= 4; - c3Point <<= 4; - for(i=0;i<8;i++) - err[i] = 0; - - for(y=0;y<4;y++) - { - int dot,lmask,step; - - dot = (dp[0] << 4) + (3*ep2[1] + 5*ep2[0]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[0] = dp[0] - stops[step]; - lmask = step; - - dot = (dp[1] << 4) + (7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[1] = dp[1] - stops[step]; - lmask |= step<<2; - - dot = (dp[2] << 4) + (7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[2] = dp[2] - stops[step]; - lmask |= step<<4; - - dot = (dp[3] << 4) + (7*ep1[2] + 5*ep2[3] + ep2[2]); - if(dot < halfPoint) - step = (dot < c0Point) ? 1 : 3; - else - step = (dot < c3Point) ? 2 : 0; - ep1[3] = dp[3] - stops[step]; - lmask |= step<<6; - - dp += 4; - mask |= lmask << (y*8); - { int *et = ep1; ep1 = ep2; ep2 = et; } // swap - } - } - - return mask; -} - -// The color optimization function. (Clever code, part 1) -static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16) -{ - int mind = 0x7fffffff,maxd = -0x7fffffff; - unsigned char *minp, *maxp; - double magn; - int v_r,v_g,v_b; - static const int nIterPower = 4; - float covf[6],vfr,vfg,vfb; - - // determine color distribution - int cov[6]; - int mu[3],min[3],max[3]; - int ch,i,iter; - - for(ch=0;ch<3;ch++) - { - const unsigned char *bp = ((const unsigned char *) block) + ch; - int muv,minv,maxv; - - muv = minv = maxv = bp[0]; - for(i=4;i<64;i+=4) - { - muv += bp[i]; - if (bp[i] < minv) minv = bp[i]; - else if (bp[i] > maxv) maxv = bp[i]; - } - - mu[ch] = (muv + 8) >> 4; - min[ch] = minv; - max[ch] = maxv; - } - - // determine covariance matrix - for (i=0;i<6;i++) - cov[i] = 0; - - for (i=0;i<16;i++) - { - int r = block[i*4+0] - mu[0]; - int g = block[i*4+1] - mu[1]; - int b = block[i*4+2] - mu[2]; - - cov[0] += r*r; - cov[1] += r*g; - cov[2] += r*b; - cov[3] += g*g; - cov[4] += g*b; - cov[5] += b*b; - } - - // convert covariance matrix to float, find principal axis via power iter - for(i=0;i<6;i++) - covf[i] = cov[i] / 255.0f; - - vfr = (float) (max[0] - min[0]); - vfg = (float) (max[1] - min[1]); - vfb = (float) (max[2] - min[2]); - - for(iter=0;iter magn) magn = STBD_FABS(vfg); - if (STBD_FABS(vfb) > magn) magn = STBD_FABS(vfb); - - if(magn < 4.0f) { // too small, default to luminance - v_r = 299; // JPEG YCbCr luma coefs, scaled by 1000. - v_g = 587; - v_b = 114; - } else { - magn = 512.0 / magn; - v_r = (int) (vfr * magn); - v_g = (int) (vfg * magn); - v_b = (int) (vfb * magn); - } - - // Pick colors at extreme points - for(i=0;i<16;i++) - { - int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b; - - if (dot < mind) { - mind = dot; - minp = block+i*4; - } - - if (dot > maxd) { - maxd = dot; - maxp = block+i*4; - } - } - - *pmax16 = stb__As16Bit(maxp[0],maxp[1],maxp[2]); - *pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]); -} - -static int stb__sclamp(float y, int p0, int p1) -{ - int x = (int) y; - if (x < p0) return p0; - if (x > p1) return p1; - return x; -} - -// The refinement function. (Clever code, part 2) -// Tries to optimize colors to suit block contents better. -// (By solving a least squares system via normal equations+Cramer's rule) -static int stb__RefineBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16, unsigned int mask) -{ - static const int w1Tab[4] = { 3,0,2,1 }; - static const int prods[4] = { 0x090000,0x000900,0x040102,0x010402 }; - // ^some magic to save a lot of multiplies in the accumulating loop... - // (precomputed products of weights for least squares system, accumulated inside one 32-bit register) - - float frb,fg; - unsigned short oldMin, oldMax, min16, max16; - int i, akku = 0, xx,xy,yy; - int At1_r,At1_g,At1_b; - int At2_r,At2_g,At2_b; - unsigned int cm = mask; - - oldMin = *pmin16; - oldMax = *pmax16; - - if((mask ^ (mask<<2)) < 4) // all pixels have the same index? - { - // yes, linear system would be singular; solve using optimal - // single-color match on average color - int r = 8, g = 8, b = 8; - for (i=0;i<16;++i) { - r += block[i*4+0]; - g += block[i*4+1]; - b += block[i*4+2]; - } - - r >>= 4; g >>= 4; b >>= 4; - - max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0]; - min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1]; - } else { - At1_r = At1_g = At1_b = 0; - At2_r = At2_g = At2_b = 0; - for (i=0;i<16;++i,cm>>=2) { - int step = cm&3; - int w1 = w1Tab[step]; - int r = block[i*4+0]; - int g = block[i*4+1]; - int b = block[i*4+2]; - - akku += prods[step]; - At1_r += w1*r; - At1_g += w1*g; - At1_b += w1*b; - At2_r += r; - At2_g += g; - At2_b += b; - } - - At2_r = 3*At2_r - At1_r; - At2_g = 3*At2_g - At1_g; - At2_b = 3*At2_b - At1_b; - - // extract solutions and decide solvability - xx = akku >> 16; - yy = (akku >> 8) & 0xff; - xy = (akku >> 0) & 0xff; - - frb = 3.0f * 31.0f / 255.0f / (xx*yy - xy*xy); - fg = frb * 63.0f / 31.0f; - - // solve. - max16 = (unsigned short)(stb__sclamp((At1_r*yy - At2_r*xy)*frb+0.5f,0,31) << 11); - max16 |= (unsigned short)(stb__sclamp((At1_g*yy - At2_g*xy)*fg +0.5f,0,63) << 5); - max16 |= (unsigned short)(stb__sclamp((At1_b*yy - At2_b*xy)*frb+0.5f,0,31) << 0); - - min16 = (unsigned short)(stb__sclamp((At2_r*xx - At1_r*xy)*frb+0.5f,0,31) << 11); - min16 |= (unsigned short)(stb__sclamp((At2_g*xx - At1_g*xy)*fg +0.5f,0,63) << 5); - min16 |= (unsigned short)(stb__sclamp((At2_b*xx - At1_b*xy)*frb+0.5f,0,31) << 0); - } - - *pmin16 = min16; - *pmax16 = max16; - return oldMin != min16 || oldMax != max16; -} - -// Color block compression -static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, int mode) -{ - unsigned int mask; - int i; - int dither; - int refinecount; - unsigned short max16, min16; - unsigned char dblock[16*4],color[4*4]; - - dither = mode & STB_DXT_DITHER; - refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1; - - // check if block is constant - for (i=1;i<16;i++) - if (((unsigned int *) block)[i] != ((unsigned int *) block)[0]) - break; - - if(i == 16) { // constant color - int r = block[0], g = block[1], b = block[2]; - mask = 0xaaaaaaaa; - max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0]; - min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1]; - } else { - // first step: compute dithered version for PCA if desired - if(dither) - stb__DitherBlock(dblock,block); - - // second step: pca+map along principal axis - stb__OptimizeColorsBlock(dither ? dblock : block,&max16,&min16); - if (max16 != min16) { - stb__EvalColors(color,max16,min16); - mask = stb__MatchColorsBlock(block,color,dither); - } else - mask = 0; - - // third step: refine (multiple times if requested) - for (i=0;i> 8); - dest[2] = (unsigned char) (min16); - dest[3] = (unsigned char) (min16 >> 8); - dest[4] = (unsigned char) (mask); - dest[5] = (unsigned char) (mask >> 8); - dest[6] = (unsigned char) (mask >> 16); - dest[7] = (unsigned char) (mask >> 24); -} - -// Alpha block compression (this is easy for a change) -static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src, int stride) -{ - int i,dist,bias,dist4,dist2,bits,mask; - - // find min/max color - int mn,mx; - mn = mx = src[0]; - - for (i=1;i<16;i++) - { - if (src[i*stride] < mn) mn = src[i*stride]; - else if (src[i*stride] > mx) mx = src[i*stride]; - } - - // encode them - dest[0] = (unsigned char)mx; - dest[1] = (unsigned char)mn; - dest += 2; - - // determine bias and emit color indices - // given the choice of mx/mn, these indices are optimal: - // http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/ - dist = mx-mn; - dist4 = dist*4; - dist2 = dist*2; - bias = (dist < 8) ? (dist - 1) : (dist/2 + 2); - bias -= mn * 7; - bits = 0,mask=0; - - for (i=0;i<16;i++) { - int a = src[i*stride]*7 + bias; - int ind,t; - - // select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max). - t = (a >= dist4) ? -1 : 0; ind = t & 4; a -= dist4 & t; - t = (a >= dist2) ? -1 : 0; ind += t & 2; a -= dist2 & t; - ind += (a >= dist); - - // turn linear scale into DXT index (0/1 are extremal pts) - ind = -ind & 7; - ind ^= (2 > ind); - - // write index - mask |= ind << bits; - if((bits += 3) >= 8) { - *dest++ = (unsigned char)mask; - mask >>= 8; - bits -= 8; - } - } -} - -static void stb__InitDXT() -{ - int i; - for(i=0;i<32;i++) - stb__Expand5[i] = (unsigned char)((i<<3)|(i>>2)); - - for(i=0;i<64;i++) - stb__Expand6[i] = (unsigned char)((i<<2)|(i>>4)); - - for(i=0;i<256+16;i++) - { - int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8; - stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)]; - stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)]; - } - - stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32); - stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64); -} - -void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode) -{ - unsigned char data[16][4]; - static int init=1; - if (init) { - stb__InitDXT(); - init=0; - } - - if (alpha) { - int i; - stb__CompressAlphaBlock(dest,(unsigned char*) src+3, 4); - dest += 8; - // make a new copy of the data in which alpha is opaque, - // because code uses a fast test for color constancy - memcpy_neon(data, src, 4*16); - for (i=0; i < 16; ++i) - data[i][3] = 255; - src = &data[0][0]; - } - - stb__CompressColorBlock(dest,(unsigned char*) src,mode); -} - -void stb_compress_bc4_block(unsigned char *dest, const unsigned char *src) -{ - stb__CompressAlphaBlock(dest,(unsigned char*) src, 1); -} - -void stb_compress_bc5_block(unsigned char *dest, const unsigned char *src) -{ - stb__CompressAlphaBlock(dest,(unsigned char*) src,2); - stb__CompressAlphaBlock(dest + 8,(unsigned char*) src+1,2); -} -#endif // STB_DXT_IMPLEMENTATION - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/deps/vitaGL/source/vitaGL.c b/deps/vitaGL/source/vitaGL.c deleted file mode 100644 index 68575e671c..0000000000 --- a/deps/vitaGL/source/vitaGL.c +++ /dev/null @@ -1,2245 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * Copyright 2020 Asakura Reiko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* - * - */ -#include "vitaGL.h" -#include "shared.h" -#include "texture_callbacks.h" - -// Shaders -#include "shaders/clear_f.h" -#include "shaders/clear_v.h" -#include "shaders/disable_color_buffer_f.h" -#include "shaders/rgb_v.h" -#include "shaders/rgba_f.h" -#include "shaders/rgba_v.h" -#include "shaders/texture2d_f.h" -#include "shaders/texture2d_rgba_f.h" -#include "shaders/texture2d_rgba_v.h" -#include "shaders/texture2d_v.h" - -// Disable color buffer shader -SceGxmShaderPatcherId disable_color_buffer_fragment_id; -const SceGxmProgramParameter *disable_color_buffer_position; -SceGxmFragmentProgram *disable_color_buffer_fragment_program_patched; -const SceGxmProgramParameter *clear_depth; - -// Clear shader -SceGxmShaderPatcherId clear_vertex_id; -SceGxmShaderPatcherId clear_fragment_id; -const SceGxmProgramParameter *clear_position; -const SceGxmProgramParameter *clear_color; -SceGxmVertexProgram *clear_vertex_program_patched; -SceGxmFragmentProgram *clear_fragment_program_patched; - -// Color (RGBA/RGB) shader -SceGxmShaderPatcherId rgba_vertex_id; -SceGxmShaderPatcherId rgb_vertex_id; -SceGxmShaderPatcherId rgba_fragment_id; -const SceGxmProgramParameter *rgba_position; -const SceGxmProgramParameter *rgba_color; -const SceGxmProgramParameter *rgba_wvp; -const SceGxmProgramParameter *rgb_position; -const SceGxmProgramParameter *rgb_color; -const SceGxmProgramParameter *rgb_wvp; -SceGxmVertexProgram *rgba_vertex_program_patched; -SceGxmVertexProgram *rgba_u8n_vertex_program_patched; -SceGxmVertexProgram *rgb_vertex_program_patched; -SceGxmVertexProgram *rgb_u8n_vertex_program_patched; -SceGxmFragmentProgram *rgba_fragment_program_patched; -const SceGxmProgram *rgba_fragment_program; - -// Texture2D shader -SceGxmShaderPatcherId texture2d_vertex_id; -SceGxmShaderPatcherId texture2d_fragment_id; -const SceGxmProgramParameter *texture2d_position; -const SceGxmProgramParameter *texture2d_texcoord; -const SceGxmProgramParameter *texture2d_wvp; -const SceGxmProgramParameter *texture2d_alpha_cut; -const SceGxmProgramParameter *texture2d_alpha_op; -const SceGxmProgramParameter *texture2d_tint_color; -const SceGxmProgramParameter *texture2d_tex_env; -const SceGxmProgramParameter *texture2d_clip_plane0; -const SceGxmProgramParameter *texture2d_clip_plane0_eq; -const SceGxmProgramParameter *texture2d_mv; -const SceGxmProgramParameter *texture2d_fog_mode; -const SceGxmProgramParameter *texture2d_fog_near; -const SceGxmProgramParameter *texture2d_fog_far; -const SceGxmProgramParameter *texture2d_fog_density; -const SceGxmProgramParameter *texture2d_fog_color; -const SceGxmProgramParameter *texture2d_tex_env_color; -SceGxmVertexProgram *texture2d_vertex_program_patched; -SceGxmFragmentProgram *texture2d_fragment_program_patched; -const SceGxmProgram *texture2d_fragment_program; - -// Texture2D+RGBA shader -SceGxmShaderPatcherId texture2d_rgba_vertex_id; -SceGxmShaderPatcherId texture2d_rgba_fragment_id; -const SceGxmProgramParameter *texture2d_rgba_position; -const SceGxmProgramParameter *texture2d_rgba_texcoord; -const SceGxmProgramParameter *texture2d_rgba_wvp; -const SceGxmProgramParameter *texture2d_rgba_alpha_cut; -const SceGxmProgramParameter *texture2d_rgba_alpha_op; -const SceGxmProgramParameter *texture2d_rgba_color; -const SceGxmProgramParameter *texture2d_rgba_tex_env; -const SceGxmProgramParameter *texture2d_rgba_clip_plane0; -const SceGxmProgramParameter *texture2d_rgba_clip_plane0_eq; -const SceGxmProgramParameter *texture2d_rgba_mv; -const SceGxmProgramParameter *texture2d_rgba_fog_mode; -const SceGxmProgramParameter *texture2d_rgba_fog_near; -const SceGxmProgramParameter *texture2d_rgba_fog_far; -const SceGxmProgramParameter *texture2d_rgba_fog_density; -const SceGxmProgramParameter *texture2d_rgba_fog_color; -const SceGxmProgramParameter *texture2d_rgba_tex_env_color; -SceGxmVertexProgram *texture2d_rgba_vertex_program_patched; -SceGxmVertexProgram *texture2d_rgba_u8n_vertex_program_patched; -SceGxmFragmentProgram *texture2d_rgba_fragment_program_patched; -const SceGxmProgram *texture2d_rgba_fragment_program; - -typedef struct gpubuffer { - void *ptr; - int32_t size; -} gpubuffer; - -// sceGxm viewport setup (NOTE: origin is on center screen) -float x_port = 480.0f; -float y_port = 272.0f; -float z_port = 0.5f; -float x_scale = 480.0f; -float y_scale = -272.0f; -float z_scale = 0.5f; - -// Fullscreen sceGxm viewport (NOTE: origin is on center screen) -float fullscreen_x_port = 480.0f; -float fullscreen_y_port = 272.0f; -float fullscreen_z_port = 0.5f; -float fullscreen_x_scale = 480.0f; -float fullscreen_y_scale = -272.0f; -float fullscreen_z_scale = 0.5f; - -GLboolean vblank = GL_TRUE; // Current setting for VSync - -extern int _newlib_heap_memblock; // Newlib Heap memblock -extern unsigned _newlib_heap_size; // Newlib Heap size - -static const SceGxmProgram *const gxm_program_disable_color_buffer_f = (SceGxmProgram *)&disable_color_buffer_f; -static const SceGxmProgram *const gxm_program_clear_v = (SceGxmProgram *)&clear_v; -static const SceGxmProgram *const gxm_program_clear_f = (SceGxmProgram *)&clear_f; -static const SceGxmProgram *const gxm_program_rgba_v = (SceGxmProgram *)&rgba_v; -static const SceGxmProgram *const gxm_program_rgba_f = (SceGxmProgram *)&rgba_f; -static const SceGxmProgram *const gxm_program_rgb_v = (SceGxmProgram *)&rgb_v; -static const SceGxmProgram *const gxm_program_texture2d_v = (SceGxmProgram *)&texture2d_v; -static const SceGxmProgram *const gxm_program_texture2d_f = (SceGxmProgram *)&texture2d_f; -static const SceGxmProgram *const gxm_program_texture2d_rgba_v = (SceGxmProgram *)&texture2d_rgba_v; -static const SceGxmProgram *const gxm_program_texture2d_rgba_f = (SceGxmProgram *)&texture2d_rgba_f; - -// Disable color buffer shader -uint16_t *depth_clear_indices = NULL; // Memblock starting address for clear screen indices - -// Clear shaders -SceGxmVertexProgram *clear_vertex_program_patched; // Patched vertex program for clearing screen -vector4f *clear_vertices = NULL; // Memblock starting address for clear screen vertices -vector3f *depth_vertices = NULL; // Memblock starting address for depth clear screen vertices - -// Internal stuffs -SceGxmMultisampleMode msaa_mode = SCE_GXM_MULTISAMPLE_NONE; - -extern uint8_t use_vram; -extern uint8_t use_vram_for_usse; - -static GLuint buffers[BUFFERS_NUM]; // Buffers array -static gpubuffer gpu_buffers[BUFFERS_NUM]; // Buffers array -static SceGxmColorMask blend_color_mask = SCE_GXM_COLOR_MASK_ALL; // Current in-use color mask (glColorMask) -static SceGxmBlendFunc blend_func_rgb = SCE_GXM_BLEND_FUNC_ADD; // Current in-use RGB blend func -static SceGxmBlendFunc blend_func_a = SCE_GXM_BLEND_FUNC_ADD; // Current in-use A blend func -static int vertex_array_unit = -1; // Current in-use vertex array unit -static int index_array_unit = -1; // Current in-use index array unit - -vector4f texenv_color = { 0.0f, 0.0f, 0.0f, 0.0f }; // Current in use texture environment color - -// Internal functions - -#ifdef ENABLE_LOG -void LOG(const char *format, ...) { - __gnuc_va_list arg; - int done; - va_start(arg, format); - char msg[512]; - done = vsprintf(msg, format, arg); - va_end(arg); - int i; - sprintf(msg, "%s\n", msg); - FILE *log = fopen("ux0:/data/vitaGL.log", "a+"); - if (log != NULL) { - fwrite(msg, 1, strlen(msg), log); - fclose(log); - } -} -#endif - -static void _change_blend_factor(SceGxmBlendInfo *blend_info) { - changeCustomShadersBlend(blend_info); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - rgba_fragment_id, - SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa_mode, - blend_info, - NULL, - &rgba_fragment_program_patched); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - texture2d_fragment_id, - SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa_mode, - blend_info, - NULL, - &texture2d_fragment_program_patched); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - texture2d_rgba_fragment_id, - SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa_mode, - blend_info, - NULL, - &texture2d_rgba_fragment_program_patched); -} - -void change_blend_factor() { - static SceGxmBlendInfo blend_info; - blend_info.colorMask = blend_color_mask; - blend_info.colorFunc = blend_func_rgb; - blend_info.alphaFunc = blend_func_a; - blend_info.colorSrc = blend_sfactor_rgb; - blend_info.colorDst = blend_dfactor_rgb; - blend_info.alphaSrc = blend_sfactor_a; - blend_info.alphaDst = blend_dfactor_a; - - _change_blend_factor(&blend_info); - if (cur_program != 0) { - reloadCustomShader(); - } -} - -void change_blend_mask() { - static SceGxmBlendInfo blend_info; - blend_info.colorMask = blend_color_mask; - blend_info.colorFunc = SCE_GXM_BLEND_FUNC_NONE; - blend_info.alphaFunc = SCE_GXM_BLEND_FUNC_NONE; - blend_info.colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - blend_info.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_info.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE; - blend_info.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO; - - _change_blend_factor(&blend_info); - if (cur_program != 0) { - reloadCustomShader(); - } -} - -void disable_blend() { - if (blend_color_mask == SCE_GXM_COLOR_MASK_ALL) { - _change_blend_factor(NULL); - if (cur_program != 0) { - reloadCustomShader(); - } - } else - change_blend_mask(); -} - -void vector4f_convert_to_local_space(vector4f *out, int x, int y, int width, int height) { - out[0].x = (float)(2 * x) / DISPLAY_WIDTH_FLOAT - 1.0f; - out[0].y = (float)(2 * (x + width)) / DISPLAY_WIDTH_FLOAT - 1.0f; - out[0].z = 1.0f - (float)(2 * y) / DISPLAY_HEIGHT_FLOAT; - out[0].w = 1.0f - (float)(2 * (y + height)) / DISPLAY_HEIGHT_FLOAT; -} - -// vitaGL specific functions - -void vglUseVram(GLboolean usage) { - use_vram = usage; -} - -void vglUseVramForUSSE(GLboolean usage) { - use_vram_for_usse = usage; -} - -void vglInitWithCustomSizes(uint32_t gpu_pool_size, int width, int height, int ram_pool_size, int cdram_pool_size, int phycont_pool_size, SceGxmMultisampleMode msaa) { - // Setting our display size - msaa_mode = msaa; - DISPLAY_WIDTH = width; - DISPLAY_HEIGHT = height; - DISPLAY_WIDTH_FLOAT = width * 1.0f; - DISPLAY_HEIGHT_FLOAT = height * 1.0f; - DISPLAY_STRIDE = ALIGN(DISPLAY_WIDTH, 64); - - // Adjusting default values for internal viewport - x_port = DISPLAY_WIDTH_FLOAT / 2.0f; - x_scale = x_port; - y_scale = -(DISPLAY_HEIGHT_FLOAT / 2.0f); - y_port = -y_scale; - fullscreen_x_port = x_port; - fullscreen_x_scale = x_scale; - fullscreen_y_port = y_port; - fullscreen_y_scale = y_scale; - - // Init viewport state - gl_viewport.x = 0; - gl_viewport.y = 0; - gl_viewport.w = DISPLAY_WIDTH; - gl_viewport.h = DISPLAY_HEIGHT; - - // Initializing sceGxm - initGxm(); - - // Initializing memory heap for CDRAM and RAM memory - vgl_mem_init(ram_pool_size, cdram_pool_size, phycont_pool_size); - - // Initializing sceGxm context - initGxmContext(); - - // Creating render target for the display - createDisplayRenderTarget(); - - // Creating color surfaces for the display - initDisplayColorSurfaces(); - - // Creating depth and stencil surfaces for the display - initDepthStencilSurfaces(); - - // Starting a sceGxmShaderPatcher instance - startShaderPatcher(); - - // Disable color buffer shader register - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_disable_color_buffer_f, - &disable_color_buffer_fragment_id); - - const SceGxmProgram *disable_color_buffer_fragment_program = sceGxmShaderPatcherGetProgramFromId(disable_color_buffer_fragment_id); - - clear_depth = sceGxmProgramFindParameterByName( - disable_color_buffer_fragment_program, "depth_clear"); - - SceGxmBlendInfo disable_color_buffer_blend_info; - memset(&disable_color_buffer_blend_info, 0, sizeof(SceGxmBlendInfo)); - disable_color_buffer_blend_info.colorMask = SCE_GXM_COLOR_MASK_NONE; - disable_color_buffer_blend_info.colorFunc = SCE_GXM_BLEND_FUNC_NONE; - disable_color_buffer_blend_info.alphaFunc = SCE_GXM_BLEND_FUNC_NONE; - disable_color_buffer_blend_info.colorSrc = SCE_GXM_BLEND_FACTOR_ZERO; - disable_color_buffer_blend_info.colorDst = SCE_GXM_BLEND_FACTOR_ZERO; - disable_color_buffer_blend_info.alphaSrc = SCE_GXM_BLEND_FACTOR_ZERO; - disable_color_buffer_blend_info.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO; - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - disable_color_buffer_fragment_id, - SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa, - &disable_color_buffer_blend_info, NULL, - &disable_color_buffer_fragment_program_patched); - - vglMemType type = VGL_MEM_RAM; - clear_vertices = gpu_alloc_mapped(1 * sizeof(vector4f), &type); - depth_clear_indices = gpu_alloc_mapped(4 * sizeof(unsigned short), &type); - - vector4f_convert_to_local_space(clear_vertices, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT); - - depth_clear_indices[0] = 0; - depth_clear_indices[1] = 1; - depth_clear_indices[2] = 2; - depth_clear_indices[3] = 3; - - // Clear shader register - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_v, - &clear_vertex_id); - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_clear_f, - &clear_fragment_id); - - const SceGxmProgram *clear_vertex_program = sceGxmShaderPatcherGetProgramFromId(clear_vertex_id); - const SceGxmProgram *clear_fragment_program = sceGxmShaderPatcherGetProgramFromId(clear_fragment_id); - - clear_position = sceGxmProgramFindParameterByName( - clear_vertex_program, "position"); - - clear_color = sceGxmProgramFindParameterByName( - clear_fragment_program, "u_clear_color"); - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - clear_vertex_id, NULL, 0, NULL, 0, &clear_vertex_program_patched); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - clear_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa, NULL, NULL, - &clear_fragment_program_patched); - - // Color shader register - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_rgba_v, - &rgba_vertex_id); - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_rgb_v, - &rgb_vertex_id); - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_rgba_f, - &rgba_fragment_id); - - const SceGxmProgram *rgba_vertex_program = sceGxmShaderPatcherGetProgramFromId(rgba_vertex_id); - const SceGxmProgram *rgb_vertex_program = sceGxmShaderPatcherGetProgramFromId(rgb_vertex_id); - rgba_fragment_program = sceGxmShaderPatcherGetProgramFromId(rgba_fragment_id); - - rgba_position = sceGxmProgramFindParameterByName( - rgba_vertex_program, "aPosition"); - - rgba_color = sceGxmProgramFindParameterByName( - rgba_vertex_program, "aColor"); - - rgb_position = sceGxmProgramFindParameterByName( - rgba_vertex_program, "aPosition"); - - rgb_color = sceGxmProgramFindParameterByName( - rgba_vertex_program, "aColor"); - - SceGxmVertexAttribute rgba_vertex_attribute[2]; - SceGxmVertexStream rgba_vertex_stream[2]; - rgba_vertex_attribute[0].streamIndex = 0; - rgba_vertex_attribute[0].offset = 0; - rgba_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - rgba_vertex_attribute[0].componentCount = 3; - rgba_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex( - rgba_position); - rgba_vertex_attribute[1].streamIndex = 1; - rgba_vertex_attribute[1].offset = 0; - rgba_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - rgba_vertex_attribute[1].componentCount = 4; - rgba_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex( - rgba_color); - rgba_vertex_stream[0].stride = sizeof(vector3f); - rgba_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - rgba_vertex_stream[1].stride = sizeof(vector4f); - rgba_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - rgba_vertex_id, rgba_vertex_attribute, - 2, rgba_vertex_stream, 2, &rgba_vertex_program_patched); - - rgba_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; - rgba_vertex_stream[1].stride = sizeof(uint8_t) * 4; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - rgba_vertex_id, rgba_vertex_attribute, - 2, rgba_vertex_stream, 2, &rgba_u8n_vertex_program_patched); - - SceGxmVertexAttribute rgb_vertex_attribute[2]; - SceGxmVertexStream rgb_vertex_stream[2]; - rgb_vertex_attribute[0].streamIndex = 0; - rgb_vertex_attribute[0].offset = 0; - rgb_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - rgb_vertex_attribute[0].componentCount = 3; - rgb_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex( - rgb_position); - rgb_vertex_attribute[1].streamIndex = 1; - rgb_vertex_attribute[1].offset = 0; - rgb_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - rgb_vertex_attribute[1].componentCount = 3; - rgb_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex( - rgb_color); - rgb_vertex_stream[0].stride = sizeof(vector3f); - rgb_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - rgb_vertex_stream[1].stride = sizeof(vector3f); - rgb_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - rgb_vertex_id, rgb_vertex_attribute, - 2, rgb_vertex_stream, 2, &rgb_vertex_program_patched); - - rgb_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; - rgb_vertex_stream[1].stride = sizeof(uint8_t) * 3; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - rgb_vertex_id, rgb_vertex_attribute, - 2, rgb_vertex_stream, 2, &rgb_u8n_vertex_program_patched); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - rgba_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa, NULL, NULL, - &rgba_fragment_program_patched); - - rgba_wvp = sceGxmProgramFindParameterByName(rgba_vertex_program, "wvp"); - rgb_wvp = sceGxmProgramFindParameterByName(rgb_vertex_program, "wvp"); - - // Texture2D shader register - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_v, - &texture2d_vertex_id); - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_f, - &texture2d_fragment_id); - - const SceGxmProgram *texture2d_vertex_program = sceGxmShaderPatcherGetProgramFromId(texture2d_vertex_id); - texture2d_fragment_program = sceGxmShaderPatcherGetProgramFromId(texture2d_fragment_id); - - texture2d_position = sceGxmProgramFindParameterByName( - texture2d_vertex_program, "position"); - - texture2d_texcoord = sceGxmProgramFindParameterByName( - texture2d_vertex_program, "texcoord"); - - texture2d_alpha_cut = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "alphaCut"); - - texture2d_alpha_op = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "alphaOp"); - - texture2d_tint_color = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "tintColor"); - - texture2d_tex_env = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "texEnv"); - - texture2d_fog_mode = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "fog_mode"); - - texture2d_fog_color = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "fogColor"); - - texture2d_clip_plane0 = sceGxmProgramFindParameterByName( - texture2d_vertex_program, "clip_plane0"); - - texture2d_clip_plane0_eq = sceGxmProgramFindParameterByName( - texture2d_vertex_program, "clip_plane0_eq"); - - texture2d_mv = sceGxmProgramFindParameterByName( - texture2d_vertex_program, "modelview"); - - texture2d_fog_near = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "fog_near"); - - texture2d_fog_far = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "fog_far"); - - texture2d_fog_density = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "fog_density"); - - texture2d_tex_env_color = sceGxmProgramFindParameterByName( - texture2d_fragment_program, "texEnvColor"); - - SceGxmVertexAttribute texture2d_vertex_attribute[2]; - SceGxmVertexStream texture2d_vertex_stream[2]; - texture2d_vertex_attribute[0].streamIndex = 0; - texture2d_vertex_attribute[0].offset = 0; - texture2d_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - texture2d_vertex_attribute[0].componentCount = 3; - texture2d_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex( - texture2d_position); - texture2d_vertex_attribute[1].streamIndex = 1; - texture2d_vertex_attribute[1].offset = 0; - texture2d_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - texture2d_vertex_attribute[1].componentCount = 2; - texture2d_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex( - texture2d_texcoord); - texture2d_vertex_stream[0].stride = sizeof(vector3f); - texture2d_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - texture2d_vertex_stream[1].stride = sizeof(vector2f); - texture2d_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - texture2d_vertex_id, texture2d_vertex_attribute, - 2, texture2d_vertex_stream, 2, &texture2d_vertex_program_patched); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - texture2d_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa, NULL, NULL, - &texture2d_fragment_program_patched); - - texture2d_wvp = sceGxmProgramFindParameterByName(texture2d_vertex_program, "wvp"); - - // Texture2D+RGBA shader register - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_rgba_v, - &texture2d_rgba_vertex_id); - sceGxmShaderPatcherRegisterProgram(gxm_shader_patcher, gxm_program_texture2d_rgba_f, - &texture2d_rgba_fragment_id); - - const SceGxmProgram *texture2d_rgba_vertex_program = sceGxmShaderPatcherGetProgramFromId(texture2d_rgba_vertex_id); - texture2d_rgba_fragment_program = sceGxmShaderPatcherGetProgramFromId(texture2d_rgba_fragment_id); - - texture2d_rgba_position = sceGxmProgramFindParameterByName( - texture2d_rgba_vertex_program, "position"); - - texture2d_rgba_texcoord = sceGxmProgramFindParameterByName( - texture2d_rgba_vertex_program, "texcoord"); - - texture2d_rgba_alpha_cut = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "alphaCut"); - - texture2d_rgba_alpha_op = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "alphaOp"); - - texture2d_rgba_color = sceGxmProgramFindParameterByName( - texture2d_rgba_vertex_program, "color"); - - texture2d_rgba_tex_env = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "texEnv"); - - texture2d_rgba_fog_mode = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "fog_mode"); - - texture2d_rgba_clip_plane0 = sceGxmProgramFindParameterByName( - texture2d_rgba_vertex_program, "clip_plane0"); - - texture2d_rgba_clip_plane0_eq = sceGxmProgramFindParameterByName( - texture2d_rgba_vertex_program, "clip_plane0_eq"); - - texture2d_rgba_mv = sceGxmProgramFindParameterByName( - texture2d_rgba_vertex_program, "modelview"); - - texture2d_rgba_fog_near = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "fog_near"); - - texture2d_rgba_fog_far = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "fog_far"); - - texture2d_rgba_fog_density = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "fog_density"); - - texture2d_rgba_fog_color = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "fogColor"); - - texture2d_rgba_tex_env_color = sceGxmProgramFindParameterByName( - texture2d_rgba_fragment_program, "texEnvColor"); - - SceGxmVertexAttribute texture2d_rgba_vertex_attribute[3]; - SceGxmVertexStream texture2d_rgba_vertex_stream[3]; - texture2d_rgba_vertex_attribute[0].streamIndex = 0; - texture2d_rgba_vertex_attribute[0].offset = 0; - texture2d_rgba_vertex_attribute[0].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - texture2d_rgba_vertex_attribute[0].componentCount = 3; - texture2d_rgba_vertex_attribute[0].regIndex = sceGxmProgramParameterGetResourceIndex( - texture2d_rgba_position); - texture2d_rgba_vertex_attribute[1].streamIndex = 1; - texture2d_rgba_vertex_attribute[1].offset = 0; - texture2d_rgba_vertex_attribute[1].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - texture2d_rgba_vertex_attribute[1].componentCount = 2; - texture2d_rgba_vertex_attribute[1].regIndex = sceGxmProgramParameterGetResourceIndex( - texture2d_rgba_texcoord); - texture2d_rgba_vertex_attribute[2].streamIndex = 2; - texture2d_rgba_vertex_attribute[2].offset = 0; - texture2d_rgba_vertex_attribute[2].format = SCE_GXM_ATTRIBUTE_FORMAT_F32; - texture2d_rgba_vertex_attribute[2].componentCount = 4; - texture2d_rgba_vertex_attribute[2].regIndex = sceGxmProgramParameterGetResourceIndex( - texture2d_rgba_color); - texture2d_rgba_vertex_stream[0].stride = sizeof(vector3f); - texture2d_rgba_vertex_stream[0].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - texture2d_rgba_vertex_stream[1].stride = sizeof(vector2f); - texture2d_rgba_vertex_stream[1].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - texture2d_rgba_vertex_stream[2].stride = sizeof(vector4f); - texture2d_rgba_vertex_stream[2].indexSource = SCE_GXM_INDEX_SOURCE_INDEX_16BIT; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - texture2d_rgba_vertex_id, texture2d_rgba_vertex_attribute, - 3, texture2d_rgba_vertex_stream, 3, &texture2d_rgba_vertex_program_patched); - - texture2d_rgba_vertex_attribute[2].format = SCE_GXM_ATTRIBUTE_FORMAT_U8N; - texture2d_rgba_vertex_stream[2].stride = sizeof(uint8_t) * 4; - - sceGxmShaderPatcherCreateVertexProgram(gxm_shader_patcher, - texture2d_rgba_vertex_id, texture2d_rgba_vertex_attribute, - 3, texture2d_rgba_vertex_stream, 3, &texture2d_rgba_u8n_vertex_program_patched); - - sceGxmShaderPatcherCreateFragmentProgram(gxm_shader_patcher, - texture2d_rgba_fragment_id, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, - msaa, NULL, NULL, - &texture2d_rgba_fragment_program_patched); - - texture2d_rgba_wvp = sceGxmProgramFindParameterByName(texture2d_rgba_vertex_program, "wvp"); - - sceGxmSetTwoSidedEnable(gxm_context, SCE_GXM_TWO_SIDED_ENABLED); - - // Scissor Test shader register - sceGxmShaderPatcherCreateMaskUpdateFragmentProgram(gxm_shader_patcher, &scissor_test_fragment_program); - - scissor_test_vertices = gpu_alloc_mapped(1 * sizeof(vector4f), &type); - - // Allocate temp pool for non-VBO drawing - gpu_pool_init(gpu_pool_size); - - // Init texture units - int i, j; - for (i = 0; i < GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++) { - texture_units[i].env_mode = MODULATE; - texture_units[i].tex_id = 0; - texture_units[i].enabled = GL_FALSE; - } - - // Init texture slots - for (j = 0; j < TEXTURES_NUM; j++) { - vgl_textures[j].used = 0; - vgl_textures[j].valid = 0; - } - - // Init custom shaders - resetCustomShaders(); - - // Init buffers - for (i = 0; i < BUFFERS_NUM; i++) { - buffers[i] = BUFFERS_ADDR + i; - gpu_buffers[i].ptr = NULL; - } - - // Init scissor test state - resetScissorTestRegion(); - - // Getting newlib heap memblock starting address - void *addr = NULL; - sceKernelGetMemBlockBase(_newlib_heap_memblock, &addr); - - // Mapping newlib heap into sceGxm - sceGxmMapMemory(addr, _newlib_heap_size, SCE_GXM_MEMORY_ATTRIB_READ | SCE_GXM_MEMORY_ATTRIB_WRITE); - - // Allocating default texture object - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); -} - -void vglInitExtended(uint32_t gpu_pool_size, int width, int height, int ram_threshold, SceGxmMultisampleMode msaa) { - // Initializing sceGxm - initGxm(); - - // Getting max allocatable CDRAM and RAM memory - if (system_app_mode) { - SceAppMgrBudgetInfo info; - info.size = sizeof(SceAppMgrBudgetInfo); - sceAppMgrGetBudgetInfo(&info); - vglInitWithCustomSizes(gpu_pool_size, width, height, info.free_user_rw > ram_threshold ? info.free_user_rw - ram_threshold : info.free_user_rw, 0, 0, msaa); - } else { - SceKernelFreeMemorySizeInfo info; - info.size = sizeof(SceKernelFreeMemorySizeInfo); - sceKernelGetFreeMemorySize(&info); - vglInitWithCustomSizes(gpu_pool_size, width, height, info.size_user > ram_threshold ? info.size_user - ram_threshold : info.size_user, info.size_cdram - 256 * 1024, info.size_phycont - 1 * 1024 * 1024, msaa); - } -} - -void vglInit(uint32_t gpu_pool_size) { - vglInitExtended(gpu_pool_size, DISPLAY_WIDTH_DEF, DISPLAY_HEIGHT_DEF, 0x1000000, SCE_GXM_MULTISAMPLE_NONE); -} - -void vglEnd(void) { - // Wait for rendering to be finished - waitRenderingDone(); - - // Deallocating default vertices buffers - vgl_mem_free(clear_vertices, VGL_MEM_RAM); - vgl_mem_free(depth_vertices, VGL_MEM_RAM); - vgl_mem_free(depth_clear_indices, VGL_MEM_RAM); - vgl_mem_free(scissor_test_vertices, VGL_MEM_RAM); - - // Releasing shader programs from sceGxmShaderPatcher - sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, scissor_test_fragment_program); - sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, disable_color_buffer_fragment_program_patched); - sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, clear_vertex_program_patched); - sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, clear_fragment_program_patched); - sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, rgba_vertex_program_patched); - sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, rgb_vertex_program_patched); - sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, rgba_fragment_program_patched); - sceGxmShaderPatcherReleaseVertexProgram(gxm_shader_patcher, texture2d_vertex_program_patched); - sceGxmShaderPatcherReleaseFragmentProgram(gxm_shader_patcher, texture2d_fragment_program_patched); - - // Unregistering shader programs from sceGxmShaderPatcher - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, clear_vertex_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, clear_fragment_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, rgb_vertex_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, rgba_vertex_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, rgba_fragment_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, texture2d_vertex_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, texture2d_fragment_id); - sceGxmShaderPatcherUnregisterProgram(gxm_shader_patcher, disable_color_buffer_fragment_id); - - // Terminating shader patcher - stopShaderPatcher(); - - // Deallocating depth and stencil surfaces for display - termDepthStencilSurfaces(); - - // Terminating display's color surfaces - termDisplayColorSurfaces(); - - // Destroing display's render target - destroyDisplayRenderTarget(); - - // Terminating sceGxm context - termGxmContext(); - - // Terminating sceGxm - sceGxmTerminate(); -} - -void vglWaitVblankStart(GLboolean enable) { - vblank = enable; -} - -// openGL implementation - -void glGenBuffers(GLsizei n, GLuint *res) { - int i = 0, j = 0; -#ifndef SKIP_ERROR_HANDLING - if (n < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - for (i = 0; i < BUFFERS_NUM; i++) { - if (buffers[i] != 0x0000) { - res[j++] = buffers[i]; - buffers[i] = 0x0000; - } - if (j >= n) - break; - } -} - -void glBindBuffer(GLenum target, GLuint buffer) { -#ifndef SKIP_ERROR_HANDLING - if ((buffer != 0x0000) && ((buffer >= BUFFERS_ADDR + BUFFERS_NUM) || (buffer < BUFFERS_ADDR))) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - switch (target) { - case GL_ARRAY_BUFFER: - vertex_array_unit = buffer - BUFFERS_ADDR; - break; - case GL_ELEMENT_ARRAY_BUFFER: - index_array_unit = buffer - BUFFERS_ADDR; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glDeleteBuffers(GLsizei n, const GLuint *gl_buffers) { -#ifndef SKIP_ERROR_HANDLING - if (n < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - return; - } -#endif - int i, j; - for (j = 0; j < n; j++) { - if (gl_buffers[j] >= BUFFERS_ADDR && gl_buffers[j] < (BUFFERS_ADDR + BUFFERS_NUM)) { - uint8_t idx = gl_buffers[j] - BUFFERS_ADDR; - buffers[idx] = gl_buffers[j]; - if (gpu_buffers[idx].ptr != NULL) { - vgl_mem_free(gpu_buffers[idx].ptr, VGL_MEM_VRAM); - gpu_buffers[idx].ptr = NULL; - gpu_buffers[idx].size = 0; - } - } - } -} - -void glBufferData(GLenum target, GLsizei size, const GLvoid *data, GLenum usage) { - int idx = 0; - switch (target) { - case GL_ARRAY_BUFFER: - idx = vertex_array_unit; - break; - case GL_ELEMENT_ARRAY_BUFFER: - idx = index_array_unit; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -#ifndef SKIP_ERROR_HANDLING - if (size < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } - - if (idx < 0) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - vglMemType type = use_vram ? VGL_MEM_VRAM : VGL_MEM_RAM; - - // Free buffer if already existing. - if (gpu_buffers[idx].ptr != NULL) - vgl_mem_free(gpu_buffers[idx].ptr, type); - - gpu_buffers[idx].ptr = gpu_alloc_mapped(size, &type); - gpu_buffers[idx].size = size; - -#ifndef SKIP_ERROR_HANDLING - if (gpu_buffers[idx].ptr == NULL) { - gpu_buffers[idx].size = 0; - SET_GL_ERROR(GL_OUT_OF_MEMORY) - } -#endif - - memcpy_neon(gpu_buffers[idx].ptr, data, size); -} - -void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) { - int idx = 0; - switch (target) { - case GL_ARRAY_BUFFER: - idx = vertex_array_unit; - break; - case GL_ELEMENT_ARRAY_BUFFER: - idx = index_array_unit; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -#ifndef SKIP_ERROR_HANDLING - if ((size < 0) || (offset < 0) || ((offset + size) > gpu_buffers[idx].size)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } - - if (idx < 0) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } -#endif - - memcpy_neon(gpu_buffers[idx].ptr + offset, data, size); -} - -void glBlendFunc(GLenum sfactor, GLenum dfactor) { - switch (sfactor) { - case GL_ZERO: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case GL_ONE: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE; - break; - case GL_SRC_COLOR: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GL_DST_COLOR: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_ALPHA: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - blend_sfactor_rgb = blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - switch (dfactor) { - case GL_ZERO: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case GL_ONE: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE; - break; - case GL_SRC_COLOR: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GL_DST_COLOR: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_ALPHA: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - blend_dfactor_rgb = blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (blend_state) - change_blend_factor(); -} - -void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { - switch (srcRGB) { - case GL_ZERO: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case GL_ONE: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE; - break; - case GL_SRC_COLOR: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GL_DST_COLOR: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_ALPHA: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - blend_sfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - switch (dstRGB) { - case GL_ZERO: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case GL_ONE: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE; - break; - case GL_SRC_COLOR: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GL_DST_COLOR: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_ALPHA: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - blend_dfactor_rgb = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - switch (srcAlpha) { - case GL_ZERO: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case GL_ONE: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE; - break; - case GL_SRC_COLOR: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GL_DST_COLOR: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_ALPHA: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - blend_sfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - switch (dstAlpha) { - case GL_ZERO: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case GL_ONE: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE; - break; - case GL_SRC_COLOR: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_COLOR; - break; - case GL_ONE_MINUS_SRC_COLOR: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_COLOR; - break; - case GL_DST_COLOR: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_COLOR; - break; - case GL_ONE_MINUS_DST_COLOR: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_COLOR; - break; - case GL_SRC_ALPHA: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - break; - case GL_ONE_MINUS_SRC_ALPHA: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case GL_DST_ALPHA: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_DST_ALPHA; - break; - case GL_ONE_MINUS_DST_ALPHA: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_ONE_MINUS_DST_ALPHA; - break; - case GL_SRC_ALPHA_SATURATE: - blend_dfactor_a = SCE_GXM_BLEND_FACTOR_SRC_ALPHA_SATURATE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (blend_state) - change_blend_factor(); -} - -void glBlendEquation(GLenum mode) { - switch (mode) { - case GL_FUNC_ADD: - blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_ADD; - break; - case GL_FUNC_SUBTRACT: - blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_SUBTRACT; - break; - case GL_FUNC_REVERSE_SUBTRACT: - blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT; - break; - case GL_MIN: - blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_MIN; - break; - case GL_MAX: - blend_func_rgb = blend_func_a = SCE_GXM_BLEND_FUNC_MAX; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (blend_state) - change_blend_factor(); -} - -void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) { - switch (modeRGB) { - case GL_FUNC_ADD: - blend_func_rgb = SCE_GXM_BLEND_FUNC_ADD; - break; - case GL_FUNC_SUBTRACT: - blend_func_rgb = SCE_GXM_BLEND_FUNC_SUBTRACT; - break; - case GL_FUNC_REVERSE_SUBTRACT: - blend_func_rgb = SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT; - break; - case GL_MIN: - blend_func_rgb = SCE_GXM_BLEND_FUNC_MIN; - break; - case GL_MAX: - blend_func_rgb = SCE_GXM_BLEND_FUNC_MAX; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - switch (modeAlpha) { - case GL_FUNC_ADD: - blend_func_a = SCE_GXM_BLEND_FUNC_ADD; - break; - case GL_FUNC_SUBTRACT: - blend_func_a = SCE_GXM_BLEND_FUNC_SUBTRACT; - break; - case GL_FUNC_REVERSE_SUBTRACT: - blend_func_a = SCE_GXM_BLEND_FUNC_REVERSE_SUBTRACT; - break; - case GL_MIN: - blend_func_a = SCE_GXM_BLEND_FUNC_MIN; - break; - case GL_MAX: - blend_func_a = SCE_GXM_BLEND_FUNC_MAX; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (blend_state) - change_blend_factor(); -} - -void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { - blend_color_mask = SCE_GXM_COLOR_MASK_NONE; - if (red) - blend_color_mask += SCE_GXM_COLOR_MASK_R; - if (green) - blend_color_mask += SCE_GXM_COLOR_MASK_G; - if (blue) - blend_color_mask += SCE_GXM_COLOR_MASK_B; - if (alpha) - blend_color_mask += SCE_GXM_COLOR_MASK_A; - if (blend_state) - change_blend_factor(); - else - change_blend_mask(); -} - -void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if ((stride < 0) || (size < 2) || (size > 4)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - switch (type) { - case GL_FLOAT: - tex_unit->vertex_array.size = sizeof(GLfloat); - break; - case GL_SHORT: - tex_unit->vertex_array.size = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - tex_unit->vertex_array.num = size; - tex_unit->vertex_array.stride = stride; - tex_unit->vertex_array.pointer = pointer; -} - -void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if ((stride < 0) || (size < 3) || (size > 4)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - switch (type) { - case GL_FLOAT: - tex_unit->color_array.size = sizeof(GLfloat); - break; - case GL_SHORT: - tex_unit->color_array.size = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - tex_unit->color_array.num = size; - tex_unit->color_array.stride = stride; - tex_unit->color_array.pointer = pointer; -} - -void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if ((stride < 0) || (size < 2) || (size > 4)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - switch (type) { - case GL_FLOAT: - tex_unit->texture_array.size = sizeof(GLfloat); - break; - case GL_SHORT: - tex_unit->texture_array.size = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - - tex_unit->texture_array.num = size; - tex_unit->texture_array.stride = stride; - tex_unit->texture_array.pointer = pointer; -} - -void glDrawArrays(GLenum mode, GLint first, GLsizei count) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - SceGxmPrimitiveType gxm_p; - if (tex_unit->vertex_array_state) { - GLboolean skip_draw = GL_FALSE; - switch (mode) { - case GL_POINTS: - gxm_p = SCE_GXM_PRIMITIVE_POINTS; - break; - case GL_LINES: - gxm_p = SCE_GXM_PRIMITIVE_LINES; - if ((count % 2) != 0) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLES: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLES; - if (no_polygons_mode) - skip_draw = GL_TRUE; - else if ((count % 3) != 0) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLE_STRIP: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLE_FAN: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_FAN; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (!skip_draw) { - if (mvp_modified) { - matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix); - mvp_modified = GL_FALSE; - } - - if (tex_unit->texture_array_state) { - if (!(vgl_textures[texture2d_idx].valid)) - return; - if (tex_unit->color_array_state) { - sceGxmSetVertexProgram(gxm_context, texture2d_rgba_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_rgba_fragment_program_patched); - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_op, 0, 1, &alpha_operation); - float env_mode = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env, 0, 1, &env_mode); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density); - } else { - sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched); - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_op, 0, 1, &alpha_operation); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tint_color, 0, 4, ¤t_color.r); - float env_mode = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &env_mode); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density); - } - } else if (tex_unit->color_array_state && (tex_unit->color_array.num == 3)) { - sceGxmSetVertexProgram(gxm_context, rgb_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } else { - sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } - - void *vertex_wvp_buffer; - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer); - - if (tex_unit->texture_array_state) { - if (tex_unit->color_array_state) { - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_wvp, 0, 16, (const float *)mvp_matrix); - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_mv, 0, 16, (const float *)modelview_matrix); - } else { - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix); - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_mv, 0, 16, (const float *)modelview_matrix); - } - sceGxmSetFragmentTexture(gxm_context, 0, &vgl_textures[texture2d_idx].gxm_tex); - vector3f *vertices = NULL; - vector2f *uv_map = NULL; - vector4f *colors = NULL; - uint16_t *indices; - uint16_t n; - if (vertex_array_unit >= 0) { - if (tex_unit->vertex_array.stride == 0) - vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size))); - else - vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride)); - if (tex_unit->texture_array.stride == 0) - uv_map = (vector2f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->texture_array.pointer) + (first * (tex_unit->texture_array.num * tex_unit->texture_array.size))); - else - uv_map = (vector2f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->texture_array.pointer) + (first * tex_unit->texture_array.stride)); - if (tex_unit->color_array_state) { - if (tex_unit->color_array.stride == 0) - colors = (vector4f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * (tex_unit->color_array.num * tex_unit->color_array.size))); - else - colors = (vector4f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * tex_unit->color_array.stride)); - } - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - for (n = 0; n < count; n++) { - indices[n] = n; - } - } else { - uint8_t *ptr; - uint8_t *ptr_tex; - uint8_t *ptr_clr; - vertices = (vector3f *)gpu_pool_memalign(count * sizeof(vector3f), sizeof(vector3f)); - uv_map = (vector2f *)gpu_pool_memalign(count * sizeof(vector2f), sizeof(vector2f)); - if (tex_unit->color_array_state) - colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f)); - memset(vertices, 0, (count * sizeof(vector3f))); - uint8_t vec_set = 0, tex_set = 0, clr_set = 0; - if (tex_unit->vertex_array.stride == 0) { - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size)); - memcpy_neon(&vertices[0], ptr, count * sizeof(vector3f)); - vec_set = 1; - } else - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride); - if (tex_unit->texture_array.stride == 0) { - ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (first * (tex_unit->texture_array.num * tex_unit->texture_array.size)); - memcpy_neon(&uv_map[0], ptr_tex, count * sizeof(vector2f)); - tex_set = 1; - } else - ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer) + (first * tex_unit->texture_array.stride); - if (tex_unit->color_array_state) { - if (tex_unit->color_array.stride == 0) { - ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * sizeof(vector4f)); - memcpy_neon(&colors[0], ptr_clr, count * sizeof(vector4f)); - clr_set = 1; - } else - ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * tex_unit->color_array.stride); - } - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - for (n = 0; n < count; n++) { - if (!vec_set) { - memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - ptr += tex_unit->vertex_array.stride; - } - if (!tex_set) { - memcpy_neon(&uv_map[n], ptr_tex, tex_unit->texture_array.size * tex_unit->texture_array.num); - ptr_tex += tex_unit->texture_array.stride; - } - if (tex_unit->color_array_state && (!clr_set)) { - memcpy_neon(&colors[n], ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num); - ptr_clr += tex_unit->color_array.stride; - } - indices[n] = n; - } - } - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, uv_map); - if (tex_unit->color_array_state) - sceGxmSetVertexStream(gxm_context, 2, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count); - } else if (tex_unit->color_array_state) { - if (tex_unit->color_array.num == 3) - sceGxmSetUniformDataF(vertex_wvp_buffer, rgb_wvp, 0, 16, (const float *)mvp_matrix); - else - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - vector3f *vertices = NULL; - uint8_t *colors = NULL; - uint16_t *indices; - uint16_t n = 0; - if (vertex_array_unit >= 0) { - if (tex_unit->vertex_array.stride == 0) - vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size))); - else - vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride)); - if (tex_unit->color_array.stride == 0) - colors = (uint8_t *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * (tex_unit->color_array.num * tex_unit->color_array.size))); - else - colors = (uint8_t *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer) + (first * tex_unit->color_array.stride)); - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - for (n = 0; n < count; n++) { - indices[n] = n; - } - } else { - uint8_t *ptr; - uint8_t *ptr_clr; - vertices = (vector3f *)gpu_pool_memalign(count * sizeof(vector3f), sizeof(vector3f)); - colors = (uint8_t *)gpu_pool_memalign(count * tex_unit->color_array.num * tex_unit->color_array.size, tex_unit->color_array.num * tex_unit->color_array.size); - memset(vertices, 0, (count * sizeof(vector3f))); - uint8_t vec_set = 0, clr_set = 0; - if (tex_unit->vertex_array.stride == 0) { - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * ((tex_unit->vertex_array.num * tex_unit->vertex_array.size))); - memcpy_neon(&vertices[n], ptr, count * sizeof(vector3f)); - vec_set = 1; - } else - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.stride)); - if (tex_unit->color_array.stride == 0) { - ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * ((tex_unit->color_array.num * tex_unit->color_array.size))); - memcpy_neon(&colors[n], ptr_clr, count * tex_unit->color_array.num * tex_unit->color_array.size); - clr_set = 1; - } else - ptr_clr = ((uint8_t *)tex_unit->color_array.pointer) + (first * tex_unit->color_array.size); - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - for (n = 0; n < count; n++) { - if (!vec_set) { - memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - ptr += tex_unit->vertex_array.stride; - } - if (!clr_set) { - memcpy_neon(&colors[n * tex_unit->color_array.num * tex_unit->color_array.size], ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num); - ptr_clr += tex_unit->color_array.stride; - } - indices[n] = n; - } - } - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count); - } else { - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - vector3f *vertices = NULL; - vector4f *colors = NULL; - uint16_t *indices; - uint16_t n = 0; - if (vertex_array_unit >= 0) { - if (tex_unit->vertex_array.stride == 0) - vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.num * tex_unit->vertex_array.size))); - else - vertices = (vector3f *)(((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer) + (first * tex_unit->vertex_array.stride)); - colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f)); - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - for (n = 0; n < count; n++) { - memcpy_neon(&colors[n], ¤t_color.r, sizeof(vector4f)); - indices[n] = n; - } - } else { - uint8_t *ptr; - vertices = (vector3f *)gpu_pool_memalign(count * sizeof(vector3f), sizeof(vector3f)); - colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f)); - memset(vertices, 0, (count * sizeof(vector3f))); - uint8_t vec_set = 0; - if (tex_unit->vertex_array.stride == 0) { - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * ((tex_unit->vertex_array.num * tex_unit->vertex_array.size))); - memcpy_neon(&vertices[n], ptr, count * sizeof(vector3f)); - vec_set = 1; - } else - ptr = ((uint8_t *)tex_unit->vertex_array.pointer) + (first * (tex_unit->vertex_array.stride)); - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - for (n = 0; n < count; n++) { - if (!vec_set) { - memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - ptr += tex_unit->vertex_array.stride; - } - memcpy_neon(&colors[n], ¤t_color.r, sizeof(vector4f)); - indices[n] = n; - } - } - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count); - } - } - } -} - -void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *gl_indices) { - SceGxmPrimitiveType gxm_p; - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int texture2d_idx = tex_unit->tex_id; - if (tex_unit->vertex_array_state) { - GLboolean skip_draw = GL_FALSE; -#ifndef SKIP_ERROR_HANDLING - if (type != GL_UNSIGNED_SHORT) { - SET_GL_ERROR(GL_INVALID_ENUM) - } else if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } else if (count < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - switch (mode) { - case GL_POINTS: - gxm_p = SCE_GXM_PRIMITIVE_POINTS; - break; - case GL_LINES: - gxm_p = SCE_GXM_PRIMITIVE_LINES; - break; - case GL_TRIANGLES: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLES; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLE_STRIP: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLE_FAN: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_FAN; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (!skip_draw) { - if (mvp_modified) { - matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix); - mvp_modified = GL_FALSE; - } - - if (tex_unit->texture_array_state) { - if (!(vgl_textures[texture2d_idx].valid)) - return; - if (tex_unit->color_array_state) { - sceGxmSetVertexProgram(gxm_context, texture2d_rgba_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_rgba_fragment_program_patched); - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_op, 0, 1, &alpha_operation); - float env_mode = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env, 0, 1, &env_mode); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density); - } else { - sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched); - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_op, 0, 1, &alpha_operation); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tint_color, 0, 4, ¤t_color.r); - float env_mode = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &env_mode); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_density, 0, 1, (const float *)&fog_density); - } - } else if (tex_unit->color_array_state && (tex_unit->color_array.num == 3)) { - sceGxmSetVertexProgram(gxm_context, rgb_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } else { - sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } - - void *vertex_wvp_buffer; - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer); - - if (tex_unit->texture_array_state) { - if (tex_unit->color_array_state) { - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_wvp, 0, 16, (const float *)mvp_matrix); - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_mv, 0, 16, (const float *)modelview_matrix); - } else { - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix); - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_mv, 0, 16, (const float *)modelview_matrix); - } - sceGxmSetFragmentTexture(gxm_context, 0, &vgl_textures[texture2d_idx].gxm_tex); - vector3f *vertices = NULL; - vector2f *uv_map = NULL; - vector4f *colors = NULL; - uint16_t *indices; - if (index_array_unit >= 0) - indices = (uint16_t *)((uint32_t)gpu_buffers[index_array_unit].ptr + (uint32_t)gl_indices); - else { - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - memcpy_neon(indices, gl_indices, sizeof(uint16_t) * count); - } - if (vertex_array_unit >= 0) { - vertices = (vector3f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer); - uv_map = (vector2f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->texture_array.pointer); - if (tex_unit->color_array_state) - colors = (vector4f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer); - } else { - int n = 0, j = 0; - uint64_t vertex_count_int = 0; - uint16_t *ptr_idx = (uint16_t *)gl_indices; - while (j < count) { - if (ptr_idx[j] >= vertex_count_int) - vertex_count_int = ptr_idx[j] + 1; - j++; - } - vertices = (vector3f *)gpu_pool_memalign(vertex_count_int * sizeof(vector3f), sizeof(vector3f)); - uv_map = (vector2f *)gpu_pool_memalign(vertex_count_int * sizeof(vector2f), sizeof(vector2f)); - colors = (vector4f *)gpu_pool_memalign(vertex_count_int * sizeof(vector4f), sizeof(vector4f)); - if (tex_unit->vertex_array.stride == 0) - memcpy_neon(vertices, tex_unit->vertex_array.pointer, vertex_count_int * (tex_unit->vertex_array.size * tex_unit->vertex_array.num)); - if (tex_unit->texture_array.stride == 0) - memcpy_neon(uv_map, tex_unit->texture_array.pointer, vertex_count_int * (tex_unit->texture_array.size * tex_unit->texture_array.num)); - if (tex_unit->color_array_state && (tex_unit->color_array.stride == 0)) - memcpy_neon(colors, tex_unit->color_array.pointer, vertex_count_int * (tex_unit->color_array.size * tex_unit->color_array.num)); - if ((tex_unit->vertex_array.stride != 0) || (tex_unit->texture_array.stride != 0)) { - if (tex_unit->vertex_array.stride != 0) - memset(vertices, 0, (vertex_count_int * sizeof(texture2d_vertex))); - uint8_t *ptr = ((uint8_t *)tex_unit->vertex_array.pointer); - uint8_t *ptr_tex = ((uint8_t *)tex_unit->texture_array.pointer); - for (n = 0; n < vertex_count_int; n++) { - if (tex_unit->vertex_array.stride != 0) - memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - if (tex_unit->texture_array.stride != 0) - memcpy_neon(&uv_map[n], ptr_tex, tex_unit->texture_array.size * tex_unit->texture_array.num); - ptr += tex_unit->vertex_array.stride; - ptr_tex += tex_unit->texture_array.stride; - } - } - } - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, uv_map); - if (tex_unit->color_array_state) - sceGxmSetVertexStream(gxm_context, 2, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count); - } else if (tex_unit->color_array_state) { - if (tex_unit->color_array.num == 3) - sceGxmSetUniformDataF(vertex_wvp_buffer, rgb_wvp, 0, 16, (const float *)mvp_matrix); - else - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - vector3f *vertices = NULL; - uint8_t *colors = NULL; - uint16_t *indices; - if (index_array_unit >= 0) - indices = (uint16_t *)((uint32_t)gpu_buffers[index_array_unit].ptr + (uint32_t)gl_indices); - else { - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - memcpy_neon(indices, gl_indices, sizeof(uint16_t) * count); - } - if (vertex_array_unit >= 0) { - colors = (uint8_t *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->color_array.pointer); - vertices = (vector3f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer); - } else { - int n = 0, j = 0; - uint64_t vertex_count_int = 0; - uint16_t *ptr_idx = (uint16_t *)gl_indices; - while (j < count) { - if (ptr_idx[j] >= vertex_count_int) - vertex_count_int = ptr_idx[j] + 1; - j++; - } - vertices = (vector3f *)gpu_pool_memalign(vertex_count_int * sizeof(vector3f), sizeof(vector3f)); - colors = (uint8_t *)gpu_pool_memalign(vertex_count_int * tex_unit->color_array.num * tex_unit->color_array.size, tex_unit->color_array.num * tex_unit->color_array.size); - if (tex_unit->vertex_array.stride == 0) - memcpy_neon(vertices, tex_unit->vertex_array.pointer, vertex_count_int * (tex_unit->vertex_array.size * tex_unit->vertex_array.num)); - if (tex_unit->color_array.stride == 0) - memcpy_neon(colors, tex_unit->color_array.pointer, vertex_count_int * (tex_unit->color_array.size * tex_unit->color_array.num)); - if ((tex_unit->vertex_array.stride != 0) || (tex_unit->color_array.stride != 0)) { - if (tex_unit->vertex_array.stride != 0) - memset(vertices, 0, (vertex_count_int * sizeof(texture2d_vertex))); - uint8_t *ptr = ((uint8_t *)tex_unit->vertex_array.pointer); - uint8_t *ptr_clr = ((uint8_t *)tex_unit->color_array.pointer); - for (n = 0; n < vertex_count_int; n++) { - if (tex_unit->vertex_array.stride != 0) - memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - if (tex_unit->color_array.stride != 0) - memcpy_neon(&colors[n * tex_unit->color_array.num * tex_unit->color_array.size], ptr_clr, tex_unit->color_array.size * tex_unit->color_array.num); - ptr += tex_unit->vertex_array.stride; - ptr_clr += tex_unit->color_array.stride; - } - } - } - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count); - } else { - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - vector3f *vertices = NULL; - vector4f *colors = NULL; - uint16_t *indices; - if (index_array_unit >= 0) - indices = (uint16_t *)((uint32_t)gpu_buffers[index_array_unit].ptr + (uint32_t)gl_indices); - else { - indices = (uint16_t *)gpu_pool_memalign(count * sizeof(uint16_t), sizeof(uint16_t)); - memcpy_neon(indices, gl_indices, sizeof(uint16_t) * count); - } - int n = 0, j = 0; - uint64_t vertex_count_int = 0; - uint16_t *ptr_idx = (uint16_t *)gl_indices; - while (j < count) { - if (ptr_idx[j] >= vertex_count_int) - vertex_count_int = ptr_idx[j] + 1; - j++; - } - if (vertex_array_unit >= 0) - vertices = (vector3f *)((uint32_t)gpu_buffers[vertex_array_unit].ptr + (uint32_t)tex_unit->vertex_array.pointer); - else - vertices = (vector3f *)gpu_pool_memalign(vertex_count_int * sizeof(vector3f), sizeof(vector3f)); - colors = (vector4f *)gpu_pool_memalign(vertex_count_int * tex_unit->color_array.num * tex_unit->color_array.size, tex_unit->color_array.num * tex_unit->color_array.size); - if ((!vertex_array_unit) && tex_unit->vertex_array.stride == 0) - memcpy_neon(vertices, tex_unit->vertex_array.pointer, vertex_count_int * (tex_unit->vertex_array.size * tex_unit->vertex_array.num)); - if ((!vertex_array_unit) && tex_unit->vertex_array.stride != 0) - memset(vertices, 0, (vertex_count_int * sizeof(texture2d_vertex))); - uint8_t *ptr = ((uint8_t *)tex_unit->vertex_array.pointer); - for (n = 0; n < vertex_count_int; n++) { - if ((!vertex_array_unit) && tex_unit->vertex_array.stride != 0) - memcpy_neon(&vertices[n], ptr, tex_unit->vertex_array.size * tex_unit->vertex_array.num); - memcpy_neon(&colors[n], ¤t_color.r, sizeof(vector4f)); - if (!vertex_array_unit) - ptr += tex_unit->vertex_array.stride; - } - sceGxmSetVertexStream(gxm_context, 0, vertices); - sceGxmSetVertexStream(gxm_context, 1, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, indices, count); - } - } - } -} - -void glEnableClientState(GLenum array) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - switch (array) { - case GL_VERTEX_ARRAY: - tex_unit->vertex_array_state = GL_TRUE; - break; - case GL_COLOR_ARRAY: - tex_unit->color_array_state = GL_TRUE; - break; - case GL_TEXTURE_COORD_ARRAY: - tex_unit->texture_array_state = GL_TRUE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glDisableClientState(GLenum array) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - switch (array) { - case GL_VERTEX_ARRAY: - tex_unit->vertex_array_state = GL_FALSE; - break; - case GL_COLOR_ARRAY: - tex_unit->color_array_state = GL_FALSE; - break; - case GL_TEXTURE_COORD_ARRAY: - tex_unit->texture_array_state = GL_FALSE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } -} - -void glClientActiveTexture(GLenum texture) { -#ifndef SKIP_ERROR_HANDLING - if ((texture < GL_TEXTURE0) && (texture > GL_TEXTURE31)) { - SET_GL_ERROR(GL_INVALID_ENUM) - } else -#endif - client_texture_unit = texture - GL_TEXTURE0; -} - -// VGL_EXT_gpu_objects_array extension implementation - -void vglVertexPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if ((stride < 0) || (size < 2) || (size > 4)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int bpe; - switch (type) { - case GL_FLOAT: - bpe = sizeof(GLfloat); - break; - case GL_SHORT: - bpe = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - tex_unit->vertex_object = gpu_pool_memalign(count * bpe * size, bpe * size); - if (stride == 0) - memcpy_neon(tex_unit->vertex_object, pointer, count * bpe * size); - else { - int i; - uint8_t *dst = (uint8_t *)tex_unit->vertex_object; - uint8_t *src = (uint8_t *)pointer; - for (i = 0; i < count; i++) { - memcpy_neon(dst, src, bpe * size); - dst += (bpe * size); - src += stride; - } - } -} - -void vglColorPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if ((stride < 0) || (size < 3) || (size > 4)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int bpe; - switch (type) { - case GL_FLOAT: - bpe = sizeof(GLfloat); - break; - case GL_SHORT: - bpe = sizeof(GLshort); - break; - case GL_UNSIGNED_BYTE: - bpe = sizeof(uint8_t); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - tex_unit->color_object = gpu_pool_memalign(count * bpe * size, bpe * size); - tex_unit->color_object_type = type; - if (stride == 0) - memcpy_neon(tex_unit->color_object, pointer, count * bpe * size); - else { - int i; - uint8_t *dst = (uint8_t *)tex_unit->color_object; - uint8_t *src = (uint8_t *)pointer; - for (i = 0; i < count; i++) { - memcpy_neon(dst, src, bpe * size); - dst += (bpe * size); - src += stride; - } - } -} - -void vglTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if ((stride < 0) || (size < 2) || (size > 4)) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int bpe; - switch (type) { - case GL_FLOAT: - bpe = sizeof(GLfloat); - break; - case GL_SHORT: - bpe = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - tex_unit->texture_object = gpu_pool_memalign(count * bpe * size, bpe * size); - if (stride == 0) - memcpy_neon(tex_unit->texture_object, pointer, count * bpe * size); - else { - int i; - uint8_t *dst = (uint8_t *)tex_unit->texture_object; - uint8_t *src = (uint8_t *)pointer; - for (i = 0; i < count; i++) { - memcpy_neon(dst, src, bpe * size); - dst += (bpe * size); - src += stride; - } - } -} - -void vglIndexPointer(GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer) { -#ifndef SKIP_ERROR_HANDLING - if (stride < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int bpe; - switch (type) { - case GL_FLOAT: - bpe = sizeof(GLfloat); - break; - case GL_SHORT: - bpe = sizeof(GLshort); - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - tex_unit->index_object = gpu_pool_memalign(count * bpe, bpe); - if (stride == 0) - memcpy_neon(tex_unit->index_object, pointer, count * bpe); - else { - int i; - uint8_t *dst = (uint8_t *)tex_unit->index_object; - uint8_t *src = (uint8_t *)pointer; - for (i = 0; i < count; i++) { - memcpy_neon(dst, src, bpe); - dst += bpe; - src += stride; - } - } -} - -void vglVertexPointerMapped(const GLvoid *pointer) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - tex_unit->vertex_object = (GLvoid *)pointer; -} - -void vglColorPointerMapped(GLenum type, const GLvoid *pointer) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - tex_unit->color_object = (GLvoid *)pointer; - tex_unit->color_object_type = type; -} - -void vglTexCoordPointerMapped(const GLvoid *pointer) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - tex_unit->texture_object = (GLvoid *)pointer; -} - -void vglIndexPointerMapped(const GLvoid *pointer) { - texture_unit *tex_unit = &texture_units[client_texture_unit]; - tex_unit->index_object = (GLvoid *)pointer; -} - -void vglDrawObjects(GLenum mode, GLsizei count, GLboolean implicit_wvp) { - SceGxmPrimitiveType gxm_p; - texture_unit *tex_unit = &texture_units[client_texture_unit]; - int texture2d_idx = tex_unit->tex_id; -#ifndef SKIP_ERROR_HANDLING - if (phase == MODEL_CREATION) { - SET_GL_ERROR(GL_INVALID_OPERATION) - } else if (count < 0) { - SET_GL_ERROR(GL_INVALID_VALUE) - } -#endif - GLboolean skip_draw = GL_FALSE; - switch (mode) { - case GL_POINTS: - gxm_p = SCE_GXM_PRIMITIVE_POINTS; - break; - case GL_LINES: - gxm_p = SCE_GXM_PRIMITIVE_LINES; - break; - case GL_TRIANGLES: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLES; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLE_STRIP: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_STRIP; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - case GL_TRIANGLE_FAN: - gxm_p = SCE_GXM_PRIMITIVE_TRIANGLE_FAN; - if (no_polygons_mode) - skip_draw = GL_TRUE; - break; - default: - SET_GL_ERROR(GL_INVALID_ENUM) - break; - } - if (!skip_draw) { - if (cur_program != 0) { - _vglDrawObjects_CustomShadersIMPL(mode, count, implicit_wvp); - sceGxmSetFragmentTexture(gxm_context, 0, &vgl_textures[texture2d_idx].gxm_tex); - - // TEXUNIT1 support for custom shaders - texture_unit *tex_unit2 = &texture_units[client_texture_unit + 1]; - int texture2d_idx2 = tex_unit2->tex_id; - if (vgl_textures[texture2d_idx2].valid) - sceGxmSetFragmentTexture(gxm_context, 1, &vgl_textures[texture2d_idx2].gxm_tex); - - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count); - } else { - if (tex_unit->vertex_array_state) { - if (mvp_modified) { - matrix4x4_multiply(mvp_matrix, projection_matrix, modelview_matrix); - mvp_modified = GL_FALSE; - } - if (tex_unit->texture_array_state) { - if (!(vgl_textures[texture2d_idx].valid)) - return; - if (tex_unit->color_array_state) { - if (tex_unit->color_object_type == GL_FLOAT) - sceGxmSetVertexProgram(gxm_context, texture2d_rgba_vertex_program_patched); - else - sceGxmSetVertexProgram(gxm_context, texture2d_rgba_u8n_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_rgba_fragment_program_patched); - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_alpha_op, 0, 1, &alpha_operation); - float env_mode = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env, 0, 1, &env_mode); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_rgba_fog_density, 0, 1, (const float *)&fog_density); - } else { - sceGxmSetVertexProgram(gxm_context, texture2d_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, texture2d_fragment_program_patched); - void *alpha_buffer; - sceGxmReserveFragmentDefaultUniformBuffer(gxm_context, &alpha_buffer); - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_cut, 0, 1, &alpha_ref); - float alpha_operation = (float)alpha_op; - sceGxmSetUniformDataF(alpha_buffer, texture2d_alpha_op, 0, 1, &alpha_operation); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tint_color, 0, 4, ¤t_color.r); - float env_mode = (float)tex_unit->env_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env, 0, 1, &env_mode); - float fogmode = (float)internal_fog_mode; - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_mode, 0, 1, &fogmode); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_color, 0, 4, &fog_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tint_color, 0, 4, ¤t_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_tex_env_color, 0, 4, &texenv_color.r); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_near, 0, 1, (const float *)&fog_near); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_far, 0, 1, (const float *)&fog_far); - sceGxmSetUniformDataF(alpha_buffer, texture2d_fog_density, 0, 1, (const float *)&fog_density); - } - } else if (tex_unit->color_array_state && (tex_unit->color_array.num == 3)) { - if (tex_unit->color_object_type == GL_FLOAT) - sceGxmSetVertexProgram(gxm_context, rgb_vertex_program_patched); - else - sceGxmSetVertexProgram(gxm_context, rgb_u8n_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } else { - if (tex_unit->color_object_type == GL_FLOAT) - sceGxmSetVertexProgram(gxm_context, rgba_vertex_program_patched); - else - sceGxmSetVertexProgram(gxm_context, rgba_u8n_vertex_program_patched); - sceGxmSetFragmentProgram(gxm_context, rgba_fragment_program_patched); - } - void *vertex_wvp_buffer; - sceGxmReserveVertexDefaultUniformBuffer(gxm_context, &vertex_wvp_buffer); - if (tex_unit->texture_array_state) { - if (tex_unit->color_array_state) { - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_wvp, 0, 16, (const float *)mvp_matrix); - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_rgba_mv, 0, 16, (const float *)modelview_matrix); - } else { - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_wvp, 0, 16, (const float *)mvp_matrix); - float clipplane0 = (float)clip_plane0; - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0, 0, 1, &clipplane0); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_clip_plane0_eq, 0, 4, &clip_plane0_eq.x); - sceGxmSetUniformDataF(vertex_wvp_buffer, texture2d_mv, 0, 16, (const float *)modelview_matrix); - } - sceGxmSetFragmentTexture(gxm_context, 0, &vgl_textures[texture2d_idx].gxm_tex); - sceGxmSetVertexStream(gxm_context, 0, tex_unit->vertex_object); - sceGxmSetVertexStream(gxm_context, 1, tex_unit->texture_object); - if (tex_unit->color_array_state) - sceGxmSetVertexStream(gxm_context, 2, tex_unit->color_object); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count); - } else if (tex_unit->color_array_state) { - if (tex_unit->color_array.num == 3) - sceGxmSetUniformDataF(vertex_wvp_buffer, rgb_wvp, 0, 16, (const float *)mvp_matrix); - else - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - sceGxmSetVertexStream(gxm_context, 0, tex_unit->vertex_object); - sceGxmSetVertexStream(gxm_context, 1, tex_unit->color_object); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count); - } else { - sceGxmSetUniformDataF(vertex_wvp_buffer, rgba_wvp, 0, 16, (const float *)mvp_matrix); - vector4f *colors = (vector4f *)gpu_pool_memalign(count * sizeof(vector4f), sizeof(vector4f)); - int n; - for (n = 0; n < count; n++) { - memcpy_neon(&colors[n], ¤t_color.r, sizeof(vector4f)); - } - sceGxmSetVertexStream(gxm_context, 0, tex_unit->vertex_object); - sceGxmSetVertexStream(gxm_context, 1, colors); - sceGxmDraw(gxm_context, gxm_p, SCE_GXM_INDEX_FORMAT_U16, tex_unit->index_object, count); - } - } - } - } -} - -size_t vglMemFree(vglMemType type) { - if (type >= VGL_MEM_TYPE_COUNT) - return 0; - return vgl_mempool_get_free_space(type); -} - -void *vglAlloc(uint32_t size, vglMemType type) { - if (type >= VGL_MEM_TYPE_COUNT) - return NULL; - return vgl_mempool_alloc(size, type); -} - -void vglFree(void *addr) { - vgl_mem_free(addr, VGL_MEM_RAM); // Type is discarded so we just pass a random one -} - -void vglUseExtraMem(GLboolean use) { - use_extra_mem = use; -} - -GLboolean vglHasRuntimeShaderCompiler(void) { - return is_shark_online; -} \ No newline at end of file diff --git a/deps/vitaGL/source/vitaGL.h b/deps/vitaGL/source/vitaGL.h deleted file mode 100644 index b739267308..0000000000 --- a/deps/vitaGL/source/vitaGL.h +++ /dev/null @@ -1,478 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _VITAGL_H_ -#define _VITAGL_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#ifdef HAVE_SHARK -#include -#else -#define shark_opt int32_t -#endif - -// clang-format off -#define GLboolean uint8_t -#define GLbyte int8_t -#define GLubyte uint8_t -#define GLchar char -#define GLshort int16_t -#define GLushort uint16_t -#define GLint int32_t -#define GLuint uint32_t -#define GLfixed int32_t -#define GLint64 int64_t -#define GLuint64 uint64_t -#define GLsizei int32_t -#define GLenum uint32_t -#define GLintptr int32_t -#define GLsizeiptr uint32_t -#define GLsync int32_t -#define GLfloat float -#define GLclampf float -#define GLdouble double -#define GLclampd double -#define GLvoid void - -#define GL_FALSE 0 -#define GL_TRUE 1 - -#define GL_NO_ERROR 0 - -#define GL_ZERO 0 -#define GL_ONE 1 - -#define GL_NONE 0 - -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_QUADS 0x0007 -#define GL_ADD 0x0104 -#define GL_NEVER 0x0200 -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_STACK_OVERFLOW 0x0503 -#define GL_STACK_UNDERFLOW 0x0504 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_EXP 0x0800 -#define GL_EXP2 0x0801 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_POLYGON_MODE 0x0B40 -#define GL_CULL_FACE 0x0B44 -#define GL_FOG 0x0B60 -#define GL_FOG_DENSITY 0x0B62 -#define GL_FOG_START 0x0B63 -#define GL_FOG_END 0x0B64 -#define GL_FOG_MODE 0x0B65 -#define GL_FOG_COLOR 0x0B66 -#define GL_DEPTH_TEST 0x0B71 -#define GL_STENCIL_TEST 0x0B90 -#define GL_VIEWPORT 0x0BA2 -#define GL_MODELVIEW_MATRIX 0x0BA6 -#define GL_PROJECTION_MATRIX 0x0BA7 -#define GL_ALPHA_TEST 0x0BC0 -#define GL_BLEND 0x0BE2 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 -#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 -#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C -#define GL_INVERT 0x150A -#define GL_MODELVIEW 0x1700 -#define GL_PROJECTION 0x1701 -#define GL_COLOR_INDEX 0x1900 -#define GL_RED 0x1903 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A -#define GL_POINT 0x1B00 -#define GL_LINE 0x1B01 -#define GL_FILL 0x1B02 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_MODULATE 0x2100 -#define GL_DECAL 0x2101 -#define GL_TEXTURE_ENV_MODE 0x2200 -#define GL_TEXTURE_ENV_COLOR 0x2201 -#define GL_TEXTURE_ENV 0x2300 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_REPEAT 0x2901 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_POINT 0x2A01 -#define GL_POLYGON_OFFSET_LINE 0x2A02 -#define GL_CLIP_PLANE0 0x3000 -#define GL_FUNC_ADD 0x8006 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_INTENSITY 0x8049 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_VERTEX_ARRAY 0x8074 -#define GL_COLOR_ARRAY 0x8076 -#define GL_TEXTURE_COORD_ARRAY 0x8078 -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_COLOR_TABLE 0x80D0 -#define GL_BGR 0x80E0 -#define GL_BGRA 0x80E1 -#define GL_COLOR_INDEX8_EXT 0x80E5 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_RG 0x8227 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_TEXTURE_COMPRESSION_HINT 0x84EF -#define GL_TEXTURE_LOD_BIAS 0x8501 -#define GL_INCR_WRAP 0x8507 -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_MIRROR_CLAMP_EXT 0x8742 -#define GL_DECR_WRAP 0x8508 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_STREAM_DRAW 0x88E0 -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_DRAW 0x88E4 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_SHADER_TYPE 0x8B4F -#define GL_COMPILE_STATUS 0x8B81 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 - -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 2 -#define GL_MAX_TEXTURE_LOD_BIAS 31 - -// Aliases -#define GL_CLAMP GL_CLAMP_TO_EDGE - -typedef enum GLbitfield{ - GL_DEPTH_BUFFER_BIT = 0x00000100, - GL_STENCIL_BUFFER_BIT = 0x00000400, - GL_COLOR_BUFFER_BIT = 0x00004000 -} GLbitfield; -// clang-format on - -// gl* -void glActiveTexture(GLenum texture); -void glAlphaFunc(GLenum func, GLfloat ref); -void glArrayElement(GLint i); -void glAttachShader(GLuint prog, GLuint shad); -void glBegin(GLenum mode); -void glBindBuffer(GLenum target, GLuint buffer); -void glBindFramebuffer(GLenum target, GLuint framebuffer); -void glBindTexture(GLenum target, GLuint texture); -void glBlendEquation(GLenum mode); -void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); -void glBlendFunc(GLenum sfactor, GLenum dfactor); -void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -void glBufferData(GLenum target, GLsizei size, const GLvoid *data, GLenum usage); -void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data); -void glClear(GLbitfield mask); -void glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void glClearDepth(GLdouble depth); -void glClearStencil(GLint s); -void glClientActiveTexture(GLenum texture); -void glClipPlane(GLenum plane, const GLdouble *equation); -void glColor3f(GLfloat red, GLfloat green, GLfloat blue); -void glColor3fv(const GLfloat *v); -void glColor3ub(GLubyte red, GLubyte green, GLubyte blue); -void glColor3ubv(const GLubyte *v); -void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -void glColor4fv(const GLfloat *v); -void glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); -void glColor4ubv(const GLubyte *v); -void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -void glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void glColorTable(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *data); -void glCompileShader(GLuint shader); -void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); // Mipmap levels are ignored currently -GLuint glCreateProgram(void); -GLuint glCreateShader(GLenum shaderType); -void glCullFace(GLenum mode); -void glDeleteBuffers(GLsizei n, const GLuint *gl_buffers); -void glDeleteFramebuffers(GLsizei n, GLuint *framebuffers); -void glDeleteProgram(GLuint prog); -void glDeleteShader(GLuint shad); -void glDeleteTextures(GLsizei n, const GLuint *textures); -void glDepthFunc(GLenum func); -void glDepthMask(GLboolean flag); -void glDepthRange(GLdouble nearVal, GLdouble farVal); -void glDepthRangef(GLfloat nearVal, GLfloat farVal); -void glDisable(GLenum cap); -void glDisableClientState(GLenum array); -void glDrawArrays(GLenum mode, GLint first, GLsizei count); -void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); -void glEnable(GLenum cap); -void glEnableClientState(GLenum array); -void glEnd(void); -void glFinish(void); -void glFogf(GLenum pname, GLfloat param); -void glFogfv(GLenum pname, const GLfloat *params); -void glFogi(GLenum pname, const GLint param); -void glFramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level); -void glFrontFace(GLenum mode); -void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal); -void glGenBuffers(GLsizei n, GLuint *buffers); -void glGenerateMipmap(GLenum target); -void glGenFramebuffers(GLsizei n, GLuint *ids); -void glGenTextures(GLsizei n, GLuint *textures); -void glGetBooleanv(GLenum pname, GLboolean *params); -void glGetFloatv(GLenum pname, GLfloat *data); -GLenum glGetError(void); -void glGetIntegerv(GLenum pname, GLint *data); -void glGetShaderInfoLog(GLuint handle, GLsizei maxLength, GLsizei *length, GLchar *infoLog); -void glGetShaderiv(GLuint handle, GLenum pname, GLint *params); -const GLubyte *glGetString(GLenum name); -GLint glGetUniformLocation(GLuint prog, const GLchar *name); -void glHint(GLenum target, GLenum mode); -GLboolean glIsEnabled(GLenum cap); -void glLineWidth(GLfloat width); -void glLinkProgram(GLuint progr); -void glLoadIdentity(void); -void glLoadMatrixf(const GLfloat *m); -void glMatrixMode(GLenum mode); -void glMultMatrixf(const GLfloat *m); -void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble nearVal, GLdouble farVal); -void glPointSize(GLfloat size); -void glPolygonMode(GLenum face, GLenum mode); -void glPolygonOffset(GLfloat factor, GLfloat units); -void glPopMatrix(void); -void glPushMatrix(void); -void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data); -void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); -void glScalef(GLfloat x, GLfloat y, GLfloat z); -void glScissor(GLint x, GLint y, GLsizei width, GLsizei height); -void glShaderBinary(GLsizei count, const GLuint *handles, GLenum binaryFormat, const void *binary, GLsizei length); // NOTE: Uses GXP shaders -void glShaderSource(GLuint handle, GLsizei count, const GLchar *const *string, const GLint *length); // NOTE: Uses CG shader sources -void glStencilFunc(GLenum func, GLint ref, GLuint mask); -void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); -void glStencilMask(GLuint mask); -void glStencilMaskSeparate(GLenum face, GLuint mask); -void glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass); -void glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -void glTexCoord2f(GLfloat s, GLfloat t); -void glTexCoord2fv(GLfloat *f); -void glTexCoord2i(GLint s, GLint t); -void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void glTexEnvf(GLenum target, GLenum pname, GLfloat param); -void glTexEnvfv(GLenum target, GLenum pname, GLfloat *param); -void glTexEnvi(GLenum target, GLenum pname, GLint param); -void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *data); -void glTexParameterf(GLenum target, GLenum pname, GLfloat param); -void glTexParameteri(GLenum target, GLenum pname, GLint param); -void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); -void glTranslatef(GLfloat x, GLfloat y, GLfloat z); -void glUniform1f(GLint location, GLfloat v0); -void glUniform1i(GLint location, GLint v0); -void glUniform2f(GLint location, GLfloat v0, GLfloat v1); -void glUniform2i(GLint location, GLint v0, GLint v1); -void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); -void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); -void glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); -void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -void glUseProgram(GLuint program); -void glVertex2f(GLfloat x, GLfloat y); -void glVertex3f(GLfloat x, GLfloat y, GLfloat z); -void glVertex3fv(const GLfloat *v); -void glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); -void glViewport(GLint x, GLint y, GLsizei width, GLsizei height); - -// glu* -void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); - -// VGL_EXT_gpu_objects_array extension -void vglColorPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer); -void vglColorPointerMapped(GLenum type, const GLvoid *pointer); -void vglDrawObjects(GLenum mode, GLsizei count, GLboolean implicit_wvp); -void vglIndexPointer(GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer); -void vglIndexPointerMapped(const GLvoid *pointer); -void vglTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer); -void vglTexCoordPointerMapped(const GLvoid *pointer); -void vglVertexPointer(GLint size, GLenum type, GLsizei stride, GLuint count, const GLvoid *pointer); -void vglVertexPointerMapped(const GLvoid *pointer); - -// VGL_EXT_gxp_shaders extension implementation -void vglBindAttribLocation(GLuint prog, GLuint index, const GLchar *name, const GLuint num, const GLenum type); -GLint vglBindPackedAttribLocation(GLuint prog, const GLchar *name, const GLuint num, const GLenum type, GLuint offset, GLint stride); -void vglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLuint count, const GLvoid *pointer); -void vglVertexAttribPointerMapped(GLuint index, const GLvoid *pointer); - -typedef enum { - VGL_MEM_ALL = 0, // any memory type (used to monitor total heap usage) - VGL_MEM_VRAM, // CDRAM - VGL_MEM_RAM, // USER_RW RAM - VGL_MEM_SLOW, // PHYCONT_USER_RW RAM - VGL_MEM_EXTERNAL, // newlib mem - VGL_MEM_TYPE_COUNT -} vglMemType; - -// vgl* -void *vglAlloc(uint32_t size, vglMemType type); -void vglEnableRuntimeShaderCompiler(GLboolean usage); -void vglEnd(void); -void vglFree(void *addr); -SceGxmTexture *vglGetGxmTexture(GLenum target); -void *vglGetTexDataPointer(GLenum target); -GLboolean vglHasRuntimeShaderCompiler(void); -void vglInit(uint32_t gpu_pool_size); -void vglInitExtended(uint32_t gpu_pool_size, int width, int height, int ram_threshold, SceGxmMultisampleMode msaa); -void vglInitWithCustomSizes(uint32_t gpu_pool_size, int width, int height, int ram_pool_size, int cdram_pool_size, int phycont_pool_size, SceGxmMultisampleMode msaa); -size_t vglMemFree(vglMemType type); -void vglSetParamBufferSize(uint32_t size); -void vglSetupRuntimeShaderCompiler(shark_opt opt_level, int32_t use_fastmath, int32_t use_fastprecision, int32_t use_fastint); -void vglStartRendering(); -void vglStopRendering(); -void vglStopRenderingInit(); -void vglStopRenderingTerm(); -void vglTexImageDepthBuffer(GLenum target); -void vglUpdateCommonDialog(); -void vglUseVram(GLboolean usage); -void vglUseVramForUSSE(GLboolean usage); -void vglUseExtraMem(GLboolean usage); -void vglWaitVblankStart(GLboolean enable); - -// NEON optimized memcpy -void *memcpy_neon(void *destination, const void *source, size_t num); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/deps/vitaShaRK/.gitattributes b/deps/vitaShaRK/.gitattributes deleted file mode 100644 index dfe0770424..0000000000 --- a/deps/vitaShaRK/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto diff --git a/deps/vitaShaRK/.github/FUNDING.yml b/deps/vitaShaRK/.github/FUNDING.yml deleted file mode 100644 index dbd470e946..0000000000 --- a/deps/vitaShaRK/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -patreon: Rinnegatamante diff --git a/deps/vitaShaRK/.gitignore b/deps/vitaShaRK/.gitignore deleted file mode 100644 index 4a072bdd8b..0000000000 --- a/deps/vitaShaRK/.gitignore +++ /dev/null @@ -1,59 +0,0 @@ -*.vpk -*.elf -*.velf -*.bin -*.sfo -*.S -*.wo - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Windows Installer files -*.cab -*.msi -*.msm -*.msp - -# Windows shortcuts -*.lnk - -# ========================= -# Operating System Files -# ========================= - -# OSX -# ========================= - -.DS_Store -.AppleDouble -.LSOverride - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -# Vita build stuffs -*.a -*.o diff --git a/deps/vitaShaRK/LICENSE b/deps/vitaShaRK/LICENSE deleted file mode 100644 index 8805d0dfad..0000000000 --- a/deps/vitaShaRK/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ -GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/deps/vitaShaRK/Makefile b/deps/vitaShaRK/Makefile deleted file mode 100644 index 58ce7401e2..0000000000 --- a/deps/vitaShaRK/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -TARGET := libvitashark -SOURCES := source -SHADERS := shaders - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -ASMFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.S)) -CGFILES := $(foreach dir,$(SHADERS), $(wildcard $(dir)/*.cg)) -HEADERS := $(CGFILES:.cg=.h) -OBJS := $(CFILES:.c=.o) $(ASMFILES:.S=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -AR = $(PREFIX)-gcc-ar -CFLAGS = -g -Wl,-q -O2 -ffast-math -mtune=cortex-a9 -mfpu=neon -ftree-vectorize -ASFLAGS = $(CFLAGS) - -all: $(TARGET).a - -$(TARGET).a: $(OBJS) - $(AR) -rc $@ $^ - -clean: - @rm -rf $(TARGET).a $(TARGET).elf $(OBJS) - @make -C samples/sample1 clean - @make -C samples/sample2 clean - -install: $(TARGET).a - @mkdir -p $(VITASDK)/$(PREFIX)/lib/ - cp $(TARGET).a $(VITASDK)/$(PREFIX)/lib/ - @mkdir -p $(VITASDK)/$(PREFIX)/include/ - cp source/vitashark.h $(VITASDK)/$(PREFIX)/include/ - -samples: $(TARGET).a - @make -C samples/sample1 - cp "samples/sample1/vitaShaRK-Sample001.vpk" . - @make -C samples/sample2 - cp "samples/sample1/vitaShaRK-Sample002.vpk" . diff --git a/deps/vitaShaRK/README.md b/deps/vitaShaRK/README.md deleted file mode 100644 index 53d4cd9d4b..0000000000 --- a/deps/vitaShaRK/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# vitaShaRK -**vita** **Sha**ders **R**untime **K**ompiler is a runtime shader compiler library for PSVITA/PSTV using the SceShaccCg module contained inside the PSM runtime. - -# Build Instructions -In order to build vitaShaRK, you'll first need to build SceShaccCg stubs. This is a full list of commands you can use to install this library and the required stubs: -``` -vita-libs-gen SceShaccCg.yml build -cd build -make install -cd .. -cp shacccg.h $VITASDK/arm-vita-eabi/psp2/shacccg.h -make install -``` - - -# Credits - -**frangarcj** for the original vita2d shader compiler source used as base to build up this library. diff --git a/deps/vitaShaRK/SceShaccCg.yml b/deps/vitaShaRK/SceShaccCg.yml deleted file mode 100644 index d20eae44a5..0000000000 --- a/deps/vitaShaRK/SceShaccCg.yml +++ /dev/null @@ -1,43 +0,0 @@ -version: 2 -firmware: 3.60 -modules: - SceShaccCg: - nid: 0xB3B90A35 - libraries: - SceShaccCg: - kernel: false - nid: 0xA05BBEBB - functions: - SceShaccCg_0205DE96: 0x0205DE96 - SceShaccCg_07DDFC78: 0x07DDFC78 - SceShaccCg_0E1285A6: 0x0E1285A6 - SceShaccCg_152971B1: 0x152971B1 - SceShaccCg_17223BEB: 0x17223BEB - SceShaccCg_2654E73A: 0x2654E73A - SceShaccCg_268FAEE9: 0x268FAEE9 - sceShaccCgInitializeCompileOptions: 0x3B58AFA0 - SceShaccCg_4595A388: 0x4595A388 - SceShaccCg_46FA0303: 0x46FA0303 - SceShaccCg_56BFA825: 0x56BFA825 - SceShaccCg_648739F3: 0x648739F3 - sceShaccCgCompileProgram: 0x66814F35 - SceShaccCg_6BB58825: 0x6BB58825 - sceShaccCgSetDefaultAllocator: 0x6F01D573 - SceShaccCg_6FB40CA9: 0x6FB40CA9 - SceShaccCg_7B2CF324: 0x7B2CF324 - SceShaccCg_7BC25091: 0x7BC25091 - SceShaccCg_7F430CCD: 0x7F430CCD - SceShaccCg_95F57A23: 0x95F57A23 - SceShaccCg_A067C481: 0xA067C481 - SceShaccCg_A13A8A1E: 0xA13A8A1E - SceShaccCg_A56B1A5B: 0xA56B1A5B - SceShaccCg_A7930FF6: 0xA7930FF6 - sceShaccCgInitializeCallbackList: 0xA8C2C1C8 - sceShaccCgDestroyCompileOutput: 0xAA82EF0C - SceShaccCg_B4AC9943: 0xB4AC9943 - SceShaccCg_BB703EE1: 0xBB703EE1 - SceShaccCg_D4378DB1: 0xD4378DB1 - SceShaccCg_DAD4AAE4: 0xDAD4AAE4 - SceShaccCg_DF3DDCFD: 0xDF3DDCFD - SceShaccCg_EF8D59D6: 0xEF8D59D6 - SceShaccCg_F4BAB902: 0xF4BAB902 diff --git a/deps/vitaShaRK/SceShaccCg/Makefile b/deps/vitaShaRK/SceShaccCg/Makefile deleted file mode 100644 index 495b32a861..0000000000 --- a/deps/vitaShaRK/SceShaccCg/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -ifdef VITASDK -PREFIX = $(VITASDK)/bin/ -endif - -ARCH ?= $(PREFIX)arm-vita-eabi -AS = $(ARCH)-as -AR = $(ARCH)-ar -RANLIB = $(ARCH)-ranlib - -TARGETS = libSceShaccCg_stub.a -TARGETS_WEAK = libSceShaccCg_stub_weak.a - -SceShaccCg_OBJS = SceShaccCg_SceShaccCg_SceShaccCg_0205DE96.o SceShaccCg_SceShaccCg_SceShaccCg_07DDFC78.o SceShaccCg_SceShaccCg_SceShaccCg_0E1285A6.o SceShaccCg_SceShaccCg_SceShaccCg_152971B1.o SceShaccCg_SceShaccCg_SceShaccCg_17223BEB.o SceShaccCg_SceShaccCg_SceShaccCg_2654E73A.o SceShaccCg_SceShaccCg_SceShaccCg_268FAEE9.o SceShaccCg_SceShaccCg_sceShaccCgInitializeCompileOptions.o SceShaccCg_SceShaccCg_SceShaccCg_4595A388.o SceShaccCg_SceShaccCg_SceShaccCg_46FA0303.o SceShaccCg_SceShaccCg_SceShaccCg_56BFA825.o SceShaccCg_SceShaccCg_SceShaccCg_648739F3.o SceShaccCg_SceShaccCg_sceShaccCgCompileProgram.o SceShaccCg_SceShaccCg_SceShaccCg_6BB58825.o SceShaccCg_SceShaccCg_sceShaccCgSetDefaultAllocator.o SceShaccCg_SceShaccCg_SceShaccCg_6FB40CA9.o SceShaccCg_SceShaccCg_SceShaccCg_7B2CF324.o SceShaccCg_SceShaccCg_SceShaccCg_7BC25091.o SceShaccCg_SceShaccCg_SceShaccCg_7F430CCD.o SceShaccCg_SceShaccCg_SceShaccCg_95F57A23.o SceShaccCg_SceShaccCg_SceShaccCg_A067C481.o SceShaccCg_SceShaccCg_SceShaccCg_A13A8A1E.o SceShaccCg_SceShaccCg_SceShaccCg_A56B1A5B.o SceShaccCg_SceShaccCg_SceShaccCg_A7930FF6.o SceShaccCg_SceShaccCg_sceShaccCgInitializeCallbackList.o SceShaccCg_SceShaccCg_sceShaccCgDestroyCompileOutput.o SceShaccCg_SceShaccCg_SceShaccCg_B4AC9943.o SceShaccCg_SceShaccCg_SceShaccCg_BB703EE1.o SceShaccCg_SceShaccCg_SceShaccCg_D4378DB1.o SceShaccCg_SceShaccCg_SceShaccCg_DAD4AAE4.o SceShaccCg_SceShaccCg_SceShaccCg_DF3DDCFD.o SceShaccCg_SceShaccCg_SceShaccCg_EF8D59D6.o SceShaccCg_SceShaccCg_SceShaccCg_F4BAB902.o -SceShaccCg_weak_OBJS = SceShaccCg_SceShaccCg_SceShaccCg_0205DE96.wo SceShaccCg_SceShaccCg_SceShaccCg_07DDFC78.wo SceShaccCg_SceShaccCg_SceShaccCg_0E1285A6.wo SceShaccCg_SceShaccCg_SceShaccCg_152971B1.wo SceShaccCg_SceShaccCg_SceShaccCg_17223BEB.wo SceShaccCg_SceShaccCg_SceShaccCg_2654E73A.wo SceShaccCg_SceShaccCg_SceShaccCg_268FAEE9.wo SceShaccCg_SceShaccCg_sceShaccCgInitializeCompileOptions.wo SceShaccCg_SceShaccCg_SceShaccCg_4595A388.wo SceShaccCg_SceShaccCg_SceShaccCg_46FA0303.wo SceShaccCg_SceShaccCg_SceShaccCg_56BFA825.wo SceShaccCg_SceShaccCg_SceShaccCg_648739F3.wo SceShaccCg_SceShaccCg_sceShaccCgCompileProgram.wo SceShaccCg_SceShaccCg_SceShaccCg_6BB58825.wo SceShaccCg_SceShaccCg_sceShaccCgSetDefaultAllocator.wo SceShaccCg_SceShaccCg_SceShaccCg_6FB40CA9.wo SceShaccCg_SceShaccCg_SceShaccCg_7B2CF324.wo SceShaccCg_SceShaccCg_SceShaccCg_7BC25091.wo SceShaccCg_SceShaccCg_SceShaccCg_7F430CCD.wo SceShaccCg_SceShaccCg_SceShaccCg_95F57A23.wo SceShaccCg_SceShaccCg_SceShaccCg_A067C481.wo SceShaccCg_SceShaccCg_SceShaccCg_A13A8A1E.wo SceShaccCg_SceShaccCg_SceShaccCg_A56B1A5B.wo SceShaccCg_SceShaccCg_SceShaccCg_A7930FF6.wo SceShaccCg_SceShaccCg_sceShaccCgInitializeCallbackList.wo SceShaccCg_SceShaccCg_sceShaccCgDestroyCompileOutput.wo SceShaccCg_SceShaccCg_SceShaccCg_B4AC9943.wo SceShaccCg_SceShaccCg_SceShaccCg_BB703EE1.wo SceShaccCg_SceShaccCg_SceShaccCg_D4378DB1.wo SceShaccCg_SceShaccCg_SceShaccCg_DAD4AAE4.wo SceShaccCg_SceShaccCg_SceShaccCg_DF3DDCFD.wo SceShaccCg_SceShaccCg_SceShaccCg_EF8D59D6.wo SceShaccCg_SceShaccCg_SceShaccCg_F4BAB902.wo -SceKernel_OBJS = -ALL_OBJS= - -all: $(TARGETS) $(TARGETS_WEAK) - -define LIBRARY_template - $(1): $$($(1:lib%_stub.a=%)_OBJS) - ALL_OBJS += $$($(1:lib%_stub.a=%)_OBJS) -endef -define LIBRARY_WEAK_template - $(1): $$($(1:lib%_stub_weak.a=%)_weak_OBJS) - ALL_OBJS += $$($(1:lib%_stub_weak.a=%)_weak_OBJS) -endef - -$(foreach library,$(TARGETS),$(eval $(call LIBRARY_template,$(library)))) -$(foreach library,$(TARGETS_WEAK),$(eval $(call LIBRARY_WEAK_template,$(library)))) - -install: $(TARGETS) $(TARGETS_WEAK) - cp $(TARGETS) $(VITASDK)/arm-vita-eabi/lib - cp $(TARGETS_WEAK) $(VITASDK)/arm-vita-eabi/lib - -clean: - rm -f $(TARGETS) $(TARGETS_WEAK) $(ALL_OBJS) - -$(TARGETS) $(TARGETS_WEAK): - $(AR) cru $@ $? - $(RANLIB) $@ - -%.o: %.S - $(AS) --defsym GEN_WEAK_EXPORTS=0 $< -o $@ - -%.wo: %.S - $(AS) --defsym GEN_WEAK_EXPORTS=1 $< -o $@ diff --git a/deps/vitaShaRK/include/shacccg.h b/deps/vitaShaRK/include/shacccg.h deleted file mode 100644 index aa9f6f06eb..0000000000 --- a/deps/vitaShaRK/include/shacccg.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef _PSP2_SHACCCG_H -#define _PSP2_SHACCCG_H - -#ifdef __cplusplus -extern "C" { -#endif // def __cplusplus - -typedef struct SceShaccCgCompileOptions SceShaccCgCompileOptions; -typedef struct SceShaccCgSourceFile SceShaccCgSourceFile; -typedef struct SceShaccCgSourceLocation SceShaccCgSourceLocation; -typedef void const *SceShaccCgParameter; - -typedef SceShaccCgSourceFile* (*SceShaccCgCallbackOpenFile)( - const char *fileName, - const SceShaccCgSourceLocation *includedFrom, - const SceShaccCgCompileOptions *compileOptions, - const char **errorString); - -typedef void (*SceShaccCgCallbackReleaseFile)( - const SceShaccCgSourceFile *file, - const SceShaccCgCompileOptions *compileOptions); - -typedef const char* (*SceShaccCgCallbackLocateFile)( - const char *fileName, - const SceShaccCgSourceLocation *includedFrom, - uint32_t searchPathCount, - const char *const*searchPaths, - const SceShaccCgCompileOptions *compileOptions, - const char **errorString); - -typedef const char* (*SceShaccCgCallbackAbsolutePath)( - const char *fileName, - const SceShaccCgSourceLocation *includedFrom, - const SceShaccCgCompileOptions *compileOptions); - -typedef void (*SceShaccCgCallbackReleaseFileName)( - const char *fileName, - const SceShaccCgCompileOptions *compileOptions); - -typedef int32_t (*SceShaccCgCallbackFileDate)( - const SceShaccCgSourceFile *file, - const SceShaccCgSourceLocation *includedFrom, - const SceShaccCgCompileOptions *compileOptions, - int64_t *timeLastStatusChange, - int64_t *timeLastModified); - -typedef enum SceShaccCgDiagnosticLevel { - SCE_SHACCCG_DIAGNOSTIC_LEVEL_INFO, - SCE_SHACCCG_DIAGNOSTIC_LEVEL_WARNING, - SCE_SHACCCG_DIAGNOSTIC_LEVEL_ERROR -} SceShaccCgDiagnosticLevel; - -typedef enum SceShaccCgTargetProfile { - SCE_SHACCCG_PROFILE_VP, - SCE_SHACCCG_PROFILE_FP -} SceShaccCgTargetProfile; - -typedef enum SceShaccCgCallbackDefaults { - SCE_SHACCCG_SYSTEM_FILES, - SCE_SHACCCG_TRIVIAL -} SceShaccCgCallbackDefaults; - -typedef enum SceShaccCgLocale { - SCE_SHACCCG_ENGLISH, - SCE_SHACCCG_JAPANESE -} SceShaccCgLocale; - -typedef struct SceShaccCgSourceFile { - const char *fileName; - const char *text; - uint32_t size; -} SceShaccCgSourceFile; - -typedef struct SceShaccCgSourceLocation { - const SceShaccCgSourceFile *file; - uint32_t lineNumber; - uint32_t columnNumber; -} SceShaccCgSourceLocation; - -typedef struct SceShaccCgCallbackList { - SceShaccCgCallbackOpenFile openFile; - SceShaccCgCallbackReleaseFile releaseFile; - SceShaccCgCallbackLocateFile locateFile; - SceShaccCgCallbackAbsolutePath absolutePath; - SceShaccCgCallbackReleaseFileName releaseFileName; - SceShaccCgCallbackFileDate fileDate; -} SceShaccCgCallbackList; - -typedef struct SceShaccCgCompileOptions { - const char *mainSourceFile; - SceShaccCgTargetProfile targetProfile; - const char *entryFunctionName; - uint32_t searchPathCount; - const char* const *searchPaths; - uint32_t macroDefinitionCount; - const char* const *macroDefinitions; - uint32_t includeFileCount; - const char* const *includeFiles; - uint32_t suppressedWarningsCount; - const uint32_t *suppressedWarnings; - SceShaccCgLocale locale; - int32_t useFx; - int32_t noStdlib; - int32_t optimizationLevel; - int32_t useFastmath; - int32_t useFastprecision; - int32_t useFastint; - int32_t warningsAsErrors; - int32_t performanceWarnings; - int32_t warningLevel; - int32_t pedantic; - int32_t pedanticError; - int field_5C; - int field_60; - int field_64; -} SceShaccCgCompileOptions; - -typedef struct SceShaccCgDiagnosticMessage { - SceShaccCgDiagnosticLevel level; - uint32_t code; - const SceShaccCgSourceLocation *location; - const char *message; -} SceShaccCgDiagnosticMessage; - -typedef struct SceShaccCgCompileOutput { - const uint8_t *programData; - uint32_t programSize; - int32_t diagnosticCount; - const SceShaccCgDiagnosticMessage *diagnostics; -} SceShaccCgCompileOutput; - - -int SceShaccCg_0205DE96(int); -int SceShaccCg_07DDFC78(int); -int SceShaccCg_0E1285A6(int); -int SceShaccCg_152971B1(int); -int SceShaccCg_17223BEB(int); -int SceShaccCg_2654E73A(int); -int SceShaccCg_268FAEE9(int); - -int sceShaccCgInitializeCompileOptions( - SceShaccCgCompileOptions *options); - -int SceShaccCg_4595A388(int); -int SceShaccCg_46FA0303(int); -int SceShaccCg_56BFA825(int); -int SceShaccCg_648739F3(int); - -SceShaccCgCompileOutput const *sceShaccCgCompileProgram( - const SceShaccCgCompileOptions *options, - const SceShaccCgCallbackList *callbacks, - int unk); - -int SceShaccCg_6BB58825(int); -int sceShaccCgSetDefaultAllocator(void *(*malloc_cb)(unsigned int), void (*free_cb)(void *)); -int SceShaccCg_6FB40CA9(int); -int SceShaccCg_7B2CF324(int); -int SceShaccCg_7BC25091(int); -int SceShaccCg_7F430CCD(int); -int SceShaccCg_95F57A23(int); -int SceShaccCg_A067C481(int); -int SceShaccCg_A13A8A1E(int); -int SceShaccCg_A56B1A5B(int); -int SceShaccCg_A7930FF6(int); - -void sceShaccCgInitializeCallbackList( - SceShaccCgCallbackList *callbacks, - SceShaccCgCallbackDefaults defaults); - -void sceShaccCgDestroyCompileOutput( - SceShaccCgCompileOutput const *output); - -int SceShaccCg_B4AC9943(int); -int SceShaccCg_BB703EE1(int); -int SceShaccCg_D4378DB1(int); -int SceShaccCg_DAD4AAE4(int); -int SceShaccCg_DF3DDCFD(int); -int SceShaccCg_EF8D59D6(int); -int SceShaccCg_F4BAB902(int); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* _PSP2_SHACCCG_H */ diff --git a/deps/vitaShaRK/samples/sample1/Makefile b/deps/vitaShaRK/samples/sample1/Makefile deleted file mode 100644 index 0202cf37cc..0000000000 --- a/deps/vitaShaRK/samples/sample1/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -SAMPLE_NUM := 001 -TARGET := vitaShaRK-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitashark -lSceLibKernel_stub -lSceShaccCg_stub - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VSHARK$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaShaRK/samples/sample1/main.c b/deps/vitaShaRK/samples/sample1/main.c deleted file mode 100644 index 1e312c51a7..0000000000 --- a/deps/vitaShaRK/samples/sample1/main.c +++ /dev/null @@ -1,59 +0,0 @@ -// Simple compiler with no logging - -#include -#include -#include - -const char fragment_shader[] = - "float4 main(uniform float4 u_clear_color) : COLOR\n" - "{\n" - " return u_clear_color;\n" - "}" - ; - -const char vertex_shader[] = - "void main(\n" - "float3 aPosition,\n" - "float3 aColor,\n" - "uniform float4x4 wvp,\n" - "float4 out vPosition: POSITION,\n" - "float4 out vColor: COLOR)\n" - "{\n" - " vPosition = mul(float4(aPosition, 1.f), wvp);\n" - " vColor = float4(aColor, 1.f);\n" - "}" - ; - -void saveGXP(SceGxmProgram *p, uint32_t size, const char *fname) { - FILE *f = fopen(fname, "wb"); - fwrite(p, 1, size, f); - fclose(f); -} - -int main() { - // Initializing vitaShaRK - if (shark_init(NULL) < 0) // NOTE: libshacccg.suprx will need to be placed in ur0:data - return -1; - - // Compiling fragment shader - uint32_t size = sizeof(fragment_shader) - 1; - SceGxmProgram *p = shark_compile_shader(fragment_shader, &size, SHARK_FRAGMENT_SHADER); - - // Saving compiled GXP file on SD - if (p) saveGXP(p, size, "ux0:data/clear_f.gxp"); - - shark_clear_output(); - - // Compiling vertex shader - size = sizeof(vertex_shader) - 1; - p = shark_compile_shader(vertex_shader, &size, SHARK_VERTEX_SHADER); - - // Saving compiled GXP file on SD - if (p) saveGXP(p, size, "ux0:data/rgb_v.gxp"); - - shark_clear_output(); - - shark_end(); - - return 0; -} diff --git a/deps/vitaShaRK/samples/sample2/Makefile b/deps/vitaShaRK/samples/sample2/Makefile deleted file mode 100644 index e41643545a..0000000000 --- a/deps/vitaShaRK/samples/sample2/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -SAMPLE_NUM := 002 -TARGET := vitaShaRK-Sample$(SAMPLE_NUM) -SOURCES := . - -INCLUDES := include - -LIBS = -lvitashark -lSceLibKernel_stub -lSceShaccCg_stub - -CFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.c)) -CPPFILES := $(foreach dir,$(SOURCES), $(wildcard $(dir)/*.cpp)) -BINFILES := $(foreach dir,$(DATA), $(wildcard $(dir)/*.bin)) -OBJS := $(addsuffix .o,$(BINFILES)) $(CFILES:.c=.o) $(CPPFILES:.cpp=.o) - -PREFIX = arm-vita-eabi -CC = $(PREFIX)-gcc -CXX = $(PREFIX)-g++ -CFLAGS = -g -Wl,-q -O2 -ftree-vectorize -CXXFLAGS = $(CFLAGS) -fno-exceptions -std=gnu++11 -fpermissive -ASFLAGS = $(CFLAGS) - -all: $(TARGET).vpk - -$(TARGET).vpk: eboot.bin - vita-mksfoex -s TITLE_ID=VSHARK$(SAMPLE_NUM) "$(TARGET)" param.sfo - vita-pack-vpk -s param.sfo -b eboot.bin $@ - -eboot.bin: $(TARGET).velf - vita-make-fself -s $< eboot.bin - -%.velf: %.elf - vita-elf-create $< $@ - -$(TARGET).elf: $(OBJS) - $(CC) $(CFLAGS) $^ $(LIBS) -o $@ - -clean: - @rm -rf *.velf *.elf *.vpk $(OBJS) param.sfo eboot.bin diff --git a/deps/vitaShaRK/samples/sample2/main.c b/deps/vitaShaRK/samples/sample2/main.c deleted file mode 100644 index 0d585e0201..0000000000 --- a/deps/vitaShaRK/samples/sample2/main.c +++ /dev/null @@ -1,85 +0,0 @@ -// Simple compiler with file logging - -#include -#include -#include - -const char fragment_shader[] = - "float4 main(uniform float4 u_clear_color) : COLOR\n" - "{\n" - " return u_clear_color;\n" - "}" - ; - -const char vertex_shader[] = - "void main(\n" - "float3 aPosition,\n" - "float3 aColor,\n" - "uniform float4x4 wvp,\n" - "float4 out vPosition: POSITION,\n" - "float4 out vColor: COLOR)\n" - "{\n" - " vPosition = mul(float4(aPosition, 1.f), wvp);\n" - " vColor = float4(aColor, 1.f);\n" - "}" - ; - -char curr_compilation[256]; - -void log_cb(const char *msg, shark_log_level msg_level, int line) { - FILE *f = fopen("ux0:/data/shark.log", "a+"); - switch (msg_level) { - case SHARK_LOG_INFO: - fprintf(f, "%s) INFO: %s at line %d\n", curr_compilation, msg, line); - break; - case SHARK_LOG_WARNING: - fprintf(f, "%s) WARNING: %s at line %d\n", curr_compilation, msg, line); - break; - case SHARK_LOG_ERROR: - fprintf(f, "%s) ERROR: %s at line %d\n", curr_compilation, msg, line); - break; - default: - break; - } - fclose(f); -} - -void saveGXP(SceGxmProgram *p, uint32_t size, const char *fname) { - FILE *f = fopen(fname, "wb"); - fwrite(p, 1, size, f); - fclose(f); -} - -int main() { - // Initializing vitaShaRK - if (shark_init(NULL) < 0) // NOTE: libshacccg.suprx will need to be placed in ur0:data - return -1; - - // Setting up logger - shark_install_log_cb(log_cb); - shark_set_warnings_level(SHARK_WARN_MAX); - - // Compiling fragment shader - sprintf(curr_compilation, "clear_f.gxp"); - uint32_t size = sizeof(fragment_shader) - 1; - SceGxmProgram *p = shark_compile_shader(fragment_shader, &size, SHARK_FRAGMENT_SHADER); - - // Saving compiled GXP file on SD - if (p) saveGXP(p, size, "ux0:data/clear_f.gxp"); - - shark_clear_output(); - - // Compiling vertex shader - sprintf(curr_compilation, "rgb_v.gxp"); - size = sizeof(vertex_shader) - 1; - p = shark_compile_shader(vertex_shader, &size, SHARK_VERTEX_SHADER); - - // Saving compiled GXP file on SD - if (p) saveGXP(p, size, "ux0:data/rgb_v.gxp"); - - shark_clear_output(); - - shark_end(); - - return 0; -} diff --git a/deps/vitaShaRK/source/vitashark.c b/deps/vitaShaRK/source/vitashark.c deleted file mode 100644 index 96a6c719aa..0000000000 --- a/deps/vitaShaRK/source/vitashark.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of vitaGL - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * Copyright 2020 Asakura Reiko - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "vitashark.h" -#include -#include "shacccg.h" - -// Default path for SceShaccCg module location -#define DEFAULT_SHACCCG_PATH "ur0:/data/libshacccg.suprx" - -static void (*shark_log_cb)(const char *msg, shark_log_level msg_level, int line) = NULL; -static shark_warn_level shark_warnings_level = SHARK_WARN_SILENT; - -static SceUID shark_module_id = 0; -static uint8_t shark_initialized = 0; -static SceShaccCgCompileOutput *shark_output = NULL; -static SceShaccCgSourceFile shark_input; - -// Dummy Open File callback -static SceShaccCgSourceFile *shark_open_file_cb(const char *fileName, - const SceShaccCgSourceLocation *includedFrom, - const SceShaccCgCompileOptions *compileOptions, - const char **errorString) -{ - return &shark_input; -} - -int shark_init(const char *path) { - // Initializing sceShaccCg module - if (!shark_initialized) { - shark_module_id = sceKernelLoadStartModule(path ? path : DEFAULT_SHACCCG_PATH, 0, NULL, 0, NULL, NULL); - if (shark_module_id < 0) return -1; - sceShaccCgSetDefaultAllocator(malloc, free); - shark_initialized = 1; - } - return 0; -} - -void shark_end() { - if (!shark_initialized) return; - - // Terminating sceShaccCg module - sceKernelStopUnloadModule(shark_module_id, 0, NULL, 0, NULL, NULL); - shark_initialized = 0; -} - -void shark_install_log_cb(void (*cb)(const char *msg, shark_log_level msg_level, int line)) { - shark_log_cb = cb; -} - -void shark_set_warnings_level(shark_warn_level level) { - // Changing current warnings level - shark_warnings_level = level; -} - -void shark_clear_output() { - // Clearing sceShaccCg output - if (shark_output) { - sceShaccCgDestroyCompileOutput(shark_output); - shark_output = NULL; - } -} - -SceGxmProgram *shark_compile_shader_extended(const char *src, uint32_t *size, shark_type type, shark_opt opt, int32_t use_fastmath, int32_t use_fastprecision, int32_t use_fastint) { - if (!shark_initialized) return NULL; - - // Forcing usage for memory source for the shader to compile - shark_input.fileName = ""; - shark_input.text = src; - shark_input.size = *size; - - // Properly configuring SceShaccCg with requqested settings - SceShaccCgCompileOptions options = {0}; - options.mainSourceFile = shark_input.fileName; - options.targetProfile = type; - options.entryFunctionName = "main"; - options.macroDefinitions = NULL; - options.useFx = 1; - options.warningLevel = shark_warnings_level; - options.optimizationLevel = opt; - options.useFastmath = use_fastmath; - options.useFastint = use_fastint; - options.useFastprecision = use_fastprecision; - options.pedantic = shark_warnings_level > SHARK_WARN_MEDIUM ? SHARK_ENABLE : SHARK_DISABLE; - options.performanceWarnings = shark_warnings_level > SHARK_WARN_SILENT ? SHARK_ENABLE : SHARK_DISABLE; - - // Executing shader compilation - SceShaccCgCallbackList callbacks = {0}; - sceShaccCgInitializeCallbackList(&callbacks, SCE_SHACCCG_TRIVIAL); - callbacks.openFile = shark_open_file_cb; - const SceShaccCgCompileOutput *shark_output = sceShaccCgCompileProgram(&options, &callbacks, 0); - - // Executing logging - if (shark_log_cb) { - for (int i = 0; i < shark_output->diagnosticCount; ++i) { - const SceShaccCgDiagnosticMessage *log = &shark_output->diagnostics[i]; - shark_log_cb(log->message, log->level, log->location->lineNumber); - } - } - - // Returning output - if (shark_output->programData) *size = shark_output->programSize; - return (SceGxmProgram *)shark_output->programData; -} - -SceGxmProgram *shark_compile_shader(const char *src, uint32_t *size, shark_type type) { - return shark_compile_shader_extended(src, size, type, SHARK_OPT_DEFAULT, SHARK_DISABLE, SHARK_DISABLE, SHARK_DISABLE); -} diff --git a/deps/vitaShaRK/source/vitashark.h b/deps/vitaShaRK/source/vitashark.h deleted file mode 100644 index 61d1966084..0000000000 --- a/deps/vitaShaRK/source/vitashark.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of vitaShaRK - * Copyright 2017, 2018, 2019, 2020 Rinnegatamante - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation, version 3 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _VITASHARK_H_ -#define _VITASHARK_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -typedef enum shark_opt { - SHARK_OPT_SLOW, //!< Equivalent to O0 - SHARK_OPT_SAFE, //!< Equivalent to O1 - SHARK_OPT_DEFAULT, //!< Equivalent to O2 - SHARK_OPT_FAST, //!< Equivalent to O3 - SHARK_OPT_UNSAFE //!< Equivalent to Ofast -} shark_opt; - -typedef enum shark_type { - SHARK_VERTEX_SHADER, - SHARK_FRAGMENT_SHADER -} shark_type; - -typedef enum shark_log_level { - SHARK_LOG_INFO, - SHARK_LOG_WARNING, - SHARK_LOG_ERROR -} shark_log_level; - -typedef enum shark_warn_level { - SHARK_WARN_SILENT, - SHARK_WARN_LOW, - SHARK_WARN_MEDIUM, - SHARK_WARN_HIGH, - SHARK_WARN_MAX -} shark_warn_level; - -#define SHARK_DISABLE 0 -#define SHARK_ENABLE 1 - -// Init/term routines -int shark_init(const char *path); //!< Initializes runtime shader compiler -void shark_end(); //!< Terminates runtime shader compiler and frees used memory - -// Compiling routines -SceGxmProgram *shark_compile_shader_extended(const char *src, uint32_t *size, shark_type type, shark_opt opt, int32_t use_fastmath, int32_t use_fastprecision, int32_t use_fastint); //!< Compiles a shader with extended settings -SceGxmProgram *shark_compile_shader(const char *src, uint32_t *size, shark_type type); //!< Compiles a shader -void shark_clear_output(); //!< Clears output of a compilation attempt - -// Logging routines -void shark_install_log_cb(void (*cb)(const char *msg, shark_log_level msg_level, int line)); //!< Installs a log function for info, warnings and errors -void shark_set_warnings_level(shark_warn_level level); //!< Sets warnings level for logging - -#ifdef __cplusplus -} -#endif - -#endif