Compare commits

..

665 Commits

Author SHA1 Message Date
mrq
2601afb5f3 experimental support for parsing from a float16 mesh (or a float32-quantized-as-ushort mesh) 2023-10-26 13:22:47 -05:00
Luke Benstead
0efe4c6cef Add missing defines 2023-10-19 22:26:13 +01:00
Luke Benstead
744dfb32f7 Merge branch 'fix-glshort-uv-read' into 'master'
Convert GL_SHORT to proper float on conversion

See merge request simulant/GLdc!109
2023-09-26 18:51:30 +00:00
Spencer Elliott
79172452f2 Convert GL_SHORT to proper float on conversion 2023-09-26 18:51:29 +00:00
Luke Benstead
420e2d75f2 Merge branch 'fix-glulookat-alignment' into 'master'
Fixed alignment for matrix passed into UploadMatrix4x4 in gluLookAt

See merge request simulant/GLdc!108
2023-09-20 15:47:38 +00:00
Spencer Elliott
202f546848 Fixed alignment for matrix passed into UploadMatrix4x4 in gluLookAt 2023-09-20 10:18:55 -05:00
Luke Benstead
d054dde785 Fix paletted texture glitch 2023-09-12 21:11:05 +01:00
Luke Benstead
00b4468928 Remove unused function 2023-09-11 20:42:09 +01:00
Luke Benstead
f0d799d14f Merge branch 'texture-refactor' into 'master'
Drastically refactor glTexImage2D

See merge request simulant/GLdc!107
2023-09-11 19:39:03 +00:00
Luke Benstead
1bf8554926 More erquirements 2023-09-11 20:34:18 +01:00
Luke Benstead
9bc6da9fba Add some requirements 2023-09-11 19:55:26 +01:00
Luke Benstead
a1536cba44 Add dependency 2023-09-11 17:31:08 +01:00
Luke Benstead
3eee140add Fix stage 2023-09-11 17:29:59 +01:00
Luke Benstead
43d64a4957 Fix twiddling issues 2023-09-11 17:27:04 +01:00
Luke Benstead
951ece6d19 Add test job to CI 2023-09-11 17:25:47 +01:00
Luke Benstead
61e5a7a2a6 More twiddling work 2023-09-10 19:41:25 +01:00
Luke Benstead
3308a57e59 Implement defragmenting the memory 2023-09-08 17:49:46 +01:00
Luke Benstead
db9e1cd424 Fall back to unaligned if there's no more aligned spaced 2023-09-08 09:13:33 +01:00
Luke Benstead
6eb079228e Fix infinite loop 2023-09-06 21:01:37 +01:00
Luke Benstead
7ce01ad93f Fix up paletted textures 2023-09-06 08:01:01 +01:00
Luke Benstead
12bd6f474f Fix issues with the allocator 2023-09-06 07:59:40 +01:00
Luke Benstead
e5a4f4f716 Continue fixing up paletted texture issues 2023-09-03 21:12:11 +01:00
Luke Benstead
4d39e19ed5 Start repairing paletted textures 2023-09-02 21:10:42 +01:00
Luke Benstead
49a0e103cb Fix up CI 2023-09-01 20:34:29 +01:00
Luke Benstead
9cedc81850 Fix broken merge 2023-09-01 20:29:24 +01:00
Luke Benstead
0e31aa3d27 Tweak 2023-09-01 20:25:27 +01:00
Luke Benstead
5e7b33797d Perf improvements and fixes 2023-09-01 20:25:27 +01:00
Luke Benstead
b19b9d498a Clean up the allocator code 2023-09-01 20:25:21 +01:00
Luke Benstead
36de063756 Allow configuring automatic texture twiddling in glKosInitEx
Defaults to enabled.
2023-09-01 20:23:55 +01:00
Luke Benstead
246cb997da Add optional dcprof to prof_texture_upload 2023-09-01 20:23:55 +01:00
Luke Benstead
cfbaea4a46 Don't calculate things twice 2023-09-01 08:52:01 +01:00
Luke Benstead
4b47f6878f Remove yalloc 2023-09-01 08:34:48 +01:00
Luke Benstead
3248499d5a Switch to the new allocator 2023-08-31 21:21:14 +01:00
Luke Benstead
fd9a9d1c25 Merge commit 'f49a98ab543b1be0049e07456fb23022435ba450' into texture-refactor 2023-08-31 20:49:42 +01:00
Luke Benstead
f49a98ab54 Fix allocate and free 2023-08-31 20:49:34 +01:00
Luke Benstead
f278777c0e WIP: Start implementing new allocator 2023-08-31 08:47:00 +01:00
Luke Benstead
34173d926c Drastically refactor glTexImage2D 2023-08-31 08:47:00 +01:00
Luke Benstead
77531ca347 Drastically refactor glTexImage2D 2023-08-26 20:34:11 +01:00
Luke Benstead
a05e1b01fa Make glGenerateMipmap the function, and EXT the alias 2023-07-26 20:33:12 +01:00
Luke Benstead
3dcbbdbde6 Add logging 2023-06-09 20:35:00 +01:00
Luke Benstead
92ee4f616d Set mode to PAL@50 if it's a European console without VGA 2023-06-06 21:05:52 +01:00
Luke Benstead
e7574bca1d Fix issues with GL_QUADS 2023-05-31 18:27:17 +01:00
Luke Benstead
026bdeff09 Fix infuriating memory corruption bug 2023-05-20 07:47:39 +01:00
Luke Benstead
f6713bc778 Speed up the software renderer 2023-05-20 07:45:45 +01:00
Luke Benstead
5865d57384 Wait for the store queues to finish when we've uploaded everything 2023-05-20 07:45:16 +01:00
Luke Benstead
1e3896e699 Clean up 2023-05-20 07:44:55 +01:00
Luke Benstead
bd47f333d6 Add more assertions 2023-05-20 07:43:57 +01:00
Luke Benstead
e57b503355 Fix memory errors 2023-05-18 16:44:11 +01:00
Luke Benstead
d81472ef57 Liberally assert stuff 2023-05-17 20:39:58 +01:00
Luke Benstead
462eb40d7a Fix bugs in texture deletion 2023-05-17 20:39:49 +01:00
Luke Benstead
c4c0bf4239 Fix an off-by-one error 2023-05-17 20:39:27 +01:00
Luke Benstead
9037d157d5 Clean up 2023-05-17 20:38:21 +01:00
Luke Benstead
52a0215ed8 Make sure we initialize texture 0. We don't actually use it yet
(binding zero disables texturing) but I believe the spec says that
texture 0 is the "default texture" and is an actual texture object.
2023-05-17 20:36:59 +01:00
Luke Benstead
a5891056db Many bug fixes and optimisations 2023-05-16 13:31:44 +01:00
Luke Benstead
9cffe14ad6 Clean up aligned vector 2023-05-12 20:51:36 +01:00
Luke Benstead
e683b8becb Optimisations 2023-05-11 20:00:13 +01:00
Luke Benstead
cba2fb7ceb Fix a memory corruption issue 2023-05-11 15:22:46 +01:00
Luke Benstead
c754c5c338 Ensure RelWithDebInfo builds use release flags + debugging 2023-05-11 15:22:27 +01:00
Luke Benstead
452cda5a3b Fix backface culling 2023-04-28 19:49:01 +01:00
Luke Benstead
9e1b1bc40a Merge branch 'clipping-rewrite-for-the-last-time-ffs' into 'master'
Restructure clipping to be much MUCH faster in the visible case

See merge request simulant/GLdc!105
2023-04-26 20:00:17 +00:00
Luke Benstead
0f65eab86a Much faster clipping 2023-04-26 20:50:43 +01:00
Luke Benstead
1a678d2c8d Undo some bad changes 2023-04-23 21:00:01 +01:00
Luke Benstead
0923b5c601 Further optimisations 2023-04-23 20:16:15 +01:00
Luke Benstead
2ec7055547 Optimisations 2023-04-23 07:44:09 +01:00
Luke Benstead
9cc52a01fe Better clipping 2023-04-22 20:47:45 +01:00
Luke Benstead
095ebf2790 Fix final bug 2023-04-22 11:37:42 +01:00
Luke Benstead
baa275b41b Fix a bunch of issues with clipping (almost working) 2023-04-21 20:38:21 +01:00
Luke Benstead
72c375f87c Fix some things 2023-04-21 11:39:37 +01:00
Luke Benstead
e54494e995 More clipping work 2023-04-20 20:45:59 +01:00
Luke Benstead
c5ce81a38d WIP: Restructure clipping to be much MUCH faster in the visible case
This currently only works with triangles, anything more and it crashes
due to me not queuing subsequent vertices in the strip correctly
2023-04-19 20:57:44 +01:00
Luke Benstead
34448939a4 Merge branch 'update-cubes-cmakelists' into 'master'
Update cubes sample + cmakelists

See merge request simulant/GLdc!104
2023-04-17 18:24:56 +00:00
Dave
b6249e9ca4 Update README 2023-04-17 19:35:06 +02:00
Dave
1a181f702c Update CMakeLists with CXX flags (Debug and Release) 2023-04-17 19:34:56 +02:00
Dave
3b53691e4b Change float colors to GLubyte in cubes sample 2023-04-17 19:33:59 +02:00
Luke Benstead
25d215dad3 Add some compiler flags for lolz 2023-04-11 20:46:44 +01:00
Luke Benstead
307d371c55 Various store queue shinanigans 2023-04-11 20:46:31 +01:00
Luke Benstead
4ad58bea89 Optimise glLoadMatrixf 2023-04-11 20:46:12 +01:00
Luke Benstead
8e60b18f29 Merge branch 'add-new-cubes-sample' into 'master'
Add new cubes sample

See merge request simulant/GLdc!103
2023-04-08 20:32:18 +00:00
David Reichelt
190b4ecfb7 Add include for printf 2023-04-08 20:07:21 +00:00
David Reichelt
a4b778063a Make sure ZNEAR_CLIPPING_ENABLED is defined in software renderer 2023-04-08 20:00:33 +00:00
Dave Reichelt
df9a12bbd6 Added new cubes sample
- A button toggles between glDrawElements and glDrawArrays
- B button toggles glBlend
- Start quits the sample
- Every 10 seconds a log with stats will be sent to the terminal
2023-04-08 21:42:03 +02:00
Luke Benstead
6ee9a823c1 Don't update lights unnecessarily 2023-03-23 20:01:41 +00:00
Luke Benstead
0c5f941098 Optimise nearz clipping 2023-03-17 20:40:55 +00:00
Luke Benstead
300f2a611e Optimise state management 2023-03-17 20:40:45 +00:00
Luke Benstead
e810d2567d Merge commit 'e5c6fefcd92cb6e877e8501c4b43cbf75460409d' 2023-03-16 21:24:22 +00:00
Luke Benstead
e5c6fefcd9 Optimisations 2023-03-16 21:24:12 +00:00
Luke Benstead
0cf006ebce Merge branch 'bug-fixes' into 'master'
Fix elf extension and compilation with GCC4.7

See merge request simulant/GLdc!100
2023-03-07 21:40:54 +00:00
Luke Benstead
8789d6557e Huge refactor of internal state 2023-03-07 21:27:48 +00:00
Luke Benstead
8beb295c6b Refactor state management 2023-03-07 10:19:09 +00:00
Luke Benstead
c195d471e1 Faster memcpy 2023-03-06 14:05:14 +00:00
Luke Benstead
be4c1bc14c Add missing header 2023-03-06 13:54:31 +00:00
Luke Benstead
a9f3e3a744 Fix alignments 2023-03-06 13:44:17 +00:00
Luke Benstead
f0a3465486 Use Moops memcpy 2023-03-05 21:16:12 +00:00
Luke Benstead
b08bbebf12 Mipmap fix 2023-03-05 20:26:15 +00:00
falco
e27c276daa Fixed poly/tri/quadmarks to build with GCC12
"start" is a reserved symbol within KOS, per crt1.s. Not sure why the old toolchains let us use this symbol name elsewhere, but the new GCC12 toolchain rightfully complains about duplicate symbols.

- Renamed "start" timestamp to "begin."
2023-03-04 17:35:17 -06:00
Colton Pawielski
5bb2691b91 Change CMakeLists.txt to add -mfsrra and -mfsca only if supported by compiler
GCC4.7 does not support these flags and cause a failure to build
2023-03-04 16:13:44 -06:00
Colton Pawielski
ac6914398c Fix .elf extension on C example executables 2023-03-04 16:11:11 -06:00
Colton Pawielski
8481fd05cc Add dcbuild & pcbuild folders to .gitignore 2023-03-04 16:10:34 -06:00
Luke Benstead
19288918f0 Merge branch 'Declare_glFogiv' into 'master'
declare glFogiv()

See merge request simulant/GLdc!95
2023-02-02 11:58:35 +00:00
Luke Benstead
8fff6ee1aa Treat GL_CLAMP_TO_EDGE the same as GL_CLAMP 2022-12-09 20:17:46 +00:00
Luke Benstead
ac86504549 Clean up 2022-12-03 20:01:43 +00:00
Luke Benstead
d78c6275bb Increase tri-strip length 2022-12-03 14:00:24 +00:00
Luke Benstead
69a2310a3c Default to small culling to avoid artifacts 2022-12-03 13:46:08 +00:00
Luke Benstead
5296f5c79c Optimise perspective divide assuming W is always positive 2022-11-05 20:28:24 +00:00
Luke Benstead
aa875ae4d1 Fix compiler flags 2022-11-04 19:34:42 +00:00
Luke Benstead
7db15a0e03 Fix PC build 2022-11-04 19:25:50 +00:00
Luke Benstead
b6593acc83 Switches instead of if ladders 2022-11-04 19:24:12 +00:00
Luke Benstead
8ca70a2920 Initialize submission target on boot to save runtime cost 2022-11-04 19:23:50 +00:00
Luke Benstead
4d8c507706 Fix a bug where glXPointer functions would do unnecessary work 2022-11-04 19:23:06 +00:00
Luke Benstead
a248f3a50c Faster inversion 2022-11-03 20:24:38 +00:00
Luke Benstead
6be3e6185d Faster inversion 2022-09-14 19:20:24 +01:00
Luke Benstead
3caaf798e7 Undo double transform 2022-08-25 21:25:52 +01:00
Luke Benstead
0b62ac8673 Clean ups and optimisations 2022-08-25 21:24:08 +01:00
Luke Benstead
4edf8ce04d Use the direct texture path for vbuffer uploads 2022-08-25 20:01:54 +01:00
Luke Benstead
c793e1f35d Don't submit empty lists 2022-08-24 20:31:55 +01:00
Luke Benstead
9b9db31f30 Merge branch 'super-clip' into 'master'
Super clip

See merge request simulant/GLdc!99
2022-06-13 19:26:55 +00:00
Luke Benstead
9d9a502e96 Remove old clipping 2022-06-13 20:16:46 +01:00
Luke Benstead
3d69003c5f Allow disabling near-z 2022-06-13 20:16:37 +01:00
Luke Benstead
99ae70a72b Make the software implementation use the same clipping code 2022-06-13 20:06:04 +01:00
Luke Benstead
6fb15ee4c7 Fix some winding issues 2022-06-13 20:05:54 +01:00
Luke Benstead
b17104afea Add a missing header 2022-06-13 20:05:39 +01:00
Luke Benstead
16f6100afa Fix issues and optimise 2022-06-12 19:53:26 +01:00
Luke Benstead
4827fd4c5b Fix various clipping glitches 2022-06-11 21:27:09 +01:00
Luke Benstead
53c54997c3 Fix a number of issues! 2022-06-10 20:27:21 +01:00
Luke Benstead
68c6936b25 Add nehe10 sample 2022-06-10 20:26:51 +01:00
Luke Benstead
dbb94d0cb9 Move clipping into list submission 2022-06-09 13:07:51 +01:00
Luke Benstead
193f0bdc49 Cleanup 2022-05-21 20:16:50 +01:00
Luke Benstead
9a50917062 Fix rgba vs argb inversion 2022-05-21 20:16:34 +01:00
Luke Benstead
83e325ab3c Fix CMake 32bit issues 2022-05-21 20:16:26 +01:00
Luke Benstead
0060f48202 Fix compilation issues on PC vs DC 2022-05-21 20:16:12 +01:00
Luke Benstead
fe7f9cbed0 Fix crash when generating mipmaps on 4bpp textures 2022-05-07 12:57:45 +01:00
Luke Benstead
3d1f447af9 Merge branch 'paletted-textures' into 'master'
4BPP paletted textures and OES_compressed_paletted_texture support

See merge request simulant/GLdc!98
2022-05-04 20:05:24 +00:00
Luke Benstead
d0e6b56414 Restore validation of the internalFormat (even though it's unused) 2022-05-04 21:00:15 +01:00
Luke Benstead
dc69a81da1 Remove unused code. Various clean ups 2022-05-04 20:53:18 +01:00
Luke Benstead
411d4f0e4f Add a missing space 2022-05-04 20:45:21 +01:00
Luke Benstead
dd7bb47ffb Merge remote-tracking branch 'ozzyouzo/master' into paletted-textures 2022-05-04 20:39:39 +01:00
Luke Benstead
46605c6b1a Merge branch 'Avoid_gl_h_Function_is_not_a_prototype_warning' into 'master'
gl.h: avoid gcc warning "function declaration isn’t a prototype"

See merge request simulant/GLdc!97
2022-05-04 19:20:13 +00:00
OzzyOuzo
c48bbfe07c Fixed glMultMatrixf(...)
Added _glResetSharedPalettes
2022-05-03 16:12:27 +03:00
Luke Benstead
4e8ff2f8e4 Fix texture issues 2022-04-26 20:34:14 +01:00
T_chan
cd14a5ed11 gl.h: avoid gcc warning "function declaration isn’t a prototype" 2022-02-07 16:09:00 +00:00
Luke Benstead
6f2b4d8f9f Merge branch 'Add_missing_gl_h_defines' into 'master'
Add some missing gl.h defines for portability

See merge request simulant/GLdc!96
2022-02-07 15:48:26 +00:00
T_chan
2d63fdf30f Add some missing gl.h defines for portability 2022-02-07 15:36:16 +00:00
T_chan
3160fc517d declare glFogiv() 2022-02-02 09:22:23 +00:00
Luke Benstead
774a956012 Merge branch 'refactor_nehe08' into 'master'
refactor nehe08 slightly

See merge request simulant/GLdc!94
2022-02-01 09:00:46 +00:00
T_chan
bd507f38bd refactor nehe08 slightly 2022-02-01 08:48:31 +00:00
Luke Benstead
4ad5f00538 Merge branch 'Add_gluBuild2DMipmaps' into 'master'
Add gluBuild2DMipmaps()

See merge request simulant/GLdc!93
2022-02-01 08:28:40 +00:00
T_chan
53eb2e2a51 Add gluBuild2DMipmaps() 2022-02-01 07:25:54 +00:00
Luke Benstead
5be561ce4f Merge branch 'Correct_Sample_Files_Paths' into 'master'
samples: correct image  paths & include <math.h>

See merge request simulant/GLdc!92
2022-01-31 20:47:56 +00:00
T_chan
fdac490e34 samples: correct image paths & include <math.h> 2022-01-31 16:59:05 +00:00
Luke Benstead
f5436fd31b Merge branch 'Regroup_BMP_Loading' into 'master'
regroup the BMP file loading into 1 file, and correct some types that give...

See merge request simulant/GLdc!87
2022-01-31 10:30:26 +00:00
T_chan
ae3ebe2e5c regroup the BMP file loading into 1 file, and correct some types that give... 2022-01-31 10:30:26 +00:00
Luke Benstead
d7d8f4c4f1 Merge branch 'Samples_Make_Romdisk_Conditional' into 'master'
Include romdisk only if target is dreamcast

See merge request simulant/GLdc!86
2022-01-31 10:06:02 +00:00
Luke Benstead
12080967c2 Merge branch 'Fix_depth_funcs_ortho' into 'master'
fix depth_funcs_ortho - show blue and green quads

See merge request simulant/GLdc!88
2022-01-31 10:05:03 +00:00
Luke Benstead
80ca380a22 Merge branch 'Correct_Blend_Test' into 'master'
merge of blend_test and lerabot_blend_test, addition of 1 case, and...

See merge request simulant/GLdc!89
2022-01-31 10:04:50 +00:00
T_chan
ab627b5ef5 merge of blend_test and lerabot_blend_test, addition of 1 case, and... 2022-01-31 10:04:50 +00:00
Luke Benstead
bc422f1f47 Merge branch 'Correct_lerabot01' into 'master'
dont put objects on the far plane

See merge request simulant/GLdc!90
2022-01-31 10:04:24 +00:00
Luke Benstead
b3066f991c Merge branch 'Add_glGetTexImage_stub' into 'master'
Add glGetTexImage stub for portability

See merge request simulant/GLdc!91
2022-01-31 10:03:56 +00:00
T_chan
621982d14e Add glGetTexImage stub for portability 2022-01-31 08:29:00 +00:00
T_chan
23419bf57c dont put objects on the far plane 2022-01-26 19:46:31 +00:00
T_chan
7abd878e93 AS-IS, depth_funcs_ortho only displays 1 red quad. With the fix, the 2 other quads (blue, green) become visible again 2022-01-25 20:47:40 +00:00
T_chan
0c8e11c02a Include romdisk only if target is dreamcast 2022-01-25 14:41:55 +00:00
Luke Benstead
9506237c47 Merge branch 'Solve_Warnings' into 'master'
Solve some warnings from the compilation

See merge request simulant/GLdc!83
2022-01-25 13:44:09 +00:00
Luke Benstead
e2da03ac74 Merge branch 'Remove_mipmapping_from_Nehe06' into 'master'
Remove mipmapping from Nehe06

See merge request simulant/GLdc!84
2022-01-25 13:43:49 +00:00
Luke Benstead
705cb30be8 Merge branch 'Solve_Sample_Warnings' into 'master'
solve 4 warnings about printf & long unsigned values vs %d

See merge request simulant/GLdc!85
2022-01-25 13:43:30 +00:00
T_chan
37e407d032 solve 4 warnings about printf & long unsigned values vs %d 2022-01-25 13:35:24 +00:00
T_chan
f5b63bfc97 Remove mipmapping from Nehe06 2022-01-23 13:07:58 +00:00
T_chan
b1508be822 Solve some warnings from the compilation 2022-01-20 22:42:08 +00:00
Luke Benstead
4ad2841809 Merge branch 'Add_glTexCoord1f_functions' into 'master'
Add glTexCoord1f() and glTexCoord1fv()

See merge request simulant/GLdc!80
2022-01-19 08:05:59 +00:00
Luke Benstead
cfbd126f58 Merge branch 'Add_GL_LINE_SMOOTH' into 'master'
Add GL_LINE_SMOOTH to increase portability

See merge request simulant/GLdc!82
2022-01-19 08:05:31 +00:00
Luke Benstead
ea44f21c04 Merge branch 'T_chan-master-patch-83707' into 'master'
remove duplicate defines from gl.h

See merge request simulant/GLdc!81
2022-01-19 08:05:18 +00:00
T_chan
fb2e8d7d7e Update include/GL/gl.h 2022-01-19 06:55:33 +00:00
T_chan
72b115659a remove duplicate defines from gl.h 2022-01-19 06:50:11 +00:00
T_chan
9b6c2bbb21 Add glTexCoord1f() and glTexCoord1fv() 2022-01-18 21:40:31 +00:00
Luke Benstead
f9af9af567 Merge branch 'Add_glPolygonMode_Stub' into 'master'
add glPolygonMode() stub

See merge request simulant/GLdc!79
2022-01-18 21:38:31 +00:00
Luke Benstead
8d51579870 Merge branch 'Add_Stencil_Functions_Stubs' into 'master'
Add stubs for Stencil functions glStencilFunc() and glStencilOp()

See merge request simulant/GLdc!78
2022-01-18 21:37:56 +00:00
T_chan
50aee8a92c add glPolygonMode() stub 2022-01-18 21:28:07 +00:00
T_chan
66d87fb845 Add stubs for Stencil functions glStencilFunc() and glStencilOp() 2022-01-18 20:29:27 +00:00
Luke Benstead
6802f64725 Merge branch 'Add_PixelStore_parameters' into 'master'
Add PixelStore parameters for Read/DrawPixels to increase compatibility

See merge request simulant/GLdc!77
2022-01-18 19:25:56 +00:00
Luke Benstead
11860ba6e1 Merge branch 'add_glGetTexParameterfv_stub' into 'master'
Add glGetTexParameterfv() stub to increase compatibility

See merge request simulant/GLdc!76
2022-01-18 19:25:39 +00:00
Luke Benstead
3b320bf874 Merge branch 'add_glTexParameterf' into 'master'
expose and correct glTexParameterf()

See merge request simulant/GLdc!75
2022-01-18 19:25:20 +00:00
Luke Benstead
fbf322f470 Merge branch 'add_glColor4ubv' into 'master'
Add glColor4ubv() to increase compatibility of GLdc

See merge request simulant/GLdc!74
2022-01-18 19:25:02 +00:00
Luke Benstead
482ec8b270 Merge branch 'add_GLclampd' into 'master'
add GLclampd to increase compatibility of GLdc

See merge request simulant/GLdc!73
2022-01-18 19:24:11 +00:00
T_chan
fbe310f8d5 Add PixelStore parameters for Read/DrawPixels to increase compatibility 2022-01-18 18:09:44 +00:00
T_chan
d594eff3a6 Add glGetTexParameterfv() stub to increase compatibility 2022-01-18 17:38:14 +00:00
T_chan
0d60b318da expose and correct glTexParameterf() 2022-01-18 17:23:30 +00:00
T_chan
d9a2ed7892 Add glColor4ubv() to increase compatibility of GLdc 2022-01-18 17:06:26 +00:00
T_chan
a7762aa965 add GLclampd to increase compatibility of GLdc 2022-01-18 16:51:31 +00:00
OzzyOuzo
1a456cb1a7 16bit palette color format support, extended 64 shared palette slots (4bpp), GL_OES_compressed_paletted_texture support
GL_ERROR generated when texture size > 1024
2021-12-03 09:32:53 +02:00
OzzyOuzo
8caee68df5 added _glFreePaletteSlots(..) 2021-11-30 19:23:49 +02:00
OzzyOuzo
148962254a 4bpp texture palette support, modified paletted_pcx sampled (USE_16C_PALETTE) 2021-11-18 12:04:46 +02:00
OzzyOuzo
37110ba47f 4bpp texture palette support (GL_RGBA8 pal components), modified paletted_pcx sample (USE_16C_PALETTE) 2021-11-18 11:59:37 +02:00
Luke Benstead
b710a619d5 Fix issues with bilinear mipmapping 2021-10-25 19:04:58 +01:00
Luke Benstead
e225f54386 Fix bug when glVertexPointer etc. is called without client state enabled 2021-10-02 20:01:44 +01:00
Luke Benstead
5df2190536 Fix various bugs with non-fastpath rendering 2021-10-02 14:43:23 +01:00
Luke Benstead
458fb52efb Merge branch 'fix-ci' into 'master'
Fix ci

See merge request simulant/GLdc!72
2021-10-01 20:20:29 +00:00
Luke Benstead
cef1e852f4 Fix ci 2021-10-01 20:20:29 +00:00
Luke Benstead
7d82649a62 Be sure to restore the fast path flag in glEnd 2021-10-01 21:02:13 +01:00
Luke Benstead
ecc957bcbd Merge branch 'master' into 'master'
Avoid the need to hard-reset the Dreamcast to exit the samples - use the start button in all samples

See merge request simulant/GLdc!71
2021-10-01 19:57:33 +00:00
T_chan
830a985606 Avoid the need to hard-reset the Dreamcast to exit the samples - use the start button in all samples 2021-10-01 19:57:32 +00:00
Luke Benstead
6184208598 Don't include platform.h from aligned_vector.h 2021-09-18 17:40:10 +01:00
Luke Benstead
e26fae6d2e Remove debug logging 2021-09-18 14:37:28 +01:00
Luke Benstead
dd16530a1f Fix an assertion in debug, and building on PC 2021-09-18 14:36:47 +01:00
Luke Benstead
cf996b9e80 Add tri and quad fast paths 2021-09-14 19:36:42 +01:00
Luke Benstead
7992c89758 Fix perf hit 2021-09-14 09:20:00 +01:00
Luke Benstead
9c2907e41d Small optimisation 2021-09-13 19:57:46 +01:00
Luke Benstead
4ee9c3ee64 More optimisations 2021-09-13 19:35:53 +01:00
Luke Benstead
adce2c7538 Perf tweaks 2021-09-13 12:57:52 +01:00
Luke Benstead
52ff506397 Only recalc the fast path when pointers change 2021-09-13 10:40:25 +01:00
Luke Benstead
66d09e7d77 Error cleanup and immediate mode perf improvements 2021-09-13 10:29:04 +01:00
Luke Benstead
4adc49cd40 Optimisations 2021-09-12 15:04:52 +01:00
Luke Benstead
cb96769074 Fix incorrect usage of memset 2021-09-04 13:36:59 +01:00
Luke Benstead
3332dfa74a Handle running out of PVR memory correctly 2021-09-04 12:14:31 +01:00
Luke Benstead
efc75db05c Merge branch 'master' into 'master'
Enable building for sub-architecture naomi.

See merge request simulant/GLdc!70
2021-07-05 19:27:29 +00:00
T_chan
08eebfccc0 Enable building for sub-architecture naomi.
Tested with examples nehe02, nehe06, nehe08 - displays the same as on Dreamcast.
2021-07-05 19:12:10 +00:00
Luke Benstead
fc947c49f8 Performance improvements 2021-05-25 20:40:43 +01:00
Luke Benstead
f736332eb8 Always make sure we send opaque polys with one/zero blending 2021-05-23 20:58:29 +01:00
Luke Benstead
7376d3e625 Tweak toolchain fix 2021-05-23 13:25:52 +01:00
Luke Benstead
5d4f83c53a Tweak toolchain fix 2021-05-23 13:24:29 +01:00
Luke Benstead
3975c68c5e Try to fix toolchain file on Windows 2021-05-23 13:21:08 +01:00
Luke Benstead
a79c1dd753 Set the right depth mode when autosort is on 2021-05-23 13:19:54 +01:00
Luke Benstead
cde0abd18d Force the correct depth and blend modes with PT polys 2021-05-23 13:15:07 +01:00
Luke Benstead
0789ea99b3 Disable fast mode by default 2021-05-23 13:06:11 +01:00
Luke Benstead
f0383f8e1c Remove broken check 2021-05-16 20:33:49 +01:00
Luke Benstead
5ea4313d59 Fix software renderer 2021-05-14 21:58:54 +01:00
Luke Benstead
840ac7f0cd Merge branch 'master' into 'master'
Fix memory leaks in samples

See merge request simulant/GLdc!69
2021-05-14 14:11:03 +00:00
Colton Pawielski
3d6c756ab7 Fix memory leaks in samples
Add free to end of LoadGLTextures() to release image1 after use.
2021-05-14 08:57:10 -04:00
Luke Benstead
06529d4fe7 Perf tweaks 2021-05-08 14:38:55 +01:00
Luke Benstead
cfefce44a6 Add nehe20 sample 2021-05-08 14:17:57 +01:00
Luke Benstead
a98f22e3c9 Remove old Makefiles 2021-05-08 13:15:18 +01:00
Luke Benstead
cb9d699576 Use invW as the Z axis (abandon standards compliance for speed) 2021-05-01 14:32:16 +01:00
Luke Benstead
0a8d43d47b Add nehe08 sample 2021-04-30 20:47:33 +01:00
Luke Benstead
e67f1fb8f9 Don't transform the vertex again incorrectly. Optimise 2021-04-30 07:58:57 +01:00
Luke Benstead
d05c5b8353 Remove incorrect warning 2021-04-30 07:52:12 +01:00
Luke Benstead
fcbb6418d2 Perf improvements 2021-04-26 16:16:25 +01:00
Luke Benstead
5fc77887d0 Remove unnecessary branches 2021-04-25 15:27:04 +01:00
Luke Benstead
16243acd7b More immediate mode optimisation 2021-04-25 14:21:09 +01:00
Luke Benstead
1b6f543fab Slight optimisation 2021-04-25 13:33:24 +01:00
Luke Benstead
40678836e0 Refactor viewport handling 2021-04-25 13:05:56 +01:00
Luke Benstead
57bb8c65c5 Fix artifact path 2021-04-24 11:31:11 +01:00
Luke Benstead
22680e8cbd Store the release artifacts in CI 2021-04-23 09:11:13 +01:00
Luke Benstead
1f42838992 Fix incorrect glColorPointer stride 2021-04-23 09:09:25 +01:00
Luke Benstead
28c14fdb0e Add fast path for glDrawElements 2021-04-22 17:48:15 +01:00
Luke Benstead
bb53dad90d Merge remote-tracking branch 'origin/master' 2021-04-21 21:31:21 +01:00
Luke Benstead
a7858d1f00 Merge branch 'batched-arrays' into 'master'
New Fast Path

See merge request simulant/GLdc!68
2021-04-21 16:23:43 +00:00
Luke Benstead
df2d7a210c New Fast Path 2021-04-21 16:23:43 +00:00
Luke Benstead
5a9b7bb37e Force inline aligned vector functions 2021-04-20 16:49:00 +01:00
Luke Benstead
ea25251944 Optimisations 2021-04-20 16:08:58 +01:00
Luke Benstead
faf24ac61d Small optimisations 2021-04-20 09:07:14 +01:00
Luke Benstead
b6a5ac6ce6 Optimisation in aligned_vector_extend 2021-04-19 21:29:19 +01:00
Luke Benstead
38c7967ae2 Clean up some things 2021-04-19 21:23:23 +01:00
Luke Benstead
165318ea76 Use MATH_fmac 2021-04-19 21:12:46 +01:00
Luke Benstead
1a849c8b1c Minor optimisation 2021-04-19 21:08:09 +01:00
Luke Benstead
a3c4aaac8f Don't set a zero zclip value 2021-04-19 20:51:22 +01:00
Luke Benstead
8977fbf6e2 Compile quadmark on PC 2021-04-19 20:43:56 +01:00
Luke Benstead
b480c0a01f Fix optimisations 2021-04-19 20:21:46 +01:00
Luke Benstead
eb35d607b9 Immediate mode performance optimisation 2021-04-19 10:53:08 +01:00
Luke Benstead
778e9c4e64 Optimise CompilePolyHeader 2021-04-18 21:50:41 +01:00
Luke Benstead
ce9f3677f6 Immediate mode optimisation 2021-04-18 21:33:23 +01:00
Luke Benstead
7bcbb86e80 Align to 32 byte 2021-04-18 13:57:28 +01:00
Luke Benstead
9ca68de427 Force 32-byte allocations 2021-04-18 13:57:00 +01:00
Luke Benstead
1172086378 Add debug logging and assertions to make sure we use sq_cpy aligned 2021-04-15 21:31:48 +01:00
Luke Benstead
fc1a18e002 Merge branch 'scissor' into 'master'
Implement glScissor correctly

See merge request simulant/GLdc!67
2021-04-14 20:41:10 +00:00
Luke Benstead
f03f0e8f04 Implement glScissor correctly 2021-04-14 21:38:33 +01:00
Luke Benstead
7146ed303b Add some files 2021-04-14 08:36:46 +01:00
Luke Benstead
30d76eada9 Fix texture issues 2021-04-13 21:28:59 +01:00
Luke Benstead
448f9737c4 Update README 2021-04-10 13:15:46 +01:00
Luke Benstead
ebfcd31ea0 Update .gitignore 2021-04-10 13:00:59 +01:00
Luke Benstead
8fe7a8afdf Add missing header 2021-04-10 12:58:23 +01:00
Luke Benstead
3e0569c9b8 Merge branch 'x86' into 'master'
X86

See merge request simulant/GLdc!66
2021-04-09 15:24:48 +00:00
Luke Benstead
fe616028bb X86 2021-04-09 15:24:47 +00:00
Luke Benstead
03694d85bf Minor fixes 2021-04-03 21:15:03 +01:00
Luke Benstead
8ee28fdaac Merge branch 'yalloc' into 'master'
Add upstream yalloc allocator

See merge request simulant/GLdc!65
2021-02-20 15:12:14 +00:00
Luke Benstead
8408a36629 Implement GL_ATI_meminfo 2021-02-20 15:10:35 +00:00
Luke Benstead
9ed6c0209e Defrag and retry if allocating texture memory fails 2021-02-20 15:04:40 +00:00
Luke Benstead
f9b7cd7985 Add a custom extension to query and defragment texture memory 2021-02-19 21:28:31 +00:00
Luke Benstead
425a0c2af1 Switch to yalloc 2021-02-19 07:08:58 +00:00
Luke Benstead
ddf23974bd Apply tweaks to handle larger addresses (thanks @HaydenKow) 2021-02-18 20:55:03 +00:00
Luke Benstead
8a02ee55cc Add upstream yalloc allocator 2021-02-18 20:46:25 +00:00
Luke Benstead
8c187f67de Merge branch 'master' into 'master'
Fix glViewport()

See merge request simulant/GLdc!62
2020-10-07 07:10:09 +00:00
Andress Barajas
a37ae364f0 Flip Y 2020-10-06 22:44:09 -07:00
Andress Barajas
ee8df14426 Fix origin bot-left of glViewport 2020-10-06 20:07:11 -07:00
Luke Benstead
fc4b724cb1 Merge branch 'master' into 'master'
Do NULL check before access

See merge request simulant/GLdc!61
2020-10-04 06:24:15 +00:00
Andress Barajas
700b0c6389 Do NULL check before access 2020-10-03 16:36:54 -07:00
Luke Benstead
62088d3191 Merge branch 'BBHoodsta/GLdc-master' 2020-10-03 12:05:02 +01:00
Luke Benstead
cee1c87ed5 Fix issue with glRotate 2020-10-03 11:54:25 +01:00
Andress Barajas
9bb1c3a9e1 Added new nehe lessons 2020-10-03 00:27:11 -07:00
Andress Barajas
926961fe95 Remove DS_Store files 2020-10-02 19:51:21 -07:00
Andress Barajas
c6200e8391 Added more nehe samples 2020-10-02 19:37:13 -07:00
Andress Barajas
e7d2042916 Fixed glRotate 2020-10-02 19:31:22 -07:00
Luke Benstead
44155632c1 Add version template 2020-09-28 12:52:53 +00:00
Luke Benstead
e2d0ae25a0 Delete version.h 2020-09-28 12:52:33 +00:00
Luke Benstead
e54db74914 Add version template 2020-09-28 12:52:23 +00:00
Luke Benstead
7d4207eddb Fix errors with final Z coordinate 2020-05-24 09:55:13 +01:00
Luke Benstead
d932811be4 Small optimisation 2020-05-22 07:32:02 +01:00
Luke Benstead
9bfb0c6eea Fix bug from last commit, don't apply lights at all if none are enabled 2020-05-22 07:20:08 +01:00
Luke Benstead
0a92240c64 More lighting optimisations 2020-05-21 20:14:43 +01:00
Luke Benstead
af82f7632f Fix default texture modulation 2020-05-19 21:27:34 +01:00
Luke Benstead
d6a22582f9 Small cleanup 2020-05-16 09:30:25 +01:00
Luke Benstead
29658ef3de Revert to more traditional GL depth values to fix ortho 2020-05-15 20:43:55 +01:00
Luke Benstead
17db29142a Merge branch 'master' into 'master'
SAMPLE : depth testing with ortho projection

See merge request simulant/GLdc!59
2020-05-15 19:20:09 +00:00
lerabot
3817101653 Added depth_func_ortho 2020-05-14 17:13:04 -04:00
Luke Benstead
64f2a57dd0 Tweak depth_funcs_alpha_testing sample to use glOrtho 2020-05-14 07:20:41 +01:00
Luke Benstead
06acff400c Fix the blend test sample. We're using a perspective projection where -Z goes into the screen, so we need to shift positive 2020-05-14 07:08:56 +01:00
Luke Benstead
db079fdc39 Remove .gch files 2020-05-14 07:05:47 +01:00
Luke Benstead
3945611509 Merge branch 'master' into 'experimental'
Added a new blend/alpha test

See merge request simulant/GLdc!57
2020-05-14 06:05:02 +00:00
lerabot
294819108d Merge branch 'master' of https://gitlab.com/simulant/GLdc 2020-05-13 19:05:29 -04:00
Luke Benstead
01cb46a99e Small tweak to lighting code 2020-05-13 21:04:24 +01:00
Luke Benstead
aa7320ab63 Use shifted invZ for Z to keep precision 2020-05-13 20:59:40 +01:00
lerabot
4e47b30b0a added a new depth/alpha testing sample 2020-05-13 10:34:18 -04:00
lerabot
bd59922052 updated makefile 2020-05-13 10:33:55 -04:00
lerabot
84f9711489 Updated the blend samples 2020-05-13 10:16:29 -04:00
Luke Benstead
2b9d8520bc Lighting perf improvements 2020-05-11 20:34:09 +01:00
Luke Benstead
d01b9fa85a Shift the range of final depth values so the minimum is 0.2 (KOS bgpoly depth) 2020-05-10 20:53:16 +01:00
Luke Benstead
c66f34cc62 Set Alpha flags when ALPHA_TEST is enabled 2020-05-10 13:49:45 +01:00
Luke Benstead
8e854ddef7 Fix overbright lighting 2020-05-09 06:33:28 +01:00
Luke Benstead
aa20bb20b2 Performance tweaks 2020-05-08 19:42:31 +01:00
Luke Benstead
1289a06279 Undo fmac which worked out slower 2020-05-08 13:53:56 +01:00
Luke Benstead
ab6725c5e3 Restore MAX_LIGHTS to 8 2020-05-08 10:00:03 +01:00
Luke Benstead
397d9d2915 More perf tweaks 2020-05-08 09:59:32 +01:00
Luke Benstead
8974051e38 Don't use memcpy when copying colours 2020-05-08 09:49:01 +01:00
Luke Benstead
cca09a298e Move enabled state onto the LightSource 2020-05-08 07:19:56 +01:00
Luke Benstead
814f228db9 Lighting optimisations 2020-05-07 20:58:24 +01:00
Luke Benstead
0a14db39a8 Improve the performance of _readVertexData1i3f 2020-05-06 20:15:28 +01:00
Luke Benstead
2d0e13b64e Merge branch 'refactor-draw' into 'master'
Refactor glDrawElements

See merge request simulant/GLdc!56
2020-05-06 14:29:50 +00:00
Luke Benstead
b3ded78897 Fix glDrawElements 2020-05-06 15:23:37 +01:00
Luke Benstead
177ad28219 More simplification 2020-05-06 08:42:09 +01:00
Luke Benstead
2c67560289 Refactor all the user-data reading code 2020-05-05 21:52:37 +01:00
Luke Benstead
40661e6823 Fix orthographic depth values (?) 2020-05-04 21:24:27 +01:00
Luke Benstead
5407e9643e Hacky fix for ortho projections 2020-04-07 20:44:29 +01:00
Luke Benstead
8add817086 Fix depth issues 2020-04-06 20:50:26 +01:00
Luke Benstead
f3b1848879 Merge branch 'master' of https://gitlab.com/simulant/GLdc 2020-04-05 21:13:07 +01:00
Luke Benstead
c3ae9bef64 Fix up depth functions and update sh4_math 2020-04-05 21:12:52 +01:00
Luke Benstead
9116332815 Merge branch 'einsteinx2/fix-makefile' into 'master'
Fixed Makefile GL/version.h (echo -e to printf)

See merge request simulant/GLdc!54
2020-04-05 19:13:46 +00:00
Ben Baron
0beaba5aeb Fixed Makefile GL/version.h (echo -e to printf)
The `echo -e` command is non-standard, and ends up printing a -e at the top of the version.h file. Switching it to `printf` works correctly and is the "correct" command to work in all shells.

I also removed the GL/version.h file from the git cache, as it's in .gitignore but seems to have been accidentally checked in.
2020-04-05 13:47:32 -05:00
Luke Benstead
ca7eb462fc Merge branch 'fix-clipping-2020' into 'master'
Fix clipping 2020

See merge request simulant/GLdc!53
2020-04-03 19:12:42 +00:00
Luke Benstead
cf90d10cb9 Fix clipping 2020 2020-04-03 19:12:42 +00:00
Luke Benstead
4292304df1 Implement glClearDepth 2020-03-24 13:58:44 +00:00
Luke Benstead
5c980d2183 Fix depth funcs (for now) 2020-03-23 15:22:29 +00:00
Luke Benstead
e21b7a0b9c Fix clipping 2020-03-23 13:44:24 +00:00
Luke Benstead
906423db08 Make sure we don't go beyond the bounds of PVR 2020-03-22 21:09:18 +00:00
Luke Benstead
a1eda16a26 Update SH4_math.h and stop storing the near plane 2020-03-21 21:21:46 +00:00
Luke Benstead
f2a39a4229 Implement true clipping on the near plane 2020-03-20 21:15:05 +00:00
Luke Benstead
03bc758be7 Allow enabling fsaa via the GLdcConfig struct 2020-03-18 20:47:12 +00:00
Luke Benstead
71c25829f1 Remove reference to private.h 2020-03-18 20:33:04 +00:00
Luke Benstead
921ef0c6a1 Fix clip distance 2020-03-17 20:32:14 +00:00
Luke Benstead
2f75ff8223 Merge branch 'kazade_patch_prepare' into 'master'
Kazade patch prepare

See merge request simulant/GLdc!52
2020-03-05 20:30:41 +00:00
Hayden Kowalchuk
f92030c0cb feat: error.c have PrintError reset error cond
- allows to continue finding errors instead of spamming the same error
2020-03-05 15:14:26 -05:00
Hayden Kowalchuk
ea3dec1daa feat: opengl headers expose new functionality 2020-03-05 15:13:30 -05:00
Hayden Kowalchuk
1c792df5ae fix: texture.c
- add const where needed
- move defines to private.h
- add vq offsets to mipmaplocation
- backend support for mipmap bias
- inline fixups
- have texture.c spit more helpful info on crash
- allow mipmap uploads to actuall complete
- note unused
2020-03-05 15:09:19 -05:00
Hayden Kowalchuk
35bbab8eee feat: state.c add GL_POLYGON_OFFSET, add mipmap bias
- implement simple GL_POLYGON_OFFSET implementation
- add mipmap bias as per OpenGL spec
- CLAMP gave warnings comparing unsigned to < 0
2020-03-05 15:04:44 -05:00
Hayden Kowalchuk
ddf61363a1 feat: add trimmed moop math header 2020-03-05 14:58:06 -05:00
Hayden Kowalchuk
a285c42c5f feat: make profiler compile time define 2020-03-05 14:57:51 -05:00
Hayden Kowalchuk
5a89fbcd7d fix: private.h
- add convenience defines
- note struct ordering and padding
- add const
2020-03-05 14:57:30 -05:00
Hayden Kowalchuk
bf00aca843 chore: lighting.c remove unused, add moop math
- remove unused bool
- move math func to header
- reorder const
2020-03-05 14:56:16 -05:00
Hayden Kowalchuk
87874f0f1f chore: immediate.c unused note 2020-03-05 14:54:07 -05:00
Hayden Kowalchuk
c842b6de48 chore: matrix.c unused notation, memcpy changes
- moved to memcpy4
- removed unused arrays
- moved to proper glDepthRangef signature
- rewrote gluLookAt for current and future gcc
2020-03-05 14:53:48 -05:00
Hayden Kowalchuk
651351f087 fix: glu.c changed to float, reordered math 2020-03-05 14:50:14 -05:00
Hayden Kowalchuk
c9dc5f8f8b fix: framebuffer.c marking inline, unused notation 2020-03-05 14:49:23 -05:00
Hayden Kowalchuk
e587519e14 fix: draw.c inline changes, and unused notation
- remove redundant call to isLightingEnabled
- rewrote vec3f normalize call
- moved checking for fastpath until we need it
2020-03-05 14:48:37 -05:00
Hayden Kowalchuk
eb351f519a fix: config.h moved to #pragma once
- whitespace fixes
2020-03-05 14:45:05 -05:00
Hayden Kowalchuk
c0d4e26533 feat: clip.c changed to moop math
- fmac where it was intended
2020-03-05 14:44:41 -05:00
Hayden Kowalchuk
19374bc1a4 chore: change containers
- move some math to integer
- inline some smaller functions
- whitespace fixes
2020-03-05 14:44:09 -05:00
Luke Benstead
1d1a980f16 Fix memory leak (thanks @HaydenKow) 2020-03-02 19:20:42 +00:00
Luke Benstead
7e7d90b606 Inline some things 2020-02-29 13:25:30 +00:00
Luke Benstead
937ad56c26 Fix out of bounds read 2020-02-29 09:48:52 +00:00
Luke Benstead
43a8db9e9d Remove divisions 2020-02-29 09:48:51 +00:00
Luke Benstead
a3b1ca66c3 Remove divisions 2020-02-22 21:00:33 +00:00
Luke Benstead
1520226174 Fix directional lighting 2020-02-22 20:33:23 +00:00
Luke Benstead
7fecb7a3a5 Fix directional lights 2020-02-21 14:51:05 +00:00
Luke Benstead
497ba28b4c Replace pow function 2020-02-20 09:44:45 +00:00
Luke Benstead
6b43244a1e Merge branch 'restore-color-material' into 'master'
Restore support for glColormaterial

See merge request simulant/GLdc!51
2020-02-19 10:50:31 +00:00
Luke Benstead
59118cc07d Restore support for glColormaterial 2020-02-19 10:45:31 +00:00
Luke Benstead
a502f92ded More lighting improvements 2020-02-19 09:30:26 +00:00
Luke Benstead
24fe33358c Faster floor 2020-02-17 20:49:40 +00:00
Luke Benstead
4ebd112784 Attempt to fix specular 2020-02-17 20:29:12 +00:00
Luke Benstead
28f77969ea Avoid overflows 2020-02-17 19:09:21 +00:00
Luke Benstead
29cbdc75b7 Fix a copy-paste bug (thanks @freakdave) 2020-02-17 19:05:57 +00:00
Luke Benstead
ab5dc26e33 Only calculate specular if there is an exponent 2020-02-17 19:05:18 +00:00
Luke Benstead
93be3ab757 Use super-simple floor function 2020-02-17 19:02:45 +00:00
Luke Benstead
6516f0f6f5 Prevent overflowing colours 2020-02-17 10:38:30 +00:00
Luke Benstead
5183d7b2d4 Fix strict aliasing issues 2020-02-17 10:31:26 +00:00
Luke Benstead
ab69030b1e Fix lighting colours 2020-02-17 10:21:33 +00:00
Luke Benstead
35842ad300 Faster FPOw implementation 2020-02-17 10:12:15 +00:00
Luke Benstead
2178d2f6d7 Improve lighting performance
This is (another) first pass at improving the performance of the lighting code.
As part of this refactor *we have lost glColorMaterial*. I need to figure out a
nice way of implementing it without slowing the common code path.
2020-02-16 20:36:49 +00:00
Luke Benstead
9605734476 Update Makefile 2020-01-01 14:31:55 +00:00
Luke Benstead
dafc56c396 Add new file 2020-01-01 14:30:03 +00:00
Luke Benstead
0819e1e5df Update Makefile 2020-01-01 14:28:45 +00:00
Luke Benstead
6322728fae Update Makefile 2020-01-01 14:28:25 +00:00
Luke Benstead
56b8abd758 Update Makefile 2020-01-01 14:13:34 +00:00
Luke Benstead
3c9f352827 Update Makefile 2020-01-01 14:12:12 +00:00
Luke Benstead
eeb95193ac Fix overflow 2019-12-27 19:35:18 +00:00
Luke Benstead
b2a2e71795 Much faster lighting implementation 2019-12-27 10:36:30 +00:00
Luke Benstead
b6e9b8c3ff Fix a glColorPointer call 2019-11-30 10:08:43 +00:00
Luke Benstead
a280dac778 Performance improvements 2019-11-30 10:07:41 +00:00
Luke Benstead
62b53f0fb1 Simplify swapVertex 2019-11-30 10:07:23 +00:00
Luke Benstead
e61369674c Change where txr.alpha is set 2019-11-30 10:07:04 +00:00
Luke Benstead
e97dd466aa Fix depth test functions 2019-11-30 10:06:46 +00:00
Luke Benstead
cdfb805dd9 Implement a fast path for glDrawElements 2019-11-27 20:08:29 +00:00
Luke Benstead
140eec3d92 glNormalPointer should accept GL_INT_2_10_10_10_REV, not GL_UNSIGNED_INT_2_... 2019-11-27 09:10:10 +00:00
Luke Benstead
11cd54bc0b Add partial support for GL_ARB_vertex_type_2_10_10_10_rev and also GL_NORMALIZE 2019-11-18 17:39:09 +00:00
Luke Benstead
fd3e7cde6c Improve the light sample + tweaks 2019-11-14 21:12:27 +00:00
Luke Benstead
8654ff24a2 Add light sample and fix lighting bug 2019-11-14 10:04:15 +00:00
Luke Benstead
9f3adc099a Fix a bad reference 2019-11-12 17:28:39 +00:00
Luke Benstead
05e242e054 Merge branch 'minus_fix' into 'master'
remove single minus sign

See merge request simulant/GLdc!50
2019-10-04 14:33:25 +00:00
Hayden Kowalchuk
805c68e973 remove single minus sign 2019-10-04 10:29:54 -04:00
Luke Benstead
90eb264210 Merge branch '52-fast-path' into 'master'
Resolve "Implement a fast path"

Closes #52

See merge request simulant/GLdc!49
2019-10-01 07:51:28 +00:00
Luke Benstead
f59e9bf56e Implement GL_ARB_vertex_array_bgra 2019-09-30 21:59:11 +01:00
Luke Benstead
d7e424a766 Initial implementation of a fast-path (currently some corruption) 2019-09-30 09:14:43 +01:00
Luke Benstead
2aafbfb571 Actually enable mipmapping in the paletted sample 2019-09-26 09:46:25 +01:00
Luke Benstead
7ac318e002 Merge branch '40-fix-mipmap-offsets' into 'master'
Resolve "Fix mipmap offsets"

Closes #40

See merge request simulant/GLdc!48
2019-09-26 08:19:23 +00:00
Luke Benstead
2c5b71b2b0 Implement mipmap generation for paletted textures 2019-09-26 09:17:07 +01:00
Luke Benstead
08ba39f6d1 Fix twiddled mipmap generation 2019-09-25 13:45:08 +01:00
Luke Benstead
2e1e28ce51 More mipmap generation fixes 2019-09-25 13:32:13 +01:00
Luke Benstead
36a3f7082f Implement mipmap generation for twiddled textures 2019-09-25 13:10:34 +01:00
Luke Benstead
e14db20a41 Fix a bunch of mipmap issues 2019-09-24 21:26:17 +01:00
Luke Benstead
2b53f50c46 Add some copy safety and remove some print statements 2019-09-24 19:39:23 +01:00
Luke Benstead
150c95bd33 Huge refactor of mipmap handling. All textures are now stored twiddled on the PVR 2019-09-24 15:47:23 +01:00
Luke Benstead
aafb99dede Add a mipmap sample 2019-09-23 21:31:11 +01:00
Luke Benstead
888a48562f Generate version.h and print version on boot. Fixes #46 2019-09-22 21:48:43 +01:00
Luke Benstead
8f84cbb142 Various cleanups from @mrneo 2019-09-22 20:52:58 +01:00
Luke Benstead
c92cdc927c Merge branch 'fix-gl_alpha-textures' into 'master'
Fixed GL_ALPHA support (convert to argb format)

See merge request simulant/GLdc!47
2019-09-22 19:32:00 +00:00
Ben Baron
b192bfc451 Fixed comment 2019-09-17 08:28:43 -05:00
Ben Baron
cb675434c7 Fixed GL_ALPHA support (convert to argb format) 2019-09-16 20:48:06 -05:00
Luke Benstead
96c103e379 Merge branch 'fixed-depth-issues' 2019-09-15 14:27:41 +01:00
Luke Benstead
e39632bcc4 Refactor matrix management and clipping 2019-09-14 20:51:47 +01:00
Luke Benstead
e7f2ad7dcc Optimise multitexture submission 2019-09-09 09:36:06 +01:00
Luke Benstead
3af18cb514 Refactor the perspective divide to work with glDepthRange 2019-09-08 17:27:56 +01:00
Luke Benstead
200db3593e Make primitive constants match the spec 2019-09-06 09:36:14 +01:00
Luke Benstead
1d32834b52 Simplify texture and blending context updates 2019-09-06 09:35:57 +01:00
Luke Benstead
22690600d0 Don't include kos headers from gl.h 2019-09-06 09:35:33 +01:00
Luke Benstead
4170655a88 If someone attempts to use lines, just log an error and render nothing (for now) 2019-09-06 09:34:55 +01:00
Luke Benstead
83bad86bca Add a blend_test sample 2019-09-06 09:34:33 +01:00
Luke Benstead
8e59b9adb5 Make sure we clamp floating point colours to avoid overflows 2019-09-04 17:59:57 +01:00
Luke Benstead
041b545177 Add missing glDepthRange declaration 2019-08-20 21:02:08 +01:00
Luke Benstead
57f4f62f86 Implement glColor3ubv 2019-08-20 20:42:29 +01:00
Luke Benstead
b6fccd3148 Use PVR_TXRENV_MODULATE instead of MODULATEALPHA. Fixes #48 2019-08-08 09:36:38 +01:00
Luke Benstead
b82d28130d Rewrite the lighting code 2019-08-01 20:21:13 +01:00
Luke Benstead
00c38edba9 Add polygon_offset sample (thanks mrneo240) 2019-07-17 10:46:19 +01:00
Luke Benstead
a616fe8f27 Merge branch '42-disallow-mipmaps' into 'master'
Throw GL_INVALID_OPERATION if mipmaps are specified for non-square textures

Closes #42

See merge request simulant/GLdc!44
2019-04-17 15:21:34 +00:00
Luke Benstead
3395f17687 Throw GL_INVALID_OPERATION if mipmaps are specified for non-square textures 2019-04-17 16:19:03 +01:00
Luke Benstead
f39e2c0972 Merge branch '43-allocate-when-needed' into 'master'
Only allocate space for mipmaps when necessary

Closes #43

See merge request simulant/GLdc!43
2019-04-17 14:58:53 +00:00
Luke Benstead
62743d42cb Only allocate space for mipmaps when necessary 2019-04-17 14:55:30 +01:00
Luke Benstead
a8d420299c Correctly throw GL_INVALID_VALUE for invalid sizes 2019-04-14 08:51:37 +01:00
Luke Benstead
6cfb4e437c Handle GL_DOUBLE like GL_FLOAT everywhere 2019-04-14 07:17:27 +01:00
Luke Benstead
cb692f59b4 Remove unnecessary conditional check 2019-04-01 09:57:33 +01:00
Luke Benstead
d912680ef0 Update version string 2019-03-30 07:15:50 +00:00
Luke Benstead
76c0826917 Merge branch 'slim-down-clipvertex' into 'master'
Slim down ClipVertex

Closes #36 and #37

See merge request simulant/GLdc!41
2019-03-30 07:13:26 +00:00
Luke Benstead
26dd1c1205 Tweak the polymark sample 2019-03-30 07:11:08 +00:00
Luke Benstead
e876dcb14f Massively optimise GL_POLYGON/GL_TRIANGLE_FAN 2019-03-29 11:26:19 +00:00
Luke Benstead
a88a9029f5 Add a polymark sample 2019-03-29 11:26:19 +00:00
Luke Benstead
9fafe31a37 Disable profiler 2019-03-29 11:26:19 +00:00
Luke Benstead
a75ced3fef Speed up immediate mode submission 2019-03-29 11:26:19 +00:00
Luke Benstead
1e18fbc527 Fix twiddling code. Fixes #37 2019-03-29 11:26:19 +00:00
Luke Benstead
2e33dc0718 Add missing profiler_pop(). Fixes #36 2019-03-29 11:26:19 +00:00
Luke Benstead
93311ff12c Fix twiddling code. Fixes #37 2019-03-29 07:54:50 +00:00
Luke Benstead
e2ea07ad92 Add missing profiler_pop(). Fixes #36 2019-03-29 07:51:09 +00:00
Luke Benstead
ccc9b59d03 Turn up to 11 2019-03-28 13:12:00 +00:00
Luke Benstead
41ee67cbf1 Code cleanup 2019-03-28 13:10:53 +00:00
Luke Benstead
e15a47b6fb Use the list stored on the SubmissionTarget 2019-03-28 13:09:36 +00:00
Luke Benstead
3cd15de332 Add additional traces 2019-03-28 13:09:04 +00:00
Luke Benstead
093b1af056 Add some assertions to aligned_vector 2019-03-28 13:08:23 +00:00
Luke Benstead
8982444406 Consistently allow > 16384 verts 2019-03-28 13:07:53 +00:00
Luke Benstead
cd04784c33 Fix memory corruption 2019-03-28 13:05:13 +00:00
Luke Benstead
30f8564298 Fix glDrawElements 2019-03-27 09:39:06 +00:00
Luke Benstead
434f316526 Switch pointer comparisons for counters 2019-03-26 09:09:07 +00:00
Luke Benstead
d44a24d339 Add assertions 2019-03-25 19:43:03 +00:00
Luke Benstead
9e12e15a13 Make use of swapVertex 2019-03-25 19:30:45 +00:00
Luke Benstead
bdeb9cd45a Restore clipping case that apparently can happen after all 2019-03-25 19:04:50 +00:00
Luke Benstead
e0613faced Tweak zclip demo 2019-03-25 18:51:36 +00:00
Luke Benstead
7e47b21fb5 Move back and forth in the zclip sample 2019-03-25 16:07:54 +00:00
Luke Benstead
493592ea30 Tweaks 2019-03-25 16:07:27 +00:00
Luke Benstead
ba04f62f6d Minor optimisation 2019-03-25 16:07:12 +00:00
Luke Benstead
f712f00602 Don't do anything if there are no vertices submitted 2019-03-25 16:06:41 +00:00
Luke Benstead
4355d0f224 Add additional profiler checkpoints 2019-03-25 16:06:28 +00:00
Luke Benstead
70feea6c6f Minor optimisations 2019-03-25 16:05:36 +00:00
Luke Benstead
b771a5339b Send colours as bytes in immediate mode 2019-03-25 12:56:48 +00:00
Luke Benstead
8fd90bd040 Switch back to normal swapping 2019-03-25 12:38:34 +00:00
Luke Benstead
0e71588e6c Try to optimise the quad generation 2019-03-25 10:33:05 +00:00
Luke Benstead
671881eafd Optimise GL_POLYGON rendering 2019-03-25 09:48:58 +00:00
Luke Benstead
291e82d18a Rename ClipVertex -> Vertex 2019-03-25 09:44:59 +00:00
Luke Benstead
bd0ef4cba3 Demo multitexturing in zclip, default to GL_MODULATE on multitexture 2019-03-24 14:09:52 +00:00
Luke Benstead
5e6927d9a1 Huge refactor of the drawing code 2019-03-24 08:09:02 +00:00
lerabot
f128efad6b Added comments 2019-03-21 12:16:54 -04:00
lerabot
34163498bd early test for testing depth/alpha function with .DTEX 2019-03-21 12:13:03 -04:00
Luke Benstead
3cb24c4fb4 Rename some functions 2019-03-14 13:16:55 +00:00
Luke Benstead
e9c8836181 Huge cleanup of glDrawElements handling 2019-03-14 13:15:56 +00:00
Luke Benstead
1ee16d8ee1 Slight optimisation 2019-03-13 17:38:42 +00:00
Luke Benstead
7c33f13438 Allow configuring initial capacities 2019-03-13 15:43:50 +00:00
Luke Benstead
d9539da841 Optimisations 2019-03-13 15:35:42 +00:00
Luke Benstead
8101e43e90 Fix winding issue 2019-03-13 15:19:28 +00:00
Luke Benstead
724ff628aa Fix some signedness issues 2019-03-13 15:14:09 +00:00
Luke Benstead
8b206f012e Make sure we correctly initalize the used banks 2019-03-13 12:05:06 +00:00
Luke Benstead
7d3dfeb317 Merge branch 'generate-refactor' 2019-03-13 11:24:56 +00:00
Luke Benstead
5bf58ec1a8 Refactor array submission to be (hopefully) faster 2019-03-13 11:24:35 +00:00
Luke Benstead
5da1ed732a Bump the default vbuf capacity 2019-03-13 08:53:35 +00:00
Luke Benstead
3d8fa7027b Properly forward the internal_palette_format 2019-03-13 08:51:05 +00:00
Luke Benstead
26c943c548 Optimize memory allocations 2019-03-13 07:28:23 +00:00
Luke Benstead
2ad23b1e16 Update version string 2019-03-11 19:54:55 +00:00
Luke Benstead
70ceb70f0b Fix invalid filter param 2019-03-11 19:51:13 +00:00
Luke Benstead
c73a96c1a5 Fix some more invalid GL constants 2019-03-11 19:36:07 +00:00
Luke Benstead
d21a07e799 Fix up some wrong constant values 2019-03-11 19:29:48 +00:00
Luke Benstead
8b13e3adaf Reserve 0 in the framebuffer thing (WIP) 2019-03-11 19:24:08 +00:00
Luke Benstead
032d56ce5a Merge branch 'rgb565-palettes' 2019-03-11 19:15:01 +00:00
Luke Benstead
957ebfa662 Fix texture twiddling 2019-03-11 19:14:30 +00:00
Luke Benstead
2485ea3428 Prove rectangular twiddling is broken 2019-03-11 19:08:32 +00:00
Luke Benstead
588c082ec8 Allow specifying palette, autosort, memory options via glKosInitEx 2019-03-11 19:07:59 +00:00
Luke Benstead
8f26e9c364 Fix a bug in the morton_index function 2019-03-11 09:12:48 +00:00
Luke Benstead
a561fd469f Protect against invalid read 2019-03-10 20:18:11 +00:00
Luke Benstead
834599dc4b Add glDrawBuffer stub 2019-03-10 20:05:40 +00:00
Luke Benstead
890a925225 Update README 2019-03-10 20:04:04 +00:00
Luke Benstead
8f6e43d555 Merge branch 'alpha-test' into 'master'
Implement glAlphaFunc and glEnable(GL_ALPHA_TEST)

See merge request simulant/GLdc!36
2019-03-10 20:02:24 +00:00
Luke Benstead
7512c1e767 Fix GL_ALPHA_TEST sample 2019-03-10 19:59:34 +00:00
Luke Benstead
e4186a05bf Start working on a test for GL_ALPHA_TEST 2019-03-10 19:38:47 +00:00
Luke Benstead
04dab8da9a Implement glAlphaFunc and glEnable(GL_ALPHA_TEST) 2019-03-10 17:53:58 +00:00
Luke Benstead
25bd3aedc8 Increase the max polygon size to 32 2019-03-10 16:10:59 +00:00
Luke Benstead
3e54b0298e Add thanks to Hayden Kowalchuk in the readme 2019-03-10 12:32:22 +00:00
Luke Benstead
91c3b66d73 Add GL_MODELVIEW_MATRIX as an option to glGetFloatv 2019-03-10 12:30:39 +00:00
Luke Benstead
b00b65af54 Fix issues with triangle fans / polygons 2019-03-10 12:24:27 +00:00
Luke Benstead
1807a0119c Add some missing function stubs 2019-03-10 12:19:45 +00:00
Luke Benstead
3fbb655758 Merge branch 'palette-slots' into 'master'
Palette slots

Closes #28

See merge request simulant/GLdc!35
2019-03-10 11:31:51 +00:00
Luke Benstead
259a82e69f Add support for multiple shared palettes 2019-03-10 11:18:56 +00:00
Luke Benstead
864dc45d10 Allocate palette slots on a FIFO basis 2019-03-09 14:32:50 +00:00
Luke Benstead
4d6cea59b7 Increase the max texture count 2019-03-08 21:38:39 +00:00
Luke Benstead
516cae7893 Store palettes in RAM not VRAM 2019-03-08 21:36:53 +00:00
Luke Benstead
ac3ffb9ce0 Make the binary symbols more compatible 2019-03-08 21:36:53 +00:00
Luke Benstead
dc6b067e58 Merge branch '35-fix-polygons' into 'master'
Fix drawing polygons. Fixes #35

Closes #35

See merge request simulant/GLdc!33
2019-03-07 21:45:46 +00:00
Luke Benstead
df3cdf0ebb Fix drawing polygons. Fixes #35 2019-03-07 21:41:25 +00:00
Luke Benstead
d7342fa0c0 Automatically twiddle non-twiddled palette data 2019-03-07 21:21:30 +00:00
Luke Benstead
3e1ed8a5f7 Don't reserve more space than we need 2019-03-06 08:31:06 +00:00
Luke Benstead
2ac9cac22d Use the shared palette in the sample 2019-03-04 20:56:17 +00:00
Luke Benstead
d89997a277 Simplify the element drawing 2019-03-04 20:41:33 +00:00
Luke Benstead
7c0a123aac Correctly initialize the shared palette. Fixes #34 2019-03-04 08:44:19 +00:00
Luke Benstead
efa63ebff2 Don't apply the shared palette if it hasn't been specified yet. Fixes #34 2019-03-04 08:42:24 +00:00
Luke Benstead
11bb588279 Make sure we reupload the palette if it's changed by glColorTableEXT 2019-03-03 20:21:42 +00:00
Luke Benstead
526b1f0d16 Add some assertions 2019-03-03 19:49:28 +00:00
Luke Benstead
ba4fde3975 Fix depth funcs 2019-03-03 19:41:19 +00:00
Luke Benstead
44ca14bcbd Add assertions 2019-03-03 19:11:53 +00:00
Luke Benstead
5f7fef2cf9 Prefix non-static private functions with '_gl' 2019-03-03 19:06:01 +00:00
Luke Benstead
926214bd82 Prefix some non-static private functions with '_gl' 2019-03-03 19:02:25 +00:00
Luke Benstead
2382126603 Make palette binding lazy 2019-03-03 18:56:18 +00:00
Luke Benstead
ef06af793a Don't apply the color table unless a texture is bound 2019-03-03 18:54:25 +00:00
Luke Benstead
3c3018450f Support twiddled and non-twiddled paletted textures 2019-03-03 18:49:33 +00:00
Luke Benstead
d12032c961 Store palette data in PVR ram 2019-03-03 18:49:06 +00:00
Luke Benstead
f349cd1b49 Fix packing order issue (thanks @mrneo240!) 2019-03-03 18:48:50 +00:00
Luke Benstead
cf273eab42 Add glTexParameterf (thanks @mrneo240) 2019-02-28 19:21:16 +00:00
Luke Benstead
b0c9ac7207 Remove zero special casing from named array 2019-02-28 18:33:37 +00:00
Luke Benstead
31ed419dfa Don't allow zero as a valid texture ID 2019-02-28 18:28:55 +00:00
Luke Benstead
6189f8d671 Merge branch 'implement-glGetFloatv' into 'master'
Add stub with just GL_PROJECTION_MATRIX supported

See merge request simulant/GLdc!32
2019-02-28 08:49:42 +00:00
Luke Benstead
02937ccd2c Add stub with just GL_PROJECTION_MATRIX supported 2019-02-28 08:46:13 +00:00
Luke Benstead
3345e17e3c Fix marker indexing 2019-02-28 08:34:32 +00:00
Luke Benstead
11b26c78d5 Fix an off-by-one error 2019-02-28 06:37:18 +00:00
Luke Benstead
0d460afa82 Merge branch '30-fix-bind-texture' into 'master'
Handle calling glBindTexture on an unknown name

Closes #30

See merge request simulant/GLdc!31
2019-02-27 20:48:19 +00:00
Luke Benstead
111d4ca83e Handle calling glBindTexture on an unknown name 2019-02-27 20:45:53 +00:00
Luke Benstead
e34f7e6368 Merge branch '32-narrow-to-rgb' into 'master'
Implement new conversion

Closes #32

See merge request simulant/GLdc!30
2019-02-27 20:35:01 +00:00
Luke Benstead
f6af3ab3fb Implement new conversion 2019-02-27 20:11:14 +00:00
Luke Benstead
b76dd102f7 Merge branch 'enable-ci' into 'master'
Add GitLab CI file

Closes #31

See merge request simulant/GLdc!29
2019-02-27 20:02:50 +00:00
Luke Benstead
86a921da25 Add GitLab CI file 2019-02-27 19:33:25 +00:00
Luke Benstead
920fc2b782 Increase the max number of textures to 512. Add config.h for settings like this. Fixes #29 2019-02-25 08:30:02 +00:00
Luke Benstead
7368f5c290 Add GL_SHARED_TEXTURE_PALETTE_EXT as a valid target to glColorTableEXT. Fixes #27 2019-02-25 08:26:04 +00:00
Luke Benstead
c3cd3b936c Add definition of GL_INTENSITY 2019-02-23 21:29:45 +00:00
Luke Benstead
cdd2447e07 Merge branch 'GL_EXT_shared_texture_palette' into 'master'
Implement GL_EXT_shared_texture_palette

See merge request simulant/GLdc!28
2019-02-21 21:59:58 +00:00
Luke Benstead
6d2c47bda1 Implement GL_EXT_shared_texture_palette 2019-02-21 21:58:31 +00:00
Luke Benstead
3d5b257e1b Merge branch 'ext-paletted-texture' into 'master'
Initial implementation of GL_EXT_paletted_texture

See merge request simulant/GLdc!26
2019-02-21 21:29:42 +00:00
Luke Benstead
50f1e277d8 Merge branch 'master' into ext-paletted-texture 2019-02-21 21:26:23 +00:00
Luke Benstead
464c12cfc5 Disable mipmap filtering on the paletted texture sample 2019-02-21 21:22:39 +00:00
Luke Benstead
571438ef4e Implement glColorTableEXT 2019-02-21 20:35:18 +00:00
Luke Benstead
8efd678da0 Update README 2018-10-21 10:11:45 +01:00
Luke Benstead
b9f8fe4a4d Clean up the memalign switching a bit 2018-10-18 09:54:34 +01:00
Luke Benstead
78f5fc698a
Merge pull request #27 from mrneo240/master
Minor Changes to allow windows to cleanly compile
2018-10-18 09:45:44 +01:00
mrneo240
82833f8fab
Merge pull request #1 from mrneo240/windows_fix
Fix compilation windows targets
2018-10-16 01:03:28 -04:00
Hayden Kowalchuk
0718ab0697 Fix compilation windows targets 2018-10-16 01:00:34 -04:00
Luke Benstead
df44c0ea73 More performance work and fix bugs introduced in last commit 2018-10-09 09:27:53 +01:00
Luke Benstead
18759422ea Optimise non-indexed rendering paths 2018-10-08 22:03:50 +01:00
Luke Benstead
c84f211ad0 More work towards paletted textures 2018-09-22 20:45:17 +01:00
Luke Benstead
e4f8cb8c9b Add a width limit 2018-09-20 16:48:26 +01:00
Luke Benstead
9645b10ed6 Add paletted texture to the supported extensions 2018-09-20 15:11:01 +01:00
Luke Benstead
8670fd459c More conversions 2018-09-20 15:10:08 +01:00
Luke Benstead
741707ac85 Implement conversions to RGBA8 2018-09-20 15:08:06 +01:00
Luke Benstead
21ad46ad94 Make it clear that some things aren't yet implemented 2018-09-20 15:02:22 +01:00
Luke Benstead
baf7cf5bdd Stub out glColorTableEXT 2018-09-20 15:01:13 +01:00
Luke Benstead
52e1be498e Keep header pointer updated. Fixes #25 (hopefully...) 2018-09-19 17:11:56 +01:00
Luke Benstead
e36f561ec0 Improve check 2018-09-15 17:41:58 +01:00
Luke Benstead
6aadc1124f Fix another zclipping bug 2018-09-15 17:38:42 +01:00
Luke Benstead
bc2fb6b658 Fix a clipping bug 2018-09-15 16:03:21 +01:00
Luke Benstead
7100ebe5a9 Prefix some non-static private methods 2018-09-15 11:45:38 +01:00
Luke Benstead
6cfccbd20d Inline + Static some lighting functions 2018-09-15 11:42:56 +01:00
Luke Benstead
e68c051991 Add missing glColorMaterial definition 2018-09-15 11:42:42 +01:00
Luke Benstead
17c9699966 More clipping fixes 2018-09-08 20:53:28 +01:00
Luke Benstead
06b065dc7e Return the correct count from clip 2018-09-06 20:08:55 +01:00
Luke Benstead
93af697092 Don't include the header in startOffset 2018-09-06 20:00:18 +01:00
Luke Benstead
d9fa69c288 Fix invalid memory access bug 2018-09-06 19:46:04 +01:00
Luke Benstead
b4539443f5 Allow toggling debug logging 2018-09-06 19:45:52 +01:00
Luke Benstead
d94ee888dc
Merge pull request #24 from Kazade/new-clipping
New clipping algorithm
2018-09-06 19:26:52 +01:00
Luke Benstead
e82646faff Remove old clipping code 2018-09-06 19:22:25 +01:00
Luke Benstead
af54c96ff4 Implement new culling algorithm, still some issues when GL_CULL_FACE is enabled 2018-09-06 19:19:00 +01:00
Luke Benstead
517d21b487 Begin implementing a new clipping algorithm 2018-09-03 21:48:42 +01:00
Luke Benstead
19491173e5 Set registers correctly before using store queues.
Fixes #23
2018-09-03 20:47:24 +01:00
Luke Benstead
55b3aa4ddd Fix up twiddled formats with alpha 2018-08-28 17:51:33 +01:00
Luke Benstead
963eeb54da Start work on spotlights 2018-08-28 15:55:50 +01:00
Luke Benstead
c191ced3f9 Fix issues with directional lights 2018-08-28 09:24:51 +01:00
Luke Benstead
acaecf49bc Add a missing header 2018-08-27 21:35:15 +01:00
Luke Benstead
8b3bf5a579 Fix lighting wrapping 2018-08-27 21:35:07 +01:00
Luke Benstead
8ef04be966 Try to fix directional lights 2018-08-27 20:54:20 +01:00
Luke Benstead
0d0beface3 Fix up some extension aliasing 2018-08-26 19:29:46 +01:00
Luke Benstead
b29303fb6c Implement glColorMaterial 2018-08-22 09:24:49 +01:00
Luke Benstead
21f8f9d855 Properly restore state after glEnd 2018-08-21 16:15:43 +01:00
Luke Benstead
9b0322ce8a Properly restore enabled client state when using immediate mode 2018-08-21 16:08:06 +01:00
Luke Benstead
edae8a9166 Properly pop active client texture in immediate mode 2018-08-21 15:50:59 +01:00
Luke Benstead
25de48b3f6 Fix a bug where only one texture would bind 2018-08-21 15:50:41 +01:00
Luke Benstead
0d69740231 Fix a subtle bug in NamedArray (thanks @Chilly Willy!) 2018-08-21 15:50:27 +01:00
Luke Benstead
8b834ac3f1 Avoid an additional copy of every vertex. Fixes #22 2018-08-21 09:37:19 +01:00
Luke Benstead
bccd1aa788 Start refactoring the submission process 2018-08-20 21:19:12 +01:00
Luke Benstead
80c65d4aff Remove conditional header sending, it's slightly slower 2018-08-20 20:34:11 +01:00
Luke Benstead
da97483eee Switch to using 4-byte colours internally rather than floats
These are stored in BGRA format so they can be directly cast to a uint32_t to get the
correct format for the argb param in pvr_vertex_t (yay endianess)

This results in a performance improvement as it reduces the data requirements.
2018-08-20 09:28:30 +01:00
Luke Benstead
26bd8df37c Fix some bugs with mipmaps + compressed textures 2018-08-20 08:34:54 +01:00
Luke Benstead
25e4518501 Performance optimisations 2018-08-19 21:10:42 +01:00
Luke Benstead
348e09b4aa Further optimisations 2018-08-17 21:40:27 +01:00
Luke Benstead
d36469faaf Start implementing a multitexture example 2018-08-17 07:09:53 +01:00
Luke Benstead
37ba9bf3c3 Mark mipmap levels as complete when generated 2018-08-16 17:53:39 +01:00
Luke Benstead
ba66608a96 Add a basic profiler and optimise some code 2018-08-16 17:51:15 +01:00
Luke Benstead
7d1b57fb12 Handle GL_RED -> GL_RED 2018-08-14 15:55:03 +01:00
Luke Benstead
021237f258 Fix a number of issues with texture loading 2018-08-14 09:49:31 +01:00
Luke Benstead
dca991ffe3 Fix a number of minor issues with textures 2018-08-13 09:19:16 +01:00
Luke Benstead
ea755b1650
Update README.md 2018-08-09 09:40:26 +01:00
Luke Benstead
e7cd91a91f Try to match GL filtering with PVR filtering 2018-08-09 09:32:29 +01:00
Luke Benstead
5c190c1095 Implement glGenerateMipmapEXT 2018-08-09 08:56:43 +01:00
Luke Benstead
c6ba127bc9 Always allocate room for mipmaps 2018-08-08 16:50:09 +01:00
Luke Benstead
4c99dd740a Add support for mipmapped compressed textures 2018-08-08 09:50:57 +01:00
Luke Benstead
b06f6116c8 Detect multiple mipmap levels being uploaded to glCompressedTexImage2D 2018-08-08 08:45:25 +01:00
Luke Benstead
86dd5dd2b2 glCompressedTexImage2D is an ARB extension in OpenGL 1.2.1 2018-08-07 20:49:10 +01:00
Luke Benstead
c40d3a007d Implement support for GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB and GL_COMPRESSED_TEXTURE_FORMATS_ARB 2018-08-07 20:46:26 +01:00
Luke Benstead
b6cab2f0ca
Merge pull request #18 from Kazade/compressed-textures
Compressed textures
2018-08-07 20:38:19 +01:00
Luke Benstead
c5cb41f1f1 Fix the twiddled flag 2018-08-07 20:34:07 +01:00
Luke Benstead
16d949bfbc Clean up compressed texture constants and code 2018-08-07 20:22:44 +01:00
Luke Benstead
0b91c20bbd Add support for getting the max texture size 2018-08-07 08:45:24 +01:00
Luke Benstead
85d4bb5ec3 Fix directional lighting bug 2018-08-05 14:38:04 +01:00
Luke Benstead
582a29d267 Add glMultiTexCoord2fARB 2018-08-05 09:09:38 +01:00
Luke Benstead
6942e597f4 Untested multitexture implementation 2018-08-04 21:00:26 +01:00
Luke Benstead
db0d39d487 Cleanup lighting code a bit 2018-08-04 19:34:07 +01:00
Luke Benstead
59002546e6 Fix lighting 2018-08-03 14:08:01 +01:00
Luke Benstead
332475c340 Add quadmark sample 2018-08-02 20:13:45 +01:00
Luke Benstead
0bf023b8df Fix a bug where headers weren't sent to a list 2018-08-02 19:56:50 +01:00
Luke Benstead
9371a8164f Don't send headers unnecessarily 2018-08-01 20:41:59 +01:00
Luke Benstead
4716a6a0c0 Cleanups and optimisations 2018-08-01 17:57:31 +01:00
Luke Benstead
39ac10af00 Simplify colour handling 2018-08-01 12:00:56 +01:00
Luke Benstead
bebca59796 Allow toggling z clipping 2018-08-01 11:32:07 +01:00
Luke Benstead
31e666c77a Implement support for GL_UNSIGNED_INT indices 2018-08-01 11:08:51 +01:00
Luke Benstead
8cc9e84cca Add a (broken) terrain sample 2018-08-01 11:08:39 +01:00
Luke Benstead
47d3c0f478 Minor optimisations 2018-08-01 09:57:44 +01:00
Luke Benstead
02b4b2d438 Fix clipping errors when multiple strips submitted 2018-07-31 09:32:55 +01:00
Luke Benstead
a113722d82 Update the zclip_trianglestrip sample to show glitches 2018-07-16 17:25:30 +01:00
Luke Benstead
720206810d Use a smaller near plane value (for now) 2018-07-16 09:01:11 +01:00
Luke Benstead
60c49f708e Clip using the w coordinate 2018-07-16 08:42:15 +01:00
Luke Benstead
0d921c3504 Tweaks to clipping 2018-07-15 21:27:15 +01:00
Luke Benstead
8ef63c75af 'Fix' compiling on platforms other than the DC 2018-07-15 20:44:43 +01:00
Luke Benstead
9191c93cf6
Update README.md 2018-07-15 20:03:50 +01:00
Luke Benstead
7874f7862a
Merge pull request #16 from Kazade/near-z-v2
Implement near-z clipping
2018-07-15 19:54:34 +01:00
Luke Benstead
cdef5972f5 Fix bug when clipping triangle strips 2018-07-15 19:48:56 +01:00
Luke Benstead
81b52e7a18 Finish initial pass at a zclipping implementation 2018-07-14 21:54:43 +01:00
Luke Benstead
2067115385 Handle multiple triangle strips with single-vertices behind the plane 2018-07-10 20:27:15 +01:00
Luke Benstead
5387734e6c Implement z clipping for the single-vertex case 2018-07-10 19:48:25 +01:00
Luke Benstead
ab13ed4747 Merge branch 'refactor-submit' 2018-07-09 19:01:13 +01:00
Luke Benstead
e90b5e424a Fix up triangle strip rendering 2018-07-09 19:00:50 +01:00
Luke Benstead
030cbead7b
Merge pull request #14 from Kazade/refactor-submit
Large refactor of vertex submission
2018-07-09 08:59:23 +01:00
Luke Benstead
ae335eeff1 Large refactor of vertex submission
This should be much faster as matrix loading is now minimized. Also splits transform from perspective divisionn
to lay the groundwork for near-z clipping. This also fixes GL_POLYGON submission.

Lighting can be made faster, this doesn't change the lighting algorithm, but the matrix changes should speed things up.
2018-07-09 08:57:01 +01:00
171 changed files with 29494 additions and 2665 deletions

5
.gitignore vendored
View File

@ -6,3 +6,8 @@
*.img
dc-build.sh
.buildconfig
build/*
builddir/*
version.[c|h]
pcbuild/*
dcbuild/*

45
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,45 @@
stages:
- build
- test
build:sh4-gcc:
stage: build
image: kazade/dreamcast-sdk
script:
- source /etc/bash.bashrc
- mkdir builddir
- cd builddir
- cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/Dreamcast.cmake -DCMAKE_BUILD_TYPE=Release ..
- make
- tar -zcf gldc.tar.gz libGLdc.a ../LICENSE ../README.md ../include
artifacts:
paths:
- builddir/gldc.tar.gz
build:x86-gcc:
stage: build
image: fedora:38
before_script:
- sudo dnf install -y cmake gcc gcc-c++ SDL2.i686 SDL2-devel.x86_64 glibc-devel glibc-devel.i686 SDL2-devel.i686 pkgconf-pkg-config.i686 pkgconf-pkg-config.x86_64
script:
- mkdir builddir
- cd builddir
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make
artifacts:
paths:
- builddir/tests/gldc_tests
test:x86-gcc:
stage: test
image: fedora:38
dependencies:
- build:x86-gcc
before_script:
- sudo dnf install -y cmake gcc gcc-c++ SDL2.i686 SDL2-devel glibc-devel pkgconf-pkg-config glibc-devel.i686 SDL2-devel.i686 pkgconf-pkg-config.i686
script:
- cd builddir/tests/
- SDL_VIDEODRIVER=dummy ./gldc_tests --junit-xml=report.xml
artifacts:
reports:
junit: builddir/tests/report.xml

220
CMakeLists.txt Normal file
View File

@ -0,0 +1,220 @@
cmake_minimum_required(VERSION 3.9)
project(GLdc)
set(CMAKE_VERBOSE_MAKEFILE ON)
# set the default backend
if(PLATFORM_DREAMCAST)
set(BACKEND "kospvr" CACHE STRING "Backend to use")
else()
set(BACKEND "software" CACHE STRING "Backend to use")
endif()
include(CheckIPOSupported)
check_ipo_supported(RESULT FLTO_SUPPORTED OUTPUT FLTO_ERROR)
# List of possible backends
set_property(CACHE BACKEND PROPERTY STRINGS kospvr software)
message("\nCompiling using backend: ${BACKEND}\n")
string(TOUPPER ${BACKEND} BACKEND_UPPER)
add_definitions(-DBACKEND_${BACKEND_UPPER})
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
include_directories(include)
if(NOT PLATFORM_DREAMCAST)
set(FIND_LIBRARY_USE_LIB32_PATHS true)
set(FIND_LIBRARY_USE_LIB64_PATHS false)
else()
include(CheckCCompilerFlag)
check_c_compiler_flag("-mfsrra" COMPILER_HAS_FSRRA)
check_c_compiler_flag("-mfsca" COMPILER_HAS_FSCA)
if(COMPILER_HAS_FSRRA)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfsrra")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfsrra")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -mfsrra")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -mfsrra")
endif()
if(COMPILER_HAS_FSCA)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mfsca")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mfsca")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -mfsca")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -mfsca")
endif()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ffp-contract=fast -ffast-math")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffast-math")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -ffp-contract=fast -ffast-math")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -ffast-math")
endif()
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -fexpensive-optimizations -fomit-frame-pointer -finline-functions")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++14 -O3 -g0 -s -fomit-frame-pointer -fstrict-aliasing")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -O3 -fexpensive-optimizations -fomit-frame-pointer -finline-functions")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -std=c++14 -O3 -fomit-frame-pointer -fstrict-aliasing")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -g -Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -g -Wall -Wextra")
set(
SOURCES
containers/aligned_vector.c
containers/named_array.c
containers/stack.c
GL/draw.c
GL/error.c
GL/flush.c
GL/fog.c
GL/framebuffer.c
GL/glu.c
GL/immediate.c
GL/lighting.c
GL/matrix.c
GL/state.c
GL/texture.c
GL/util.c
GL/alloc/alloc.c
${CMAKE_CURRENT_BINARY_DIR}/version.c
)
execute_process(
COMMAND git describe --abbrev=4 --dirty --always --tags
OUTPUT_VARIABLE GLDC_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
configure_file(GL/version.c.in ${CMAKE_CURRENT_BINARY_DIR}/version.c)
if(PLATFORM_DREAMCAST)
set(SOURCES ${SOURCES} GL/platforms/sh4.c)
else()
find_package(PkgConfig)
pkg_check_modules(SDL2 REQUIRED sdl2)
include_directories(${SDL2_INCLUDE_DIRS})
link_libraries(${SDL2_LIBRARIES})
set(
SOURCES
${SOURCES}
GL/platforms/software.c
GL/platforms/software/edge_equation.c
GL/platforms/software/parameter_equation.c
)
endif()
add_library(GLdc STATIC ${SOURCES})
if(FLTO_SUPPORTED)
set_property(TARGET GLdc PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
if(NOT PLATFORM_DREAMCAST)
set_target_properties(GLdc PROPERTIES
COMPILE_OPTIONS "-m32"
LINK_OPTIONS "-m32"
)
endif()
link_libraries(m)
include_directories(include)
link_libraries(GLdc)
function(gen_sample sample)
set(SAMPLE_SRCS ${ARGN})
set(GENROMFS "$ENV{KOS_BASE}/utils/genromfs/genromfs")
set(BIN2O $ENV{KOS_BASE}/utils/bin2o/bin2o)
set(ROMDISK_IMG "${CMAKE_SOURCE_DIR}/samples/${sample}/romdisk.img")
set(ROMDISK_O "${CMAKE_SOURCE_DIR}/samples/${sample}/romdisk.o")
set(ROMDISK_DIR "${CMAKE_SOURCE_DIR}/samples/${sample}/romdisk")
add_executable(${sample} ${SAMPLE_SRCS})
if(FLTO_SUPPORTED)
# FIXME: Cubes + LTO causes an ICE
if(NOT ${sample} MATCHES "cubes")
set_property(TARGET ${sample} PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
endif()
endif()
if(PLATFORM_DREAMCAST)
if(EXISTS "${CMAKE_SOURCE_DIR}/samples/${sample}/romdisk")
message("Generating romdisk for sample: ${sample}")
add_custom_command(
OUTPUT ${ROMDISK_IMG}
COMMAND ${GENROMFS} -f ${ROMDISK_IMG} -d ${ROMDISK_DIR} -v
)
add_custom_command(
OUTPUT ${ROMDISK_O}
COMMAND ${BIN2O} romdisk.img romdisk romdisk.o
DEPENDS ${ROMDISK_IMG}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/samples/${sample}"
)
add_custom_target(${sample}_romdisk DEPENDS ${ROMDISK_O})
add_dependencies(${sample} ${sample}_romdisk)
target_link_libraries(${sample} ${ROMDISK_O})
else()
message("No such romdisk for sample: ${sample} at 'samples/${sample}/romdisk'")
endif()
else()
set_target_properties(${sample} PROPERTIES
COMPILE_OPTIONS "-m32"
LINK_OPTIONS "-m32"
)
endif()
endfunction()
add_subdirectory(tests)
gen_sample(blend_test samples/blend_test/main.c)
gen_sample(depth_funcs samples/depth_funcs/main.c)
gen_sample(depth_funcs_alpha_testing samples/depth_funcs_alpha_testing/main.c samples/depth_funcs_alpha_testing/gl_png.c)
gen_sample(depth_funcs_ortho samples/depth_funcs_ortho/main.c)
gen_sample(lerabot01 samples/lerabot01/main.c samples/loadbmp.c)
gen_sample(lights samples/lights/main.c samples/loadbmp.c)
gen_sample(mipmap samples/mipmap/main.c samples/loadbmp.c)
gen_sample(multitexture_arrays samples/multitexture_arrays/main.c samples/multitexture_arrays/pvr-texture.c)
gen_sample(nehe02 samples/nehe02/main.c)
gen_sample(nehe02de samples/nehe02de/main.c)
gen_sample(nehe02va samples/nehe02va/main.c)
gen_sample(nehe03 samples/nehe03/main.c)
gen_sample(nehe04 samples/nehe04/main.c)
gen_sample(nehe05 samples/nehe05/main.c)
gen_sample(nehe06 samples/nehe06/main.c samples/loadbmp.c)
gen_sample(nehe06_vq samples/nehe06_vq/main.c)
gen_sample(nehe06_4444twid samples/nehe06_4444twid/main.c)
gen_sample(nehe08 samples/nehe08/main.c samples/nehe08/pvr-texture.c)
gen_sample(nehe10 samples/nehe10/main.c samples/loadbmp.c)
gen_sample(nehe20 samples/nehe20/main.c samples/loadbmp.c)
gen_sample(ortho2d samples/ortho2d/main.c)
gen_sample(paletted samples/paletted/main.c)
gen_sample(paletted_pcx samples/paletted_pcx/main.c)
gen_sample(polygon_offset samples/polygon_offset/main.c)
gen_sample(terrain samples/terrain/main.c)
gen_sample(zclip samples/zclip/main.c)
gen_sample(zclip_triangle samples/zclip_triangle/main.c)
gen_sample(zclip_trianglestrip samples/zclip_trianglestrip/main.c)
gen_sample(scissor samples/scissor/main.c)
gen_sample(polymark samples/polymark/main.c)
gen_sample(cubes samples/cubes/main.cpp)
gen_sample(zclip_test tests/zclip/main.cpp)
if(PLATFORM_DREAMCAST)
gen_sample(trimark samples/trimark/main.c)
gen_sample(quadmark samples/quadmark/main.c samples/profiler.c)
gen_sample(prof_texture_upload samples/prof_texture_upload/main.c samples/profiler.c)
else()
gen_sample(quadmark samples/quadmark/main.c)
gen_sample(prof_texture_upload samples/prof_texture_upload/main.c)
endif()

534
GL/alloc/alloc.c Normal file
View File

@ -0,0 +1,534 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "alloc.h"
/* This allocator is designed so that ideally all allocations larger
* than 2k, fall on a 2k boundary. Smaller allocations will
* never cross a 2k boundary.
*
* House keeping is stored in RAM to avoid reading back from the
* VRAM to check for usage. Headers can't be easily stored in the
* blocks anyway as they have to be 2k aligned (so you'd need to
* store them in reverse or something)
*
* Defragmenting the pool will move larger allocations first, then
* smaller ones, recursively until you tell it to stop, or until things
* stop moving.
*
* The maximum pool size is 8M, made up of:
*
* - 4096 blocks of 2k
* - each with 8 sub-blocks of 256 bytes
*
* Why?
*
* The PVR performs better if textures don't cross 2K memory
* addresses, so we try to avoid that. Obviously we can't
* if the allocation is > 2k, but in that case we can at least
* align with 2k and the VQ codebook (which is usually 2k) will
* be in its own page.
*
* The smallest PVR texture allowed is 8x8 at 16 bit (so 128 bytes)
* but we're unlikely to use too many of those, so having a min sub-block
* size of 256 should be OK (a 16x16 image is 512, so two sub-blocks).
*
* We could go down to 128 bytes if wastage is an issue, but then we have
* to store double the number of usage markers.
*
* FIXME:
*
* - Only operates on one pool (ignores what you pass)
*/
#include <assert.h>
#include <stdio.h>
#define EIGHT_MEG (8 * 1024 * 1024)
#define TWO_KILOBYTES (2 * 1024)
#define BLOCK_COUNT (EIGHT_MEG / TWO_KILOBYTES)
#define ALLOC_DEBUG 0
#if ALLOC_DEBUG
#define DBG_MSG(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
#else
#define DBG_MSG(fmt, ...) do {} while (0)
#endif
static inline intptr_t round_up(intptr_t n, int multiple)
{
if((n % multiple) == 0) {
return n;
}
assert(multiple);
return ((n + multiple - 1) / multiple) * multiple;
}
struct AllocEntry {
void* pointer;
size_t size;
struct AllocEntry* next;
};
typedef struct {
/* This is a usage bitmask for each block. A block
* is divided into 8 x 256 byte subblocks. If a block
* is entirely used, it's value will be 255, if
* it's entirely free then it will be 0.
*/
uint8_t block_usage[BLOCK_COUNT];
uint8_t* pool; // Pointer to the memory pool
size_t pool_size; // Size of the memory pool
uint8_t* base_address; // First 2k aligned address in the pool
size_t block_count; // Number of 2k blocks in the pool
/* It's frustrating that we need to do this dynamically
* but we need to know the size allocated when we free()...
* we could store it statically but it would take 64k if we had
* an array of block_index -> block size where there would be 2 ** 32
* entries of 16 bit block sizes. The drawback (aside the memory usage)
* would be that we won't be able to order by size, so defragging will
* take much more time.*/
struct AllocEntry* allocations;
} PoolHeader;
static PoolHeader pool_header = {
{0}, NULL, 0, NULL, 0, NULL
};
void* alloc_base_address(void* pool) {
(void) pool;
return pool_header.base_address;
}
size_t alloc_block_count(void* pool) {
(void) pool;
return pool_header.block_count;
}
static inline void* calc_address(
uint8_t* block_usage_iterator,
int bit_offset,
size_t required_subblocks,
size_t* start_subblock_out
) {
uintptr_t offset = (block_usage_iterator - pool_header.block_usage) * 8;
offset += (bit_offset + 1);
offset -= required_subblocks;
if(start_subblock_out) {
*start_subblock_out = offset;
}
return pool_header.base_address + (offset * 256);
}
void* alloc_next_available_ex(void* pool, size_t required_size, size_t* start_subblock, size_t* required_subblocks);
void* alloc_next_available(void* pool, size_t required_size) {
return alloc_next_available_ex(pool, required_size, NULL, NULL);
}
void* alloc_next_available_ex(void* pool, size_t required_size, size_t* start_subblock_out, size_t* required_subblocks_out) {
(void) pool;
uint8_t* it = pool_header.block_usage;
uint32_t required_subblocks = (required_size / 256);
if(required_size % 256) required_subblocks += 1;
/* Anything gte to 2048 must be aligned to a 2048 boundary */
bool requires_alignment = required_size >= 2048;
if(required_subblocks_out) {
*required_subblocks_out = required_subblocks;
}
/* This is a fallback option. If while we're searching we find a possible slot
* but it's not aligned, or it's straddling a 2k boundary, then we store
* it here and if we reach the end of the search and find nothing better
* we use this instead */
uint8_t* poor_option = NULL;
size_t poor_start_subblock = 0;
uint32_t found_subblocks = 0;
uint32_t found_poor_subblocks = 0;
for(size_t j = 0; j < pool_header.block_count; ++j, ++it) {
/* We just need to find enough consecutive blocks */
if(found_subblocks < required_subblocks) {
uint8_t t = *it;
/* Optimisation only. Skip over full blocks */
if(t == 255) {
found_subblocks = 0;
found_poor_subblocks = 0;
} else {
/* Now let's see how many consecutive blocks we can find */
for(int i = 0; i < 8; ++i) {
if((t & 0x80) == 0) {
bool block_overflow = (
required_size < 2048 && found_subblocks > 0 && i == 0
);
bool reset_subblocks = (
(requires_alignment && found_subblocks == 0 && i != 0) ||
block_overflow
);
if(reset_subblocks) {
// Ignore this subblock, because we want the first subblock to be aligned
// at a 2048 boundary and this one isn't (i != 0)
found_subblocks = 0;
} else {
found_subblocks++;
}
/* If we reset the subblocks due to an overflow, we still
* want to count this free subblock in our count */
if(block_overflow) {
found_subblocks++;
}
found_poor_subblocks++;
if(found_subblocks >= required_subblocks) {
/* We found space! Now calculate the address */
return calc_address(it, i, required_subblocks, start_subblock_out);
}
if(!poor_option && (found_poor_subblocks >= required_subblocks)) {
poor_option = calc_address(it, i, required_subblocks, &poor_start_subblock);
}
} else {
found_subblocks = 0;
found_poor_subblocks = 0;
}
t <<= 1;
}
}
}
}
if(poor_option) {
if(start_subblock_out) {
*start_subblock_out = poor_start_subblock;
}
return poor_option;
} else {
return NULL;
}
}
int alloc_init(void* pool, size_t size) {
(void) pool;
if(pool_header.pool) {
return -1;
}
if(size > EIGHT_MEG) { // FIXME: >= ?
return -1;
}
uint8_t* p = (uint8_t*) pool;
memset(pool_header.block_usage, 0, BLOCK_COUNT);
pool_header.pool = pool;
pool_header.pool_size = size;
intptr_t base_address = (intptr_t) pool_header.pool;
base_address = round_up(base_address, 2048);
pool_header.base_address = (uint8_t*) base_address;
pool_header.block_count = ((p + size) - pool_header.base_address) / 2048;
pool_header.allocations = NULL;
assert(((uintptr_t) pool_header.base_address) % 2048 == 0);
return 0;
}
void alloc_shutdown(void* pool) {
(void) pool;
if(!pool_header.pool) {
return;
}
struct AllocEntry* it = pool_header.allocations;
while(it) {
struct AllocEntry* next = it->next;
free(it);
it = next;
}
memset(&pool_header, 0, sizeof(pool_header));
pool_header.pool = NULL;
}
static inline uint32_t size_to_subblock_count(size_t size) {
uint32_t required_subblocks = (size / 256);
if(size % 256) required_subblocks += 1;
return required_subblocks;
}
static inline uint32_t subblock_from_pointer(void* p) {
uint8_t* ptr = (uint8_t*) p;
return (ptr - pool_header.base_address) / 256;
}
static inline void block_and_offset_from_subblock(size_t sb, size_t* b, uint8_t* off) {
*b = sb / 8;
*off = (sb % 8);
}
void* alloc_malloc(void* pool, size_t size) {
DBG_MSG("Allocating: %d\n", size);
size_t start_subblock, required_subblocks;
void* ret = alloc_next_available_ex(pool, size, &start_subblock, &required_subblocks);
if(ret) {
size_t block;
uint8_t offset;
block_and_offset_from_subblock(start_subblock, &block, &offset);
uint8_t mask = 0;
DBG_MSG("Alloc: size: %d, rs: %d, sb: %d, b: %d, off: %d\n", size, required_subblocks, start_subblock, start_subblock / 8, start_subblock % 8);
/* Toggle any bits for the first block */
int c = (required_subblocks < 8) ? required_subblocks : 8;
for(int i = 0; i < c; ++i) {
mask |= (1 << (7 - (offset + i)));
required_subblocks--;
}
if(mask) {
pool_header.block_usage[block++] |= mask;
}
/* Fill any full blocks in the middle of the allocation */
while(required_subblocks > 8) {
pool_header.block_usage[block++] = 255;
required_subblocks -= 8;
}
/* Fill out any trailing subblocks */
mask = 0;
for(size_t i = 0; i < required_subblocks; ++i) {
mask |= (1 << (7 - i));
}
if(mask) {
pool_header.block_usage[block++] |= mask;
}
/* Insert allocations in the list by size descending so that when we
* defrag we can move the larger blocks before the smaller ones without
* much effort */
struct AllocEntry* new_entry = (struct AllocEntry*) malloc(sizeof(struct AllocEntry));
new_entry->pointer = ret;
new_entry->size = size;
new_entry->next = NULL;
struct AllocEntry* it = pool_header.allocations;
struct AllocEntry* last = NULL;
if(!it) {
pool_header.allocations = new_entry;
} else {
while(it) {
if(it->size < size) {
if(last) {
last->next = new_entry;
} else {
pool_header.allocations = new_entry;
}
new_entry->next = it;
break;
} else if(!it->next) {
it->next = new_entry;
new_entry->next = NULL;
break;
}
last = it;
it = it->next;
}
}
}
DBG_MSG("Alloc done\n");
return ret;
}
static void alloc_release_blocks(struct AllocEntry* it) {
size_t used_subblocks = size_to_subblock_count(it->size);
size_t subblock = subblock_from_pointer(it->pointer);
size_t block;
uint8_t offset;
block_and_offset_from_subblock(subblock, &block, &offset);
uint8_t mask = 0;
DBG_MSG("Free: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset);
/* Wipe out any leading subblocks */
int c = (used_subblocks < 8) ? used_subblocks : 8;
for(int i = 0; i < c; ++i) {
mask |= (1 << (7 - (offset + i)));
used_subblocks--;
}
if(mask) {
pool_header.block_usage[block++] &= ~mask;
}
/* Clear any full blocks in the middle of the allocation */
while(used_subblocks > 8) {
pool_header.block_usage[block++] = 0;
used_subblocks -= 8;
}
/* Wipe out any trailing subblocks */
mask = 0;
for(size_t i = 0; i < used_subblocks; ++i) {
mask |= (1 << (7 - i));
}
if(mask) {
pool_header.block_usage[block++] &= ~mask;
}
}
void alloc_free(void* pool, void* p) {
(void) pool;
struct AllocEntry* it = pool_header.allocations;
struct AllocEntry* last = NULL;
while(it) {
if(it->pointer == p) {
alloc_release_blocks(it);
if(last) {
last->next = it->next;
} else {
assert(it == pool_header.allocations);
pool_header.allocations = it->next;
}
DBG_MSG("Freed: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset);
free(it);
break;
}
last = it;
it = it->next;
}
DBG_MSG("Free done\n");
}
void alloc_run_defrag(void* pool, defrag_address_move callback, int max_iterations, void* user_data) {
for(int i = 0; i < max_iterations; ++i) {
bool move_occurred = false;
struct AllocEntry* it = pool_header.allocations;
if(!it) {
return;
}
while(it) {
void* potential_dest = alloc_next_available(pool, it->size);
if(potential_dest < it->pointer) {
potential_dest = alloc_malloc(pool, it->size);
memcpy(potential_dest, it->pointer, it->size);
/* Mark this block as now free, but don't fiddle with the
* allocation list */
alloc_release_blocks(it);
callback(it->pointer, potential_dest, user_data);
it->pointer = potential_dest;
move_occurred = true;
}
it = it->next;
}
if(!move_occurred) {
return;
}
}
}
static inline uint8_t count_ones(uint8_t byte) {
static const uint8_t NIBBLE_LOOKUP [16] = {
0, 1, 1, 2, 1, 2, 2, 3,
1, 2, 2, 3, 2, 3, 3, 4
};
return NIBBLE_LOOKUP[byte & 0x0F] + NIBBLE_LOOKUP[byte >> 4];
}
size_t alloc_count_free(void* pool) {
(void) pool;
uint8_t* it = pool_header.block_usage;
uint8_t* end = it + pool_header.block_count;
size_t total_free = 0;
while(it < end) {
total_free += count_ones(*it) * 256;
++it;
}
return total_free;
}
size_t alloc_count_continuous(void* pool) {
(void) pool;
size_t largest_block = 0;
uint8_t* it = pool_header.block_usage;
uint8_t* end = it + pool_header.block_count;
size_t current_block = 0;
while(it < end) {
uint8_t t = *it++;
if(!t) {
current_block += 2048;
} else {
for(int i = 7; i >= 0; --i) {
bool bitset = (t & (1 << i));
if(bitset) {
current_block += (7 - i) * 256;
if(largest_block < current_block) {
largest_block = current_block;
current_block = 0;
}
}
}
}
}
return largest_block;
}

29
GL/alloc/alloc.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
int alloc_init(void* pool, size_t size);
void alloc_shutdown(void* pool);
void *alloc_malloc(void* pool, size_t size);
void alloc_free(void* pool, void* p);
typedef void (defrag_address_move)(void*, void*, void*);
void alloc_run_defrag(void* pool, defrag_address_move callback, int max_iterations, void* user_data);
size_t alloc_count_free(void* pool);
size_t alloc_count_continuous(void* pool);
void* alloc_next_available(void* pool, size_t required_size);
void* alloc_base_address(void* pool);
size_t alloc_block_count(void* pool);
#ifdef __cplusplus
}
#endif

View File

@ -1,34 +0,0 @@
#include <float.h>
#include "clip.h"
ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, float* vout, float* t) {
if(v1[2] < dist && v2[2] < dist) {
// Both behind, no clipping
return CLIP_RESULT_ALL_BEHIND;
}
if(v1[2] > dist && v2[2] > dist) {
return CLIP_RESULT_ALL_IN_FRONT;
}
float vec [] = {v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2]};
/*
* The plane normal will always be pointing down the negative Z so we can simplify the dot products as x and y will always be zero
* the resulting calculation will result in simply -z of the vector
*/
float vecDotP = -vec[2];
/* If the dot product is zero there is no intersection */
if(vecDotP > FLT_MIN || vecDotP < -FLT_MIN) {
*t = (-(dist - v1[2])) / vecDotP;
vout[0] = v1[0] + (vec[0] * (*t));
vout[1] = v1[1] + (vec[1] * (*t));
vout[2] = v1[2] + (vec[2] * (*t));
return (v1[2] >= dist) ? CLIP_RESULT_FRONT_TO_BACK : CLIP_RESULT_BACK_TO_FRONT;
} else {
return CLIP_RESULT_ALL_ON_PLANE;
}
}

View File

@ -1,22 +0,0 @@
#ifndef CLIP_H
#define CLIP_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
CLIP_RESULT_ALL_IN_FRONT,
CLIP_RESULT_ALL_BEHIND,
CLIP_RESULT_ALL_ON_PLANE,
CLIP_RESULT_FRONT_TO_BACK,
CLIP_RESULT_BACK_TO_FRONT
} ClipResult;
ClipResult clipLineToNearZ(const float* v1, const float* v2, const float dist, float* vout, float* t);
#ifdef __cplusplus
}
#endif
#endif // CLIP_H

4
GL/config.h Normal file
View File

@ -0,0 +1,4 @@
#pragma once
/* This figure is derived from the needs of Quake 1 */
#define MAX_TEXTURE_COUNT 1088

1675
GL/draw.c

File diff suppressed because it is too large Load Diff

127
GL/draw_fastpath.inc Normal file
View File

@ -0,0 +1,127 @@
/* THIS FILE IS INCLUDED BY draw.c TO AVOID CODE DUPLICATION. IT'S AN UGLY HACK */
#define FUNC_NAME(mode) static void generateArraysFastPath##_##mode(SubmissionTarget* target, const GLsizei first, const GLuint count)
#define MAKE_FUNC(mode) FUNC_NAME(mode)
MAKE_FUNC(POLYMODE)
{
static const float w = 1.0f;
if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
/* If we don't have vertices, do nothing */
return;
}
/* This is the best value we have. PROCESS_VERTEX_FLAGS needs to operate on quads and tris and so
this need to be divisible by 4 and 3. Even though we should be able to go much higher than this
and still be cache-local, trial and error says otherwise... */
#define BATCH_SIZE 60
GLuint min = 0;
GLuint stride;
const GLubyte* ptr;
Vertex* it;
VertexExtra* ve;
for(min = 0; min < count; min += BATCH_SIZE) {
const Vertex* start = ((Vertex*) _glSubmissionTargetStart(target)) + min;
const int_fast32_t loop = ((min + BATCH_SIZE) > count) ? count - min : BATCH_SIZE;
const int offset = (first + min);
stride = ATTRIB_POINTERS.uv.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG) ? ATTRIB_POINTERS.uv.ptr + ((first + min) * stride) : NULL;
it = (Vertex*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
PREFETCH(ptr + stride);
it->uv[0] = ((float*) ptr)[0];
it->uv[1] = ((float*) ptr)[1];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
it->uv[0] = 0;
it->uv[1] = 0;
}
}
stride = ATTRIB_POINTERS.colour.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) ? ATTRIB_POINTERS.colour.ptr + (offset * stride) : NULL;
it = (Vertex*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
PREFETCH(ptr + stride);
it->bgra[0] = ptr[0];
it->bgra[1] = ptr[1];
it->bgra[2] = ptr[2];
it->bgra[3] = ptr[3];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
*((uint32_t*) it->bgra) = ~0;
}
}
stride = ATTRIB_POINTERS.vertex.stride;
ptr = ATTRIB_POINTERS.vertex.ptr + (offset * stride);
it = (Vertex*) start;
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
PREFETCH(ptr + stride);
TransformVertex((const float*) ptr, &w, it->xyz, &it->w);
PROCESS_VERTEX_FLAGS(it, min + i);
ptr += stride;
}
start = aligned_vector_at(target->extras, min);
stride = ATTRIB_POINTERS.st.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & ST_ENABLED_FLAG) ? ATTRIB_POINTERS.st.ptr + (offset * stride) : NULL;
ve = (VertexExtra*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
PREFETCH(ptr + stride);
ve->st[0] = ((float*) ptr)[0];
ve->st[1] = ((float*) ptr)[1];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
ve->st[0] = 0;
ve->st[1] = 0;
}
}
stride = ATTRIB_POINTERS.normal.stride;
ptr = (ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) ? ATTRIB_POINTERS.normal.ptr + (offset * stride) : NULL;
ve = (VertexExtra*) start;
if(ptr) {
PREFETCH(ptr);
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
PREFETCH(ptr + stride);
ve->nxyz[0] = ((float*) ptr)[0];
ve->nxyz[1] = ((float*) ptr)[1];
ve->nxyz[2] = ((float*) ptr)[2];
ptr += stride;
}
} else {
for(int_fast32_t i = 0; i < loop; ++i, ++ve) {
ve->nxyz[0] = 0;
ve->nxyz[1] = 0;
ve->nxyz[2] = 0;
}
}
}
}

View File

@ -8,12 +8,12 @@
KOS Open GL State Machine Error Code Implementation.
*/
#include "gl.h"
#include <stdio.h>
static GLenum last_error = GL_NO_ERROR;
static char error_function[64] = { '\0' };
#include "private.h"
GLenum LAST_ERROR = GL_NO_ERROR;
char ERROR_FUNCTION[64] = { '\0' };
/* Quoth the GL Spec:
When an error occurs, the error flag is set to the appropriate error code
@ -24,49 +24,9 @@ static char error_function[64] = { '\0' };
Nothing in the spec requires recording multiple error flags, although it is
allowed by the spec. We take the easy way out for now. */
void _glKosThrowError(GLenum error, const char *function) {
if(last_error == GL_NO_ERROR) {
last_error = error;
sprintf(error_function, "%s\n", function);
}
}
GLubyte _glKosHasError() {
return (last_error != GL_NO_ERROR) ? GL_TRUE : GL_FALSE;
}
static void _glKosResetError() {
last_error = GL_NO_ERROR;
sprintf(error_function, "\n");
}
void _glKosPrintError() {
if(!_glKosHasError()) {
return;
}
printf("\nKOS GL ERROR THROWN BY FUNCTION: %s\n", error_function);
switch(last_error) {
case GL_INVALID_ENUM:
printf("KOS GL ERROR: GL_INVALID_ENUM\n");
break;
case GL_OUT_OF_MEMORY:
printf("KOS GL ERROR: GL_OUT_OF_MEMORY\n");
break;
case GL_INVALID_OPERATION:
printf("KOS GL ERROR: GL_INVALID_OPERATION\n");
break;
case GL_INVALID_VALUE:
printf("KOS GL ERROR: GL_INVALID_VALUE\n");
break;
default:
break;
}
}
GLenum glGetError(void) {
GLenum rv = last_error;
GLenum rv = LAST_ERROR;
_glKosResetError();
return rv;
}

View File

@ -1,106 +1,142 @@
#include <kos.h>
#include "../containers/aligned_vector.h"
#include "private.h"
#define TA_SQ_ADDR (unsigned int *)(void *) \
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
PolyList OP_LIST;
PolyList PT_LIST;
PolyList TR_LIST;
static PolyList OP_LIST;
static PolyList PT_LIST;
static PolyList TR_LIST;
/**
* FAST_MODE will use invW for all Z coordinates sent to the
* GPU.
*
* This will break orthographic mode so default is FALSE
**/
static void pvr_list_submit(void *src, int n) {
GLuint *d = TA_SQ_ADDR;
GLuint *s = src;
#define FAST_MODE GL_FALSE
/* fill/write queues as many times necessary */
while(n--) {
__asm__("pref @%0" : : "r"(s + 8)); /* prefetch 32 bytes for next loop */
d[0] = *(s++);
d[1] = *(s++);
d[2] = *(s++);
d[3] = *(s++);
d[4] = *(s++);
d[5] = *(s++);
d[6] = *(s++);
d[7] = *(s++);
__asm__("pref @%0" : : "r"(d));
d += 8;
}
GLboolean AUTOSORT_ENABLED = GL_FALSE;
/* Wait for both store queues to complete */
d = (GLuint *)0xe0000000;
d[0] = d[8] = 0;
PolyList* _glOpaquePolyList() {
return &OP_LIST;
}
static void _initPVR() {
pvr_init_params_t params = {
/* Enable opaque and translucent polygons with size 32 and 32 */
{ PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32 },
PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
0, /* No DMA */
0, /* No FSAA */
1 /* Disable translucent auto-sorting to match traditional GL */
};
PolyList* _glPunchThruPolyList() {
return &PT_LIST;
}
PolyList *_glTransparentPolyList() {
return &TR_LIST;
}
void APIENTRY glFlush() {
}
void APIENTRY glFinish() {
pvr_init(&params);
}
PolyList* activePolyList() {
if(isBlendingEnabled()) {
return &TR_LIST;
} else {
return &OP_LIST;
void APIENTRY glKosInitConfig(GLdcConfig* config) {
config->autosort_enabled = GL_FALSE;
config->fsaa_enabled = GL_FALSE;
config->initial_op_capacity = 1024 * 3;
config->initial_pt_capacity = 512 * 3;
config->initial_tr_capacity = 1024 * 3;
config->initial_immediate_capacity = 1024 * 3;
// RGBA4444 is the fastest general format - 8888 will cause a perf issue
config->internal_palette_format = GL_RGBA4;
config->texture_twiddle = GL_TRUE;
}
static bool _initialized = false;
void APIENTRY glKosInitEx(GLdcConfig* config) {
if(_initialized) {
return;
}
_initialized = true;
TRACE();
printf("\nWelcome to GLdc! Git revision: %s\n\n", GLDC_VERSION);
InitGPU(config->autosort_enabled, config->fsaa_enabled);
AUTOSORT_ENABLED = config->autosort_enabled;
_glInitSubmissionTarget();
_glInitMatrices();
_glInitAttributePointers();
_glInitContext();
_glInitLights();
_glInitImmediateMode(config->initial_immediate_capacity);
_glInitFramebuffers();
_glSetInternalPaletteFormat(config->internal_palette_format);
_glInitTextures();
if(config->texture_twiddle) {
glEnable(GL_TEXTURE_TWIDDLE_KOS);
}
OP_LIST.list_type = GPU_LIST_OP_POLY;
PT_LIST.list_type = GPU_LIST_PT_POLY;
TR_LIST.list_type = GPU_LIST_TR_POLY;
aligned_vector_init(&OP_LIST.vector, sizeof(Vertex));
aligned_vector_init(&PT_LIST.vector, sizeof(Vertex));
aligned_vector_init(&TR_LIST.vector, sizeof(Vertex));
aligned_vector_reserve(&OP_LIST.vector, config->initial_op_capacity);
aligned_vector_reserve(&PT_LIST.vector, config->initial_pt_capacity);
aligned_vector_reserve(&TR_LIST.vector, config->initial_tr_capacity);
}
void APIENTRY glKosShutdown() {
aligned_vector_clear(&OP_LIST.vector);
aligned_vector_clear(&PT_LIST.vector);
aligned_vector_clear(&TR_LIST.vector);
}
void APIENTRY glKosInit() {
TRACE();
_initPVR();
initMatrices();
initAttributePointers();
initContext();
initLights();
initImmediateMode();
initFramebuffers();
_glKosInitTextures();
OP_LIST.list_type = PVR_LIST_OP_POLY;
PT_LIST.list_type = PVR_LIST_PT_POLY;
TR_LIST.list_type = PVR_LIST_TR_POLY;
aligned_vector_init(&OP_LIST.vector, sizeof(PVRCommand));
aligned_vector_init(&PT_LIST.vector, sizeof(PVRCommand));
aligned_vector_init(&TR_LIST.vector, sizeof(PVRCommand));
GLdcConfig config;
glKosInitConfig(&config);
glKosInitEx(&config);
}
void APIENTRY glKosSwapBuffers() {
TRACE();
pvr_wait_ready();
SceneBegin();
if(aligned_vector_header(&OP_LIST.vector)->size > 2) {
SceneListBegin(GPU_LIST_OP_POLY);
SceneListSubmit((Vertex*) aligned_vector_front(&OP_LIST.vector), aligned_vector_size(&OP_LIST.vector));
SceneListFinish();
}
pvr_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_submit(OP_LIST.vector.data, OP_LIST.vector.size);
pvr_list_finish();
if(aligned_vector_header(&PT_LIST.vector)->size > 2) {
SceneListBegin(GPU_LIST_PT_POLY);
SceneListSubmit((Vertex*) aligned_vector_front(&PT_LIST.vector), aligned_vector_size(&PT_LIST.vector));
SceneListFinish();
}
pvr_list_begin(PVR_LIST_PT_POLY);
pvr_list_submit(PT_LIST.vector.data, PT_LIST.vector.size);
pvr_list_finish();
pvr_list_begin(PVR_LIST_TR_POLY);
pvr_list_submit(TR_LIST.vector.data, TR_LIST.vector.size);
pvr_list_finish();
pvr_scene_finish();
if(aligned_vector_header(&TR_LIST.vector)->size > 2) {
SceneListBegin(GPU_LIST_TR_POLY);
SceneListSubmit((Vertex*) aligned_vector_front(&TR_LIST.vector), aligned_vector_size(&TR_LIST.vector));
SceneListFinish();
}
SceneFinish();
aligned_vector_clear(&OP_LIST.vector);
aligned_vector_clear(&PT_LIST.vector);
aligned_vector_clear(&TR_LIST.vector);
_glApplyScissor(true);
}

View File

@ -10,13 +10,13 @@ static GLfloat FOG_COLOR [] = {0.0f, 0.0f, 0.0f, 0.0f};
static void updatePVRFog() {
if(FOG_MODE == GL_LINEAR) {
pvr_fog_table_linear(FOG_START, FOG_END);
GPUSetFogLinear(FOG_START, FOG_END);
} else if(FOG_MODE == GL_EXP) {
pvr_fog_table_exp(FOG_DENSITY);
GPUSetFogExp(FOG_DENSITY);
} else if(FOG_MODE == GL_EXP2) {
pvr_fog_table_exp2(FOG_DENSITY);
GPUSetFogExp2(FOG_DENSITY);
}
pvr_fog_table_color(FOG_COLOR[3], FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2]);
GPUSetFogColor(FOG_COLOR[3], FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2]);
}
void APIENTRY glFogf(GLenum pname, GLfloat param) {
@ -40,7 +40,6 @@ void APIENTRY glFogf(GLenum pname, GLfloat param) {
case GL_FOG_INDEX:
default: {
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
}
}
}

View File

@ -1,6 +1,6 @@
#include <stdio.h>
#include "private.h"
#include "../include/glkos.h"
typedef struct {
GLuint index;
@ -15,11 +15,14 @@ static FrameBuffer* ACTIVE_FRAMEBUFFER = NULL;
static NamedArray FRAMEBUFFERS;
void initFramebuffers() {
void _glInitFramebuffers() {
named_array_init(&FRAMEBUFFERS, sizeof(FrameBuffer), 32);
// Reserve zero so that it is never given to anyone as an ID!
named_array_reserve(&FRAMEBUFFERS, 0);
}
void wipeTextureOnFramebuffers(GLuint texture) {
void _glWipeTextureOnFramebuffers(GLuint texture) {
/* Spec says we don't update inactive framebuffers, they'll presumably just cause
* a GL_INVALID_OPERATION if we try to render to them */
if(ACTIVE_FRAMEBUFFER && ACTIVE_FRAMEBUFFER->texture_id == texture) {
@ -57,6 +60,7 @@ void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers) {
}
void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
_GL_UNUSED(target);
TRACE();
if(framebuffer) {
@ -70,29 +74,272 @@ void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
}
void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
_GL_UNUSED(target);
_GL_UNUSED(attachment);
_GL_UNUSED(textarget);
_GL_UNUSED(level);
if(texture != 0 && !glIsTexture(texture)) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
_glKosPrintError();
return;
}
if(!ACTIVE_FRAMEBUFFER) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
_glKosPrintError();
return;
}
ACTIVE_FRAMEBUFFER->texture_id = texture;
}
void APIENTRY glGenerateMipmapEXT(GLenum target) {
GL_FORCE_INLINE GLuint A1555(GLuint v) {
const GLuint MASK = (1 << 15);
return (v & MASK) >> 8;
}
GL_FORCE_INLINE GLuint R1555(GLuint v) {
const GLuint MASK = (31 << 10);
return (v & MASK) >> 7;
}
GL_FORCE_INLINE GLuint G1555(GLuint v) {
const GLuint MASK = (31 << 5);
return (v & MASK) >> 2;
}
GL_FORCE_INLINE GLuint B1555(GLuint v) {
const GLuint MASK = (31 << 0);
return (v & MASK) << 3;
}
GL_FORCE_INLINE GLuint A4444(GLuint v) {
const GLuint MASK = (0xF << 12);
return (v & MASK) >> 12;
}
GL_FORCE_INLINE GLuint R4444(GLuint v) {
const GLuint MASK = (0xF << 8);
return (v & MASK) >> 8;
}
GL_FORCE_INLINE GLuint G4444(GLuint v) {
const GLuint MASK = (0xF << 4);
return (v & MASK) >> 4;
}
GL_FORCE_INLINE GLuint B4444(GLuint v) {
const GLuint MASK = (0xF << 0);
return (v & MASK) >> 0;
}
GL_FORCE_INLINE GLuint R565(GLuint v) {
const GLuint MASK = (31 << 11);
return (v & MASK) >> 8;
}
GL_FORCE_INLINE GLuint G565(GLuint v) {
const GLuint MASK = (63 << 5);
return (v & MASK) >> 3;
}
GL_FORCE_INLINE GLuint B565(GLuint v) {
const GLuint MASK = (31 << 0);
return (v & MASK) << 3;
}
static GL_NO_INSTRUMENT GLboolean _glCalculateAverageTexel(GLuint pvrFormat, const GLubyte* src1, const GLubyte* src2, const GLubyte* src3, const GLubyte* src4, GLubyte* t) {
GLuint a, r, g, b;
GLubyte format = ((pvrFormat & (1 << 27)) | (pvrFormat & (1 << 26))) >> 26;
const GLubyte ARGB1555 = 0;
const GLubyte ARGB4444 = 1;
const GLubyte RGB565 = 2;
if((pvrFormat & GPU_TXRFMT_PAL8BPP) == GPU_TXRFMT_PAL8BPP) {
/* Paletted... all we can do really is just pick one of the
* 4 texels.. unless we want to change the palette (bad) or
* pick the closest available colour (slow, and probably bad)
*/
*t = *src1;
} else if(format == RGB565) {
GLushort* s1 = (GLushort*) src1;
GLushort* s2 = (GLushort*) src2;
GLushort* s3 = (GLushort*) src3;
GLushort* s4 = (GLushort*) src4;
GLushort* d1 = (GLushort*) t;
r = R565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
g = G565(*s1) + G565(*s2) + G565(*s3) + G565(*s4);
b = B565(*s1) + B565(*s2) + B565(*s3) + B565(*s4);
r /= 4;
g /= 4;
b /= 4;
*d1 = PACK_RGB565(r, g, b);
} else if(format == ARGB4444) {
GLushort* s1 = (GLushort*) src1;
GLushort* s2 = (GLushort*) src2;
GLushort* s3 = (GLushort*) src3;
GLushort* s4 = (GLushort*) src4;
GLushort* d1 = (GLushort*) t;
a = A4444(*s1) + A4444(*s2) + A4444(*s3) + A4444(*s4);
r = R4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
g = G4444(*s1) + G4444(*s2) + G4444(*s3) + G4444(*s4);
b = B4444(*s1) + B4444(*s2) + B4444(*s3) + B4444(*s4);
a /= 4;
r /= 4;
g /= 4;
b /= 4;
*d1 = PACK_ARGB4444(a, r, g, b);
} else {
gl_assert(format == ARGB1555);
GLushort* s1 = (GLushort*) src1;
GLushort* s2 = (GLushort*) src2;
GLushort* s3 = (GLushort*) src3;
GLushort* s4 = (GLushort*) src4;
GLushort* d1 = (GLushort*) t;
a = A1555(*s1) + A1555(*s2) + A1555(*s3) + A1555(*s4);
r = R1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
g = G1555(*s1) + G1555(*s2) + G1555(*s3) + G1555(*s4);
b = B1555(*s1) + B1555(*s2) + B1555(*s3) + B1555(*s4);
a /= 4;
r /= 4;
g /= 4;
b /= 4;
*d1 = PACK_ARGB1555((GLubyte) a, (GLubyte) r, (GLubyte) g, (GLubyte) b);
}
return GL_TRUE;
}
GLboolean _glGenerateMipmapTwiddled(const GLuint pvrFormat, const GLubyte* prevData, GLuint thisWidth, GLuint thisHeight, GLubyte* thisData) {
uint32_t lastWidth = thisWidth * 2;
uint32_t lastHeight = thisHeight * 2;
uint32_t i, j;
uint32_t stride = 0;
if((pvrFormat & GPU_TXRFMT_PAL8BPP) == GPU_TXRFMT_PAL8BPP) {
stride = 1;
} else {
stride = 2;
}
for(i = 0, j = 0; i < lastWidth * lastHeight; i += 4, j++) {
/* In a twiddled texture, the neighbouring texels
* are next to each other. By averaging them we just basically shrink
* the reverse Ns so each reverse N becomes the next level down... if that makes sense!? */
const GLubyte* s1 = &prevData[i * stride];
const GLubyte* s2 = s1 + stride;
const GLubyte* s3 = s2 + stride;
const GLubyte* s4 = s3 + stride;
GLubyte* t = &thisData[j * stride];
gl_assert(s4 < prevData + (lastHeight * lastWidth * stride));
gl_assert(t < thisData + (thisHeight * thisWidth * stride));
_glCalculateAverageTexel(pvrFormat, s1, s2, s3, s4, t);
}
return GL_TRUE;
}
void APIENTRY glGenerateMipmap(GLenum target) {
if(target != GL_TEXTURE_2D) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
TextureObject* tex = _glGetBoundTexture();
if(!tex || !tex->data || !tex->mipmapCount) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
if(tex->width != tex->height) {
fprintf(stderr, "[GL ERROR] Mipmaps cannot be supported on non-square textures\n");
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
if((tex->color & GPU_TXRFMT_PAL4BPP) == GPU_TXRFMT_PAL4BPP) {
fprintf(stderr, "[GL ERROR] Mipmap generation not supported for 4BPP paletted textures\n");
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
if((tex->color & GPU_TXRFMT_NONTWIDDLED) == GPU_TXRFMT_NONTWIDDLED) {
/* glTexImage2D should twiddle internally textures in nearly all cases
* so this error is unlikely */
fprintf(stderr, "[GL ERROR] Mipmaps are only supported on twiddled textures\n");
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
GLboolean complete = _glIsMipmapComplete(tex);
if(!complete && tex->isCompressed) {
fprintf(stderr, "[GL ERROR] Generating mipmaps for compressed textures is not yet supported\n");
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
if(complete) {
/* Nothing to do */
return;
}
GLuint i;
GLuint prevWidth = tex->width;
GLuint prevHeight = tex->height;
/* Make sure there is room for the mipmap data on the texture object */
_glAllocateSpaceForMipmaps(tex);
for(i = 1; i < _glGetMipmapLevelCount(tex); ++i) {
GLubyte* prevData = _glGetMipmapLocation(tex, i - 1);
GLubyte* thisData = _glGetMipmapLocation(tex, i);
GLuint thisWidth = (prevWidth > 1) ? prevWidth / 2 : 1;
GLuint thisHeight = (prevHeight > 1) ? prevHeight / 2 : 1;
_glGenerateMipmapTwiddled(tex->color, prevData, thisWidth, thisHeight, thisData);
tex->mipmap |= (1 << i);
prevWidth = thisWidth;
prevHeight = thisHeight;
}
gl_assert(_glIsMipmapComplete(tex));
}
/* generate mipmaps for any image provided by the user and then pass them to OpenGL */
GLAPI GLvoid APIENTRY gluBuild2DMipmaps(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height,
GLenum format, GLenum type, const void *data){
/* 2d texture, level of detail 0 (normal), 3 components (red, green, blue),
width & height of the image, border 0 (normal), rgb color data,
unsigned byte data, and finally the data itself. */
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
}
GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target) {
if(target != GL_FRAMEBUFFER_EXT) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
return 0;
}

20
GL/gl_assert.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef NDEBUG
/* We're debugging, use normal assert */
#include <assert.h>
#define gl_assert assert
#else
/* Release mode, use our custom assert */
#include <stdio.h>
#include <stdlib.h>
#define gl_assert(x) \
do {\
if(!(x)) {\
fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\
exit(1);\
}\
} while(0); \
#endif

View File

@ -4,14 +4,12 @@
/* Set the Perspective */
void APIENTRY gluPerspective(GLfloat angle, GLfloat aspect,
GLfloat znear, GLfloat zfar) {
GLfloat xmin, xmax, ymin, ymax;
GLfloat fW, fH;
ymax = znear * tanf(angle * F_PI / 360.0f);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
fH = tanf(angle * (M_PI / 360.0f)) * znear;
fW = fH * aspect;
glFrustum(xmin, xmax, ymin, ymax, znear, zfar);
glFrustum(-fW, fW, -fH, fH, znear, zfar);
}
void APIENTRY gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) {

View File

@ -7,45 +7,78 @@
* 3. This is entirely untested.
*/
#include "../include/gl.h"
#include <string.h>
#include <stdio.h>
#include "private.h"
static GLboolean IMMEDIATE_MODE_ACTIVE = GL_FALSE;
extern inline GLuint _glRecalcFastPath();
GLboolean IMMEDIATE_MODE_ACTIVE = GL_FALSE;
static GLenum ACTIVE_POLYGON_MODE = GL_TRIANGLES;
static GLfloat __attribute__((aligned(32))) NORMAL[3] = {0.0f, 0.0f, 1.0f};
static GLubyte __attribute__((aligned(32))) COLOR[4] = {255, 255, 255, 255}; /* ARGB order for speed */
static GLfloat __attribute__((aligned(32))) UV_COORD[2] = {0.0f, 0.0f};
static GLfloat __attribute__((aligned(32))) ST_COORD[2] = {0.0f, 0.0f};
static AlignedVector VERTICES;
static AlignedVector COLOURS;
static AlignedVector TEXCOORDS;
static AlignedVector NORMALS;
static AttribPointerList IM_ATTRIBS;
/* We store the list of attributes that have been "enabled" by a call to
glColor, glNormal, glTexCoord etc. otherwise we already have defaults that
can be applied faster */
static GLuint IM_ENABLED_VERTEX_ATTRIBUTES = 0;
typedef struct __attribute__((aligned(32))) {
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat u;
GLfloat v;
GLfloat s;
GLfloat t;
GLubyte bgra[4];
GLfloat nx;
GLfloat ny;
GLfloat nz;
GLuint padding[5];
} IMVertex;
static GLfloat NORMAL[3] = {0.0f, 0.0f, 1.0f};
static GLfloat COLOR[4] = {1.0f, 1.0f, 1.0f, 1.0f};
static GLfloat TEXCOORD[2] = {0.0f, 0.0f};
void _glInitImmediateMode(GLuint initial_size) {
aligned_vector_init(&VERTICES, sizeof(IMVertex));
aligned_vector_reserve(&VERTICES, initial_size);
IM_ATTRIBS.vertex.ptr = aligned_vector_front(&VERTICES);
IM_ATTRIBS.vertex.size = 3;
IM_ATTRIBS.vertex.type = GL_FLOAT;
IM_ATTRIBS.vertex.stride = sizeof(IMVertex);
void initImmediateMode() {
aligned_vector_init(&VERTICES, sizeof(GLfloat));
aligned_vector_init(&COLOURS, sizeof(GLfloat));
aligned_vector_init(&TEXCOORDS, sizeof(GLfloat));
aligned_vector_init(&NORMALS, sizeof(GLfloat));
}
IM_ATTRIBS.uv.ptr = IM_ATTRIBS.vertex.ptr + (sizeof(GLfloat) * 3);
IM_ATTRIBS.uv.stride = sizeof(IMVertex);
IM_ATTRIBS.uv.type = GL_FLOAT;
IM_ATTRIBS.uv.size = 2;
GLubyte checkImmediateModeInactive(const char* func) {
/* Returns 1 on error */
if(IMMEDIATE_MODE_ACTIVE) {
_glKosThrowError(GL_INVALID_OPERATION, func);
_glKosPrintError();
return 1;
}
IM_ATTRIBS.st.ptr = IM_ATTRIBS.vertex.ptr + (sizeof(GLfloat) * 5);
IM_ATTRIBS.st.stride = sizeof(IMVertex);
IM_ATTRIBS.st.type = GL_FLOAT;
IM_ATTRIBS.st.size = 2;
return 0;
IM_ATTRIBS.colour.ptr = IM_ATTRIBS.vertex.ptr + (sizeof(GLfloat) * 7);
IM_ATTRIBS.colour.size = GL_BGRA; /* Flipped color order */
IM_ATTRIBS.colour.type = GL_UNSIGNED_BYTE;
IM_ATTRIBS.colour.stride = sizeof(IMVertex);
IM_ATTRIBS.normal.ptr = IM_ATTRIBS.vertex.ptr + (sizeof(GLfloat) * 7) + sizeof(uint32_t);
IM_ATTRIBS.normal.stride = sizeof(IMVertex);
IM_ATTRIBS.normal.type = GL_FLOAT;
IM_ATTRIBS.normal.size = 3;
}
void APIENTRY glBegin(GLenum mode) {
if(IMMEDIATE_MODE_ACTIVE) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
_glKosPrintError();
return;
}
@ -54,44 +87,101 @@ void APIENTRY glBegin(GLenum mode) {
}
void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
COLOR[0] = r;
COLOR[1] = g;
COLOR[2] = b;
COLOR[3] = a;
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[A8IDX] = (GLubyte)(a * 255.0f);
COLOR[R8IDX] = (GLubyte)(r * 255.0f);
COLOR[G8IDX] = (GLubyte)(g * 255.0f);
COLOR[B8IDX] = (GLubyte)(b * 255.0f);
}
void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
glColor4f(
((GLfloat) r) / 255.0f,
((GLfloat) g) / 255.0f,
((GLfloat) b) / 255.0f,
((GLfloat) a) / 255.0f
);
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[A8IDX] = a;
COLOR[R8IDX] = r;
COLOR[G8IDX] = g;
COLOR[B8IDX] = b;
}
void APIENTRY glColor4ubv(const GLubyte *v) {
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[A8IDX] = v[3];
COLOR[R8IDX] = v[0];
COLOR[G8IDX] = v[1];
COLOR[B8IDX] = v[2];
}
void APIENTRY glColor4fv(const GLfloat* v) {
glColor4f(v[0], v[1], v[2], v[3]);
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[B8IDX] = (GLubyte)(v[2] * 255);
COLOR[G8IDX] = (GLubyte)(v[1] * 255);
COLOR[R8IDX] = (GLubyte)(v[0] * 255);
COLOR[A8IDX] = (GLubyte)(v[3] * 255);
}
void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) {
static float a = 1.0f;
glColor4f(r, g, b, a);
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[B8IDX] = (GLubyte)(b * 255.0f);
COLOR[G8IDX] = (GLubyte)(g * 255.0f);
COLOR[R8IDX] = (GLubyte)(r * 255.0f);
COLOR[A8IDX] = 255;
}
void APIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue) {
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[A8IDX] = 255;
COLOR[R8IDX] = red;
COLOR[G8IDX] = green;
COLOR[B8IDX] = blue;
}
void APIENTRY glColor3ubv(const GLubyte *v) {
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[A8IDX] = 255;
COLOR[R8IDX] = v[0];
COLOR[G8IDX] = v[1];
COLOR[B8IDX] = v[2];
}
void APIENTRY glColor3fv(const GLfloat* v) {
glColor3f(v[0], v[1], v[2]);
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
COLOR[A8IDX] = 255;
COLOR[R8IDX] = (GLubyte)(v[0] * 255);
COLOR[G8IDX] = (GLubyte)(v[1] * 255);
COLOR[B8IDX] = (GLubyte)(v[2] * 255);
}
void APIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
aligned_vector_push_back(&VERTICES, &x, 1);
aligned_vector_push_back(&VERTICES, &y, 1);
aligned_vector_push_back(&VERTICES, &z, 1);
IM_ENABLED_VERTEX_ATTRIBUTES |= VERTEX_ENABLED_FLAG;
IMVertex* vert = aligned_vector_extend(&VERTICES, 1);
/* Push back the stashed colour, normal and texcoord */
aligned_vector_push_back(&COLOURS, COLOR, 4);
aligned_vector_push_back(&TEXCOORDS, TEXCOORD, 2);
aligned_vector_push_back(&NORMALS, NORMAL, 3);
/* Resizing could've invalidated the pointers */
IM_ATTRIBS.vertex.ptr = VERTICES.data;
IM_ATTRIBS.uv.ptr = IM_ATTRIBS.vertex.ptr + 12;
IM_ATTRIBS.st.ptr = IM_ATTRIBS.uv.ptr + 8;
IM_ATTRIBS.colour.ptr = IM_ATTRIBS.st.ptr + 8;
IM_ATTRIBS.normal.ptr = IM_ATTRIBS.colour.ptr + 4;
uint32_t* dest = (uint32_t*) &vert->x;
*(dest++) = *((uint32_t*) &x);
*(dest++) = *((uint32_t*) &y);
*(dest++) = *((uint32_t*) &z);
*(dest++) = *((uint32_t*) &UV_COORD[0]);
*(dest++) = *((uint32_t*) &UV_COORD[1]);
*(dest++) = *((uint32_t*) &ST_COORD[0]);
*(dest++) = *((uint32_t*) &ST_COORD[1]);
*(dest++) = *((uint32_t*) COLOR);
*(dest++) = *((uint32_t*) &NORMAL[0]);
*(dest++) = *((uint32_t*) &NORMAL[1]);
*(dest++) = *((uint32_t*) &NORMAL[2]);
}
void APIENTRY glVertex3fv(const GLfloat* v) {
@ -107,6 +197,7 @@ void APIENTRY glVertex2fv(const GLfloat* v) {
}
void APIENTRY glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
_GL_UNUSED(w);
glVertex3f(x, y, z);
}
@ -114,9 +205,35 @@ void APIENTRY glVertex4fv(const GLfloat* v) {
glVertex4f(v[0], v[1], v[2], v[3]);
}
void APIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
if(target == GL_TEXTURE0) {
IM_ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG;
UV_COORD[0] = s;
UV_COORD[1] = t;
} else if(target == GL_TEXTURE1) {
IM_ENABLED_VERTEX_ATTRIBUTES |= ST_ENABLED_FLAG;
ST_COORD[0] = s;
ST_COORD[1] = t;
} else {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
}
}
void APIENTRY glTexCoord1f(GLfloat u) {
IM_ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG;
UV_COORD[0] = u;
UV_COORD[1] = 0.0f;
}
void APIENTRY glTexCoord1fv(const GLfloat* v) {
glTexCoord1f(v[0]);
}
void APIENTRY glTexCoord2f(GLfloat u, GLfloat v) {
TEXCOORD[0] = u;
TEXCOORD[1] = v;
IM_ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG;
UV_COORD[0] = u;
UV_COORD[1] = v;
}
void APIENTRY glTexCoord2fv(const GLfloat* v) {
@ -124,6 +241,7 @@ void APIENTRY glTexCoord2fv(const GLfloat* v) {
}
void APIENTRY glNormal3f(GLfloat x, GLfloat y, GLfloat z) {
IM_ENABLED_VERTEX_ATTRIBUTES |= NORMAL_ENABLED_FLAG;
NORMAL[0] = x;
NORMAL[1] = y;
NORMAL[2] = z;
@ -136,28 +254,38 @@ void APIENTRY glNormal3fv(const GLfloat* v) {
void APIENTRY glEnd() {
IMMEDIATE_MODE_ACTIVE = GL_FALSE;
/* FIXME: Push pointer state */
GLuint* attrs = &ENABLED_VERTEX_ATTRIBUTES;
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
/* Redirect attrib pointers */
AttribPointerList stashed_attrib_pointers = ATTRIB_POINTERS;
ATTRIB_POINTERS = IM_ATTRIBS;
glVertexPointer(3, GL_FLOAT, 0, VERTICES.data);
glColorPointer(4, GL_FLOAT, 0, COLOURS.data);
glNormalPointer(GL_FLOAT, 0, NORMALS.data);
GLuint prevAttrs = *attrs;
glClientActiveTextureARB(GL_TEXTURE0);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORDS.data);
*attrs = IM_ENABLED_VERTEX_ATTRIBUTES;
glDrawArrays(ACTIVE_POLYGON_MODE, 0, VERTICES.size / 3);
/* Store the fast path enabled setting so we can restore it
* after drawing */
const GLboolean fp_was_enabled = FAST_PATH_ENABLED;
#ifndef NDEBUG
// Immediate mode should always activate the fast path
GLuint fastPathEnabled = _glRecalcFastPath();
gl_assert(fastPathEnabled);
#else
/* If we're not debugging, set to true - we assume we haven't broken it! */
FAST_PATH_ENABLED = GL_TRUE;
#endif
glDrawArrays(ACTIVE_POLYGON_MODE, 0, aligned_vector_header(&VERTICES)->size);
ATTRIB_POINTERS = stashed_attrib_pointers;
*attrs = prevAttrs;
aligned_vector_clear(&VERTICES);
aligned_vector_clear(&COLOURS);
aligned_vector_clear(&TEXCOORDS);
aligned_vector_clear(&NORMALS);
/* FIXME: Pop pointers */
FAST_PATH_ENABLED = fp_was_enabled;
}
void APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {

View File

@ -1,55 +1,118 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <dc/vec3f.h>
#include "private.h"
#include "platform.h"
static GLfloat SCENE_AMBIENT [] = {0.2, 0.2, 0.2, 1.0};
static GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE;
static GLenum COLOR_CONTROL = GL_SINGLE_COLOR;
static GLboolean TWO_SIDED_LIGHTING = GL_FALSE;
#define _MIN(x, y) (x < y) ? x : y
static LightSource LIGHTS[MAX_LIGHTS];
static Material MATERIAL;
/* Lighting will not be calculated if the attenuation
* multiplier ends up less than this value */
#define ATTENUATION_THRESHOLD 100.0f
void _glPrecalcLightingValues(GLuint mask) {
/* Pre-calculate lighting values */
GLshort i;
Material* material = _glActiveMaterial();
if(mask & AMBIENT_MASK) {
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
light->ambientMaterial[0] = light->ambient[0] * material->ambient[0];
light->ambientMaterial[1] = light->ambient[1] * material->ambient[1];
light->ambientMaterial[2] = light->ambient[2] * material->ambient[2];
light->ambientMaterial[3] = light->ambient[3] * material->ambient[3];
}
}
if(mask & DIFFUSE_MASK) {
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
light->diffuseMaterial[0] = light->diffuse[0] * material->diffuse[0];
light->diffuseMaterial[1] = light->diffuse[1] * material->diffuse[1];
light->diffuseMaterial[2] = light->diffuse[2] * material->diffuse[2];
light->diffuseMaterial[3] = light->diffuse[3] * material->diffuse[3];
}
}
if(mask & SPECULAR_MASK) {
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
light->specularMaterial[0] = light->specular[0] * material->specular[0];
light->specularMaterial[1] = light->specular[1] * material->specular[1];
light->specularMaterial[2] = light->specular[2] * material->specular[2];
light->specularMaterial[3] = light->specular[3] * material->specular[3];
}
}
/* If ambient or emission are updated, we need to update
* the base colour. */
if((mask & AMBIENT_MASK) || (mask & EMISSION_MASK) || (mask & SCENE_AMBIENT_MASK)) {
GLfloat* scene_ambient = _glLightModelSceneAmbient();
material->baseColour[0] = MATH_fmac(scene_ambient[0], material->ambient[0], material->emissive[0]);
material->baseColour[1] = MATH_fmac(scene_ambient[1], material->ambient[1], material->emissive[1]);
material->baseColour[2] = MATH_fmac(scene_ambient[2], material->ambient[2], material->emissive[2]);
material->baseColour[3] = MATH_fmac(scene_ambient[3], material->ambient[3], material->emissive[3]);
}
}
void _glInitLights() {
Material* material = _glActiveMaterial();
void initLights() {
static GLfloat ONE [] = {1.0f, 1.0f, 1.0f, 1.0f};
static GLfloat ZERO [] = {0.0f, 0.0f, 0.0f, 1.0f};
static GLfloat PARTIAL [] = {0.2f, 0.2f, 0.2f, 1.0f};
static GLfloat MOSTLY [] = {0.8f, 0.8f, 0.8f, 1.0f};
memcpy(MATERIAL.ambient, PARTIAL, sizeof(GLfloat) * 4);
memcpy(MATERIAL.diffuse, MOSTLY, sizeof(GLfloat) * 4);
memcpy(MATERIAL.specular, ZERO, sizeof(GLfloat) * 4);
memcpy(MATERIAL.emissive, ZERO, sizeof(GLfloat) * 4);
MATERIAL.exponent = 0.0f;
memcpy(material->ambient, PARTIAL, sizeof(GLfloat) * 4);
memcpy(material->diffuse, MOSTLY, sizeof(GLfloat) * 4);
memcpy(material->specular, ZERO, sizeof(GLfloat) * 4);
memcpy(material->emissive, ZERO, sizeof(GLfloat) * 4);
material->exponent = 0.0f;
GLubyte i;
for(i = 0; i < MAX_LIGHTS; ++i) {
memcpy(LIGHTS[i].ambient, ZERO, sizeof(GLfloat) * 4);
memcpy(LIGHTS[i].diffuse, ONE, sizeof(GLfloat) * 4);
memcpy(LIGHTS[i].specular, ONE, sizeof(GLfloat) * 4);
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
memcpy(light->ambient, ZERO, sizeof(GLfloat) * 4);
memcpy(light->diffuse, ONE, sizeof(GLfloat) * 4);
memcpy(light->specular, ONE, sizeof(GLfloat) * 4);
if(i > 0) {
memcpy(LIGHTS[i].diffuse, ZERO, sizeof(GLfloat) * 4);
memcpy(LIGHTS[i].specular, ZERO, sizeof(GLfloat) * 4);
memcpy(light->diffuse, ZERO, sizeof(GLfloat) * 4);
memcpy(light->specular, ZERO, sizeof(GLfloat) * 4);
}
LIGHTS[i].position[0] = LIGHTS[i].position[1] = LIGHTS[i].position[3] = 0.0f;
LIGHTS[i].position[2] = 1.0f;
light->position[0] = light->position[1] = light->position[3] = 0.0f;
light->position[2] = 1.0f;
light->isDirectional = GL_TRUE;
light->isEnabled = GL_FALSE;
LIGHTS[i].spot_direction[0] = LIGHTS[i].spot_direction[1] = 0.0f;
LIGHTS[i].spot_direction[2] = -1.0f;
light->spot_direction[0] = light->spot_direction[1] = 0.0f;
light->spot_direction[2] = -1.0f;
LIGHTS[i].spot_exponent = 0.0f;
LIGHTS[i].spot_cutoff = 180.0f;
light->spot_exponent = 0.0f;
light->spot_cutoff = 180.0f;
LIGHTS[i].constant_attenuation = 1.0f;
LIGHTS[i].linear_attenuation = 0.0f;
LIGHTS[i].quadratic_attenuation = 0.0f;
light->constant_attenuation = 1.0f;
light->linear_attenuation = 0.0f;
light->quadratic_attenuation = 0.0f;
}
_glPrecalcLightingValues(~0);
_glRecalcEnabledLights();
}
void APIENTRY glLightModelf(GLenum pname, const GLfloat param) {
glLightModelfv(pname, &param);
}
@ -60,100 +123,143 @@ void APIENTRY glLightModeli(GLenum pname, const GLint param) {
void APIENTRY glLightModelfv(GLenum pname, const GLfloat *params) {
switch(pname) {
case GL_LIGHT_MODEL_AMBIENT:
memcpy(SCENE_AMBIENT, params, sizeof(GLfloat) * 4);
break;
case GL_LIGHT_MODEL_AMBIENT: {
if(memcmp(_glGetLightModelSceneAmbient(), params, sizeof(float) * 4) != 0) {
_glSetLightModelSceneAmbient(params);
_glPrecalcLightingValues(SCENE_AMBIENT_MASK);
}
} break;
case GL_LIGHT_MODEL_LOCAL_VIEWER:
VIEWER_IN_EYE_COORDINATES = (*params) ? GL_TRUE : GL_FALSE;
_glSetLightModelViewerInEyeCoordinates((*params) ? GL_TRUE : GL_FALSE);
break;
case GL_LIGHT_MODEL_TWO_SIDE:
/* Not implemented */
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
}
}
void APIENTRY glLightModeliv(GLenum pname, const GLint* params) {
switch(pname) {
case GL_LIGHT_MODEL_COLOR_CONTROL:
COLOR_CONTROL = *params;
_glSetLightModelColorControl(*params);
break;
case GL_LIGHT_MODEL_LOCAL_VIEWER:
VIEWER_IN_EYE_COORDINATES = (*params) ? GL_TRUE : GL_FALSE;
_glSetLightModelViewerInEyeCoordinates((*params) ? GL_TRUE : GL_FALSE);
break;
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
}
}
void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
GLubyte idx = light & 0xF;
if(idx >= MAX_LIGHTS) {
if(idx >= MAX_GLDC_LIGHTS) {
_glKosThrowError(GL_INVALID_VALUE, __func__);
return;
}
GLuint mask = (pname == GL_AMBIENT) ? AMBIENT_MASK :
(pname == GL_DIFFUSE) ? DIFFUSE_MASK :
(pname == GL_SPECULAR) ? SPECULAR_MASK : 0;
LightSource* l = _glLightAt(idx);
GLboolean rebuild = GL_FALSE;
switch(pname) {
case GL_AMBIENT:
memcpy(LIGHTS[idx].ambient, params, sizeof(GLfloat) * 4);
rebuild = memcmp(l->ambient, params, sizeof(GLfloat) * 4) != 0;
if(rebuild) {
memcpy(l->ambient, params, sizeof(GLfloat) * 4);
}
break;
case GL_DIFFUSE:
memcpy(LIGHTS[idx].diffuse, params, sizeof(GLfloat) * 4);
rebuild = memcmp(l->diffuse, params, sizeof(GLfloat) * 4) != 0;
if(rebuild) {
memcpy(l->diffuse, params, sizeof(GLfloat) * 4);
}
break;
case GL_SPECULAR:
memcpy(LIGHTS[idx].specular, params, sizeof(GLfloat) * 4);
rebuild = memcmp(l->specular, params, sizeof(GLfloat) * 4) != 0;
if(rebuild) {
memcpy(l->specular, params, sizeof(GLfloat) * 4);
}
break;
case GL_POSITION:
memcpy(LIGHTS[idx].position, params, sizeof(GLfloat) * 4);
case GL_POSITION: {
memcpy(l->position, params, sizeof(GLfloat) * 4);
l->isDirectional = params[3] == 0.0f;
if(l->isDirectional) {
//FIXME: Do we need to rotate directional lights?
} else {
_glMatrixLoadModelView();
TransformVec3(l->position);
}
}
break;
case GL_SPOT_DIRECTION: {
l->spot_direction[0] = params[0];
l->spot_direction[1] = params[1];
l->spot_direction[2] = params[2];
} break;
case GL_CONSTANT_ATTENUATION:
case GL_LINEAR_ATTENUATION:
case GL_QUADRATIC_ATTENUATION:
case GL_SPOT_CUTOFF:
case GL_SPOT_DIRECTION:
case GL_SPOT_EXPONENT:
glLightf(light, pname, *params);
break;
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
return;
}
if(rebuild) {
_glPrecalcLightingValues(mask);
}
}
void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) {
GLubyte idx = light & 0xF;
if(idx >= MAX_LIGHTS) {
if(idx >= MAX_GLDC_LIGHTS) {
_glKosThrowError(GL_INVALID_VALUE, __func__);
return;
}
LightSource* l = _glLightAt(idx);
switch(pname) {
case GL_CONSTANT_ATTENUATION:
LIGHTS[idx].constant_attenuation = param;
l->constant_attenuation = param;
break;
case GL_LINEAR_ATTENUATION:
LIGHTS[idx].linear_attenuation = param;
l->linear_attenuation = param;
break;
case GL_QUADRATIC_ATTENUATION:
LIGHTS[idx].quadratic_attenuation = param;
l->quadratic_attenuation = param;
break;
case GL_SPOT_EXPONENT:
l->spot_exponent = param;
break;
case GL_SPOT_CUTOFF:
l->spot_cutoff = param;
break;
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
}
}
void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param) {
if(face == GL_BACK || pname != GL_SHININESS) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
return;
}
MATERIAL.exponent = param;
_glActiveMaterial()->exponent = _MIN(param, 128); /* 128 is the max according to the GL spec */
}
void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param) {
@ -161,122 +267,378 @@ void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param) {
}
void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
if(pname == GL_SHININESS) {
glMaterialf(face, pname, *params);
return;
}
if(face == GL_BACK) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
return;
}
Material* material = _glActiveMaterial();
GLboolean rebuild = GL_FALSE;
switch(pname) {
case GL_AMBIENT:
memcpy(MATERIAL.ambient, params, sizeof(GLfloat) * 4);
case GL_SHININESS:
glMaterialf(face, pname, *params);
rebuild = GL_TRUE;
break;
case GL_AMBIENT: {
if(memcmp(material->ambient, params, sizeof(float) * 4) != 0) {
vec4cpy(material->ambient, params);
rebuild = GL_TRUE;
}
} break;
case GL_DIFFUSE:
memcpy(MATERIAL.diffuse, params, sizeof(GLfloat) * 4);
if(memcmp(material->diffuse, params, sizeof(float) * 4) != 0) {
vec4cpy(material->diffuse, params);
rebuild = GL_TRUE;
}
break;
case GL_SPECULAR:
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
if(memcmp(material->specular, params, sizeof(float) * 4) != 0) {
vec4cpy(material->specular, params);
rebuild = GL_TRUE;
}
break;
case GL_EMISSION:
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
if(memcmp(material->emissive, params, sizeof(float) * 4) != 0) {
vec4cpy(material->emissive, params);
rebuild = GL_TRUE;
}
break;
case GL_AMBIENT_AND_DIFFUSE: {
glMaterialfv(face, GL_AMBIENT, params);
glMaterialfv(face, GL_DIFFUSE, params);
rebuild = (
memcmp(material->ambient, params, sizeof(float) * 4) != 0 ||
memcmp(material->diffuse, params, sizeof(float) * 4) != 0
);
if(rebuild) {
vec4cpy(material->ambient, params);
vec4cpy(material->diffuse, params);
}
} break;
case GL_COLOR_INDEXES:
default: {
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
return;
}
}
if(rebuild) {
GLuint updateMask = (pname == GL_AMBIENT) ? AMBIENT_MASK:
(pname == GL_DIFFUSE) ? DIFFUSE_MASK:
(pname == GL_SPECULAR) ? SPECULAR_MASK:
(pname == GL_EMISSION) ? EMISSION_MASK:
(pname == GL_AMBIENT_AND_DIFFUSE) ? AMBIENT_MASK | DIFFUSE_MASK : 0;
_glPrecalcLightingValues(updateMask);
}
}
inline void initVec3(struct vec3f* v, const GLfloat* src) {
memcpy(v, src, sizeof(GLfloat) * 3);
void APIENTRY glColorMaterial(GLenum face, GLenum mode) {
if(face != GL_FRONT_AND_BACK) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
}
GLint validModes[] = {GL_AMBIENT, GL_DIFFUSE, GL_AMBIENT_AND_DIFFUSE, GL_EMISSION, GL_SPECULAR, 0};
if(_glCheckValidEnum(mode, validModes, __func__) != 0) {
return;
}
GLenum mask = (mode == GL_AMBIENT) ? AMBIENT_MASK:
(mode == GL_DIFFUSE) ? DIFFUSE_MASK:
(mode == GL_AMBIENT_AND_DIFFUSE) ? AMBIENT_MASK | DIFFUSE_MASK:
(mode == GL_EMISSION) ? EMISSION_MASK : SPECULAR_MASK;
_glSetColorMaterialMask(mask);
_glSetColorMaterialMode(mode);
}
/* Fast POW Implementation - Less accurate, but much faster than math.h */
#define EXP_A 184
#define EXP_C 16249
GL_FORCE_INLINE void bgra_to_float(const uint8_t* input, GLfloat* output) {
static const float scale = 1.0f / 255.0f;
static float FEXP(float y) {
union {
float d;
struct {
short j, i;
} n;
} eco;
eco.n.i = EXP_A * (y) + (EXP_C);
eco.n.j = 0;
return eco.d;
output[0] = ((float) input[R8IDX]) * scale;
output[1] = ((float) input[G8IDX]) * scale;
output[2] = ((float) input[B8IDX]) * scale;
output[3] = ((float) input[A8IDX]) * scale;
}
static float FLOG(float y) {
int *nTemp = (int *)&y;
y = (*nTemp) >> 16;
return (y - EXP_C) / EXP_A;
void _glUpdateColourMaterialA(const GLubyte* argb) {
Material* material = _glActiveMaterial();
float colour[4];
bgra_to_float(argb, colour);
vec4cpy(material->ambient, colour);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
}
static float FPOW(float b, float p) {
return FEXP(FLOG(b) * p);
void _glUpdateColourMaterialD(const GLubyte* argb) {
Material* material = _glActiveMaterial();
float colour[4];
bgra_to_float(argb, colour);
vec4cpy(material->diffuse, colour);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
}
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) __attribute__((optimize("fast-math")));
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour) {
LightSource* l = &LIGHTS[light];
void _glUpdateColourMaterialE(const GLubyte* argb) {
Material* material = _glActiveMaterial();
struct vec3f L = {
l->position[0] - pos[0],
l->position[1] - pos[1],
l->position[2] - pos[2]
};
float colour[4];
bgra_to_float(argb, colour);
vec4cpy(material->emissive, colour);
struct vec3f N = {
normal[0],
normal[1],
normal[2]
};
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
}
struct vec3f V = {
pos[0],
pos[1],
pos[2]
};
void _glUpdateColourMaterialAD(const GLubyte* argb) {
Material* material = _glActiveMaterial();
GLfloat d;
vec3f_length(L.x, L.y, L.z, d);
float colour[4];
bgra_to_float(argb, colour);
vec4cpy(material->ambient, colour);
vec4cpy(material->diffuse, colour);
vec3f_normalize(L.x, L.y, L.z);
vec3f_normalize(V.x, V.y, V.z);
GLenum mask = _glColorMaterialMode();
_glPrecalcLightingValues(mask);
}
GLfloat NdotL;
vec3f_dot(N.x, N.y, N.z, L.x, L.y, L.z, NdotL);
GLfloat f = (NdotL < 0) ? 0 : 1;
GLfloat VdotN;
vec3f_dot(V.x, V.y, V.z, N.x, N.y, N.z, VdotN);
GLfloat VdotR = VdotN - NdotL;
GLfloat specularPower = FPOW(VdotR > 0 ? VdotR : 0, MATERIAL.exponent);
GLfloat att = (l->position[3] == 0.0f) ? 1.0f : (
1.0f / (l->constant_attenuation + (l->linear_attenuation * d) + (l->quadratic_attenuation * d * d))
GL_FORCE_INLINE GLboolean isDiffuseColorMaterial() {
GLenum mode = _glColorMaterialMode();
return (
mode == GL_DIFFUSE ||
mode == GL_AMBIENT_AND_DIFFUSE
);
colour[0] = att * (l->ambient[0] * MATERIAL.ambient[0] + f * (l->diffuse[0] * MATERIAL.diffuse[0] * NdotL + l->specular[0] * MATERIAL.specular[0] * specularPower));
colour[1] = att * (l->ambient[1] * MATERIAL.ambient[1] + f * (l->diffuse[1] * MATERIAL.diffuse[1] * NdotL + l->specular[1] * MATERIAL.specular[1] * specularPower));
colour[2] = att * (l->ambient[2] * MATERIAL.ambient[2] + f * (l->diffuse[2] * MATERIAL.diffuse[2] * NdotL + l->specular[2] * MATERIAL.specular[2] * specularPower));
colour[3] = MATERIAL.diffuse[3];
if(colour[0] > 1.0f) colour[0] = 1.0f;
if(colour[1] > 1.0f) colour[1] = 1.0f;
if(colour[2] > 1.0f) colour[2] = 1.0f;
if(colour[3] > 1.0f) colour[3] = 1.0f;
}
GL_FORCE_INLINE GLboolean isAmbientColorMaterial() {
GLenum mode = _glColorMaterialMode();
return (
mode == GL_AMBIENT ||
mode == GL_AMBIENT_AND_DIFFUSE
);
}
GL_FORCE_INLINE GLboolean isSpecularColorMaterial() {
GLenum mode = _glColorMaterialMode();
return (mode == GL_SPECULAR);
}
/*
* Implementation from here (MIT):
* https://github.com/appleseedhq/appleseed/blob/master/src/appleseed/foundation/math/fastmath.h
*/
GL_FORCE_INLINE float faster_pow2(const float p) {
// Underflow of exponential is common practice in numerical routines, so handle it here.
const float clipp = p < -126.0f ? -126.0f : p;
const union { uint32_t i; float f; } v =
{
(uint32_t) ((1 << 23) * (clipp + 126.94269504f))
};
return v.f;
}
GL_FORCE_INLINE float faster_log2(const float x) {
gl_assert(x >= 0.0f);
const union { float f; uint32_t i; } vx = { x };
const float y = (float) (vx.i) * 1.1920928955078125e-7f;
return y - 126.94269504f;
}
GL_FORCE_INLINE float faster_pow(const float x, const float p) {
return faster_pow2(p * faster_log2(x));
}
GL_FORCE_INLINE void _glLightVertexDirectional(
float* final, uint8_t lid,
float LdotN, float NdotH) {
Material* material = _glActiveMaterial();
LightSource* light = _glLightAt(lid);
float FI = (material->exponent) ?
faster_pow((LdotN != 0.0f) * NdotH, material->exponent) : 1.0f;
#define _PROCESS_COMPONENT(X) \
final[X] += (LdotN * light->diffuseMaterial[X] + light->ambientMaterial[X]) \
+ (FI * light->specularMaterial[X]); \
_PROCESS_COMPONENT(0);
_PROCESS_COMPONENT(1);
_PROCESS_COMPONENT(2);
#undef _PROCESS_COMPONENT
}
GL_FORCE_INLINE void _glLightVertexPoint(
float* final, uint8_t lid,
float LdotN, float NdotH, float att) {
Material* material = _glActiveMaterial();
LightSource* light = _glLightAt(lid);
float FI = (material->exponent) ?
faster_pow((LdotN != 0.0f) * NdotH, material->exponent) : 1.0f;
#define _PROCESS_COMPONENT(X) \
final[X] += ((LdotN * light->diffuseMaterial[X] + light->ambientMaterial[X]) \
+ (FI * light->specularMaterial[X])) * att; \
_PROCESS_COMPONENT(0);
_PROCESS_COMPONENT(1);
_PROCESS_COMPONENT(2);
#undef _PROCESS_COMPONENT
}
void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count) {
GLubyte i;
GLuint j;
Material* material = _glActiveMaterial();
Vertex* vertex = vertices;
EyeSpaceData* data = es;
/* Calculate the colour material function once */
void (*updateColourMaterial)(const GLubyte*) = NULL;
if(_glIsColorMaterialEnabled()) {
GLenum mode = _glColorMaterialMode();
switch(mode) {
case GL_AMBIENT:
updateColourMaterial = _glUpdateColourMaterialA;
break;
case GL_DIFFUSE:
updateColourMaterial = _glUpdateColourMaterialD;
break;
case GL_EMISSION:
updateColourMaterial = _glUpdateColourMaterialE;
break;
case GL_AMBIENT_AND_DIFFUSE:
updateColourMaterial = _glUpdateColourMaterialAD;
break;
}
}
/* Calculate the ambient lighting and set up colour material */
for(j = 0; j < count; ++j, ++vertex, ++data) {
if(updateColourMaterial) {
updateColourMaterial(vertex->bgra);
}
/* Copy the base colour across */
vec4cpy(data->finalColour, material->baseColour);
}
if(!_glEnabledLightCount()) {
return;
}
vertex = vertices;
data = es;
for(j = 0; j < count; ++j, ++vertex, ++data) {
/* Direction to vertex in eye space */
float Vx = -vertex->xyz[0];
float Vy = -vertex->xyz[1];
float Vz = -vertex->xyz[2];
VEC3_NORMALIZE(Vx, Vy, Vz);
const float Nx = data->n[0];
const float Ny = data->n[1];
const float Nz = data->n[2];
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
LightSource* light = _glLightAt(i);
if(!light->isEnabled) {
continue;
}
float Lx = light->position[0] - vertex->xyz[0];
float Ly = light->position[1] - vertex->xyz[1];
float Lz = light->position[2] - vertex->xyz[2];
if(light->isDirectional) {
float Hx = (Lx + 0);
float Hy = (Ly + 0);
float Hz = (Lz + 1);
VEC3_NORMALIZE(Lx, Ly, Lz);
VEC3_NORMALIZE(Hx, Hy, Hz);
float LdotN, NdotH;
VEC3_DOT(
Nx, Ny, Nz, Lx, Ly, Lz, LdotN
);
VEC3_DOT(
Nx, Ny, Nz, Hx, Hy, Hz, NdotH
);
if(LdotN < 0.0f) LdotN = 0.0f;
if(NdotH < 0.0f) NdotH = 0.0f;
_glLightVertexDirectional(
data->finalColour,
i, LdotN, NdotH
);
} else {
float D;
VEC3_LENGTH(Lx, Ly, Lz, D);
float att = (
light->constant_attenuation + (
light->linear_attenuation * D
) + (light->quadratic_attenuation * D * D)
);
/* Anything over the attenuation threshold will
* be a tiny value after inversion (< 0.01f) so
* let's just skip the lighting at that point */
if(att < ATTENUATION_THRESHOLD) {
att = MATH_Fast_Invert(att);
float Hx = (Lx + Vx);
float Hy = (Ly + Vy);
float Hz = (Lz + Vz);
VEC3_NORMALIZE(Lx, Ly, Lz);
VEC3_NORMALIZE(Hx, Hy, Hz);
float LdotN, NdotH;
VEC3_DOT(
Nx, Ny, Nz, Lx, Ly, Lz, LdotN
);
VEC3_DOT(
Nx, Ny, Nz, Hx, Hy, Hz, NdotH
);
if(LdotN < 0.0f) LdotN = 0.0f;
if(NdotH < 0.0f) NdotH = 0.0f;
_glLightVertexPoint(
data->finalColour,
i, LdotN, NdotH, att
);
}
}
}
vertex->bgra[R8IDX] = clamp(data->finalColour[0] * 255.0f, 0, 255);
vertex->bgra[G8IDX] = clamp(data->finalColour[1] * 255.0f, 0, 255);
vertex->bgra[B8IDX] = clamp(data->finalColour[2] * 255.0f, 0, 255);
vertex->bgra[A8IDX] = clamp(data->finalColour[3] * 255.0f, 0, 255);
}
}
#undef LIGHT_COMPONENT

View File

@ -1,49 +1,57 @@
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <dc/matrix.h>
#include "private.h"
#include "../include/gl.h"
#include "../containers/stack.h"
#define DEG2RAD (0.01745329251994329576923690768489)
/* Viewport mapping */
static GLfloat gl_viewport_scale[3], gl_viewport_offset[3];
/* Depth range */
static GLclampf gl_depthrange_near, gl_depthrange_far;
GLfloat DEPTH_RANGE_MULTIPLIER_L = (1 - 0) / 2;
GLfloat DEPTH_RANGE_MULTIPLIER_H = (0 + 1) / 2;
/* Viewport size */
static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height;
static Stack __attribute__((aligned(32))) MATRIX_STACKS[4]; // modelview, projection, texture
static Matrix4x4 __attribute__((aligned(32))) NORMAL_MATRIX;
static Stack MATRIX_STACKS[3]; // modelview, projection, texture
static matrix_t NORMAL_MATRIX __attribute__((aligned(32)));
static matrix_t SCREENVIEW_MATRIX __attribute__((aligned(32)));
static matrix_t RENDER_MATRIX __attribute__((aligned(32)));
Viewport VIEWPORT = {
0, 0, 640, 480, 320.0f, 240.0f, 320.0f, 240.0f
};
static GLenum MATRIX_MODE = GL_MODELVIEW;
static GLubyte MATRIX_IDX = 0;
static const matrix_t IDENTITY = {
{1.0f, 0.0f, 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, 0.0f},
{0.0f, 0.0f, 0.0f, 1.0f}
static const Matrix4x4 __attribute__((aligned(32))) IDENTITY = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
void APIENTRY glDepthRange(GLclampf n, GLclampf f);
GLfloat NEAR_PLANE_DISTANCE = 0.0f;
void initMatrices() {
init_stack(&MATRIX_STACKS[0], sizeof(matrix_t), 32);
init_stack(&MATRIX_STACKS[1], sizeof(matrix_t), 32);
init_stack(&MATRIX_STACKS[2], sizeof(matrix_t), 32);
Matrix4x4* _glGetProjectionMatrix() {
return (Matrix4x4*) stack_top(&MATRIX_STACKS[1]);
}
Matrix4x4* _glGetModelViewMatrix() {
return (Matrix4x4*) stack_top(&MATRIX_STACKS[0]);
}
void _glInitMatrices() {
init_stack(&MATRIX_STACKS[0], sizeof(Matrix4x4), 32);
init_stack(&MATRIX_STACKS[1], sizeof(Matrix4x4), 32);
init_stack(&MATRIX_STACKS[2], sizeof(Matrix4x4), 32);
stack_push(&MATRIX_STACKS[0], IDENTITY);
stack_push(&MATRIX_STACKS[1], IDENTITY);
stack_push(&MATRIX_STACKS[2], IDENTITY);
memcpy(NORMAL_MATRIX, IDENTITY, sizeof(matrix_t));
memcpy(SCREENVIEW_MATRIX, IDENTITY, sizeof(matrix_t));
MEMCPY4(NORMAL_MATRIX, IDENTITY, sizeof(Matrix4x4));
const VideoMode* vid_mode = GetVideoMode();
glDepthRange(0.0f, 1.0f);
glViewport(0, 0, vid_mode->width, vid_mode->height);
@ -87,7 +95,7 @@ static void transpose(GLfloat* m) {
}
static void recalculateNormalMatrix() {
memcpy(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(matrix_t));
MEMCPY4(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(Matrix4x4));
inverse((GLfloat*) NORMAL_MATRIX);
transpose((GLfloat*) NORMAL_MATRIX);
}
@ -98,7 +106,11 @@ void APIENTRY glMatrixMode(GLenum mode) {
}
void APIENTRY glPushMatrix() {
stack_push(MATRIX_STACKS + MATRIX_IDX, stack_top(MATRIX_STACKS + MATRIX_IDX));
void* top = stack_top(MATRIX_STACKS + MATRIX_IDX);
assert(top);
void* ret = stack_push(MATRIX_STACKS + MATRIX_IDX, top);
(void) ret;
assert(ret);
}
void APIENTRY glPopMatrix() {
@ -113,9 +125,22 @@ void APIENTRY glLoadIdentity() {
}
void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_translate(x, y, z);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
const Matrix4x4 trn __attribute__((aligned(32))) = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
x, y, z, 1.0f
};
void* top = stack_top(MATRIX_STACKS + MATRIX_IDX);
assert(top);
UploadMatrix4x4(top);
MultiplyMatrix4x4(&trn);
top = stack_top(MATRIX_STACKS + MATRIX_IDX);
assert(top);
DownloadMatrix4x4(top);
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -124,9 +149,16 @@ void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) {
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_scale(x, y, z);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
const Matrix4x4 scale __attribute__((aligned(32))) = {
x, 0.0f, 0.0f, 0.0f,
0.0f, y, 0.0f, 0.0f,
0.0f, 0.0f, z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
MultiplyMatrix4x4(&scale);
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -134,13 +166,42 @@ void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) {
}
void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
float r = DEG2RAD * -angle;
Matrix4x4 rotate __attribute__((aligned(32))) = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
vec3f_normalize(x, y, z);
float r = DEG2RAD * angle;
float c = cos(r);
float s = sin(r);
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_rotate(r * x, r * y, r * z);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
VEC3_NORMALIZE(x, y, z);
float invc = 1.0f - c;
float xs = x * s;
float zs = z * s;
float ys = y * s;
float xz = x * z;
float xy = y * x;
float yz = y * z;
rotate[M0] = (x * x) * invc + c;
rotate[M1] = xy * invc + zs;
rotate[M2] = xz * invc - ys;
rotate[M4] = xy * invc - zs;
rotate[M5] = (y * y) * invc + c;
rotate[M6] = yz * invc + xs;
rotate[M8] = xz * invc + ys;
rotate[M9] = yz * invc - xs;
rotate[M10] = (z * z) * invc + c;
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
MultiplyMatrix4x4((const Matrix4x4*) &rotate);
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -149,7 +210,10 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
/* Load an arbitrary matrix */
void APIENTRY glLoadMatrixf(const GLfloat *m) {
stack_replace(MATRIX_STACKS + MATRIX_IDX, m);
static Matrix4x4 __attribute__((aligned(32))) TEMP;
memcpy(TEMP, m, sizeof(float) * 16);
stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP);
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -162,23 +226,23 @@ void APIENTRY glOrtho(GLfloat left, GLfloat right,
GLfloat znear, GLfloat zfar) {
/* Ortho Matrix */
static matrix_t OrthoMatrix __attribute__((aligned(32))) = {
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f }
Matrix4x4 OrthoMatrix __attribute__((aligned(32))) = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
OrthoMatrix[0][0] = 2.0f / (right - left);
OrthoMatrix[1][1] = 2.0f / (top - bottom);
OrthoMatrix[2][2] = -2.0f / (zfar - znear);
OrthoMatrix[3][0] = -(right + left) / (right - left);;
OrthoMatrix[3][1] = -(top + bottom) / (top - bottom);
OrthoMatrix[3][2] = -(zfar + znear) / (zfar - znear);
OrthoMatrix[M0] = 2.0f / (right - left);
OrthoMatrix[M5] = 2.0f / (top - bottom);
OrthoMatrix[M10] = -2.0f / (zfar - znear);
OrthoMatrix[M12] = -(right + left) / (right - left);
OrthoMatrix[M13] = -(top + bottom) / (top - bottom);
OrthoMatrix[M14] = -(zfar + znear) / (zfar - znear);
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_apply(&OrthoMatrix);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
MultiplyMatrix4x4((const Matrix4x4*) &OrthoMatrix);
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
}
@ -188,40 +252,39 @@ void APIENTRY glFrustum(GLfloat left, GLfloat right,
GLfloat znear, GLfloat zfar) {
/* Frustum Matrix */
static matrix_t FrustumMatrix __attribute__((aligned(32))) = {
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, -1.0f },
{ 0.0f, 0.0f, 0.0f, 0.0f }
};
Matrix4x4 FrustumMatrix __attribute__((aligned(32)));
FrustumMatrix[0][0] = (2.0f * znear) / (right - left);
FrustumMatrix[2][0] = (right + left) / (right - left);
FrustumMatrix[1][1] = (2.0f * znear) / (top - bottom);
FrustumMatrix[2][1] = (top + bottom) / (top - bottom);
FrustumMatrix[2][2] = zfar / (zfar - znear);
FrustumMatrix[3][2] = -(zfar * znear) / (zfar - znear);
MEMSET(FrustumMatrix, 0, sizeof(float) * 16);
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_apply(&FrustumMatrix);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
const float near2 = 2.0f * znear;
const float A = (right + left) / (right - left);
const float B = (top + bottom) / (top - bottom);
const float C = -((zfar + znear) / (zfar - znear));
const float D = -((2.0f * zfar * znear) / (zfar - znear));
FrustumMatrix[M0] = near2 / (right - left);
FrustumMatrix[M5] = near2 / (top - bottom);
FrustumMatrix[M8] = A;
FrustumMatrix[M9] = B;
FrustumMatrix[M10] = C;
FrustumMatrix[M11] = -1.0f;
FrustumMatrix[M14] = D;
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
MultiplyMatrix4x4((const Matrix4x4*) &FrustumMatrix);
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
}
/* Multiply the current matrix by an arbitrary matrix */
void glMultMatrixf(const GLfloat *m) {
static matrix_t TEMP __attribute__((aligned(32))) = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f }
};
Matrix4x4 TEMP __attribute__((aligned(32)));
MEMCPY4(TEMP, m, sizeof(Matrix4x4));
memcpy(TEMP, m, sizeof(matrix_t));
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_apply(&TEMP);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
MultiplyMatrix4x4(&TEMP);
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -230,8 +293,32 @@ void glMultMatrixf(const GLfloat *m) {
/* Load an arbitrary transposed matrix */
void glLoadTransposeMatrixf(const GLfloat *m) {
stack_replace(MATRIX_STACKS + MATRIX_IDX, m);
transpose(stack_top(MATRIX_STACKS + MATRIX_IDX));
/* We store matrices transpose anyway, so m will be
* transpose compared to all other matrices */
static Matrix4x4 TEMP __attribute__((aligned(32)));
TEMP[M0] = m[0];
TEMP[M1] = m[4];
TEMP[M2] = m[8];
TEMP[M3] = m[12];
TEMP[M4] = m[1];
TEMP[M5] = m[5];
TEMP[M6] = m[9];
TEMP[M7] = m[13];
TEMP[M8] = m[3];
TEMP[M9] = m[6];
TEMP[M10] = m[10];
TEMP[M11] = m[14];
TEMP[M12] = m[4];
TEMP[M13] = m[7];
TEMP[M14] = m[11];
TEMP[M15] = m[15];
stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP);
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -240,28 +327,31 @@ void glLoadTransposeMatrixf(const GLfloat *m) {
/* Multiply the current matrix by an arbitrary transposed matrix */
void glMultTransposeMatrixf(const GLfloat *m) {
static matrix_t ml;
static Matrix4x4 TEMP __attribute__((aligned(32)));
ml[0][0] = m[0];
ml[0][1] = m[4];
ml[0][2] = m[8];
ml[0][3] = m[12];
ml[1][0] = m[1];
ml[1][1] = m[5];
ml[1][2] = m[9];
ml[1][3] = m[13];
ml[2][0] = m[2];
ml[2][1] = m[6];
ml[2][2] = m[10];
ml[2][3] = m[14];
ml[3][0] = m[3];
ml[3][1] = m[7];
ml[3][2] = m[11];
ml[3][3] = m[15];
TEMP[M0] = m[0];
TEMP[M1] = m[4];
TEMP[M2] = m[8];
TEMP[M3] = m[12];
mat_load(stack_top(MATRIX_STACKS + MATRIX_IDX));
mat_apply(&ml);
mat_store(stack_top(MATRIX_STACKS + MATRIX_IDX));
TEMP[M4] = m[1];
TEMP[M5] = m[5];
TEMP[M6] = m[9];
TEMP[M7] = m[13];
TEMP[M8] = m[3];
TEMP[M9] = m[6];
TEMP[M10] = m[10];
TEMP[M11] = m[14];
TEMP[M12] = m[4];
TEMP[M13] = m[7];
TEMP[M14] = m[11];
TEMP[M15] = m[15];
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
MultiplyMatrix4x4((const Matrix4x4*) &TEMP);
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
if(MATRIX_MODE == GL_MODELVIEW) {
recalculateNormalMatrix();
@ -270,137 +360,113 @@ void glMultTransposeMatrixf(const GLfloat *m) {
/* Set the GL viewport */
void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
gl_viewport_x1 = x;
gl_viewport_y1 = y;
gl_viewport_width = width;
gl_viewport_height = height;
/* Calculate the viewport scale and offset */
gl_viewport_scale[0] = (GLfloat)width / 2.0f;
gl_viewport_offset[0] = gl_viewport_scale[0] + (GLfloat)x;
gl_viewport_scale[1] = (GLfloat)height / 2.0f;
gl_viewport_offset[1] = gl_viewport_scale[1] + (GLfloat)y;
gl_viewport_scale[2] = (gl_depthrange_far - gl_depthrange_near) / 2.0f;
gl_viewport_offset[2] = (gl_depthrange_near + gl_depthrange_far) / 2.0f;
gl_viewport_offset[2] += 0.0001f;
/* Set the Screenview Matrix based on the viewport */
SCREENVIEW_MATRIX[0][0] = gl_viewport_scale[0];
SCREENVIEW_MATRIX[1][1] = -gl_viewport_scale[1];
SCREENVIEW_MATRIX[2][2] = 1;
SCREENVIEW_MATRIX[3][0] = gl_viewport_offset[0];
SCREENVIEW_MATRIX[3][1] = vid_mode->height - gl_viewport_offset[1];
VIEWPORT.x = x;
VIEWPORT.y = y;
VIEWPORT.width = width;
VIEWPORT.height = height;
VIEWPORT.hwidth = ((GLfloat) VIEWPORT.width) * 0.5f;
VIEWPORT.hheight = ((GLfloat) VIEWPORT.height) * 0.5f;
VIEWPORT.x_plus_hwidth = VIEWPORT.x + VIEWPORT.hwidth;
VIEWPORT.y_plus_hheight = VIEWPORT.y + VIEWPORT.hheight;
}
/* Set the depth range */
void APIENTRY glDepthRange(GLclampf n, GLclampf f) {
/* clamp the values... */
void APIENTRY glDepthRangef(GLclampf n, GLclampf f) {
if(n < 0.0f) n = 0.0f;
else if(n > 1.0f) n = 1.0f;
if(f < 0.0f) f = 0.0f;
else if(f > 1.0f) f = 1.0f;
gl_depthrange_near = n;
gl_depthrange_far = f;
/* Adjust the viewport scale and offset for Z */
gl_viewport_scale[2] = ((f - n) / 2.0f);
gl_viewport_offset[2] = (n + f) / 2.0f;
DEPTH_RANGE_MULTIPLIER_L = (f - n) / 2.0f;
DEPTH_RANGE_MULTIPLIER_H = (n + f) / 2.0f;
}
/* Vector Cross Product - Used by glhLookAtf2 */
void APIENTRY glDepthRange(GLclampf n, GLclampf f){
glDepthRangef(n,f);
}
/* Vector Cross Product - Used by gluLookAt */
static inline void vec3f_cross(const GLfloat* v1, const GLfloat* v2, GLfloat* result) {
result[0] = v1[1] * v2[2] - v1[2] * v2[1];
result[1] = v1[2] * v2[0] - v1[0] * v2[2];
result[2] = v1[0] * v2[1] - v1[1] * v2[0];
}
/* glhLookAtf2 adapted from http://www.opengl.org/wiki/GluLookAt_code */
void glhLookAtf2(const GLfloat* eyePosition3D,
const GLfloat* center3D,
const GLfloat* upVector3D) {
GL_FORCE_INLINE void vec3f_normalize_sh4(float *v){
float length, ilength;
/* Look-At Matrix */
static matrix_t MatrixLookAt __attribute__((aligned(32))) = {
{ 1.0f, 0.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f, 0.0f },
{ 0.0f, 0.0f, 0.0f, 1.0f }
};
GLfloat forward[3];
GLfloat side[3];
GLfloat up[3];
vec3f_sub_normalize(center3D[0], center3D[1], center3D[2],
eyePosition3D[0], eyePosition3D[1], eyePosition3D[2],
forward[0], forward[1], forward[2]);
//Side = forward x up
vec3f_cross(forward, upVector3D, side);
vec3f_normalize(side[0], side[1], side[2]);
//Recompute up as: up = side x forward
vec3f_cross(side, forward, up);
MatrixLookAt[0][0] = side[0];
MatrixLookAt[1][0] = side[1];
MatrixLookAt[2][0] = side[2];
MatrixLookAt[3][0] = 0;
MatrixLookAt[0][1] = up[0];
MatrixLookAt[1][1] = up[1];
MatrixLookAt[2][1] = up[2];
MatrixLookAt[3][1] = 0;
MatrixLookAt[0][2] = -forward[0];
MatrixLookAt[1][2] = -forward[1];
MatrixLookAt[2][2] = -forward[2];
MatrixLookAt[3][2] = 0;
MatrixLookAt[0][3] =
MatrixLookAt[1][3] =
MatrixLookAt[2][3] = 0;
MatrixLookAt[3][3] = 1;
// Does not modify internal Modelview matrix
mat_load(&MatrixLookAt);
mat_translate(-eyePosition3D[0], -eyePosition3D[1], -eyePosition3D[2]);
mat_apply(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
mat_store(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
ilength = MATH_fsrra(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
length = MATH_Fast_Invert(ilength);
if (length)
{
v[0] *= ilength;
v[1] *= ilength;
v[2] *= ilength;
}
}
void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
GLfloat upz) {
GLfloat eye [] = { eyex, eyey, eyez };
GLfloat point [] = { centerx, centery, centerz };
GLfloat up [] = { upx, upy, upz };
glhLookAtf2(eye, point, up);
GLfloat m [16] __attribute__((aligned(32)));
GLfloat f [3];
GLfloat u [3];
GLfloat s [3];
f[0] = centerx - eyex;
f[1] = centery - eyey;
f[2] = centerz - eyez;
u[0] = upx;
u[1] = upy;
u[2] = upz;
vec3f_normalize_sh4(f);
vec3f_cross(f, u, s);
vec3f_normalize_sh4(s);
vec3f_cross(s, f, u);
m[0] = s[0]; m[4] = s[1]; m[8] = s[2]; m[12] = 0.0f;
m[1] = u[0]; m[5] = u[1]; m[9] = u[2]; m[13] = 0.0f;
m[2] = -f[0]; m[6] = -f[1]; m[10] = -f[2]; m[14] = 0.0f;
m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f;
static Matrix4x4 trn __attribute__((aligned(32))) = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};
trn[M12] = -eyex;
trn[M13] = -eyey;
trn[M14] = -eyez;
// Does not modify internal Modelview matrix
UploadMatrix4x4((const Matrix4x4*) &m);
MultiplyMatrix4x4((const Matrix4x4*) &trn);
MultiplyMatrix4x4(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
DownloadMatrix4x4(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
}
void _applyRenderMatrix() {
mat_load(&SCREENVIEW_MATRIX);
mat_apply(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
mat_apply(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
mat_store(&RENDER_MATRIX);
void _glMatrixLoadTexture() {
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF)));
}
void _matrixLoadRender() {
mat_load(&RENDER_MATRIX);
void _glMatrixLoadModelView() {
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
}
void _matrixLoadTexture() {
mat_load(stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF)));
void _glMatrixLoadProjection() {
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
}
void _matrixLoadModelView() {
mat_load(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
void _glMatrixLoadModelViewProjection() {
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
}
void _matrixLoadNormal() {
mat_load(&NORMAL_MATRIX);
void _glMatrixLoadNormal() {
UploadMatrix4x4((const Matrix4x4*) &NORMAL_MATRIX);
}

452
GL/platform.h Normal file
View File

@ -0,0 +1,452 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include "gl_assert.h"
#include "types.h"
#define MEMSET(dst, v, size) memset((dst), (v), (size))
typedef enum GPUAlpha {
GPU_ALPHA_DISABLE = 0,
GPU_ALPHA_ENABLE = 1
} GPUAlpha;
typedef enum GPUTexture {
GPU_TEXTURE_DISABLE = 0,
GPU_TEXTURE_ENABLE = 1
} GPUTexture;
typedef enum GPUTextureAlpha {
GPU_TXRALPHA_DISABLE = 1,
GPU_TXRALPHA_ENABLE = 0
} GPUTextureAlpha;
typedef enum GPUList {
GPU_LIST_OP_POLY = 0,
GPU_LIST_OP_MOD = 1,
GPU_LIST_TR_POLY = 2,
GPU_LIST_TR_MOD = 3,
GPU_LIST_PT_POLY = 4
} GPUList;
typedef enum GPUBlend {
GPU_BLEND_ZERO = 0,
GPU_BLEND_ONE = 1,
GPU_BLEND_DESTCOLOR = 2,
GPU_BLEND_INVDESTCOLOR = 3,
GPU_BLEND_SRCALPHA = 4,
GPU_BLEND_INVSRCALPHA = 5,
GPU_BLEND_DESTALPHA = 6,
GPU_BLEND_INVDESTALPHA = 7
} GPUBlend;
typedef enum GPUDepthCompare {
GPU_DEPTHCMP_NEVER = 0,
GPU_DEPTHCMP_LESS = 1,
GPU_DEPTHCMP_EQUAL = 2,
GPU_DEPTHCMP_LEQUAL = 3,
GPU_DEPTHCMP_GREATER = 4,
GPU_DEPTHCMP_NOTEQUAL = 5,
GPU_DEPTHCMP_GEQUAL = 6,
GPU_DEPTHCMP_ALWAYS = 7
} GPUDepthCompare;
typedef enum GPUTextureFormat {
GPU_TXRFMT_NONE,
GPU_TXRFMT_VQ_DISABLE = (0 << 30),
GPU_TXRFMT_VQ_ENABLE = (1 << 30),
GPU_TXRFMT_ARGB1555 = (0 << 27),
GPU_TXRFMT_RGB565 = (1 << 27),
GPU_TXRFMT_ARGB4444 = (2 << 27),
GPU_TXRFMT_YUV422 = (3 << 27),
GPU_TXRFMT_BUMP = (4 << 27),
GPU_TXRFMT_PAL4BPP = (5 << 27),
GPU_TXRFMT_PAL8BPP = (6 << 27),
GPU_TXRFMT_TWIDDLED = (0 << 26),
GPU_TXRFMT_NONTWIDDLED = (1 << 26),
GPU_TXRFMT_NOSTRIDE = (0 << 21),
GPU_TXRFMT_STRIDE = (1 << 21)
} GPUTextureFormat;
static inline uint32_t GPUPaletteSelect8BPP(uint32_t x) {
return x << 25;
}
static inline uint32_t GPUPaletteSelect4BPP(uint32_t x) {
return x << 21;
}
typedef enum GPUCulling {
GPU_CULLING_NONE = 0,
GPU_CULLING_SMALL = 1,
GPU_CULLING_CCW = 2,
GPU_CULLING_CW = 3
} GPUCulling;
typedef enum GPUUVFlip {
GPU_UVFLIP_NONE = 0,
GPU_UVFLIP_V = 1,
GPU_UVFLIP_U = 2,
GPU_UVFLIP_UV = 3
} GPUUVFlip;
typedef enum GPUUVClamp {
GPU_UVCLAMP_NONE = 0,
GPU_UVCLAMP_V = 1,
GPU_UVCLAMP_U = 2,
GPU_UVCLAMP_UV = 3
} GPUUVClamp;
typedef enum GPUColorClamp {
GPU_CLRCLAMP_DISABLE = 0,
GPU_CLRCLAMP_ENABLE = 1
} GPUColorClamp;
typedef enum GPUFilter {
GPU_FILTER_NEAREST = 0,
GPU_FILTER_BILINEAR = 2,
GPU_FILTER_TRILINEAR1 = 4,
GPU_FILTER_TRILINEAR2 = 6
} GPUFilter;
typedef enum GPUDepthWrite {
GPU_DEPTHWRITE_ENABLE = 0,
GPU_DEPTHWRITE_DISABLE = 1
} GPUDepthWrite;
typedef enum GPUUserClip {
GPU_USERCLIP_DISABLE = 0,
GPU_USERCLIP_INSIDE = 2,
GPU_USERCLIP_OUTSIDE = 3
} GPUUserClip;
typedef enum GPUColorFormat {
GPU_CLRFMT_ARGBPACKED = 0,
GPU_CLRFMT_4FLOATS = 1,
GPU_CLRFMT_INTENSITY = 2,
GPU_CLRFMT_INTENSITY_PREV = 3
} GPUColorFormat;
typedef enum GPUUVFormat {
GPU_UVFMT_32BIT = 0,
GPU_UVFMT_16BIT = 1
} GPUUVFormat;
typedef enum GPUPaletteFormat {
GPU_PAL_ARGB1555 = 0,
GPU_PAL_RGB565 = 1,
GPU_PAL_ARGB4444 = 2,
GPU_PAL_ARGB8888 = 3
} GPUPaletteFormat;
typedef enum GPUFog {
GPU_FOG_TABLE = 0,
GPU_FOG_VERTEX = 1,
GPU_FOG_DISABLE = 2,
GPU_FOG_TABLE2 = 3
} GPUFog;
typedef enum GPUShade {
GPU_SHADE_FLAT = 0,
GPU_SHADE_GOURAUD = 1
} GPUShade;
typedef enum GPUTextureEnv {
GPU_TXRENV_REPLACE = 0,
GPU_TXRENV_MODULATE = 1,
GPU_TXRENV_DECAL = 2,
GPU_TXRENV_MODULATEALPHA = 3
} GPUTextureEnv;
typedef struct VideoMode {
uint16_t width;
uint16_t height;
} VideoMode;
const VideoMode* GetVideoMode();
/* Duplication of pvr_poly_cxt_t from KOS so that we can
* compile on non-KOS platforms for testing */
typedef struct {
GPUList list_type;
struct {
int alpha;
int shading;
int fog_type;
int culling;
int color_clamp;
int clip_mode;
int modifier_mode;
int specular;
int alpha2;
int fog_type2;
int color_clamp2;
} gen;
struct {
int src;
int dst;
int src_enable;
int dst_enable;
int src2;
int dst2;
int src_enable2;
int dst_enable2;
} blend;
struct {
int color;
int uv;
int modifier;
} fmt;
struct {
int comparison;
int write;
} depth;
struct {
int enable;
int filter;
int mipmap;
int mipmap_bias;
int uv_flip;
int uv_clamp;
int alpha;
int env;
int width;
int height;
int format;
void* base;
} txr;
struct {
int enable;
int filter;
int mipmap;
int mipmap_bias;
int uv_flip;
int uv_clamp;
int alpha;
int env;
int width;
int height;
int format;
void* base;
} txr2;
} PolyContext;
typedef struct {
uint32_t cmd;
uint32_t mode1;
uint32_t mode2;
uint32_t mode3;
uint32_t d1;
uint32_t d2;
uint32_t d3;
uint32_t d4;
} PolyHeader;
enum GPUCommand {
GPU_CMD_POLYHDR = 0x80840000,
GPU_CMD_VERTEX = 0xe0000000,
GPU_CMD_VERTEX_EOL = 0xf0000000,
GPU_CMD_USERCLIP = 0x20000000,
GPU_CMD_MODIFIER = 0x80000000,
GPU_CMD_SPRITE = 0xA0000000
};
typedef float Matrix4x4[16];
void SceneBegin();
void SceneListBegin(GPUList list);
void SceneListSubmit(Vertex* v2, int n);
void SceneListFinish();
void SceneFinish();
#define GPU_TA_CMD_TYPE_SHIFT 24
#define GPU_TA_CMD_TYPE_MASK (7 << GPU_TA_CMD_TYPE_SHIFT)
#define GPU_TA_CMD_USERCLIP_SHIFT 16
#define GPU_TA_CMD_USERCLIP_MASK (3 << GPU_TA_CMD_USERCLIP_SHIFT)
#define GPU_TA_CMD_CLRFMT_SHIFT 4
#define GPU_TA_CMD_CLRFMT_MASK (7 << GPU_TA_CMD_CLRFMT_SHIFT)
#define GPU_TA_CMD_SPECULAR_SHIFT 2
#define GPU_TA_CMD_SPECULAR_MASK (1 << GPU_TA_CMD_SPECULAR_SHIFT)
#define GPU_TA_CMD_SHADE_SHIFT 1
#define GPU_TA_CMD_SHADE_MASK (1 << GPU_TA_CMD_SHADE_SHIFT)
#define GPU_TA_CMD_UVFMT_SHIFT 0
#define GPU_TA_CMD_UVFMT_MASK (1 << GPU_TA_CMD_UVFMT_SHIFT)
#define GPU_TA_CMD_MODIFIER_SHIFT 7
#define GPU_TA_CMD_MODIFIER_MASK (1 << GPU_TA_CMD_MODIFIER_SHIFT)
#define GPU_TA_CMD_MODIFIERMODE_SHIFT 6
#define GPU_TA_CMD_MODIFIERMODE_MASK (1 << GPU_TA_CMD_MODIFIERMODE_SHIFT)
#define GPU_TA_PM1_DEPTHCMP_SHIFT 29
#define GPU_TA_PM1_DEPTHCMP_MASK (7 << GPU_TA_PM1_DEPTHCMP_SHIFT)
#define GPU_TA_PM1_CULLING_SHIFT 27
#define GPU_TA_PM1_CULLING_MASK (3 << GPU_TA_PM1_CULLING_SHIFT)
#define GPU_TA_PM1_DEPTHWRITE_SHIFT 26
#define GPU_TA_PM1_DEPTHWRITE_MASK (1 << GPU_TA_PM1_DEPTHWRITE_SHIFT)
#define GPU_TA_PM1_TXRENABLE_SHIFT 25
#define GPU_TA_PM1_TXRENABLE_MASK (1 << GPU_TA_PM1_TXRENABLE_SHIFT)
#define GPU_TA_PM1_MODIFIERINST_SHIFT 29
#define GPU_TA_PM1_MODIFIERINST_MASK (3 << GPU_TA_PM1_MODIFIERINST_SHIFT)
#define GPU_TA_PM2_SRCBLEND_SHIFT 29
#define GPU_TA_PM2_SRCBLEND_MASK (7 << GPU_TA_PM2_SRCBLEND_SHIFT)
#define GPU_TA_PM2_DSTBLEND_SHIFT 26
#define GPU_TA_PM2_DSTBLEND_MASK (7 << GPU_TA_PM2_DSTBLEND_SHIFT)
#define GPU_TA_PM2_SRCENABLE_SHIFT 25
#define GPU_TA_PM2_SRCENABLE_MASK (1 << GPU_TA_PM2_SRCENABLE_SHIFT)
#define GPU_TA_PM2_DSTENABLE_SHIFT 24
#define GPU_TA_PM2_DSTENABLE_MASK (1 << GPU_TA_PM2_DSTENABLE_SHIFT)
#define GPU_TA_PM2_FOG_SHIFT 22
#define GPU_TA_PM2_FOG_MASK (3 << GPU_TA_PM2_FOG_SHIFT)
#define GPU_TA_PM2_CLAMP_SHIFT 21
#define GPU_TA_PM2_CLAMP_MASK (1 << GPU_TA_PM2_CLAMP_SHIFT)
#define GPU_TA_PM2_ALPHA_SHIFT 20
#define GPU_TA_PM2_ALPHA_MASK (1 << GPU_TA_PM2_ALPHA_SHIFT)
#define GPU_TA_PM2_TXRALPHA_SHIFT 19
#define GPU_TA_PM2_TXRALPHA_MASK (1 << GPU_TA_PM2_TXRALPHA_SHIFT)
#define GPU_TA_PM2_UVFLIP_SHIFT 17
#define GPU_TA_PM2_UVFLIP_MASK (3 << GPU_TA_PM2_UVFLIP_SHIFT)
#define GPU_TA_PM2_UVCLAMP_SHIFT 15
#define GPU_TA_PM2_UVCLAMP_MASK (3 << GPU_TA_PM2_UVCLAMP_SHIFT)
#define GPU_TA_PM2_FILTER_SHIFT 12
#define GPU_TA_PM2_FILTER_MASK (7 << GPU_TA_PM2_FILTER_SHIFT)
#define GPU_TA_PM2_MIPBIAS_SHIFT 8
#define GPU_TA_PM2_MIPBIAS_MASK (15 << GPU_TA_PM2_MIPBIAS_SHIFT)
#define GPU_TA_PM2_TXRENV_SHIFT 6
#define GPU_TA_PM2_TXRENV_MASK (3 << GPU_TA_PM2_TXRENV_SHIFT)
#define GPU_TA_PM2_USIZE_SHIFT 3
#define GPU_TA_PM2_USIZE_MASK (7 << GPU_TA_PM2_USIZE_SHIFT)
#define GPU_TA_PM2_VSIZE_SHIFT 0
#define GPU_TA_PM2_VSIZE_MASK (7 << GPU_TA_PM2_VSIZE_SHIFT)
#define GPU_TA_PM3_MIPMAP_SHIFT 31
#define GPU_TA_PM3_MIPMAP_MASK (1 << GPU_TA_PM3_MIPMAP_SHIFT)
#define GPU_TA_PM3_TXRFMT_SHIFT 0
#define GPU_TA_PM3_TXRFMT_MASK 0xffffffff
static inline int DimensionFlag(const int w) {
switch(w) {
case 16: return 1;
case 32: return 2;
case 64: return 3;
case 128: return 4;
case 256: return 5;
case 512: return 6;
case 1024: return 7;
case 8:
default:
return 0;
}
}
/* Compile a polygon context into a polygon header */
static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
uint32_t txr_base;
/* Basically we just take each parameter, clip it, shift it
into place, and OR it into the final result. */
/* The base values for CMD */
dst->cmd = GPU_CMD_POLYHDR;
dst->cmd |= src->txr.enable << 3;
/* Or in the list type, shading type, color and UV formats */
dst->cmd |= (src->list_type << GPU_TA_CMD_TYPE_SHIFT) & GPU_TA_CMD_TYPE_MASK;
dst->cmd |= (src->fmt.color << GPU_TA_CMD_CLRFMT_SHIFT) & GPU_TA_CMD_CLRFMT_MASK;
dst->cmd |= (src->gen.shading << GPU_TA_CMD_SHADE_SHIFT) & GPU_TA_CMD_SHADE_MASK;
dst->cmd |= (src->fmt.uv << GPU_TA_CMD_UVFMT_SHIFT) & GPU_TA_CMD_UVFMT_MASK;
dst->cmd |= (src->gen.clip_mode << GPU_TA_CMD_USERCLIP_SHIFT) & GPU_TA_CMD_USERCLIP_MASK;
dst->cmd |= (src->fmt.modifier << GPU_TA_CMD_MODIFIER_SHIFT) & GPU_TA_CMD_MODIFIER_MASK;
dst->cmd |= (src->gen.modifier_mode << GPU_TA_CMD_MODIFIERMODE_SHIFT) & GPU_TA_CMD_MODIFIERMODE_MASK;
dst->cmd |= (src->gen.specular << GPU_TA_CMD_SPECULAR_SHIFT) & GPU_TA_CMD_SPECULAR_MASK;
/* Polygon mode 1 */
dst->mode1 = (src->depth.comparison << GPU_TA_PM1_DEPTHCMP_SHIFT) & GPU_TA_PM1_DEPTHCMP_MASK;
dst->mode1 |= (src->gen.culling << GPU_TA_PM1_CULLING_SHIFT) & GPU_TA_PM1_CULLING_MASK;
dst->mode1 |= (src->depth.write << GPU_TA_PM1_DEPTHWRITE_SHIFT) & GPU_TA_PM1_DEPTHWRITE_MASK;
dst->mode1 |= (src->txr.enable << GPU_TA_PM1_TXRENABLE_SHIFT) & GPU_TA_PM1_TXRENABLE_MASK;
/* Polygon mode 2 */
dst->mode2 = (src->blend.src << GPU_TA_PM2_SRCBLEND_SHIFT) & GPU_TA_PM2_SRCBLEND_MASK;
dst->mode2 |= (src->blend.dst << GPU_TA_PM2_DSTBLEND_SHIFT) & GPU_TA_PM2_DSTBLEND_MASK;
dst->mode2 |= (src->blend.src_enable << GPU_TA_PM2_SRCENABLE_SHIFT) & GPU_TA_PM2_SRCENABLE_MASK;
dst->mode2 |= (src->blend.dst_enable << GPU_TA_PM2_DSTENABLE_SHIFT) & GPU_TA_PM2_DSTENABLE_MASK;
dst->mode2 |= (src->gen.fog_type << GPU_TA_PM2_FOG_SHIFT) & GPU_TA_PM2_FOG_MASK;
dst->mode2 |= (src->gen.color_clamp << GPU_TA_PM2_CLAMP_SHIFT) & GPU_TA_PM2_CLAMP_MASK;
dst->mode2 |= (src->gen.alpha << GPU_TA_PM2_ALPHA_SHIFT) & GPU_TA_PM2_ALPHA_MASK;
if(src->txr.enable == GPU_TEXTURE_DISABLE) {
dst->mode3 = 0;
}
else {
dst->mode2 |= (src->txr.alpha << GPU_TA_PM2_TXRALPHA_SHIFT) & GPU_TA_PM2_TXRALPHA_MASK;
dst->mode2 |= (src->txr.uv_flip << GPU_TA_PM2_UVFLIP_SHIFT) & GPU_TA_PM2_UVFLIP_MASK;
dst->mode2 |= (src->txr.uv_clamp << GPU_TA_PM2_UVCLAMP_SHIFT) & GPU_TA_PM2_UVCLAMP_MASK;
dst->mode2 |= (src->txr.filter << GPU_TA_PM2_FILTER_SHIFT) & GPU_TA_PM2_FILTER_MASK;
dst->mode2 |= (src->txr.mipmap_bias << GPU_TA_PM2_MIPBIAS_SHIFT) & GPU_TA_PM2_MIPBIAS_MASK;
dst->mode2 |= (src->txr.env << GPU_TA_PM2_TXRENV_SHIFT) & GPU_TA_PM2_TXRENV_MASK;
dst->mode2 |= (DimensionFlag(src->txr.width) << GPU_TA_PM2_USIZE_SHIFT) & GPU_TA_PM2_USIZE_MASK;
dst->mode2 |= (DimensionFlag(src->txr.height) << GPU_TA_PM2_VSIZE_SHIFT) & GPU_TA_PM2_VSIZE_MASK;
/* Polygon mode 3 */
dst->mode3 = (src->txr.mipmap << GPU_TA_PM3_MIPMAP_SHIFT) & GPU_TA_PM3_MIPMAP_MASK;
dst->mode3 |= (src->txr.format << GPU_TA_PM3_TXRFMT_SHIFT) & GPU_TA_PM3_TXRFMT_MASK;
/* Convert the texture address */
txr_base = (uint32_t) src->txr.base;
txr_base = (txr_base & 0x00fffff8) >> 3;
dst->mode3 |= txr_base;
}
if(src->fmt.modifier && src->gen.modifier_mode) {
/* If we're affected by a modifier volume, silently promote the header
to the one that is affected by a modifier volume. */
dst->d1 = dst->mode2;
dst->d2 = dst->mode3;
}
else {
dst->d1 = dst->d2 = 0xffffffff;
}
dst->d3 = dst->d4 = 0xffffffff;
}
#ifdef BACKEND_KOSPVR
#include "platforms/sh4.h"
#else
#include "platforms/software.h"
#endif

470
GL/platforms/sh4.c Normal file
View File

@ -0,0 +1,470 @@
#include "../platform.h"
#include "sh4.h"
#define CLIP_DEBUG 0
#define PVR_VERTEX_BUF_SIZE 2560 * 256
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define SQ_BASE_ADDRESS (void*) 0xe0000000
GL_FORCE_INLINE bool glIsVertex(const float flags) {
return flags == GPU_CMD_VERTEX_EOL || flags == GPU_CMD_VERTEX;
}
GL_FORCE_INLINE bool glIsLastVertex(const float flags) {
return flags == GPU_CMD_VERTEX_EOL;
}
void InitGPU(_Bool autosort, _Bool fsaa) {
pvr_init_params_t params = {
/* Enable opaque and translucent polygons with size 32 and 32 */
{PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32},
PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
0, /* No DMA */
fsaa, /* No FSAA */
(autosort) ? 0 : 1 /* Disable translucent auto-sorting to match traditional GL */
};
pvr_init(&params);
/* If we're PAL and we're NOT VGA, then use 50hz by default. This is the safest
thing to do. If someone wants to force 60hz then they can call vid_set_mode later and hopefully
that'll work... */
int cable = vid_check_cable();
int region = flashrom_get_region();
if(region == FLASHROM_REGION_EUROPE && cable != CT_VGA) {
printf("PAL region without VGA - enabling 50hz");
vid_set_mode(DM_640x480_PAL_IL, PM_RGB565);
}
}
void SceneBegin() {
pvr_wait_ready();
pvr_scene_begin();
}
void SceneListBegin(GPUList list) {
pvr_list_begin(list);
}
GL_FORCE_INLINE float _glFastInvert(float x) {
return (1.f / __builtin_sqrtf(x * x));
}
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) {
TRACE();
const float f = _glFastInvert(vertex->w);
/* Convert to NDC and apply viewport */
vertex->xyz[0] = (vertex->xyz[0] * f * 320) + 320;
vertex->xyz[1] = (vertex->xyz[1] * f * -240) + 240;
/* Orthographic projections need to use invZ otherwise we lose
the depth information. As w == 1, and clip-space range is -w to +w
we add 1.0 to the Z to bring it into range. We add a little extra to
avoid a divide by zero.
*/
if(vertex->w == 1.0f) {
vertex->xyz[2] = _glFastInvert(1.0001f + vertex->xyz[2]);
} else {
vertex->xyz[2] = f;
}
}
volatile uint32_t *sq = SQ_BASE_ADDRESS;
static inline void _glFlushBuffer() {
TRACE();
/* Wait for both store queues to complete */
sq = (uint32_t*) 0xe0000000;
sq[0] = sq[8] = 0;
}
static inline void _glPushHeaderOrVertex(Vertex* v) {
TRACE();
uint32_t* s = (uint32_t*) v;
sq[0] = *(s++);
sq[1] = *(s++);
sq[2] = *(s++);
sq[3] = *(s++);
sq[4] = *(s++);
sq[5] = *(s++);
sq[6] = *(s++);
sq[7] = *(s++);
__asm__("pref @%0" : : "r"(sq));
sq += 8;
}
static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, Vertex* vout) {
const static float o = 0.003921569f; // 1 / 255
const float d0 = v1->w + v1->xyz[2];
const float d1 = v2->w + v2->xyz[2];
const float t = (fabs(d0) * (1.0f / sqrtf((d1 - d0) * (d1 - d0)))) + 0.000001f;
const float invt = 1.0f - t;
vout->xyz[0] = invt * v1->xyz[0] + t * v2->xyz[0];
vout->xyz[1] = invt * v1->xyz[1] + t * v2->xyz[1];
vout->xyz[2] = invt * v1->xyz[2] + t * v2->xyz[2];
vout->uv[0] = invt * v1->uv[0] + t * v2->uv[0];
vout->uv[1] = invt * v1->uv[1] + t * v2->uv[1];
vout->w = invt * v1->w + t * v2->w;
const float m = 255 * t;
const float n = 255 - m;
vout->bgra[0] = (v1->bgra[0] * n + v2->bgra[0] * m) * o;
vout->bgra[1] = (v1->bgra[1] * n + v2->bgra[1] * m) * o;
vout->bgra[2] = (v1->bgra[2] * n + v2->bgra[2] * m) * o;
vout->bgra[3] = (v1->bgra[3] * n + v2->bgra[3] * m) * o;
}
#define SPAN_SORT_CFG 0x005F8030
static volatile uint32_t* PVR_LMMODE0 = (uint32_t*) 0xA05F6884;
static volatile uint32_t *PVR_LMMODE1 = (uint32_t*) 0xA05F6888;
static volatile uint32_t *QACR = (uint32_t*) 0xFF000038;
void SceneListSubmit(Vertex* v2, int n) {
TRACE();
/* You need at least a header, and 3 vertices to render anything */
if(n < 4) {
return;
}
const float h = GetVideoMode()->height;
PVR_SET(SPAN_SORT_CFG, 0x0);
//Set PVR DMA registers
*PVR_LMMODE0 = 0;
*PVR_LMMODE1 = 0;
//Set QACR registers
QACR[1] = QACR[0] = 0x11;
#if CLIP_DEBUG
Vertex* vertex = (Vertex*) src;
for(int i = 0; i < n; ++i) {
fprintf(stderr, "{%f, %f, %f, %f}, // %x (%x)\n", vertex[i].xyz[0], vertex[i].xyz[1], vertex[i].xyz[2], vertex[i].w, vertex[i].flags, &vertex[i]);
}
fprintf(stderr, "----\n");
#endif
uint8_t visible_mask = 0;
uint8_t counter = 0;
sq = SQ_BASE_ADDRESS;
for(int i = 0; i < n; ++i, ++v2) {
PREFETCH(v2 + 1);
switch(v2->flags) {
case GPU_CMD_VERTEX_EOL:
if(counter < 2) {
continue;
}
counter = 0;
break;
case GPU_CMD_VERTEX:
++counter;
if(counter < 3) {
continue;
}
break;
default:
_glPushHeaderOrVertex(v2);
counter = 0;
continue;
};
Vertex* const v0 = v2 - 2;
Vertex* const v1 = v2 - 1;
visible_mask = (
(v0->xyz[2] > -v0->w) << 0 |
(v1->xyz[2] > -v1->w) << 1 |
(v2->xyz[2] > -v2->w) << 2 |
(counter == 0) << 3
);
switch(visible_mask) {
case 15: /* All visible, but final vertex in strip */
{
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v1, h);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v2, h);
_glPushHeaderOrVertex(v2);
}
break;
case 7:
/* All visible, push the first vertex and move on */
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
break;
case 9:
/* First vertex was visible, last in strip */
{
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
}
break;
case 1:
/* First vertex was visible, but not last in strip */
{
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(b);
}
break;
case 10:
case 2:
/* Second vertex was visible. In self case we need to create a triangle and produce
two new vertices: 1-2, and 2-3. */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v1);
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = v2->flags;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
}
break;
case 11:
case 3: /* First and second vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v1);
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glClipEdge(v1, v2, a);
a->flags = v2->flags;
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(c);
_glPushHeaderOrVertex(a);
}
break;
case 12:
case 4:
/* Third vertex was visible. */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
_glClipEdge(v2, v0, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
if(counter % 2 == 1) {
_glPushHeaderOrVertex(a);
}
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
}
break;
case 13:
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
c->flags = GPU_CMD_VERTEX_EOL;
_glPushHeaderOrVertex(c);
}
break;
case 5: /* First and third vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
}
break;
case 14:
case 6: /* Second and third vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[4];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
Vertex* d = &scratch[3];
memcpy_vertex(c, v1);
memcpy_vertex(d, v2);
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(d, h);
_glPushHeaderOrVertex(d);
}
break;
case 8:
default:
break;
}
}
_glFlushBuffer();
}
void SceneListFinish() {
pvr_list_finish();
}
void SceneFinish() {
pvr_scene_finish();
}
const VideoMode* GetVideoMode() {
static VideoMode mode;
mode.width = vid_mode->width;
mode.height = vid_mode->height;
return &mode;
}

196
GL/platforms/sh4.h Normal file
View File

@ -0,0 +1,196 @@
#pragma once
#include <kos.h>
#include <dc/matrix.h>
#include <dc/pvr.h>
#include <dc/vec3f.h>
#include <dc/fmath.h>
#include <dc/matrix3d.h>
#include "../types.h"
#include "../private.h"
#include "sh4_math.h"
#ifndef NDEBUG
#define PERF_WARNING(msg) printf("[PERF] %s\n", msg)
#else
#define PERF_WARNING(msg) (void) 0
#endif
#ifndef GL_FORCE_INLINE
#define GL_NO_INSTRUMENT inline __attribute__((no_instrument_function))
#define GL_INLINE_DEBUG GL_NO_INSTRUMENT __attribute__((always_inline))
#define GL_FORCE_INLINE static GL_INLINE_DEBUG
#endif
#define PREFETCH(addr) __builtin_prefetch((addr))
GL_FORCE_INLINE void* memcpy_fast(void *dest, const void *src, size_t len) {
if(!len) {
return dest;
}
const uint8_t *s = (uint8_t *)src;
uint8_t *d = (uint8_t *)dest;
uint32_t diff = (uint32_t)d - (uint32_t)(s + 1); // extra offset because input gets incremented before output is calculated
// Underflow would be like adding a negative offset
// Can use 'd' as a scratch reg now
asm volatile (
"clrs\n" // Align for parallelism (CO) - SH4a use "stc SR, Rn" instead with a dummy Rn
".align 2\n"
"0:\n\t"
"dt %[size]\n\t" // (--len) ? 0 -> T : 1 -> T (EX 1)
"mov.b @%[in]+, %[scratch]\n\t" // scratch = *(s++) (LS 1/2)
"bf.s 0b\n\t" // while(s != nexts) aka while(!T) (BR 1/2)
" mov.b %[scratch], @(%[offset], %[in])\n" // *(datatype_of_s*) ((char*)s + diff) = scratch, where src + diff = dest (LS 1)
: [in] "+&r" ((uint32_t)s), [scratch] "=&r" ((uint32_t)d), [size] "+&r" (len) // outputs
: [offset] "z" (diff) // inputs
: "t", "memory" // clobbers
);
return dest;
}
/* We use sq_cpy if the src and size is properly aligned. We control that the
* destination is properly aligned so we assert that. */
#define FASTCPY(dst, src, bytes) \
do { \
if(bytes % 32 == 0 && ((uintptr_t) src % 4) == 0) { \
gl_assert(((uintptr_t) dst) % 32 == 0); \
sq_cpy(dst, src, bytes); \
} else { \
memcpy_fast(dst, src, bytes); \
} \
} while(0)
#define MEMCPY4(dst, src, bytes) memcpy_fast(dst, src, bytes)
#define MEMSET4(dst, v, size) memset4((dst), (v), (size))
#define VEC3_NORMALIZE(x, y, z) vec3f_normalize((x), (y), (z))
#define VEC3_LENGTH(x, y, z, l) vec3f_length((x), (y), (z), (l))
#define VEC3_DOT(x1, y1, z1, x2, y2, z2, d) vec3f_dot((x1), (y1), (z1), (x2), (y2), (z2), (d))
GL_FORCE_INLINE void UploadMatrix4x4(const Matrix4x4* mat) {
mat_load((matrix_t*) mat);
}
GL_FORCE_INLINE void DownloadMatrix4x4(Matrix4x4* mat) {
mat_store((matrix_t*) mat);
}
GL_FORCE_INLINE void MultiplyMatrix4x4(const Matrix4x4* mat) {
mat_apply((matrix_t*) mat);
}
GL_FORCE_INLINE void TransformVec3(float* x) {
mat_trans_single4(x[0], x[1], x[2], x[3]);
}
/* Transform a 3-element vector using the stored matrix (w == 1) */
GL_FORCE_INLINE void TransformVec3NoMod(const float* xIn, float* xOut) {
mat_trans_single3_nodiv_nomod(xIn[0], xIn[1], xIn[2], xOut[0], xOut[1], xOut[2]);
}
/* Transform a 3-element normal using the stored matrix (w == 0)*/
GL_FORCE_INLINE void TransformNormalNoMod(const float* in, float* out) {
mat_trans_normal3_nomod(in[0], in[1], in[2], out[0], out[1], out[2]);
}
/* Transform a 4-element vector in-place by the stored matrix */
inline void TransformVec4(float* x) {
}
GL_FORCE_INLINE void TransformVertex(const float* xyz, const float* w, float* oxyz, float* ow) {
register float __x __asm__("fr12") = (xyz[0]);
register float __y __asm__("fr13") = (xyz[1]);
register float __z __asm__("fr14") = (xyz[2]);
register float __w __asm__("fr15") = (*w);
__asm__ __volatile__(
"fldi1 fr15\n"
"ftrv xmtrx,fv12\n"
: "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w)
: "0" (__x), "1" (__y), "2" (__z), "3" (__w)
);
oxyz[0] = __x;
oxyz[1] = __y;
oxyz[2] = __z;
*ow = __w;
}
static inline void TransformVertices(Vertex* vertices, const int count) {
Vertex* it = vertices;
for(int i = 0; i < count; ++i, ++it) {
register float __x __asm__("fr12") = (it->xyz[0]);
register float __y __asm__("fr13") = (it->xyz[1]);
register float __z __asm__("fr14") = (it->xyz[2]);
register float __w __asm__("fr15") = (it->w);
__asm__ __volatile__(
"fldi1 fr15\n"
"ftrv xmtrx,fv12\n"
: "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w)
: "0" (__x), "1" (__y), "2" (__z), "3" (__w)
);
it->xyz[0] = __x;
it->xyz[1] = __y;
it->xyz[2] = __z;
it->w = __w;
}
}
void InitGPU(_Bool autosort, _Bool fsaa);
static inline size_t GPUMemoryAvailable() {
return pvr_mem_available();
}
static inline void* GPUMemoryAlloc(size_t size) {
return pvr_mem_malloc(size);
}
static inline void GPUSetPaletteFormat(GPUPaletteFormat format) {
pvr_set_pal_format(format);
}
static inline void GPUSetPaletteEntry(uint32_t idx, uint32_t value) {
pvr_set_pal_entry(idx, value);
}
static inline void GPUSetBackgroundColour(float r, float g, float b) {
pvr_set_bg_color(r, g, b);
}
#define PT_ALPHA_REF 0x011c
static inline void GPUSetAlphaCutOff(uint8_t val) {
PVR_SET(PT_ALPHA_REF, val);
}
static inline void GPUSetClearDepth(float v) {
pvr_set_zclip(v);
}
static inline void GPUSetFogLinear(float start, float end) {
pvr_fog_table_linear(start, end);
}
static inline void GPUSetFogExp(float density) {
pvr_fog_table_exp(density);
}
static inline void GPUSetFogExp2(float density) {
pvr_fog_table_exp2(density);
}
static inline void GPUSetFogColor(float r, float g, float b, float a) {
pvr_fog_table_color(r, g, b, a);
}

2139
GL/platforms/sh4_math.h Normal file

File diff suppressed because it is too large Load Diff

658
GL/platforms/software.c Normal file
View File

@ -0,0 +1,658 @@
#include <SDL.h>
#include <stdlib.h>
#include <string.h>
#include "../private.h"
#include "../platform.h"
#include "software.h"
#include "software/edge_equation.h"
#include "software/parameter_equation.h"
#define CLIP_DEBUG 0
#define ZNEAR_CLIPPING_ENABLED 1
static size_t AVAILABLE_VRAM = 8 * 1024 * 1024;
static Matrix4x4 MATRIX;
static SDL_Window* WINDOW = NULL;
static SDL_Renderer* RENDERER = NULL;
static uint8_t BACKGROUND_COLOR[3] = {0, 0, 0};
GPUCulling CULL_MODE = GPU_CULLING_CCW;
static VideoMode vid_mode = {
640, 480
};
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
AlignedVector vbuffer;
void InitGPU(_Bool autosort, _Bool fsaa) {
// 32-bit SDL has trouble with the wayland driver for some reason
setenv("SDL_VIDEODRIVER", "x11", 1);
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
WINDOW = SDL_CreateWindow(
"GLdc",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
vid_mode.width, vid_mode.height,
SDL_WINDOW_SHOWN
);
RENDERER = SDL_CreateRenderer(
WINDOW, -1, SDL_RENDERER_ACCELERATED
);
aligned_vector_init(&vbuffer, sizeof(SDL_Vertex));
}
void SceneBegin() {
SDL_SetRenderDrawColor(RENDERER, BACKGROUND_COLOR[0], BACKGROUND_COLOR[1], BACKGROUND_COLOR[2], 0);
SDL_RenderClear(RENDERER);
}
static Vertex BUFFER[1024 * 32];
static uint32_t vertex_counter = 0;
GL_FORCE_INLINE bool glIsVertex(const float flags) {
return flags == GPU_CMD_VERTEX_EOL || flags == GPU_CMD_VERTEX;
}
GL_FORCE_INLINE bool glIsLastVertex(const float flags) {
return flags == GPU_CMD_VERTEX_EOL;
}
void SceneListBegin(GPUList list) {
vertex_counter = 0;
}
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) {
const float f = 1.0f / (vertex->w);
/* Convert to NDC and apply viewport */
vertex->xyz[0] = __builtin_fmaf(
VIEWPORT.hwidth, vertex->xyz[0] * f, VIEWPORT.x_plus_hwidth
);
vertex->xyz[1] = h - __builtin_fmaf(
VIEWPORT.hheight, vertex->xyz[1] * f, VIEWPORT.y_plus_hheight
);
if(vertex->w == 1.0f) {
vertex->xyz[2] = 1.0f / (1.0001f + vertex->xyz[2]);
} else {
vertex->xyz[2] = f;
}
}
GL_FORCE_INLINE void _glPushHeaderOrVertex(const Vertex* v) {
#ifndef NDEBUG
if(glIsVertex(v->flags)) {
gl_assert(!isnan(v->xyz[2]));
gl_assert(!isnan(v->w));
}
#endif
#if CLIP_DEBUG
printf("Submitting: %x (%x)\n", v, v->flags);
#endif
BUFFER[vertex_counter++] = *v;
}
static inline void _glFlushBuffer() {}
GL_FORCE_INLINE void _glClipEdge(const Vertex* v1, const Vertex* v2, Vertex* vout) {
const static float o = 0.003921569f; // 1 / 255
const float d0 = v1->w + v1->xyz[2];
const float d1 = v2->w + v2->xyz[2];
const float t = (fabs(d0) * (1.0f / sqrtf((d1 - d0) * (d1 - d0)))) + 0.000001f;
const float invt = 1.0f - t;
vout->xyz[0] = invt * v1->xyz[0] + t * v2->xyz[0];
vout->xyz[1] = invt * v1->xyz[1] + t * v2->xyz[1];
vout->xyz[2] = invt * v1->xyz[2] + t * v2->xyz[2];
vout->uv[0] = invt * v1->uv[0] + t * v2->uv[0];
vout->uv[1] = invt * v1->uv[1] + t * v2->uv[1];
vout->w = invt * v1->w + t * v2->w;
const float m = 255 * t;
const float n = 255 - m;
vout->bgra[0] = (v1->bgra[0] * n + v2->bgra[0] * m) * o;
vout->bgra[1] = (v1->bgra[1] * n + v2->bgra[1] * m) * o;
vout->bgra[2] = (v1->bgra[2] * n + v2->bgra[2] * m) * o;
vout->bgra[3] = (v1->bgra[3] * n + v2->bgra[3] * m) * o;
}
void SceneListSubmit(Vertex* v2, int n) {
/* You need at least a header, and 3 vertices to render anything */
if(n < 4) {
return;
}
const float h = GetVideoMode()->height;
uint8_t visible_mask = 0;
uint8_t counter = 0;
for(int i = 0; i < n; ++i, ++v2) {
PREFETCH(v2 + 1);
switch(v2->flags) {
case GPU_CMD_VERTEX_EOL:
if(counter < 2) {
continue;
}
counter = 0;
break;
case GPU_CMD_VERTEX:
++counter;
if(counter < 3) {
continue;
}
break;
default:
_glPushHeaderOrVertex(v2);
counter = 0;
continue;
};
Vertex* const v0 = v2 - 2;
Vertex* const v1 = v2 - 1;
visible_mask = (
(v0->xyz[2] > -v0->w) << 0 |
(v1->xyz[2] > -v1->w) << 1 |
(v2->xyz[2] > -v2->w) << 2 |
(counter == 0) << 3
);
switch(visible_mask) {
case 15: /* All visible, but final vertex in strip */
{
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v1, h);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v2, h);
_glPushHeaderOrVertex(v2);
}
break;
case 7:
/* All visible, push the first vertex and move on */
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
break;
case 9:
/* First vertex was visible, last in strip */
{
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
}
break;
case 1:
/* First vertex was visible, but not last in strip */
{
Vertex __attribute__((aligned(32))) scratch[2];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(b);
}
break;
case 10:
case 2:
/* Second vertex was visible. In self case we need to create a triangle and produce
two new vertices: 1-2, and 2-3. */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v1);
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = v2->flags;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
}
break;
case 11:
case 3: /* First and second vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v1);
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glClipEdge(v1, v2, a);
a->flags = v2->flags;
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(c);
_glPushHeaderOrVertex(a);
}
break;
case 12:
case 4:
/* Third vertex was visible. */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
_glClipEdge(v2, v0, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
if(counter % 2 == 1) {
_glPushHeaderOrVertex(a);
}
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
}
break;
case 13:
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
c->flags = GPU_CMD_VERTEX_EOL;
_glPushHeaderOrVertex(c);
}
break;
case 5: /* First and third vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[3];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
memcpy_vertex(c, v2);
c->flags = GPU_CMD_VERTEX;
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v1, v2, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(v0, h);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
}
break;
case 14:
case 6: /* Second and third vertex were visible */
{
Vertex __attribute__((aligned(32))) scratch[4];
Vertex* a = &scratch[0];
Vertex* b = &scratch[1];
Vertex* c = &scratch[2];
Vertex* d = &scratch[3];
memcpy_vertex(c, v1);
memcpy_vertex(d, v2);
_glClipEdge(v0, v1, a);
a->flags = GPU_CMD_VERTEX;
_glClipEdge(v2, v0, b);
b->flags = GPU_CMD_VERTEX;
_glPerspectiveDivideVertex(a, h);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(c, h);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(b, h);
_glPushHeaderOrVertex(b);
_glPushHeaderOrVertex(c);
_glPerspectiveDivideVertex(d, h);
_glPushHeaderOrVertex(d);
}
break;
case 8:
default:
break;
}
}
_glFlushBuffer();
}
void SceneListFinish() {
uint32_t vidx = 0;
const uint32_t* flags = (const uint32_t*) BUFFER;
uint32_t step = sizeof(Vertex) / sizeof(uint32_t);
for(int i = 0; i < vertex_counter; ++i, flags += step) {
if((*flags & GPU_CMD_POLYHDR) == GPU_CMD_POLYHDR) {
vidx = 0;
uint32_t mode1 = *(flags + 1);
// Extract culling mode
uint32_t mask = mode1 & GPU_TA_PM1_CULLING_MASK;
CULL_MODE = mask >> GPU_TA_PM1_CULLING_SHIFT;
} else {
switch(*flags) {
case GPU_CMD_VERTEX_EOL:
case GPU_CMD_VERTEX: // Fallthrough
vidx++;
break;
default:
break;
}
}
if(vidx > 2) {
Vertex* v0 = (Vertex*) (flags - step - step);
Vertex* v1 = (Vertex*) (flags - step);
Vertex* v2 = (Vertex*) (flags);
SDL_Vertex sv0 = {
{v0->xyz[0], v0->xyz[1]},
{v0->bgra[2], v0->bgra[1], v0->bgra[0], v0->bgra[3]},
{v0->uv[0], v0->uv[1]}
};
SDL_Vertex sv1 = {
{v1->xyz[0], v1->xyz[1]},
{v1->bgra[2], v1->bgra[1], v1->bgra[0], v1->bgra[3]},
{v1->uv[0], v1->uv[1]}
};
SDL_Vertex sv2 = {
{v2->xyz[0], v2->xyz[1]},
{v2->bgra[2], v2->bgra[1], v2->bgra[0], v2->bgra[3]},
{v2->uv[0], v2->uv[1]}
};
aligned_vector_push_back(&vbuffer, &sv0, 1);
aligned_vector_push_back(&vbuffer, &sv1, 1);
aligned_vector_push_back(&vbuffer, &sv2, 1);
}
if((*flags) == GPU_CMD_VERTEX_EOL) {
vidx = 0;
}
}
SDL_SetRenderDrawColor(RENDERER, 255, 255, 255, 255);
SDL_RenderGeometry(RENDERER, NULL, aligned_vector_front(&vbuffer), aligned_vector_size(&vbuffer), NULL, 0);
}
void SceneFinish() {
SDL_RenderPresent(RENDERER);
/* Only sensible place to hook the quit signal */
SDL_Event e;
while (SDL_PollEvent(&e)) {
switch (e.type) {
case SDL_QUIT:
exit(0);
break;
default:
break;
}
}
}
void UploadMatrix4x4(const Matrix4x4* mat) {
memcpy(&MATRIX, mat, sizeof(Matrix4x4));
}
void MultiplyMatrix4x4(const Matrix4x4* mat) {
Matrix4x4 product;
product[0] = MATRIX[0] * (*mat)[0] + MATRIX[4] * (*mat)[1] + MATRIX[8] * (*mat)[2] + MATRIX[12] * (*mat)[3];
product[1] = MATRIX[1] * (*mat)[0] + MATRIX[5] * (*mat)[1] + MATRIX[9] * (*mat)[2] + MATRIX[13] * (*mat)[3];
product[2] = MATRIX[2] * (*mat)[0] + MATRIX[6] * (*mat)[1] + MATRIX[10] * (*mat)[2] + MATRIX[14] * (*mat)[3];
product[3] = MATRIX[3] * (*mat)[0] + MATRIX[7] * (*mat)[1] + MATRIX[11] * (*mat)[2] + MATRIX[15] * (*mat)[3];
product[4] = MATRIX[0] * (*mat)[4] + MATRIX[4] * (*mat)[5] + MATRIX[8] * (*mat)[6] + MATRIX[12] * (*mat)[7];
product[5] = MATRIX[1] * (*mat)[4] + MATRIX[5] * (*mat)[5] + MATRIX[9] * (*mat)[6] + MATRIX[13] * (*mat)[7];
product[6] = MATRIX[2] * (*mat)[4] + MATRIX[6] * (*mat)[5] + MATRIX[10] * (*mat)[6] + MATRIX[14] * (*mat)[7];
product[7] = MATRIX[3] * (*mat)[4] + MATRIX[7] * (*mat)[5] + MATRIX[11] * (*mat)[6] + MATRIX[15] * (*mat)[7];
product[8] = MATRIX[0] * (*mat)[8] + MATRIX[4] * (*mat)[9] + MATRIX[8] * (*mat)[10] + MATRIX[12] * (*mat)[11];
product[9] = MATRIX[1] * (*mat)[8] + MATRIX[5] * (*mat)[9] + MATRIX[9] * (*mat)[10] + MATRIX[13] * (*mat)[11];
product[10] = MATRIX[2] * (*mat)[8] + MATRIX[6] * (*mat)[9] + MATRIX[10] * (*mat)[10] + MATRIX[14] * (*mat)[11];
product[11] = MATRIX[3] * (*mat)[8] + MATRIX[7] * (*mat)[9] + MATRIX[11] * (*mat)[10] + MATRIX[15] * (*mat)[11];
product[12] = MATRIX[0] * (*mat)[12] + MATRIX[4] * (*mat)[13] + MATRIX[8] * (*mat)[14] + MATRIX[12] * (*mat)[15];
product[13] = MATRIX[1] * (*mat)[12] + MATRIX[5] * (*mat)[13] + MATRIX[9] * (*mat)[14] + MATRIX[13] * (*mat)[15];
product[14] = MATRIX[2] * (*mat)[12] + MATRIX[6] * (*mat)[13] + MATRIX[10] * (*mat)[14] + MATRIX[14] * (*mat)[15];
product[15] = MATRIX[3] * (*mat)[12] + MATRIX[7] * (*mat)[13] + MATRIX[11] * (*mat)[14] + MATRIX[15] * (*mat)[15];
UploadMatrix4x4(&product);
}
void DownloadMatrix4x4(Matrix4x4* mat) {
memcpy(mat, &MATRIX, sizeof(Matrix4x4));
}
const VideoMode* GetVideoMode() {
return &vid_mode;
}
size_t GPUMemoryAvailable() {
return AVAILABLE_VRAM;
}
void* GPUMemoryAlloc(size_t size) {
if(size > AVAILABLE_VRAM) {
return NULL;
} else {
AVAILABLE_VRAM -= size;
return malloc(size);
}
}
void GPUSetPaletteFormat(GPUPaletteFormat format) {
}
void GPUSetPaletteEntry(uint32_t idx, uint32_t value) {
}
void GPUSetBackgroundColour(float r, float g, float b) {
BACKGROUND_COLOR[0] = r * 255.0f;
BACKGROUND_COLOR[1] = g * 255.0f;
BACKGROUND_COLOR[2] = b * 255.0f;
}
void GPUSetAlphaCutOff(uint8_t v) {
}
void GPUSetClearDepth(float v) {
}
void GPUSetFogLinear(float start, float end) {
}
void GPUSetFogExp(float density) {
}
void GPUSetFogExp2(float density) {
}
void GPUSetFogColor(float r, float g, float b, float a) {
}
void TransformVec3NoMod(const float* v, float* ret) {
ret[0] = v[0] * MATRIX[0] + v[1] * MATRIX[4] + v[2] * MATRIX[8] + 1.0f * MATRIX[12];
ret[1] = v[0] * MATRIX[1] + v[1] * MATRIX[5] + v[2] * MATRIX[9] + 1.0f * MATRIX[13];
ret[2] = v[0] * MATRIX[2] + v[1] * MATRIX[6] + v[2] * MATRIX[10] + 1.0f * MATRIX[14];
}
void TransformVec4NoMod(const float* v, float* ret) {
ret[0] = v[0] * MATRIX[0] + v[1] * MATRIX[4] + v[2] * MATRIX[8] + v[3] * MATRIX[12];
ret[1] = v[0] * MATRIX[1] + v[1] * MATRIX[5] + v[2] * MATRIX[9] + v[3] * MATRIX[13];
ret[2] = v[0] * MATRIX[2] + v[1] * MATRIX[6] + v[2] * MATRIX[10] + v[3] * MATRIX[14];
ret[3] = v[0] * MATRIX[3] + v[1] * MATRIX[7] + v[2] * MATRIX[11] + v[3] * MATRIX[15];
}
void TransformVec3(float* v) {
float ret[3];
TransformVec3NoMod(v, ret);
FASTCPY(v, ret, sizeof(float) * 3);
}
void TransformVec4(float* v) {
float ret[4];
TransformVec4NoMod(v, ret);
FASTCPY(v, ret, sizeof(float) * 4);
}
void TransformVertices(Vertex* vertices, const int count) {
float ret[4];
for(int i = 0; i < count; ++i, ++vertices) {
ret[0] = vertices->xyz[0];
ret[1] = vertices->xyz[1];
ret[2] = vertices->xyz[2];
ret[3] = 1.0f;
TransformVec4(ret);
vertices->xyz[0] = ret[0];
vertices->xyz[1] = ret[1];
vertices->xyz[2] = ret[2];
vertices->w = ret[3];
}
}
void TransformVertex(const float* xyz, const float* w, float* oxyz, float* ow) {
float ret[4];
ret[0] = xyz[0];
ret[1] = xyz[1];
ret[2] = xyz[2];
ret[3] = *w;
TransformVec4(ret);
oxyz[0] = ret[0];
oxyz[1] = ret[1];
oxyz[2] = ret[2];
*ow = ret[3];
}

75
GL/platforms/software.h Normal file
View File

@ -0,0 +1,75 @@
#pragma once
#include <math.h>
#include <memory.h>
#include "../types.h"
#define PREFETCH(addr) do {} while(0)
#define MATH_Fast_Divide(n, d) (n / d)
#define MATH_fmac(a, b, c) (a * b + c)
#define MATH_Fast_Sqrt(x) sqrtf((x))
#define MATH_fsrra(x) (1.0f / sqrtf((x)))
#define MATH_Fast_Invert(x) (1.0f / (x))
#define FASTCPY(dst, src, bytes) memcpy(dst, src, bytes)
#define MEMCPY(dst, src, bytes) memcpy(dst, src, bytes)
#define MEMCPY4(dst, src, bytes) memcpy(dst, src, bytes)
#define MEMSET4(dst, v, size) memset((dst), (v), (size))
#define VEC3_NORMALIZE(x, y, z) \
do { \
float l = MATH_fsrra((x) * (x) + (y) * (y) + (z) * (z)); \
x *= l; \
y *= l; \
z *= l; \
} while(0)
#define VEC3_LENGTH(x, y, z, d) \
d = MATH_Fast_Sqrt((x) * (x) + (y) * (y) + (z) * (z))
#define VEC3_DOT(x1, y1, z1, x2, y2, z2, d) \
d = (x1 * x2) + (y1 * y2) + (z1 * z2)
struct PolyHeader;
struct PolyContext;
void UploadMatrix4x4(const Matrix4x4* mat);
void MultiplyMatrix4x4(const Matrix4x4* mat);
void DownloadMatrix4x4(Matrix4x4* mat);
/* Transform a 3-element vector in-place using the stored matrix (w == 1) */
void TransformVec3(float* v);
/* Transform a 3-element vector using the stored matrix (w == 1) */
void TransformVec3NoMod(const float* v, float* ret);
/* Transform a 3-element normal using the stored matrix (w == 0)*/
static inline void TransformNormalNoMod(const float* xIn, float* xOut) {
(void) xIn;
(void) xOut;
}
void TransformVertices(Vertex* vertices, const int count);
void TransformVertex(const float* xyz, const float* w, float* oxyz, float* ow);
void InitGPU(_Bool autosort, _Bool fsaa);
enum GPUPaletteFormat;
size_t GPUMemoryAvailable();
void* GPUMemoryAlloc(size_t size);
void GPUSetPaletteFormat(GPUPaletteFormat format);
void GPUSetPaletteEntry(uint32_t idx, uint32_t value);
void GPUSetBackgroundColour(float r, float g, float b);
void GPUSetAlphaCutOff(uint8_t v);
void GPUSetClearDepth(float v);
void GPUSetFogLinear(float start, float end);
void GPUSetFogExp(float density);
void GPUSetFogExp2(float density);
void GPUSetFogColor(float r, float g, float b, float a);

View File

@ -0,0 +1,20 @@
#include "edge_equation.h"
void EdgeEquationInit(EdgeEquation* edge, const float* v0, const float* v1) {
edge->a = v0[1] - v1[1];
edge->b = v1[0] - v0[0];
edge->c = -(edge->a * (v0[0] + v1[0]) + edge->b * (v0[1] + v1[1])) / 2;
edge->tie = edge->a != 0 ? edge->a > 0 : edge->b > 0;
}
float EdgeEquationEvaluate(const EdgeEquation* edge, float x, float y) {
return edge->a * x + edge->b * y + edge->c;
}
bool EdgeEquationTestValue(const EdgeEquation* edge, float value) {
return (value >= 0 || (value == 0 && edge->tie));
}
bool EdgeEquationTestPoint(const EdgeEquation* edge, float x, float y) {
return EdgeEquationTestValue(edge, EdgeEquationEvaluate(edge, x, y));
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
typedef struct EdgeEquation {
float a;
float b;
float c;
bool tie;
} EdgeEquation;
void EdgeEquationInit(EdgeEquation* edge, const float* v0, const float* v1);
float EdgeEquationEvaluate(const EdgeEquation* edge, float x, float y);
bool EdgeEquationTestValue(const EdgeEquation* edge, float value);
bool EdgeEquationTestPoint(const EdgeEquation* edge, float x, float y);

View File

@ -0,0 +1,16 @@
#include "parameter_equation.h"
#include "edge_equation.h"
void ParameterEquationInit(ParameterEquation* equation, float p0, float p1, float p2, const EdgeEquation* e0, const EdgeEquation* e1, const EdgeEquation* e2, float area) {
float factor = 1.0f / (2.0f * area);
equation->a = factor * (p0 * e0->a + p1 * e1->a + p2 * e2->a);
equation->b = factor * (p0 * e0->b + p1 * e1->b + p2 * e2->b);
equation->c = factor * (p0 * e0->c + p1 * e1->c + p2 * e2->c);
}
float ParameterEquationEvaluate(const ParameterEquation* equation, float x, float y) {
return equation->a * x + equation->b * y + equation->c;
}

View File

@ -0,0 +1,16 @@
#pragma once
typedef struct ParameterEquation {
float a;
float b;
float c;
} ParameterEquation;
struct EdgeEquation;
void ParameterEquationInit(
ParameterEquation* equation,
float p0, float p1, float p2,
const struct EdgeEquation* e0, const struct EdgeEquation* e1, const struct EdgeEquation* e2, float area);
float ParameterEquationEvaluate(const ParameterEquation* equation, float x, float y);

View File

@ -1,18 +1,94 @@
#ifndef PRIVATE_H
#define PRIVATE_H
#include "../include/gl.h"
#include <stdint.h>
#include <stdio.h>
#include "gl_assert.h"
#include "platform.h"
#include "types.h"
#include "../include/GL/gl.h"
#include "../include/GL/glext.h"
#include "../include/GL/glkos.h"
#include "../containers/aligned_vector.h"
#include "../containers/named_array.h"
#include "./clip.h"
#define MAX_GLDC_4BPP_PALETTE_SLOTS 16
#define MAX_GLDC_PALETTE_SLOTS 4
#define MAX_GLDC_SHARED_PALETTES (MAX_GLDC_PALETTE_SLOTS*MAX_GLDC_4BPP_PALETTE_SLOTS)
extern void* memcpy4 (void *dest, const void *src, size_t count);
#define GL_NO_INSTRUMENT inline __attribute__((no_instrument_function))
#define GL_INLINE_DEBUG GL_NO_INSTRUMENT __attribute__((always_inline))
#define GL_FORCE_INLINE static GL_INLINE_DEBUG
#define _GL_UNUSED(x) (void)(x)
#define _PACK4(v) ((v * 0xF) / 0xFF)
#define PACK_ARGB4444(a,r,g,b) (_PACK4(a) << 12) | (_PACK4(r) << 8) | (_PACK4(g) << 4) | (_PACK4(b))
#define PACK_ARGB8888(a,r,g,b) ( ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF) )
#define PACK_ARGB1555(a,r,g,b) \
(((GLushort)(a > 0) << 15) | (((GLushort) r >> 3) << 10) | (((GLushort)g >> 3) << 5) | ((GLushort)b >> 3))
#define PACK_RGB565(r,g,b) \
((((GLushort)r & 0xf8) << 8) | (((GLushort) g & 0xfc) << 3) | ((GLushort) b >> 3))
#define TRACE_ENABLED 0
#define TRACE() if(TRACE_ENABLED) {fprintf(stderr, "%s\n", __func__);}
#define TRACE() if(TRACE_ENABLED) {fprintf(stderr, "%s\n", __func__);} (void) 0
#define VERTEX_ENABLED_FLAG (1 << 0)
#define UV_ENABLED_FLAG (1 << 1)
#define ST_ENABLED_FLAG (1 << 2)
#define DIFFUSE_ENABLED_FLAG (1 << 3)
#define NORMAL_ENABLED_FLAG (1 << 4)
#define MAX_TEXTURE_SIZE 1024
typedef struct {
unsigned int cmd[8];
} PVRCommand;
/* This gives us an easy way to switch
* internal matrix order if necessary */
#define TRANSPOSE 0
#if TRANSPOSE
#define M0 0
#define M1 4
#define M2 8
#define M3 12
#define M4 1
#define M5 5
#define M6 9
#define M7 13
#define M8 2
#define M9 6
#define M10 10
#define M11 14
#define M12 3
#define M13 7
#define M14 11
#define M15 15
#else
#define M0 0
#define M1 1
#define M2 2
#define M3 3
#define M4 4
#define M5 5
#define M6 6
#define M7 7
#define M8 8
#define M9 9
#define M10 10
#define M11 11
#define M12 12
#define M13 13
#define M14 14
#define M15 15
#endif
typedef struct {
unsigned int flags; /* Constant PVR_CMD_USERCLIP */
@ -29,23 +105,82 @@ typedef struct {
} PolyList;
typedef struct {
GLint x;
GLint y;
GLint width;
GLint height;
float x_plus_hwidth;
float y_plus_hheight;
float hwidth; /* width * 0.5f */
float hheight; /* height * 0.5f */
} Viewport;
extern Viewport VIEWPORT;
typedef struct {
/* Palette data is always stored in RAM as RGBA8888 and packed as ARGB8888
* when uploaded to the PVR */
GLubyte* data;
GLushort width; /* The user specified width */
GLushort size; /* The size of the bank (16 or 256) */
GLenum format;
GLshort bank;
} TexturePalette;
typedef struct {
//0
GLuint index;
GLuint color; /* This is the PVR texture format */
//8
GLenum minFilter;
GLenum magFilter;
//16
GLvoid *data;
TexturePalette* palette;
//24
GLushort width;
GLushort height;
GLuint color; /* This is the PVR texture format */
//28
GLushort mipmap; /* Bitmask of supplied mipmap levels */
/* When using the shared palette, this is the bank (0-3) */
GLushort shared_bank;
//32
GLuint dataStride;
//36
GLubyte mipmap_bias;
GLubyte env;
GLubyte filter;
GLubyte mip_map;
GLubyte mipmapCount; /* The number of mipmap levels */
GLubyte uv_clamp;
GLuint index;
GLvoid *data;
} TextureObject;
//40
/* Mipmap textures have a different
* offset for the base level when supplying the data, this
* keeps track of that. baseDataOffset == 0
* means that the texture has no mipmaps
*/
GLuint baseDataOffset;
GLuint baseDataSize; /* The data size of mipmap level 0 */
//48
GLboolean isCompressed;
GLboolean isPaletted;
//50
GLenum internalFormat;
//54
GLubyte padding[10]; // Pad to 64-bytes
} __attribute__((aligned(32))) TextureObject;
typedef struct {
GLfloat emissive[4];
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat specular[4];
/* Valid values are 0-128 */
GLfloat exponent;
/* Base ambient + emission colour for
* the current material + light */
GLfloat baseColour[4];
} Material;
typedef struct {
@ -59,60 +194,391 @@ typedef struct {
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat ambient[4];
GLboolean isDirectional;
GLboolean isEnabled;
/* We set these when the material changes
* so we don't calculate them per-vertex. They are
* light_value * materia_value */
GLfloat ambientMaterial[4];
GLfloat diffuseMaterial[4];
GLfloat specularMaterial[4];
} LightSource;
PolyList *activePolyList();
#define argbcpy(dst, src) \
*((GLuint*) dst) = *((const GLuint*) src) \
void initAttributePointers();
void initContext();
void initLights();
void initImmediateMode();
void initMatrices();
void initFramebuffers();
void _matrixLoadNormal();
void _matrixLoadModelView();
void _matrixLoadTexture();
void _matrixLoadRender();
void _applyRenderMatrix();
typedef struct {
float xy[2];
} _glvec2;
void wipeTextureOnFramebuffers(GLuint texture);
GLubyte checkImmediateModeInactive(const char* func);
typedef struct {
float xyz[3];
} _glvec3;
pvr_poly_cxt_t* getPVRContext();
GLubyte _glKosInitTextures();
void updatePVRTextureContext(pvr_poly_cxt_t* context, TextureObject* tx1);
TextureObject* getTexture0();
TextureObject* getTexture1();
TextureObject* getBoundTexture();
GLboolean isBlendingEnabled();
typedef struct {
float xyzw[4];
} _glvec4;
GLboolean isLightingEnabled();
GLboolean isLightEnabled(GLubyte light);
void calculateLightingContribution(const GLint light, const GLfloat* pos, const GLfloat* normal, GLfloat* colour);
#define vec2cpy(dst, src) \
*((_glvec2*) dst) = *((_glvec2*) src)
void _glKosThrowError(GLenum error, const char *function);
void _glKosPrintError();
GLubyte _glKosHasError();
#define vec3cpy(dst, src) \
*((_glvec3*) dst) = *((_glvec3*) src)
#define PVR_VERTEX_BUF_SIZE 2560 * 256
#define MAX_TEXTURE_UNITS 2
#define MAX_LIGHTS 8
#define vec4cpy(dst, src) \
*((_glvec4*) dst) = *((_glvec4*) src)
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
GL_FORCE_INLINE float clamp(float d, float min, float max) {
return (d < min) ? min : (d > max) ? max : d;
}
#define mat_trans_fv12() { \
__asm__ __volatile__( \
"fldi1 fr15\n" \
"ftrv xmtrx, fv12\n" \
"fldi1 fr14\n" \
"fdiv fr15, fr14\n" \
"fmul fr14, fr12\n" \
"fmul fr14, fr13\n" \
: "=f" (__x), "=f" (__y), "=f" (__z) \
: "0" (__x), "1" (__y), "2" (__z) \
: "fr15" ); \
GL_FORCE_INLINE void memcpy_vertex(Vertex *dest, const Vertex *src) {
#ifdef __DREAMCAST__
_Complex float double_scratch;
asm volatile (
"fschg\n\t"
"clrs\n\t"
".align 2\n\t"
"fmov.d @%[in]+, %[scratch]\n\t"
"fmov.d %[scratch], @%[out]\n\t"
"fmov.d @%[in]+, %[scratch]\n\t"
"add #8, %[out]\n\t"
"fmov.d %[scratch], @%[out]\n\t"
"fmov.d @%[in]+, %[scratch]\n\t"
"add #8, %[out]\n\t"
"fmov.d %[scratch], @%[out]\n\t"
"fmov.d @%[in], %[scratch]\n\t"
"add #8, %[out]\n\t"
"fmov.d %[scratch], @%[out]\n\t"
"fschg\n"
: [in] "+&r" ((uint32_t) src), [scratch] "=&d" (double_scratch), [out] "+&r" ((uint32_t) dest)
:
: "t", "memory" // clobbers
);
#else
*dest = *src;
#endif
}
#define swapVertex(a, b) \
do { \
Vertex __attribute__((aligned(32))) c; \
memcpy_vertex(&c, a); \
memcpy_vertex(a, b); \
memcpy_vertex(b, &c); \
} while(0)
/* ClipVertex doesn't have room for these, so we need to parse them
* out separately. Potentially 'w' will be housed here if we support oargb */
typedef struct {
float nxyz[3];
float st[2];
} VertexExtra;
/* Generating PVR vertices from the user-submitted data gets complicated, particularly
* when a realloc could invalidate pointers. This structure holds all the information
* we need on the target vertex array to allow passing around to the various stages (e.g. generate/clip etc.)
*/
typedef struct __attribute__((aligned(32))) {
PolyList* output;
uint32_t header_offset; // The offset of the header in the output list
uint32_t start_offset; // The offset into the output list
uint32_t count; // The number of vertices in this output
/* Pointer to count * VertexExtra; */
AlignedVector* extras;
} SubmissionTarget;
Vertex* _glSubmissionTargetStart(SubmissionTarget* target);
Vertex* _glSubmissionTargetEnd(SubmissionTarget* target);
typedef enum {
CLIP_RESULT_ALL_IN_FRONT,
CLIP_RESULT_ALL_BEHIND,
CLIP_RESULT_ALL_ON_PLANE,
CLIP_RESULT_FRONT_TO_BACK,
CLIP_RESULT_BACK_TO_FRONT
} ClipResult;
#define A8IDX 3
#define R8IDX 2
#define G8IDX 1
#define B8IDX 0
struct SubmissionTarget;
PolyList* _glOpaquePolyList();
PolyList* _glPunchThruPolyList();
PolyList *_glTransparentPolyList();
void _glInitAttributePointers();
void _glInitContext();
void _glInitLights();
void _glInitImmediateMode(GLuint initial_size);
void _glInitMatrices();
void _glInitFramebuffers();
void _glInitSubmissionTarget();
void _glMatrixLoadNormal();
void _glMatrixLoadModelView();
void _glMatrixLoadProjection();
void _glMatrixLoadTexture();
void _glMatrixLoadModelViewProjection();
extern GLfloat DEPTH_RANGE_MULTIPLIER_L;
extern GLfloat DEPTH_RANGE_MULTIPLIER_H;
Matrix4x4* _glGetProjectionMatrix();
Matrix4x4* _glGetModelViewMatrix();
void _glWipeTextureOnFramebuffers(GLuint texture);
GLubyte _glInitTextures();
void _glUpdatePVRTextureContext(PolyContext* context, GLshort textureUnit);
void _glAllocateSpaceForMipmaps(TextureObject* active);
typedef struct {
const void* ptr; // 4
GLenum type; // 4
GLsizei stride; // 4
GLint size; // 4
} AttribPointer;
typedef struct {
AttribPointer vertex; // 16
AttribPointer colour; // 32
AttribPointer uv; // 48
AttribPointer st; // 64
AttribPointer normal; // 80
AttribPointer padding; // 96
} AttribPointerList;
GLboolean _glCheckValidEnum(GLint param, GLint* values, const char* func);
GLuint* _glGetEnabledAttributes();
AttribPointer* _glGetVertexAttribPointer();
AttribPointer* _glGetDiffuseAttribPointer();
AttribPointer* _glGetNormalAttribPointer();
AttribPointer* _glGetUVAttribPointer();
AttribPointer* _glGetSTAttribPointer();
GLenum _glGetShadeModel();
TextureObject* _glGetTexture0();
TextureObject* _glGetTexture1();
TextureObject* _glGetBoundTexture();
extern GLubyte ACTIVE_TEXTURE;
extern GLboolean TEXTURES_ENABLED[];
GLubyte _glGetActiveTexture();
GLint _glGetTextureInternalFormat();
GLboolean _glGetTextureTwiddle();
void _glSetTextureTwiddle(GLboolean v);
GLuint _glGetActiveClientTexture();
TexturePalette* _glGetSharedPalette(GLshort bank);
void _glSetInternalPaletteFormat(GLenum val);
GLboolean _glIsSharedTexturePaletteEnabled();
void _glApplyColorTable(TexturePalette *palette);
GLboolean _glIsBlendingEnabled();
GLboolean _glIsAlphaTestEnabled();
GLboolean _glIsCullingEnabled();
GLboolean _glIsDepthTestEnabled();
GLboolean _glIsDepthWriteEnabled();
GLboolean _glIsScissorTestEnabled();
GLboolean _glIsFogEnabled();
GLenum _glGetDepthFunc();
GLenum _glGetCullFace();
GLenum _glGetFrontFace();
GLenum _glGetBlendSourceFactor();
GLenum _glGetBlendDestFactor();
extern PolyList OP_LIST;
extern PolyList PT_LIST;
extern PolyList TR_LIST;
GL_FORCE_INLINE PolyList* _glActivePolyList() {
if(_glIsBlendingEnabled()) {
return &TR_LIST;
} else if(_glIsAlphaTestEnabled()) {
return &PT_LIST;
} else {
return &OP_LIST;
}
}
GLboolean _glIsMipmapComplete(const TextureObject* obj);
GLubyte* _glGetMipmapLocation(const TextureObject* obj, GLuint level);
GLuint _glGetMipmapLevelCount(const TextureObject* obj);
GLboolean _glIsLightingEnabled();
void _glEnableLight(GLubyte light, GLboolean value);
GLboolean _glIsColorMaterialEnabled();
GLboolean _glIsNormalizeEnabled();
extern AttribPointerList ATTRIB_POINTERS;
extern GLuint ENABLED_VERTEX_ATTRIBUTES;
extern GLuint FAST_PATH_ENABLED;
GL_FORCE_INLINE GLuint _glIsVertexDataFastPathCompatible() {
/* The fast path is enabled when all enabled elements of the vertex
* match the output format. This means:
*
* xyz == 3f
* uv == 2f
* rgba == argb4444
* st == 2f
* normal == 3f
*
* When this happens we do inline straight copies of the enabled data
* and transforms for positions and normals happen while copying.
*/
if((ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
if(ATTRIB_POINTERS.vertex.size != 3 || ATTRIB_POINTERS.vertex.type != GL_FLOAT) {
return GL_FALSE;
}
}
if((ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG)) {
if(ATTRIB_POINTERS.uv.size != 2 || ATTRIB_POINTERS.uv.type != GL_FLOAT) {
return GL_FALSE;
}
}
if((ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG)) {
/* FIXME: Shouldn't this be a reversed format? */
if(ATTRIB_POINTERS.colour.size != GL_BGRA || ATTRIB_POINTERS.colour.type != GL_UNSIGNED_BYTE) {
return GL_FALSE;
}
}
if((ENABLED_VERTEX_ATTRIBUTES & ST_ENABLED_FLAG)) {
if(ATTRIB_POINTERS.st.size != 2 || ATTRIB_POINTERS.st.type != GL_FLOAT) {
return GL_FALSE;
}
}
if((ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG)) {
if(ATTRIB_POINTERS.normal.size != 3 || ATTRIB_POINTERS.normal.type != GL_FLOAT) {
return GL_FALSE;
}
}
return GL_TRUE;
}
GL_FORCE_INLINE GLuint _glRecalcFastPath() {
FAST_PATH_ENABLED = _glIsVertexDataFastPathCompatible();
return FAST_PATH_ENABLED;
}
extern GLboolean IMMEDIATE_MODE_ACTIVE;
extern GLenum LAST_ERROR;
extern char ERROR_FUNCTION[64];
GL_FORCE_INLINE const char* _glErrorEnumAsString(GLenum error) {
switch(error) {
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
default:
return "GL_UNKNOWN_ERROR";
}
}
GL_FORCE_INLINE void _glKosThrowError(GLenum error, const char *function) {
if(LAST_ERROR == GL_NO_ERROR) {
LAST_ERROR = error;
sprintf(ERROR_FUNCTION, "%s\n", function);
fprintf(stderr, "GL ERROR: %s when calling %s\n", _glErrorEnumAsString(LAST_ERROR), ERROR_FUNCTION);
}
}
GL_FORCE_INLINE GLubyte _glKosHasError() {
return (LAST_ERROR != GL_NO_ERROR) ? GL_TRUE : GL_FALSE;
}
GL_FORCE_INLINE void _glKosResetError() {
LAST_ERROR = GL_NO_ERROR;
sprintf(ERROR_FUNCTION, "\n");
}
GL_FORCE_INLINE GLboolean _glCheckImmediateModeInactive(const char* func) {
/* Returns 1 on error */
if(IMMEDIATE_MODE_ACTIVE) {
_glKosThrowError(GL_INVALID_OPERATION, func);
return GL_TRUE;
}
return GL_FALSE;
}
typedef struct {
float n[3]; // 12 bytes
float finalColour[4]; //28 bytes
uint32_t padding; // 32 bytes
} EyeSpaceData;
extern void _glPerformLighting(Vertex* vertices, EyeSpaceData *es, const uint32_t count);
unsigned char _glIsClippingEnabled();
void _glEnableClipping(unsigned char v);
GLuint _glFreeTextureMemory();
GLuint _glUsedTextureMemory();
GLuint _glFreeContiguousTextureMemory();
void _glApplyScissor(bool force);
void _glSetColorMaterialMask(GLenum mask);
void _glSetColorMaterialMode(GLenum mode);
GLenum _glColorMaterialMode();
Material* _glActiveMaterial();
void _glSetLightModelViewerInEyeCoordinates(GLboolean v);
void _glSetLightModelSceneAmbient(const GLfloat* v);
void _glSetLightModelColorControl(GLint v);
GLuint _glEnabledLightCount();
void _glRecalcEnabledLights();
GLfloat* _glLightModelSceneAmbient();
GLfloat* _glGetLightModelSceneAmbient();
LightSource* _glLightAt(GLuint i);
GLboolean _glNearZClippingEnabled();
GLboolean _glGPUStateIsDirty();
void _glGPUStateMarkClean();
void _glGPUStateMarkDirty();
#define MAX_GLDC_TEXTURE_UNITS 2
#define MAX_GLDC_LIGHTS 8
#define AMBIENT_MASK 1
#define DIFFUSE_MASK 2
#define EMISSION_MASK 4
#define SPECULAR_MASK 8
#define SCENE_AMBIENT_MASK 16
/* This is from KOS pvr_buffers.c */
#define PVR_MIN_Z 0.0001f
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
#define CLAMP( X, _MIN, _MAX ) ( (X)<(_MIN) ? (_MIN) : ((X)>(_MAX) ? (_MAX) : (X)) )
#endif // PRIVATE_H

View File

@ -1,68 +0,0 @@
#include "profile.h"
Profiler __profiler;
void profiler_init() {
__profiler.trace_count = 0;
}
static uint32_t time_now_in_ms() {
return timer_us_gettime64() / 1000;
}
static int compare(const void* trace1, const void* trace2) {
Trace* t1 = (Trace*) trace1;
Trace* t2 = (Trace*) trace2;
return (t1->total_time < t2->total_time) ? -1 : (t2->total_time < t1->total_time) ? 1 : 0;
}
void profiler_dump(uint32_t ms) {
static uint32_t time_since_last = time_now_in_ms();
uint32_t now = time_now_in_ms();
if((now - time_since_last) >= ms) {
qsort(__profiler.traces, __profiler.trace_count, sizeof(Trace), compare);
fprintf(stderr, "Function\t\t\t\tTotal Time\t\t\t\tBreakdown\n");
for(uint8_t i = 0; i < __profiler.trace_count; ++i) {
Trace* trace = __profiler.traces + i;
fprintf(stderr, "%s\t\t\t\t%dms\n", trace->name, trace->total_time);
for(uint8_t j = 0; j < trace->max_checkpoints; ++j) {
fprintf(stderr, "\t\t\t\t\t\t\t\t%d: %dms\n", trace->checkpoints[j].total_time);
}
fprintf(stderr, "\n\n");
}
time_since_last -= ms;
}
}
void profiler_register_trace(Trace* trace, const char* func_name) {
__profiler.traces[__profiler.trace_count++] = trace;
trace->calls = 0;
trace->max_checkpoints = 0;
trace->total_time = 0;
trace->start = 0;
strncpy(trace->name, func_name, 128);
}
void profiler_trace_start(Trace* trace) {
trace->start = time_now_in_ms();
trace->calls++;
}
void profiler_trace_checkpoint(Trace* trace, int counter) {
uint32_t now = time_now_in_ms();
uint32_t checkpoint_time = (now - trace->start);
trace->total_time += checkpoint_time;
trace->start = now;
trace->checkpoints[counter].total_time + checkpoint_time;
trace->checkpoints[counter].calls++;
}

View File

@ -1,74 +0,0 @@
#ifndef PROFILE_H
#define PROFILE_H
#include <stdint.h>
#include "../containers/aligned_vector.h"
/* USAGE:
*
* profiler_init();
*
* void my_func() {
* TRACE_START();
*
* ...
*
* TRACE_CHECKPOINT();
*
* ...
*
* TRACE_CHECKPOINT();
* }
*
* profiler_dump(1000);
*
*
* Output:
*
* Name Total Time Breakdown
* -------------------------------------------------
my_func 15.33
0: 4.23
1: 11.10
*/
typedef struct {
uint32_t total_time;
uint32_t calls;
} Checkpoint;
typedef struct {
char name[128];
uint32_t calls;
uint32_t start;
uint32_t total_time;
Checkpoint checkpoints[16];
uint8_t max_checkpoints;
} Trace;
struct Profiler {
Trace traces[256];
uint8_t trace_count;
};
extern Profiler __profiler;
void profiler_init();
void profiler_dump(uint32_t ms);
void profiler_register_trace(Trace* trace, const char* func_name);
void profiler_trace_start(Trace* trace);
void profiler_trace_checkpoint(Trace* trace, int counter);
#define TRACE_START() \
int __sc = 0; \
static char __trace_registered = 0;
static Trace __trace; \
if(!_trace_registered) {profiler_register_trace(&__trace, __func__); __trace_registered = 1;} \
profiler_trace_start(&__trace);
#define TRACE_CHECKPOINT() \
profiler_trace_checkpoint(&__trace, __sc++);
#endif // PROFILE_H

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

16
GL/types.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <stdint.h>
typedef struct {
/* Same 32 byte layout as pvr_vertex_t */
uint32_t flags;
float xyz[3];
float uv[2];
uint8_t bgra[4];
/* In the pvr_vertex_t structure, this next 4 bytes is oargb
* but we're not using that for now, so having W here makes the code
* simpler */
float w;
} __attribute__ ((aligned (32))) Vertex;

15
GL/util.c Normal file
View File

@ -0,0 +1,15 @@
#include "private.h"
void APIENTRY glVertexPackColor3fKOS(GLVertexKOS* vertex, float r, float g, float b) {
vertex->bgra[3] = 255;
vertex->bgra[2] = (r * 255.0f);
vertex->bgra[1] = (g * 255.0f);
vertex->bgra[0] = (b * 255.0f);
}
void APIENTRY glVertexPackColor4fKOS(GLVertexKOS* vertex, float r, float g, float b, float a) {
vertex->bgra[3] = (a * 255.0f);
vertex->bgra[2] = (r * 255.0f);
vertex->bgra[1] = (g * 255.0f);
vertex->bgra[0] = (b * 255.0f);
}

2
GL/version.c.in Normal file
View File

@ -0,0 +1,2 @@
const char* GLDC_VERSION = "@GLDC_VERSION@";

View File

@ -1,32 +0,0 @@
# KallistiOS ##version##
#
# kos-ports/libgl Makefile
# Copyright (C) 2013, 2014 Josh Pearson
# Copyright (C) 2014 Lawrence Sebald
# Copyright (C) 2018 Luke Benstead
TARGET = libGLdc.a
OBJS = GL/draw.o GL/flush.o GL/framebuffer.o GL/immediate.o GL/lighting.o GL/state.o GL/texture.o GL/glu.o
OBJS += GL/matrix.o GL/fog.o GL/error.o GL/clip.o containers/stack.o containers/named_array.o containers/aligned_vector.o
SUBDIRS =
KOS_CFLAGS += -ffast-math -O3 -Iinclude
link:
$(KOS_AR) rcs $(TARGET) $(OBJS)
build: $(OBJS) link
samples: build
$(KOS_MAKE) -C samples all
defaultall: create_kos_link $(OBJS) subdirs linklib samples
include $(KOS_BASE)/addons/Makefile.prefab
# creates the kos link to the headers
create_kos_link:
rm -f ../include/GL
ln -s ../GLdc/include ../include/GL

View File

@ -1,6 +1,8 @@
# GLdc
**Development of GLdc has moved to [Gitlab](https://gitlab.com/simulant/GLdc)**
This is a partial implementation of OpenGL 1.2 for the SEGA Dreamcast for use
with the KallistiOS SDK.
@ -12,19 +14,50 @@ features via extensions.
Things left to (re)implement:
- Near-Z clipping (Tricky)
- Spotlights (Trivial)
- Framebuffer extension (Trivial)
- Multitexturing (Trivial)
- Texture Matrix (Trivial)
- Mipmapping (Trivial)
Things I'd like to do:
- Use a clean "gl.h"
- Define an extension for modifier volumes
- Support `GL_ALPHA_TEST` using punch-thru polys
- Add support for point sprites
- Optimise, add unit tests for correctness
# Compiling
GLdc uses CMake for its build system, it currently ships with two "backends":
- kospvr - This is the hardware-accelerated Dreamcast backend
- software - This is a stub software rasterizer used for testing testing and debugging
To compile a Dreamcast debug build, you'll want to do something like the following:
```
mkdir dcbuild
cd dcbuild
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/Dreamcast.cmake -G "Unix Makefiles" ..
make
```
For a release build, replace the cmake line with with the following:
```
cmake -DCMAKE_TOOLCHAIN_FILE=../toolchains/Dreamcast.cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release ..
```
You will need KallistiOS compiled and configured (e.g. the KOS_BASE environment
variable must be set)
To compile for PC:
```
mkdir pcbuild
cd pcbuild
cmake -G "Unix Makefiles" ..
make
```
# Special Thanks!
- Massive shout out to Hayden Kowalchuk for diagnosing and fixing a large number of bugs while porting GL Quake to the Dreamcast. Absolute hero!

View File

@ -1,101 +1,56 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <stdio.h>
#ifndef __APPLE__
#include <malloc.h>
#ifdef _arch_dreamcast
#include "../GL/private.h"
#else
/* Linux + Kos define this, OSX does not, so just use malloc there */
#define memalign(x, size) malloc((size))
#define FASTCPY memcpy
#endif
#include "aligned_vector.h"
void aligned_vector_init(AlignedVector* vector, unsigned int element_size) {
vector->size = vector->capacity = 0;
vector->element_size = element_size;
extern inline void* aligned_vector_resize(AlignedVector* vector, const uint32_t element_count);
extern inline void* aligned_vector_extend(AlignedVector* vector, const uint32_t additional_count);
extern inline void* aligned_vector_reserve(AlignedVector* vector, uint32_t element_count);
extern inline void* aligned_vector_push_back(AlignedVector* vector, const void* objs, uint32_t count);
void aligned_vector_init(AlignedVector* vector, uint32_t element_size) {
/* Now initialize the header*/
AlignedVectorHeader* const hdr = &vector->hdr;
hdr->size = 0;
hdr->capacity = ALIGNED_VECTOR_CHUNK_SIZE;
hdr->element_size = element_size;
vector->data = NULL;
/* Reserve some initial capacity */
aligned_vector_reserve(vector, ALIGNED_VECTOR_INITIAL_CAPACITY);
}
void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count) {
if(element_count <= vector->capacity) {
return;
}
unsigned int original_byte_size = vector->size * vector->element_size;
unsigned int new_byte_size = element_count * vector->element_size;
unsigned char* original_data = vector->data;
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
if(original_data) {
memcpy(vector->data, original_data, original_byte_size);
free(original_data);
}
vector->capacity = element_count;
}
void aligned_vector_push_back(AlignedVector* vector, const void* objs, unsigned int count) {
/* Resize enough room */
unsigned int initial_size = vector->size;
aligned_vector_resize(vector, vector->size + count);
unsigned char* dest = vector->data + (vector->element_size * initial_size);
/* Copy the objects in */
memcpy(dest, objs, vector->element_size * count);
}
void aligned_vector_resize(AlignedVector* vector, const unsigned int element_count) {
/* Don't change memory when resizing downwards, just change the size */
if(element_count <= vector->size) {
vector->size = element_count;
return;
}
if(vector->capacity < element_count) {
/* Reserve more than we need so that a subsequent push_back doesn't trigger yet another
* resize */
aligned_vector_reserve(vector, (int) ceil(((float)element_count) * 1.5f));
}
vector->size = element_count;
}
void* aligned_vector_at(AlignedVector* vector, const unsigned int index) {
return &vector->data[index * vector->element_size];
}
void* aligned_vector_extend(AlignedVector* vector, const unsigned int additional_count) {
const unsigned int current = vector->size;
aligned_vector_resize(vector, vector->size + additional_count);
return aligned_vector_at(vector, current);
}
void aligned_vector_clear(AlignedVector* vector) {
vector->size = 0;
/* Reserve some initial capacity. This will do the allocation but not set up the header */
void* ptr = aligned_vector_reserve(vector, ALIGNED_VECTOR_CHUNK_SIZE);
assert(ptr);
(void) ptr;
}
void aligned_vector_shrink_to_fit(AlignedVector* vector) {
if(vector->size == 0) {
AlignedVectorHeader* const hdr = &vector->hdr;
if(hdr->size == 0) {
uint32_t element_size = hdr->element_size;
free(vector->data);
/* Reallocate the header */
vector->data = NULL;
vector->capacity = 0;
hdr->size = hdr->capacity = 0;
hdr->element_size = element_size;
} else {
unsigned int new_byte_size = vector->size * vector->element_size;
unsigned char* original_data = vector->data;
uint32_t new_byte_size = (hdr->size * hdr->element_size);
uint8_t* original_data = vector->data;
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
if(original_data) {
memcpy(vector->data, original_data, new_byte_size);
FASTCPY(vector->data, original_data, new_byte_size);
free(original_data);
}
vector->capacity = vector->size;
hdr->capacity = hdr->size;
}
}

View File

@ -1,31 +1,222 @@
#ifndef ALIGNED_VECTOR_H
#define ALIGNED_VECTOR_H
#pragma once
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__APPLE__) || defined(__WIN32__)
/* Linux + Kos define this, OSX does not, so just use malloc there */
static inline void* memalign(size_t alignment, size_t size) {
(void) alignment;
return malloc(size);
}
#else
#include <malloc.h>
#endif
#ifdef __cplusplus
#define AV_FORCE_INLINE static inline
#else
#define AV_NO_INSTRUMENT inline __attribute__((no_instrument_function))
#define AV_INLINE_DEBUG AV_NO_INSTRUMENT __attribute__((always_inline))
#define AV_FORCE_INLINE static AV_INLINE_DEBUG
#endif
#ifdef __DREAMCAST__
#include <kos/string.h>
AV_FORCE_INLINE void *AV_MEMCPY4(void *dest, const void *src, size_t len)
{
if(!len)
{
return dest;
}
const uint8_t *s = (uint8_t *)src;
uint8_t *d = (uint8_t *)dest;
uint32_t diff = (uint32_t)d - (uint32_t)(s + 1); // extra offset because input gets incremented before output is calculated
// Underflow would be like adding a negative offset
// Can use 'd' as a scratch reg now
asm volatile (
"clrs\n" // Align for parallelism (CO) - SH4a use "stc SR, Rn" instead with a dummy Rn
".align 2\n"
"0:\n\t"
"dt %[size]\n\t" // (--len) ? 0 -> T : 1 -> T (EX 1)
"mov.b @%[in]+, %[scratch]\n\t" // scratch = *(s++) (LS 1/2)
"bf.s 0b\n\t" // while(s != nexts) aka while(!T) (BR 1/2)
" mov.b %[scratch], @(%[offset], %[in])\n" // *(datatype_of_s*) ((char*)s + diff) = scratch, where src + diff = dest (LS 1)
: [in] "+&r" ((uint32_t)s), [scratch] "=&r" ((uint32_t)d), [size] "+&r" (len) // outputs
: [offset] "z" (diff) // inputs
: "t", "memory" // clobbers
);
return dest;
}
#else
#define AV_MEMCPY4 memcpy
#endif
typedef struct {
unsigned int size;
unsigned int capacity;
unsigned char* data;
unsigned int element_size;
uint32_t size;
uint32_t capacity;
uint32_t element_size;
} __attribute__((aligned(32))) AlignedVectorHeader;
typedef struct {
AlignedVectorHeader hdr;
uint8_t* data;
} AlignedVector;
#define ALIGNED_VECTOR_INITIAL_CAPACITY 256u
#define ALIGNED_VECTOR_CHUNK_SIZE 256u
#define ROUND_TO_CHUNK_SIZE(v) \
((((v) + ALIGNED_VECTOR_CHUNK_SIZE - 1) / ALIGNED_VECTOR_CHUNK_SIZE) * ALIGNED_VECTOR_CHUNK_SIZE)
void aligned_vector_init(AlignedVector* vector, uint32_t element_size);
AV_FORCE_INLINE void* aligned_vector_at(const AlignedVector* vector, const uint32_t index) {
const AlignedVectorHeader* hdr = &vector->hdr;
assert(index < hdr->size);
return vector->data + (index * hdr->element_size);
}
AV_FORCE_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t element_count) {
AlignedVectorHeader* hdr = &vector->hdr;
if(element_count < hdr->capacity) {
return aligned_vector_at(vector, element_count);
}
uint32_t original_byte_size = (hdr->size * hdr->element_size);
/* We overallocate so that we don't make small allocations during push backs */
element_count = ROUND_TO_CHUNK_SIZE(element_count);
uint32_t new_byte_size = (element_count * hdr->element_size);
uint8_t* original_data = vector->data;
vector->data = (uint8_t*) memalign(0x20, new_byte_size);
assert(vector->data);
AV_MEMCPY4(vector->data, original_data, original_byte_size);
free(original_data);
hdr->capacity = element_count;
return vector->data + original_byte_size;
}
AV_FORCE_INLINE AlignedVectorHeader* aligned_vector_header(const AlignedVector* vector) {
return (AlignedVectorHeader*) &vector->hdr;
}
AV_FORCE_INLINE uint32_t aligned_vector_size(const AlignedVector* vector) {
const AlignedVectorHeader* hdr = &vector->hdr;
return hdr->size;
}
AV_FORCE_INLINE uint32_t aligned_vector_capacity(const AlignedVector* vector) {
const AlignedVectorHeader* hdr = &vector->hdr;
return hdr->capacity;
}
AV_FORCE_INLINE void* aligned_vector_front(const AlignedVector* vector) {
return vector->data;
}
#define av_assert(x) \
do {\
if(!(x)) {\
fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\
exit(1);\
}\
} while(0); \
/* Resizes the array and returns a pointer to the first new element (if upsizing) or NULL (if downsizing) */
AV_FORCE_INLINE void* aligned_vector_resize(AlignedVector* vector, const uint32_t element_count) {
void* ret = NULL;
AlignedVectorHeader* hdr = &vector->hdr;
uint32_t previous_count = hdr->size;
if(hdr->capacity <= element_count) {
/* If we didn't have capacity, increase capacity (slow) */
aligned_vector_reserve(vector, element_count);
hdr->size = element_count;
ret = aligned_vector_at(vector, previous_count);
av_assert(hdr->size == element_count);
av_assert(hdr->size <= hdr->capacity);
} else if(previous_count < element_count) {
/* So we grew, but had the capacity, just get a pointer to
* where we were */
hdr->size = element_count;
av_assert(hdr->size < hdr->capacity);
ret = aligned_vector_at(vector, previous_count);
} else if(hdr->size != element_count) {
hdr->size = element_count;
av_assert(hdr->size < hdr->capacity);
}
return ret;
}
AV_FORCE_INLINE void* aligned_vector_push_back(AlignedVector* vector, const void* objs, uint32_t count) {
/* Resize enough room */
AlignedVectorHeader* hdr = &vector->hdr;
assert(count);
assert(hdr->element_size);
#ifndef NDEBUG
uint32_t element_size = hdr->element_size;
uint32_t initial_size = hdr->size;
#endif
uint8_t* dest = (uint8_t*) aligned_vector_resize(vector, hdr->size + count);
assert(dest);
/* Copy the objects in */
AV_MEMCPY4(dest, objs, hdr->element_size * count);
assert(hdr->element_size == element_size);
assert(hdr->size == initial_size + count);
return dest;
}
AV_FORCE_INLINE void* aligned_vector_extend(AlignedVector* vector, const uint32_t additional_count) {
AlignedVectorHeader* hdr = &vector->hdr;
void* ret = aligned_vector_resize(vector, hdr->size + additional_count);
assert(ret); // Should always return something
return ret;
}
AV_FORCE_INLINE void aligned_vector_clear(AlignedVector* vector){
AlignedVectorHeader* hdr = &vector->hdr;
hdr->size = 0;
}
void aligned_vector_init(AlignedVector* vector, unsigned int element_size);
void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count);
void aligned_vector_push_back(AlignedVector* vector, const void* objs, unsigned int count);
void aligned_vector_resize(AlignedVector* vector, const unsigned int element_count);
void* aligned_vector_at(AlignedVector* vector, const unsigned int index);
void* aligned_vector_extend(AlignedVector* vector, const unsigned int additional_count);
void aligned_vector_clear(AlignedVector* vector);
void aligned_vector_shrink_to_fit(AlignedVector* vector);
void aligned_vector_cleanup(AlignedVector* vector);
AV_FORCE_INLINE void* aligned_vector_back(AlignedVector* vector){
AlignedVectorHeader* hdr = &vector->hdr;
return aligned_vector_at(vector, hdr->size ? hdr->size - 1 : 0);
}
#ifdef __cplusplus
}
#endif
#endif // ALIGNED_VECTOR_H

View File

@ -1,6 +1,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#ifndef __APPLE__
#include <malloc.h>
@ -15,8 +17,7 @@ void named_array_init(NamedArray* array, unsigned int element_size, unsigned int
array->element_size = element_size;
array->max_element_count = max_elements;
float c = (float) max_elements / 8.0f;
array->marker_count = (unsigned char) ceil(c);
array->marker_count = (unsigned char)((max_elements+8-1)/8);
#ifdef _arch_dreamcast
// Use 32-bit aligned memory on the Dreamcast
@ -26,28 +27,18 @@ void named_array_init(NamedArray* array, unsigned int element_size, unsigned int
array->elements = (unsigned char*) malloc(element_size * max_elements);
array->used_markers = (unsigned char*) malloc(array->marker_count);
#endif
memset(array->used_markers, 0, sizeof(array->marker_count));
}
char named_array_used(NamedArray* array, unsigned int id) {
id--;
unsigned int i = id / 8;
unsigned int j = id % 8;
unsigned char v = array->used_markers[i] & (unsigned char) (1 << j);
return !!(v);
memset(array->used_markers, 0, sizeof(unsigned char) * array->marker_count);
}
void* named_array_alloc(NamedArray* array, unsigned int* new_id) {
unsigned int i = 0, j = 0;
for(i = 0; i < array->marker_count; ++i) {
for(j = 0; j < 8; ++j) {
unsigned int id = (i * 8) + j + 1;
unsigned int id = (i * 8) + j;
if(!named_array_used(array, id)) {
array->used_markers[i] |= (unsigned char) 1 << j;
*new_id = id;
unsigned char* ptr = &array->elements[(id - 1) * array->element_size];
unsigned char* ptr = &array->elements[id * array->element_size];
memset(ptr, 0, array->element_size);
return ptr;
}
@ -57,25 +48,35 @@ void* named_array_alloc(NamedArray* array, unsigned int* new_id) {
return NULL;
}
void named_array_release(NamedArray* array, unsigned int new_id) {
new_id--;
void* named_array_reserve(NamedArray* array, unsigned int id) {
if(!named_array_used(array, id)) {
unsigned int j = (id % 8);
unsigned int i = id / 8;
assert(!named_array_used(array, id));
array->used_markers[i] |= (unsigned char) 1 << j;
assert(named_array_used(array, id));
unsigned char* ptr = &array->elements[id * array->element_size];
memset(ptr, 0, array->element_size);
return ptr;
}
return named_array_get(array, id);
}
void named_array_release(NamedArray* array, unsigned int new_id) {
unsigned int i = new_id / 8;
unsigned int j = new_id % 8;
array->used_markers[i] &= (unsigned char) ~(1 << j);
}
void* named_array_get(NamedArray* array, unsigned int id) {
if(id == 0) {
return NULL;
}
if(!named_array_used(array, id)) {
return NULL;
}
return &array->elements[(id - 1) * array->element_size];
return &array->elements[id * array->element_size];
}
void named_array_cleanup(NamedArray* array) {

View File

@ -1,3 +1,5 @@
#pragma once
#ifndef NAMED_ARRAY_H
#define NAMED_ARRAY_H
@ -14,8 +16,17 @@ typedef struct {
} NamedArray;
void named_array_init(NamedArray* array, unsigned int element_size, unsigned int max_elements);
char named_array_used(NamedArray* array, unsigned int id);
static inline char named_array_used(NamedArray* array, unsigned int id) {
const unsigned int i = id / 8;
const unsigned int j = id % 8;
unsigned char v = array->used_markers[i] & (unsigned char) (1 << j);
return !!(v);
}
void* named_array_alloc(NamedArray* array, unsigned int* new_id);
void* named_array_reserve(NamedArray* array, unsigned int id);
void named_array_release(NamedArray* array, unsigned int new_id);
void* named_array_get(NamedArray* array, unsigned int id);
void named_array_cleanup(NamedArray* array);

View File

@ -1,10 +1,13 @@
#include <string.h>
#include <stdlib.h>
#ifndef __APPLE__
#include <malloc.h>
#else
#if defined(__APPLE__) || defined(__WIN32__)
/* Linux + Kos define this, OSX does not, so just use malloc there */
#define memalign(x, size) malloc((size))
static inline void* memalign(size_t alignment, size_t size) {
return malloc(size);
}
#else
#include <malloc.h>
#endif
#include "stack.h"

View File

@ -19,33 +19,41 @@ __BEGIN_DECLS
#include <math.h>
#include <dc/fmath.h>
#include <dc/matrix.h>
#include <dc/matrix3d.h>
#include <dc/pvr.h>
#include <dc/vec3f.h>
#include <dc/video.h>
#if __STDCPP_FLOAT16_T__
#include <stdfloat>
#endif
/* Primitive Types taken from GL for compatability */
/* Not all types are implemented in Open GL DC V.1.0 */
#define GL_POINTS 0x01
#define GL_LINES 0x02
#define GL_LINE_LOOP 0x03
#define GL_LINE_STRIP 0x04
#define GL_TRIANGLES 0x05
#define GL_TRIANGLE_STRIP 0x06
#define GL_TRIANGLE_FAN 0x07
#define GL_QUADS 0x08
#define GL_QUAD_STRIP 0x09
#define GL_POLYGON 0x0A
#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_QUAD_STRIP 0x0008
#define GL_POLYGON 0x0009
/* FrontFaceDirection */
#define GL_CW 0x0900
#define GL_CCW 0x0901
#define GL_NONE 0
#define GL_FRONT_LEFT 0x0400
#define GL_FRONT_RIGHT 0x0401
#define GL_BACK_LEFT 0x0402
#define GL_BACK_RIGHT 0x0403
#define GL_FRONT 0x0404
#define GL_BACK 0x0405
#define GL_LEFT 0x0406
#define GL_RIGHT 0x0407
#define GL_FRONT_AND_BACK 0x0408
#define GL_AUX0 0x0409
#define GL_AUX1 0x040A
#define GL_AUX2 0x040B
#define GL_AUX3 0x040C
#define GL_CULL_FACE 0x0B44
#define GL_CULL_FACE_MODE 0x0B45
#define GL_FRONT_FACE 0x0B46
@ -54,6 +62,12 @@ __BEGIN_DECLS
#define GL_SCISSOR_TEST 0x0008 /* capability bit */
#define GL_SCISSOR_BOX 0x0C10
/* Stencil actions */
#define GL_KEEP 0x1E00
#define GL_INCR 0x1E02
#define GL_DECR 0x1E03
#define GL_INVERT 0x150A
/* Matrix modes */
#define GL_MATRIX_MODE 0x0BA0
#define GL_MODELVIEW 0x1700
@ -104,18 +118,14 @@ __BEGIN_DECLS
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_TEXTURE_FILTER GL_TEXTURE_MIN_FILTER
#define GL_FILTER_NONE 0x0
#define GL_FILTER_BILINEAR 0x1
#define GL_REPEAT 0x2901
#define GL_CLAMP 0x2900
/* Texture Environment */
#define GL_TEXTURE_ENV_MODE 0x2200
#define GL_REPLACE 0x0
#define GL_MODULATE 0x1
#define GL_DECAL 0x2
#define GL_MODULATEALPHA 0x3
#define GL_REPLACE 0x1E01
#define GL_MODULATE 0x2100
#define GL_DECAL 0x2101
/* TextureMagFilter */
#define GL_NEAREST 0x2600
@ -189,6 +199,14 @@ __BEGIN_DECLS
#define GL_SCISSOR_BIT 0x00080000
#define GL_ALL_ATTRIB_BITS 0x000FFFFF
/* Clip planes */
#define GL_CLIP_PLANE0 0x3000
#define GL_CLIP_PLANE1 0x3001
#define GL_CLIP_PLANE2 0x3002
#define GL_CLIP_PLANE3 0x3003
#define GL_CLIP_PLANE4 0x3004
#define GL_CLIP_PLANE5 0x3005
/* Fog */
#define GL_FOG 0x0004 /* capability bit */
#define GL_FOG_MODE 0x0B65
@ -236,6 +254,13 @@ __BEGIN_DECLS
#define GL_SINGLE_COLOR 0x81F9
#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
/* glPolygonOffset */
#define GL_POLYGON_OFFSET_FACTOR 0x8038
#define GL_POLYGON_OFFSET_UNITS 0x2A00
#define GL_POLYGON_OFFSET_POINT 0x2A01
#define GL_POLYGON_OFFSET_LINE 0x2A02
#define GL_POLYGON_OFFSET_FILL 0x8037
/* Client state caps */
#define GL_VERTEX_ARRAY 0x8074
#define GL_NORMAL_ARRAY 0x8075
@ -284,12 +309,13 @@ __BEGIN_DECLS
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_DOUBLE 0x140A
#define GL_HALF_FLOAT 0x140B
#define GL_2_BYTES 0x1407
#define GL_3_BYTES 0x1408
#define GL_4_BYTES 0x1409
/* ErrorCode */
#define GL_NO_ERROR 0
#define GL_NO_ERROR ((GLenum) 0)
#define GL_INVALID_ENUM 0x0500
#define GL_INVALID_VALUE 0x0501
#define GL_INVALID_OPERATION 0x0502
@ -329,9 +355,6 @@ __BEGIN_DECLS
#define GL_VERSION 0x1F02
#define GL_EXTENSIONS 0x1F03
/* GL KOS near Z-CLIPPING */
#define GL_KOS_NEARZ_CLIPPING 0x0020 /* capability bit */
/* GL KOS Texture Matrix Enable Bit */
#define GL_KOS_TEXTURE_MATRIX 0x002F
@ -341,25 +364,10 @@ __BEGIN_DECLS
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
/*
* Dreamcast specific compressed + twiddled formats.
* We use constants from the range 0xEEE0 onwards
* to avoid trampling any real GL constants (this is in the middle of the
* any_vendor_future_use range defined in the GL enum.spec file.
*/
#define GL_UNSIGNED_SHORT_5_6_5_TWID_KOS 0xEEE0
#define GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS 0xEEE2
#define GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS 0xEEE3
#define GL_UNSIGNED_SHORT_5_6_5_VQ_KOS 0xEEE4
#define GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_KOS 0xEEE6
#define GL_UNSIGNED_SHORT_4_4_4_4_VQ_KOS 0xEEE7
#define GL_UNSIGNED_SHORT_5_6_5_VQ_TWID_KOS 0xEEE8
#define GL_UNSIGNED_SHORT_1_5_5_5_REV_VQ_TWID_KOS 0xEEEA
#define GL_UNSIGNED_SHORT_4_4_4_4_REV_VQ_TWID_KOS 0xEEEB
#define GL_COLOR_INDEX 0x1900
#define GL_RED 0x1903
#define GL_GREEN 0x1904
#define GL_BLUE 0x1905
@ -368,7 +376,76 @@ __BEGIN_DECLS
#define GL_RGBA 0x1908
#define GL_LUMINANCE 0x1909
#define GL_LUMINANCE_ALPHA 0x190A
#define GL_R3_G3_B2 0x2A10
#define GL_ALPHA4 0x803B
#define GL_ALPHA8 0x803C
#define GL_ALPHA12 0x803D
#define GL_ALPHA16 0x803E
#define GL_LUMINANCE4 0x803F
#define GL_LUMINANCE8 0x8040
#define GL_LUMINANCE12 0x8041
#define GL_LUMINANCE16 0x8042
#define GL_LUMINANCE4_ALPHA4 0x8043
#define GL_LUMINANCE6_ALPHA2 0x8044
#define GL_LUMINANCE8_ALPHA8 0x8045
#define GL_LUMINANCE12_ALPHA4 0x8046
#define GL_LUMINANCE12_ALPHA12 0x8047
#define GL_LUMINANCE16_ALPHA16 0x8048
#define GL_INTENSITY4 0x804A
#define GL_INTENSITY8 0x804B
#define GL_INTENSITY12 0x804C
#define GL_INTENSITY16 0x804D
#define GL_BGR 0x80E0
#define GL_BGRA 0x80E1
#define GL_INTENSITY 0x8049
#define GL_RGB4 0x804F
#define GL_RGB5 0x8050
#define GL_RGB8 0x8051
#define GL_RGB10 0x8052
#define GL_RGB12 0x8053
#define GL_RGB16 0x8054
#define GL_RGBA2 0x8055
#define GL_RGBA4 0x8056
#define GL_RGB5_A1 0x8057
#define GL_RGBA8 0x8058
#define GL_RGB10_A2 0x8059
#define GL_RGBA12 0x805A
#define GL_RGBA16 0x805B
#define GL_R8 0x8229
#define GL_RG8 0x822B
#define GL_RG 0x8227
#define GL_R16 0x822A
#define GL_RG16 0x822C
#define GL_COMPRESSED_RED 0x8225
#define GL_COMPRESSED_RG 0x8226
/* Polygons */
#define GL_POINT 0x1B00
#define GL_LINE 0x1B01
#define GL_FILL 0x1B02
#define GL_CW 0x0900
#define GL_CCW 0x0901
#define GL_FRONT 0x0404
#define GL_BACK 0x0405
#define GL_POLYGON_MODE 0x0B40
#define GL_POLYGON_SMOOTH 0x0B41
#define GL_POLYGON_STIPPLE 0x0B42
#define GL_EDGE_FLAG 0x0B43
#define GL_CULL_FACE 0x0B44
#define GL_CULL_FACE_MODE 0x0B45
#define GL_FRONT_FACE 0x0B46
#define GL_POLYGON_OFFSET_FACTOR 0x8038
#define GL_POLYGON_OFFSET_UNITS 0x2A00
#define GL_POLYGON_OFFSET_POINT 0x2A01
#define GL_POLYGON_OFFSET_LINE 0x2A02
#define GL_POLYGON_OFFSET_FILL 0x8037
#define GLbyte char
#define GLshort short
@ -379,26 +456,47 @@ __BEGIN_DECLS
#define GLushort unsigned short
#define GLuint unsigned int
#define GLenum unsigned int
#define GLsizei unsigned long
#define GLsizei unsigned int
#define GLfixed const unsigned int
#define GLclampf float
#define GLclampd float
#define GLubyte unsigned char
#define GLbitfield unsigned long
#define GLbitfield unsigned int
#define GLboolean unsigned char
#define GL_FALSE 0
#define GL_TRUE 1
#if __STDCPP_FLOAT16_T__
#define GLhalf std::float16_t
#else
#define GLhalf unsigned short
#endif
/* Stubs for portability */
#define GL_ALPHA_TEST 0
#define GL_STENCIL_TEST 0
#define GL_CLAMP_TO_EDGE 0
#define GL_UNPACK_ALIGNMENT 0
#define GL_LINE_SMOOTH 0x0B20
#define GL_ALPHA_TEST 0x0BC0
#define GL_STENCIL_TEST 0x0B90
#define GL_STENCIL_WRITEMASK 0x0B98
#define GL_INDEX_WRITEMASK 0x0C21
#define GL_COLOR_WRITEMASK 0x0C23
#define GL_UNPACK_SWAP_BYTES 0x0CF0
#define GL_UNPACK_LSB_FIRST 0x0CF1
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#define GL_UNPACK_SKIP_ROWS 0x0CF3
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
#define GL_UNPACK_ALIGNMENT 0x0CF5
#define GL_PACK_SWAP_BYTES 0x0D00
#define GL_PACK_LSB_FIRST 0x0D01
#define GL_PACK_ROW_LENGTH 0x0D02
#define GL_PACK_SKIP_ROWS 0x0D03
#define GL_PACK_SKIP_PIXELS 0x0D04
#define GL_PACK_ALIGNMENT 0x0D05
#define GLAPI extern
#define APIENTRY
/* Initialize the GL pipeline. GL will initialize the PVR. */
GLAPI void APIENTRY glKosInit();
GLAPI void APIENTRY glFlush(void);
GLAPI void APIENTRY glFinish(void);
/* Start Submission of Primitive Data */
/* Currently Supported Primitive Types:
@ -410,16 +508,21 @@ GLAPI void APIENTRY glKosInit();
GLAPI void APIENTRY glBegin(GLenum mode);
/* Finish Submission of Primitive Data */
GLAPI void APIENTRY glEnd();
GLAPI void APIENTRY glEnd(void);
/* Primitive Texture Coordinate Submission */
GLAPI void APIENTRY glTexCoord1f(GLfloat u);
GLAPI void APIENTRY glTexCoord1fv(const GLfloat *u);
GLAPI void APIENTRY glTexCoord2f(GLfloat u, GLfloat v);
GLAPI void APIENTRY glTexCoord2fv(const GLfloat *uv);
/* Primitive Color Submission */
GLAPI void APIENTRY glColor1ui(GLuint argb);
GLAPI void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
GLAPI void APIENTRY glColor4ubv(const GLubyte *v);
GLAPI void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b);
GLAPI void APIENTRY glColor3ub(GLubyte r, GLubyte g, GLubyte b);
GLAPI void APIENTRY glColor3ubv(const GLubyte *v);
GLAPI void APIENTRY glColor3fv(const GLfloat *rgb);
GLAPI void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
GLAPI void APIENTRY glColor4fv(const GLfloat *rgba);
@ -469,11 +572,16 @@ GLAPI void APIENTRY glDisable(GLenum cap);
GLAPI void APIENTRY glClear(GLuint mode);
GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
GLAPI void APIENTRY glReadBuffer(GLenum mode);
GLAPI void APIENTRY glDrawBuffer(GLenum mode);
/* Depth Testing */
GLAPI void APIENTRY glClearDepth(GLfloat depth);
GLAPI void APIENTRY glClearDepthf(GLfloat depth);
GLAPI void APIENTRY glDepthMask(GLboolean flag);
GLAPI void APIENTRY glDepthFunc(GLenum func);
GLAPI void APIENTRY glDepthRange(GLclampf n, GLclampf f);
GLAPI void APIENTRY glDepthRangef(GLclampf n, GLclampf f);
/* Hints */
/* Currently Supported Capabilities:
@ -492,6 +600,7 @@ GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor);
/* Texturing */
GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param);
GLAPI void APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param);
GLAPI void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param);
GLAPI void APIENTRY glTexEnvf(GLenum target, GLenum pname, GLfloat param);
@ -531,23 +640,13 @@ GLAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalForma
GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *data);
/* Loads VQ compressed texture from SH4 RAM into PVR VRAM */
/* internalformat must be one of the following constants:
GL_UNSIGNED_SHORT_5_6_5_VQ
GL_UNSIGNED_SHORT_5_6_5_VQ_TWID
GL_UNSIGNED_SHORT_4_4_4_4_VQ
GL_UNSIGNED_SHORT_4_4_4_4_VQ_TWID
GL_UNSIGNED_SHORT_1_5_5_5_VQ
GL_UNSIGNED_SHORT_1_5_5_5_VQ_TWID
*/
GLAPI void APIENTRY glCompressedTexImage2D(GLenum target,
GLint level,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLsizei imageSize,
const GLvoid *data);
GLAPI void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
GLAPI void APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
GLAPI void APIENTRY glCopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
GLAPI void APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
GLAPI void APIENTRY glCopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
GLAPI void APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
/* GL Array API - Only GL_TRIANGLES, GL_TRIANGLE_STRIP, and GL_QUADS are supported */
GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type,
@ -575,15 +674,15 @@ GLAPI void APIENTRY glDisableClientState(GLenum cap);
GLAPI void APIENTRY glMatrixMode(GLenum mode);
GLAPI void APIENTRY glLoadIdentity();
GLAPI void APIENTRY glLoadIdentity(void);
GLAPI void APIENTRY glLoadMatrixf(const GLfloat *m);
GLAPI void APIENTRY glLoadTransposeMatrixf(const GLfloat *m);
GLAPI void APIENTRY glMultMatrixf(const GLfloat *m);
GLAPI void APIENTRY glMultTransposeMatrixf(const GLfloat *m);
GLAPI void APIENTRY glPushMatrix();
GLAPI void APIENTRY glPopMatrix();
GLAPI void APIENTRY glPushMatrix(void);
GLAPI void APIENTRY glPopMatrix(void);
GLAPI void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z);
#define glTranslated glTranslatef
@ -611,6 +710,7 @@ GLAPI void APIENTRY glFrustum(GLfloat left, GLfloat right,
/* Fog Functions - client must enable GL_FOG for this to take effect */
GLAPI void APIENTRY glFogi(GLenum pname, GLint param);
GLAPI void APIENTRY glFogf(GLenum pname, GLfloat param);
GLAPI void APIENTRY glFogiv(GLenum pname, const GLint* params);
GLAPI void APIENTRY glFogfv(GLenum pname, const GLfloat *params);
/* Lighting Functions - client must enable GL_LIGHTING for this to take effect */
@ -629,19 +729,14 @@ GLAPI void APIENTRY glLightModeliv(GLenum pname, const GLint *params);
GLAPI void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param);
GLAPI void APIENTRY glMaterialf(GLenum face, GLenum pname, const GLfloat param);
GLAPI void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
/* Returns the size needed to store a mip-mapped texture generated by gluBuild2DMipmaps(...) */
GLAPI GLuint APIENTRY glKosMipMapTexSize(GLuint width, GLuint height);
GLAPI void APIENTRY glColorMaterial(GLenum face, GLenum mode);
/* glGet Functions */
GLAPI void APIENTRY glGetBooleanv(GLenum pname, GLboolean* params);
GLAPI void APIENTRY glGetIntegerv(GLenum pname, GLint *params);
GLAPI void APIENTRY glGetFloatv(GLenum pname, GLfloat *params);
GLAPI GLboolean APIENTRY glIsEnabled(GLenum cap);
GLAPI const GLbyte* APIENTRY glGetString(GLenum name);
/* Multi-Texture Extensions - Currently not supported in immediate mode */
GLAPI void APIENTRY glActiveTextureARB(GLenum texture);
GLAPI void APIENTRY glClientActiveTextureARB(GLenum texture);
GLAPI const GLubyte* APIENTRY glGetString(GLenum name);
/* Error handling */
GLAPI GLenum APIENTRY glGetError(void);
@ -649,10 +744,15 @@ GLAPI GLenum APIENTRY glGetError(void);
/* Non Operational Stubs for portability */
GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref);
GLAPI void APIENTRY glLineWidth(GLfloat width);
GLAPI void APIENTRY glPolygonMode(GLenum face, GLenum mode);
GLAPI void APIENTRY glPolygonOffset(GLfloat factor, GLfloat units);
GLAPI void APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint * params);
GLAPI void APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
GLAPI void APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint *params);
GLAPI void APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
GLAPI void APIENTRY glPixelStorei(GLenum pname, GLint param);
GLAPI void APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask);
GLAPI void APIENTRY glStencilOp(GLenum sfail, GLenum dpfail, GLenum dppass);
GLAPI void APIENTRY glGetTexImage(GLenum tex, GLint lod, GLenum format, GLenum type, GLvoid* img);
__END_DECLS

231
include/GL/glext.h Normal file
View File

@ -0,0 +1,231 @@
/* KallistiGL for KallistiOS ##version##
libgl/glext.h
Copyright (C) 2014 Josh Pearson
Copyright (c) 2007-2013 The Khronos Group Inc.
*/
#ifndef __GL_GLEXT_H
#define __GL_GLEXT_H
#include <sys/cdefs.h>
__BEGIN_DECLS
#define GL_TEXTURE0_ARB 0x84C0
#define GL_TEXTURE1_ARB 0x84C1
#define GL_TEXTURE2_ARB 0x84C2
#define GL_TEXTURE3_ARB 0x84C3
#define GL_TEXTURE4_ARB 0x84C4
#define GL_TEXTURE5_ARB 0x84C5
#define GL_TEXTURE6_ARB 0x84C6
#define GL_TEXTURE7_ARB 0x84C7
#define GL_TEXTURE8_ARB 0x84C8
#define GL_TEXTURE9_ARB 0x84C9
#define GL_TEXTURE10_ARB 0x84CA
#define GL_TEXTURE11_ARB 0x84CB
#define GL_TEXTURE12_ARB 0x84CC
#define GL_TEXTURE13_ARB 0x84CD
#define GL_TEXTURE14_ARB 0x84CE
#define GL_TEXTURE15_ARB 0x84CF
#define GL_TEXTURE16_ARB 0x84D0
#define GL_TEXTURE17_ARB 0x84D1
#define GL_TEXTURE18_ARB 0x84D2
#define GL_TEXTURE19_ARB 0x84D3
#define GL_TEXTURE20_ARB 0x84D4
#define GL_TEXTURE21_ARB 0x84D5
#define GL_TEXTURE22_ARB 0x84D6
#define GL_TEXTURE23_ARB 0x84D7
#define GL_TEXTURE24_ARB 0x84D8
#define GL_TEXTURE25_ARB 0x84D9
#define GL_TEXTURE26_ARB 0x84DA
#define GL_TEXTURE27_ARB 0x84DB
#define GL_TEXTURE28_ARB 0x84DC
#define GL_TEXTURE29_ARB 0x84DD
#define GL_TEXTURE30_ARB 0x84DE
#define GL_TEXTURE31_ARB 0x84DF
#define GL_ACTIVE_TEXTURE_ARB 0x84E0
#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
#define GL_CLAMP_TO_EDGE 0x812F
#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
#define GL_MULTISAMPLE_ARB 0x809D
#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
#define GL_SAMPLE_COVERAGE_ARB 0x80A0
#define GL_SAMPLE_BUFFERS_ARB 0x80A8
#define GL_SAMPLES_ARB 0x80A9
#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
#define GL_MULTISAMPLE_BIT_ARB 0x20000000
#define GL_NORMAL_MAP_ARB 0x8511
#define GL_REFLECTION_MAP_ARB 0x8512
#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
#define GL_COMPRESSED_ALPHA_ARB 0x84E9
#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGBA_ARB 0x84EE
#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
#define GL_FRAMEBUFFER_EXT 0x8D40
#define GL_RENDERBUFFER_EXT 0x8D41
#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
/* Multitexture extensions */
GLAPI void APIENTRY glActiveTextureARB(GLenum texture);
GLAPI void APIENTRY glClientActiveTextureARB(GLenum texture);
GLAPI void APIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t);
GLAPI void APIENTRY glGenFramebuffersEXT(GLsizei n, GLuint* framebuffers);
GLAPI void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers);
GLAPI void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer);
GLAPI void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
GLAPI void APIENTRY glGenerateMipmap(GLenum target);
GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target);
GLAPI GLboolean APIENTRY glIsFramebufferEXT(GLuint framebuffer);
/* ext_paletted_texture */
#define GL_COLOR_INDEX1_EXT 0x80E2
#define GL_COLOR_INDEX2_EXT 0x80E3
#define GL_COLOR_INDEX4_EXT 0x80E4
#define GL_COLOR_INDEX8_EXT 0x80E5
#define GL_COLOR_INDEX12_EXT 0x80E6
#define GL_COLOR_INDEX16_EXT 0x80E7
#define GL_COLOR_TABLE_FORMAT_EXT 0x80D8
#define GL_COLOR_TABLE_WIDTH_EXT 0x80D9
#define GL_COLOR_TABLE_RED_SIZE_EXT 0x80DA
#define GL_COLOR_TABLE_GREEN_SIZE_EXT 0x80DB
#define GL_COLOR_TABLE_BLUE_SIZE_EXT 0x80DC
#define GL_COLOR_TABLE_ALPHA_SIZE_EXT 0x80DD
#define GL_COLOR_TABLE_LUMINANCE_SIZE_EXT 0x80DE
#define GL_COLOR_TABLE_INTENSITY_SIZE_EXT 0x80DF
#define GL_TEXTURE_INDEX_SIZE_EXT 0x80ED
#define GL_SHARED_TEXTURE_PALETTE_EXT 0x81FB
GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *data);
GLAPI void APIENTRY glColorSubTableEXT(GLenum target, GLsizei start, GLsizei count, GLenum format, GLenum type, const GLvoid *data);
GLAPI void APIENTRY glGetColorTableEXT(GLenum target, GLenum format, GLenum type, GLvoid *data);
GLAPI void APIENTRY glGetColorTableParameterivEXT(GLenum target, GLenum pname, GLint *params);
GLAPI void APIENTRY glGetColorTableParameterfvEXT(GLenum target, GLenum pname, GLfloat *params);
/* ext OES_compressed_paletted_texture */
/* PixelInternalFormat */
//Ozzy: used MesaGL definitions please adjust if it causes probs.
#define GL_PALETTE4_RGB8_OES 0x8B90
#define GL_PALETTE4_RGBA8_OES 0x8B91
#define GL_PALETTE4_R5_G6_B5_OES 0x8B92
#define GL_PALETTE4_RGBA4_OES 0x8B93
#define GL_PALETTE4_RGB5_A1_OES 0x8B94
#define GL_PALETTE8_RGB8_OES 0x8B95
#define GL_PALETTE8_RGBA8_OES 0x8B96
#define GL_PALETTE8_R5_G6_B5_OES 0x8B97
#define GL_PALETTE8_RGBA4_OES 0x8B98
#define GL_PALETTE8_RGB5_A1_OES 0x8B99
/* Loads VQ compressed texture from SH4 RAM into PVR VRAM */
/* internalformat must be one of the following constants:
GL_UNSIGNED_SHORT_5_6_5_VQ
GL_UNSIGNED_SHORT_5_6_5_VQ_TWID
GL_UNSIGNED_SHORT_4_4_4_4_VQ
GL_UNSIGNED_SHORT_4_4_4_4_VQ_TWID
GL_UNSIGNED_SHORT_1_5_5_5_VQ
GL_UNSIGNED_SHORT_1_5_5_5_VQ_TWID
*/
GLAPI void APIENTRY glCompressedTexImage2DARB(GLenum target,
GLint level,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLint border,
GLsizei imageSize,
const GLvoid *data);
/* Core aliases */
#define GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
#define glActiveTexture glActiveTextureARB
#define glClientActiveTexture glClientActiveTextureARB
#define glMultiTexCoord2f glMultiTexCoord2fARB
#define glGenerateMipmapEXT glGenerateMipmap
#define glCompressedTexImage2D glCompressedTexImage2DARB
#ifndef GL_VERSION_1_4
#define GL_VERSION_1_4 1
#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
#define GL_TEXTURE_LOD_BIAS 0x8501
#define GL_MAX_TEXTURE_LOD_BIAS_DEFAULT 7
#define GL_KOS_INTERNAL_DEFAULT_MIPMAP_LOD_BIAS 4
#endif
#ifndef GL_EXT_texture_lod_bias
#define GL_EXT_texture_lod_bias 1
#define GL_MAX_TEXTURE_LOD_BIAS_EXT 0x84FD
#define GL_TEXTURE_FILTER_CONTROL_EXT 0x8500
#define GL_TEXTURE_LOD_BIAS_EXT 0x8501
#endif /* GL_EXT_texture_lod_bias */
/* ATI_meminfo */
#define GL_VBO_FREE_MEMORY_ATI 0x87FB
#define GL_TEXTURE_FREE_MEMORY_ATI 0x87FC
#define GL_RENDERBUFFER_FREE_MEMORY_ATI 0x87FD
__END_DECLS
#endif /* !__GL_GLEXT_H */

218
include/GL/glkos.h Normal file
View File

@ -0,0 +1,218 @@
#pragma once
#include "gl.h"
__BEGIN_DECLS
extern const char* GLDC_VERSION;
/*
* Dreamcast specific compressed + twiddled formats.
* We use constants from the range 0xEEE0 onwards
* to avoid trampling any real GL constants (this is in the middle of the
* any_vendor_future_use range defined in the GL enum.spec file.
*/
#define GL_UNSIGNED_SHORT_5_6_5_TWID_KOS 0xEEE0
#define GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS 0xEEE2
#define GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS 0xEEE3
#define GL_COMPRESSED_RGB_565_VQ_KOS 0xEEE4
#define GL_COMPRESSED_ARGB_1555_VQ_KOS 0xEEE6
#define GL_COMPRESSED_ARGB_4444_VQ_KOS 0xEEE7
#define GL_COMPRESSED_RGB_565_VQ_TWID_KOS 0xEEE8
#define GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS 0xEEEA
#define GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS 0xEEEB
#define GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS 0xEEEC
#define GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS 0xEEED
#define GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS 0xEEEE
#define GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS 0xEEEF
#define GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS 0xEEF0
#define GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS 0xEEF1
#define GL_NEARZ_CLIPPING_KOS 0xEEFA
/* Initialize the GL pipeline. GL will initialize the PVR. */
GLAPI void APIENTRY glKosInit();
typedef struct {
/* If GL_TRUE, enables pvr autosorting, this *will* break glDepthFunc/glDepthTest */
GLboolean autosort_enabled;
/* If GL_TRUE, enables the PVR FSAA */
GLboolean fsaa_enabled;
/* The internal format for paletted textures, must be GL_RGBA4 (default) or GL_RGBA8 */
GLenum internal_palette_format;
/* Initial capacity of each of the OP, TR and PT lists in vertices */
GLuint initial_op_capacity;
GLuint initial_tr_capacity;
GLuint initial_pt_capacity;
GLuint initial_immediate_capacity;
/* Default: True
*
* Whether glTexImage should automatically twiddle textures
* if the internal format is a generic format (e.g. GL_RGB).
* this is the same as calling glEnable(GL_TEXTURE_TWIDDLE_KOS)
* on boot */
GLboolean texture_twiddle;
} GLdcConfig;
typedef struct {
GLuint padding0;
GLfloat x;
GLfloat y;
GLfloat z;
GLfloat u;
GLfloat v;
GLubyte bgra[4];
GLuint padding1;
} GLVertexKOS;
GLAPI void APIENTRY glVertexPackColor3fKOS(GLVertexKOS* vertex, float r, float g, float b);
GLAPI void APIENTRY glVertexPackColor4fKOS(GLVertexKOS* vertex, float r, float g, float b, float a);
GLAPI void APIENTRY glKosInitConfig(GLdcConfig* config);
/* Usage:
*
* GLdcConfig config;
* glKosInitConfig(&config);
*
* config.autosort_enabled = GL_TRUE;
*
* glKosInitEx(&config);
*/
GLAPI void APIENTRY glKosInitEx(GLdcConfig* config);
GLAPI void APIENTRY glKosSwapBuffers();
GLAPI void APIENTRY glKosShutdown();
/*
* CUSTOM EXTENSION multiple_shared_palette_KOS
*
* This extension allows using up to 4 different shared palettes
* with ColorTableEXT. The following constants are provided
* to use as targets for ColorTableExt:
*
* - SHARED_TEXTURE_PALETTE_0_KOS
* - SHARED_TEXTURE_PALETTE_1_KOS
* - SHARED_TEXTURE_PALETTE_2_KOS
* - SHARED_TEXTURE_PALETTE_3_KOS
*
* In this use case SHARED_TEXTURE_PALETTE_0_KOS is interchangable with SHARED_TEXTURE_PALETTE_EXT
* (both refer to the first shared palette).
*
* To select which palette a texture uses, a new pname is accepted by TexParameteri: SHARED_TEXTURE_BANK_KOS
* by default textures use shared palette 0.
*/
#define GL_SHARED_TEXTURE_PALETTE_0_KOS 0xEEFC
#define GL_SHARED_TEXTURE_PALETTE_1_KOS 0xEEFD
#define GL_SHARED_TEXTURE_PALETTE_2_KOS 0xEEFE
#define GL_SHARED_TEXTURE_PALETTE_3_KOS 0xEEFF
#define GL_SHARED_TEXTURE_PALETTE_4_KOS 0xEF00
#define GL_SHARED_TEXTURE_PALETTE_5_KOS 0xEF01
#define GL_SHARED_TEXTURE_PALETTE_6_KOS 0xEF02
#define GL_SHARED_TEXTURE_PALETTE_7_KOS 0xEF03
#define GL_SHARED_TEXTURE_PALETTE_8_KOS 0xEF04
#define GL_SHARED_TEXTURE_PALETTE_9_KOS 0xEF05
#define GL_SHARED_TEXTURE_PALETTE_10_KOS 0xEF06
#define GL_SHARED_TEXTURE_PALETTE_11_KOS 0xEF07
#define GL_SHARED_TEXTURE_PALETTE_12_KOS 0xEF08
#define GL_SHARED_TEXTURE_PALETTE_13_KOS 0xEF09
#define GL_SHARED_TEXTURE_PALETTE_14_KOS 0xEF0A
#define GL_SHARED_TEXTURE_PALETTE_15_KOS 0xEF0B
#define GL_SHARED_TEXTURE_PALETTE_16_KOS 0xEF0C
#define GL_SHARED_TEXTURE_PALETTE_17_KOS 0xEF0D
#define GL_SHARED_TEXTURE_PALETTE_18_KOS 0xEF0E
#define GL_SHARED_TEXTURE_PALETTE_19_KOS 0xEF0F
#define GL_SHARED_TEXTURE_PALETTE_20_KOS 0xEF10
#define GL_SHARED_TEXTURE_PALETTE_21_KOS 0xEF11
#define GL_SHARED_TEXTURE_PALETTE_22_KOS 0xEF12
#define GL_SHARED_TEXTURE_PALETTE_23_KOS 0xEF13
#define GL_SHARED_TEXTURE_PALETTE_24_KOS 0xEF14
#define GL_SHARED_TEXTURE_PALETTE_25_KOS 0xEF15
#define GL_SHARED_TEXTURE_PALETTE_26_KOS 0xEF16
#define GL_SHARED_TEXTURE_PALETTE_27_KOS 0xEF17
#define GL_SHARED_TEXTURE_PALETTE_28_KOS 0xEF18
#define GL_SHARED_TEXTURE_PALETTE_29_KOS 0xEF19
#define GL_SHARED_TEXTURE_PALETTE_30_KOS 0xEF1A
#define GL_SHARED_TEXTURE_PALETTE_31_KOS 0xEF1B
#define GL_SHARED_TEXTURE_PALETTE_32_KOS 0xEF1C
#define GL_SHARED_TEXTURE_PALETTE_33_KOS 0xEF1D
#define GL_SHARED_TEXTURE_PALETTE_34_KOS 0xEF1E
#define GL_SHARED_TEXTURE_PALETTE_35_KOS 0xEF1F
#define GL_SHARED_TEXTURE_PALETTE_36_KOS 0xEF20
#define GL_SHARED_TEXTURE_PALETTE_37_KOS 0xEF21
#define GL_SHARED_TEXTURE_PALETTE_38_KOS 0xEF22
#define GL_SHARED_TEXTURE_PALETTE_39_KOS 0xEF23
#define GL_SHARED_TEXTURE_PALETTE_40_KOS 0xEF24
#define GL_SHARED_TEXTURE_PALETTE_41_KOS 0xEF25
#define GL_SHARED_TEXTURE_PALETTE_42_KOS 0xEF26
#define GL_SHARED_TEXTURE_PALETTE_43_KOS 0xEF27
#define GL_SHARED_TEXTURE_PALETTE_44_KOS 0xEF28
#define GL_SHARED_TEXTURE_PALETTE_45_KOS 0xEF29
#define GL_SHARED_TEXTURE_PALETTE_46_KOS 0xEF2A
#define GL_SHARED_TEXTURE_PALETTE_47_KOS 0xEF2B
#define GL_SHARED_TEXTURE_PALETTE_48_KOS 0xEF2C
#define GL_SHARED_TEXTURE_PALETTE_49_KOS 0xEF2D
#define GL_SHARED_TEXTURE_PALETTE_50_KOS 0xEF2E
#define GL_SHARED_TEXTURE_PALETTE_51_KOS 0xEF2F
#define GL_SHARED_TEXTURE_PALETTE_52_KOS 0xEF30
#define GL_SHARED_TEXTURE_PALETTE_53_KOS 0xEF31
#define GL_SHARED_TEXTURE_PALETTE_54_KOS 0xEF32
#define GL_SHARED_TEXTURE_PALETTE_55_KOS 0xEF33
#define GL_SHARED_TEXTURE_PALETTE_56_KOS 0xEF34
#define GL_SHARED_TEXTURE_PALETTE_57_KOS 0xEF35
#define GL_SHARED_TEXTURE_PALETTE_58_KOS 0xEF36
#define GL_SHARED_TEXTURE_PALETTE_59_KOS 0xEF37
#define GL_SHARED_TEXTURE_PALETTE_60_KOS 0xEF38
#define GL_SHARED_TEXTURE_PALETTE_61_KOS 0xEF39
#define GL_SHARED_TEXTURE_PALETTE_62_KOS 0xEF3A
#define GL_SHARED_TEXTURE_PALETTE_63_KOS 0xEF3B
/* Pass to glTexParameteri to set the shared bank */
#define GL_SHARED_TEXTURE_BANK_KOS 0xEF3C
/* Memory allocation extension (GL_KOS_texture_memory_management) */
GLAPI GLvoid APIENTRY glDefragmentTextureMemory_KOS(void);
/* glGet extensions */
#define GL_FREE_TEXTURE_MEMORY_KOS 0xEF3D
#define GL_USED_TEXTURE_MEMORY_KOS 0xEF3E
#define GL_FREE_CONTIGUOUS_TEXTURE_MEMORY_KOS 0xEF3F
//for palette internal format (glfcConfig)
#define GL_RGB565_KOS 0xEF40
#define GL_ARGB4444_KOS 0xEF41
#define GL_ARGB1555_KOS 0xEF42
#define GL_RGB565_TWID_KOS 0xEF43
#define GL_ARGB4444_TWID_KOS 0xEF44
#define GL_ARGB1555_TWID_KOS 0xEF45
#define GL_COLOR_INDEX8_TWID_KOS 0xEF46
#define GL_COLOR_INDEX4_TWID_KOS 0xEF47
#define GL_RGB_TWID_KOS 0xEF48
#define GL_RGBA_TWID_KOS 0xEF49
/* glGet extensions */
#define GL_TEXTURE_INTERNAL_FORMAT_KOS 0xEF50
/* If enabled, will twiddle texture uploads where possible */
#define GL_TEXTURE_TWIDDLE_KOS 0xEF51
__END_DECLS

View File

@ -17,7 +17,7 @@
__BEGIN_DECLS
#ifndef BUILD_LIBGL
#include <GL/gl.h>
#include "gl.h"
#endif
#define GLU_FALSE 0
@ -34,6 +34,11 @@ GLAPI void APIENTRY gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
GLfloat centerx, GLfloat centery, GLfloat centerz,
GLfloat upx, GLfloat upy, GLfloat upz);
/* generate mipmaps for any image provided by the user and then pass them to OpenGL */
GLAPI GLint APIENTRY gluBuild2DMipmaps(GLenum target, GLint internalFormat,
GLsizei width, GLsizei height,
GLenum format, GLenum type, const void *data);
GLAPI const GLubyte* APIENTRY gluErrorString(GLenum error);
__END_DECLS

View File

@ -1,92 +0,0 @@
/* KallistiGL for KallistiOS ##version##
libgl/glext.h
Copyright (C) 2014 Josh Pearson
Copyright (c) 2007-2013 The Khronos Group Inc.
*/
#ifndef __GL_GLEXT_H
#define __GL_GLEXT_H
#include <sys/cdefs.h>
__BEGIN_DECLS
#define GL_TEXTURE0_ARB 0x84C0
#define GL_TEXTURE1_ARB 0x84C1
#define GL_TEXTURE2_ARB 0x84C2
#define GL_TEXTURE3_ARB 0x84C3
#define GL_TEXTURE4_ARB 0x84C4
#define GL_TEXTURE5_ARB 0x84C5
#define GL_TEXTURE6_ARB 0x84C6
#define GL_TEXTURE7_ARB 0x84C7
#define GL_TEXTURE8_ARB 0x84C8
#define GL_TEXTURE9_ARB 0x84C9
#define GL_TEXTURE10_ARB 0x84CA
#define GL_TEXTURE11_ARB 0x84CB
#define GL_TEXTURE12_ARB 0x84CC
#define GL_TEXTURE13_ARB 0x84CD
#define GL_TEXTURE14_ARB 0x84CE
#define GL_TEXTURE15_ARB 0x84CF
#define GL_TEXTURE16_ARB 0x84D0
#define GL_TEXTURE17_ARB 0x84D1
#define GL_TEXTURE18_ARB 0x84D2
#define GL_TEXTURE19_ARB 0x84D3
#define GL_TEXTURE20_ARB 0x84D4
#define GL_TEXTURE21_ARB 0x84D5
#define GL_TEXTURE22_ARB 0x84D6
#define GL_TEXTURE23_ARB 0x84D7
#define GL_TEXTURE24_ARB 0x84D8
#define GL_TEXTURE25_ARB 0x84D9
#define GL_TEXTURE26_ARB 0x84DA
#define GL_TEXTURE27_ARB 0x84DB
#define GL_TEXTURE28_ARB 0x84DC
#define GL_TEXTURE29_ARB 0x84DD
#define GL_TEXTURE30_ARB 0x84DE
#define GL_TEXTURE31_ARB 0x84DF
#define GL_ACTIVE_TEXTURE_ARB 0x84E0
#define GL_CLIENT_ACTIVE_TEXTURE_ARB 0x84E1
#define GL_MAX_TEXTURE_UNITS_ARB 0x84E2
#define GL_TRANSPOSE_MODELVIEW_MATRIX_ARB 0x84E3
#define GL_TRANSPOSE_PROJECTION_MATRIX_ARB 0x84E4
#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
#define GL_MULTISAMPLE_ARB 0x809D
#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
#define GL_SAMPLE_COVERAGE_ARB 0x80A0
#define GL_SAMPLE_BUFFERS_ARB 0x80A8
#define GL_SAMPLES_ARB 0x80A9
#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
#define GL_MULTISAMPLE_BIT_ARB 0x20000000
#define GL_NORMAL_MAP_ARB 0x8511
#define GL_REFLECTION_MAP_ARB 0x8512
#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
#define GL_TEXTURE_BINDING_CUBE_MAP_ARB 0x8514
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB 0x8515
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB 0x8516
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB 0x8517
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB 0x8518
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB 0x8519
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB 0x851A
#define GL_PROXY_TEXTURE_CUBE_MAP_ARB 0x851B
#define GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB 0x851C
#define GL_COMPRESSED_ALPHA_ARB 0x84E9
#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGBA_ARB 0x84EE
#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
__END_DECLS
#endif /* !__GL_GLEXT_H */

View File

@ -1,51 +0,0 @@
#ifndef GLKOS_H
#define GLKOS_H
#include "gl.h"
__BEGIN_DECLS
#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
#define GL_FRAMEBUFFER_EXT 0x8D40
#define GL_RENDERBUFFER_EXT 0x8D41
#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
GLAPI void APIENTRY glKosSwapBuffers();
GLAPI void APIENTRY glGenFramebuffersEXT(GLsizei n, GLuint* framebuffers);
GLAPI void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers);
GLAPI void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer);
GLAPI void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
GLAPI void APIENTRY glGenerateMipmapEXT(GLenum target);
GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target);
GLAPI GLboolean APIENTRY glIsFramebufferEXT(GLuint framebuffer);
__END_DECLS
#endif // GLKOS_H

View File

@ -1,16 +0,0 @@
# Manipulate the CFLAGS to look our *our* version of the library and includes
INC_DIR = $(abspath ../include)
LIB_DIR = $(abspath ../)
export CFLAGS := $(CFLAGS) -I $(INC_DIR)
export OBJEXTRA := $(LIB_DIR)/libGLdc.a
all:
$(KOS_MAKE) -C nehe02 all
$(KOS_MAKE) -C nehe02va all
$(KOS_MAKE) -C nehe03 all
$(KOS_MAKE) -C nehe06 all
$(KOS_MAKE) -C ortho2d all
$(KOS_MAKE) -C lerabot01 all
$(KOS_MAKE) -C zclip all

157
samples/blend_test/main.c Normal file
View File

@ -0,0 +1,157 @@
/*
* This sample demonstrates blending, and the importance of drawing order,
* depth testing and z-value.
* This is a merge of lerabot_blend_test and blend_test, with 1 added case,
* and with adapted/corrected explanation
*/
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glDisable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
void DrawQuad(const float* colour) {
glBegin(GL_QUADS);
glColor4fv(colour);
glVertex3f(-1.0,-1.0, 0.0);
glVertex3f( 1.0,-1.0, 0.0);
glVertex3f( 1.0, 1.0, 0.0);
glVertex3f(-1.0, 1.0, 0.0);
glEnd();
}
/* The main drawing function. */
void DrawGLScene()
{
const float RED [] = {1.0, 0, 0, 0.5};
const float BLUE [] = {0.0, 0, 1, 0.5};
const float NONE [] = {0, 0, 0, 0};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
// LEFT UPPER SECTION
glLoadIdentity(); // Reset The View
glTranslatef(-4.0, 2.0, -10);
// This draws 2 quads, a red first, then an overlapping blue one.
// Both quads are drawn at the SAME z-value
// With depth test GL_LEQUAL, this means blending for the overlapping part
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
DrawQuad(RED);
glTranslatef(1.0, 0, 0);
DrawQuad(BLUE);
glDisable(GL_BLEND);
// RIGHT UPPER SECTION
glTranslatef(4.0, 0, 0);
// This draws 2 quads, a red first, then an overlapping blue one.
// The blue quad has a LOWER z-value, so it is behind the red quad.
// With depth test GL_LEQUAL, the blue part is not considered for the overlapping part, so no blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
DrawQuad(RED);
glTranslatef(1.0, 0, -0.01);
DrawQuad(BLUE);
glDisable(GL_BLEND);
// LEFT DOWN SECTION
glLoadIdentity(); // Reset The View
glTranslatef(-4.0, -1.0, -10);
// This draws 2 quads, a red first, then an overlapping blue one.
// The blue quad has a HIGHER z-value, so it is in front the red quad.
// With depth test GL_LEQUAL, this means blending for the overlapping part
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
DrawQuad(RED);
glTranslatef(1.0, 0, 0.01);
DrawQuad(BLUE);
glDisable(GL_BLEND);
// RIGHT DOWN SECTION
glTranslatef(4.0, 0.0, -0.01);
// This is basically the same as the RIGHT UPPER SECTION, except that the blue quad
// is drawn first.
// With depth test GL_LEQUAL, this means blending for the overlapping part
// <- the order of drawing is important for blending !
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glTranslatef(1.0, 0.0, -0.01);
DrawQuad(BLUE);
glTranslatef(-1.0, 0.0, 0.01);
DrawQuad(RED);
glDisable(GL_BLEND);
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

446
samples/cubes/main.cpp Normal file
View File

@ -0,0 +1,446 @@
#include <cstdio>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#ifdef __DREAMCAST__
#include <kos.h>
float avgfps = -1;
#endif
#include "GL/gl.h"
#include "GL/glkos.h"
#include "GL/glu.h"
#include "GL/glext.h"
#define PI 3.14159265358979323846264338327950288f
#define RAD_TO_DEG 57.295779513082320876798154814105f
#define MAX_CUBES 350
float timeElapsed = 0.0f;
const float dt = 1.0f / 60.0f;
float angle = 0;
const float invAngle360 = 1.0f / 360.0f;
const float cameraDistance = 3.0f;
bool isDrawingArrays = false;
bool isBlendingEnabled = true;
bool isRunning = true;
typedef struct
{
GLubyte r;
GLubyte g;
GLubyte b;
GLubyte a;
} Color;
Color colors[] =
{
{255, 0, 0, 128},
{0, 255, 0, 128},
{0, 0, 255, 128},
{255, 255, 0, 128},
{255, 0, 255, 128},
{0, 255, 255, 128}
};
Color faceColors[24];
float cubeVertices[] =
{
// Front face
-1.0f, -1.0f, +1.0f, // vertex 0
+1.0f, -1.0f, +1.0f, // vertex 1
+1.0f, +1.0f, +1.0f, // vertex 2
-1.0f, +1.0f, +1.0f, // vertex 3
// Back face
-1.0f, -1.0f, -1.0f, // vertex 4
+1.0f, -1.0f, -1.0f, // vertex 5
+1.0f, +1.0f, -1.0f, // vertex 6
-1.0f, +1.0f, -1.0f, // vertex 7
// Top face
-1.0f, +1.0f, +1.0f, // vertex 8
+1.0f, +1.0f, +1.0f, // vertex 9
+1.0f, +1.0f, -1.0f, // vertex 10
-1.0f, +1.0f, -1.0f, // vertex 11
// Bottom face
-1.0f, -1.0f, +1.0f, // vertex 12
+1.0f, -1.0f, +1.0f, // vertex 13
+1.0f, -1.0f, -1.0f, // vertex 14
-1.0f, -1.0f, -1.0f, // vertex 15
// Right face
+1.0f, -1.0f, +1.0f, // vertex 16
+1.0f, -1.0f, -1.0f, // vertex 17
+1.0f, +1.0f, -1.0f, // vertex 18
+1.0f, +1.0f, +1.0f, // vertex 19
// Left face
-1.0f, -1.0f, +1.0f, // vertex 20
-1.0f, -1.0f, -1.0f, // vertex 21
-1.0f, +1.0f, -1.0f, // vertex 22
-1.0f, +1.0f, +1.0f // vertex 23
};
// Set up indices array
unsigned int cubeIndices[] =
{
// Front face
0, 1, 2, 3,
// Back face
4, 5, 6, 7,
// Top face
8, 9, 10, 11,
// Bottom face
12, 13, 14, 15,
// Right face
16, 17, 18, 19,
// Left face
20, 21, 22, 23
};
typedef struct
{
float r;
float x, y, z;
float vx, vy, vz;
} Cube;
Cube cubes[MAX_CUBES];
int numCubes = 0;
// Create a 4x4 identity matrix
float cubeTransformationMatrix[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f };
void debugLog(const char* msg) {
#ifdef __DREAMCAST__
dbglog(DBG_KDEBUG, "%s\n", msg);
#else
printf("%s\n", msg);
#endif
}
void runningStats() {
#ifdef __DREAMCAST__
pvr_stats_t stats;
pvr_get_stats(&stats);
if (avgfps != -1)
avgfps = (avgfps + stats.frame_rate) * 0.5f;
else
avgfps = stats.frame_rate;
#endif
}
void avgStats() {
#ifdef __DREAMCAST__
dbglog(DBG_DEBUG, "Average frame rate: ~%f fps\n", avgfps);
#endif
}
void stats() {
#ifdef __DREAMCAST__
pvr_stats_t stats;
pvr_get_stats(&stats);
dbglog(DBG_DEBUG, "3D Stats: %d VBLs, current frame rate ~%f fps\n", stats.vbl_count, stats.frame_rate);
avgStats();
#endif
}
void addCube(float r, float x, float y, float z, float vx, float vy, float vz)
{
if (numCubes < MAX_CUBES) {
cubes[numCubes].r = r;
cubes[numCubes].x = x;
cubes[numCubes].y = y;
cubes[numCubes].z = z;
cubes[numCubes].vx = vx;
cubes[numCubes].vy = vy;
cubes[numCubes].vz = vz;
numCubes++;
}
}
void addCubeQuick(float x, float y, float z, float scale_factor)
{
addCube(0.5f * scale_factor, x, y, z, 0, 0, 0);
}
void updateCubes(float dt)
{
for (size_t i = 0; i < numCubes; i++)
{
Cube* cube = &cubes[i];
cube->x += cube->vx * dt;
cube->y += cube->vy * dt;
cube->z += cube->vz * dt;
if (cube->x < -3 || cube->x > +3) { cube->vx *= -1; }
if (cube->y < -3 || cube->y > +3) { cube->vy *= -1; }
if (cube->z < -3 || cube->z > +3) { cube->vz *= -1; }
}
}
void renderUnitCube()
{
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, cubeVertices);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, faceColors);
if (isDrawingArrays) {
glDrawArrays(GL_QUADS, 0, 24);
}
else {
glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cubeIndices);
}
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
void renderCubes(float angle)
{
for (size_t i = 0; i < numCubes; i++) {
const float scale_factor = 0.05f + (i / (float)numCubes) * 0.35f;
Cube* cube = &cubes[i];
glPushMatrix(); // Save previous camera state
glMatrixMode(GL_MODELVIEW);
glTranslatef(cube->x, cube->y, cube->z);
glRotatef(angle, 1, 1, 1); // Rotate camera / object
glScalef(scale_factor, scale_factor, scale_factor); // Apply scale factor
renderUnitCube();
glPopMatrix(); // Restore previous camera state
}
}
float rnd(float Min, float Max)
{
return (Max - Min) * (float)rand() / (float)RAND_MAX + Min;
}
void initialize()
{
debugLog("Initialize video output");
glKosInit();
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
if (isBlendingEnabled)
{
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE);
glViewport(0, 0, 640, 480);
glClearColor(0.0f, 0.0f, 0.3f, 1.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Set up colors (each face has a different color)
for (int i = 0; i < 6; i++)
{
faceColors[i * 4] = colors[i];
faceColors[i * 4 + 1] = colors[i];
faceColors[i * 4 + 2] = colors[i];
faceColors[i * 4 + 3] = colors[i];
}
}
void updateTimer()
{
timeElapsed += dt;
if (timeElapsed > 10.0f)
{
stats();
timeElapsed = 0.0f;
}
}
void updateLogic()
{
updateTimer();
const int fullRot = (int)(angle * invAngle360);
angle -= fullRot * 360.0f;
angle += 50.0f * dt;
const float zoomVal = __builtin_sinf(timeElapsed) * 5.0f;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Set up the camera position and orientation
float cameraPos[] = { 0.0f, 0.0f, cameraDistance };
float cameraTarget[] = { 0.0f, 0.0f, 0.0f };
float cameraUp[] = { 0.0f, 1.0f, 0.0f };
// Move the camera
gluLookAt(cameraPos[0], cameraPos[1], cameraPos[2],
cameraTarget[0], cameraTarget[1], cameraTarget[2],
cameraUp[0], cameraUp[1], cameraUp[2]);
glTranslatef(0.0f, 0.0f, -cameraDistance + zoomVal);
// Apply cube transformation (identity matrix)
glLoadIdentity();
updateCubes(dt);
renderCubes(angle);
// Reset ModelView matrix to remove camera transformation
float matrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
matrix[12] = 0.0f;
matrix[13] = 0.0f;
matrix[14] = 0.0f;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(matrix);
}
void updateInput()
{
#ifdef __DREAMCAST__
static uint8_t prevButtons = 0;
maple_device_t* cont;
cont_state_t* state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if (cont)
{
state = (cont_state_t*)maple_dev_status(cont);
if (state && (state->buttons & CONT_START) && !(prevButtons & CONT_START))
{
isRunning = false;
}
if (state && (state->buttons & CONT_A) && !(prevButtons & CONT_A))
{
isDrawingArrays = !isDrawingArrays;
if (isDrawingArrays)
{
glClearColor(0.3f, 0.0f, 0.3f, 1.0f);
}
else
{
glClearColor(0.0f, 0.0f, 0.3f, 1.0f);
}
}
if (state && (state->buttons & CONT_B) && !(prevButtons & CONT_B))
{
isBlendingEnabled = !isBlendingEnabled;
if (isBlendingEnabled)
{
glEnable(GL_BLEND);
}
else
{
glDisable(GL_BLEND);
}
}
prevButtons = state->buttons;
}
#endif
}
void swapBuffers()
{
#ifdef __DREAMCAST__
glKosSwapBuffers();
#endif
}
int main(int argc, char* argv[])
{
initialize();
// Setup camera frustum
const float aspectRatio = 640.0f / 480.0f;
const float fov = 60;
const float zNear = 0.1f;
const float zFar = 1000.0f;
gluPerspective(fov, aspectRatio, zNear, zFar);
for (size_t i = 0; i < MAX_CUBES; i++)
{
const float r = rnd(0.1f, 0.5f);
const float x = rnd(-3.0f, 3.0f);
const float y = rnd(-3.0f, 3.0f);
const float z = rnd(-3.0f, 3.0f);
const float vx = rnd(-2.0f, 2.0f);
const float vy = rnd(-2.0f, 2.0f);
const float vz = rnd(-2.0f, 2.0f);
addCube(r, x, y, z, vx, vy, vz);
}
while (isRunning)
{
updateLogic();
updateInput();
swapBuffers();
runningStats();
}
avgStats();
return 0;
}

144
samples/depth_funcs/main.c Normal file
View File

@ -0,0 +1,144 @@
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
void DrawSquare(float width, float r, float g, float b, float z) {
width /= 2;
glColor3f(r, g, b);
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glVertex3f(-width, width, z); // Top Left
glVertex3f( width, width, z); // Top Right
glVertex3f( width,-width, z); // Bottom Right
glVertex3f(-width,-width, z); // Bottom Left
glEnd(); // done with the polygon
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glDepthFunc(GL_ALWAYS);
DrawSquare(100, 1, 1, 1, -5.0f);
glTranslatef(-2.0, 1.5, 0.0f);
glDepthFunc(GL_LEQUAL);
DrawSquare(1.0, 1, 0, 0, -5.0f);
glPushMatrix();
glTranslatef(0, -1.5, 0);
DrawSquare(1.0, 1, 0, 0, -4.9f);
glPopMatrix();
glTranslatef(1.1, 0, 0);
glDepthFunc(GL_EQUAL);
DrawSquare(1.0, 1, 0, 0, -5.0f);
glPushMatrix();
glTranslatef(0, -1.5, 0);
DrawSquare(1.0, 1, 0, 0, -5.0f);
glPopMatrix();
glTranslatef(1.1, 0, 0);
glDepthFunc(GL_GEQUAL);
DrawSquare(1.0, 1, 0, 0, -5.0f);
glPushMatrix();
glTranslatef(0, -1.5, 0);
DrawSquare(1.0, 1, 0, 0, -5.1f);
glPopMatrix();
glTranslatef(1.1, 0, 0);
glDepthFunc(GL_LESS);
DrawSquare(1.0, 1, 0, 0, -4.9f);
glPushMatrix();
glTranslatef(0, -1.5, 0);
DrawSquare(1.0, 1, 0, 0, -4.8f);
glPopMatrix();
glTranslatef(1.1, 0, 0);
glDepthFunc(GL_GREATER);
DrawSquare(1.0, 1, 0, 0, -5.1f);
glPushMatrix();
glTranslatef(0, -1.5, 0);
DrawSquare(1.0, 1, 0, 0, -5.2f);
glPopMatrix();
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

View File

@ -0,0 +1,236 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <GL/gl.h>
#include <GL/glkos.h>
#include <GL/glext.h>
#include <GL/glu.h>
#include "gl_png.h"
#define CLEANUP(x) { ret = (x); goto cleanup; }
GLfloat global_diffuse[] = {1.0, 1.0, 1.0, 1.0};
GLfloat global_ambient[] = {1.0, 1.0, 1.0, 1.0};
int dtex_to_gl_texture(texture *tex, char* filename) {
// Load Texture
Image *image;
// allocate space for texture
image = (Image *) malloc(sizeof(Image));
if (image == NULL) {
printf("No memory for .DTEX file\n");
return(0);
}
FILE* file = NULL;
// make sure the file is there.
if ((file = fopen(filename, "rb")) == NULL)
{
printf("File not found");
return 0;
}
struct {
char id[4]; // 'DTEX'
GLushort width;
GLushort height;
GLuint type;
GLuint size;
} header;
fread(&header, sizeof(header), 1, file);
GLboolean twiddled = (header.type & (1 << 26)) < 1;
GLboolean compressed = (header.type & (1 << 30)) > 0;
GLboolean mipmapped = (header.type & (1 << 31)) > 0;
GLboolean strided = (header.type & (1 << 25)) > 0;
GLuint format = (header.type >> 27) & 0b111;
image->data = (char *) malloc (header.size);
image->sizeX = header.width;
image->sizeY = header.height;
image->dataSize = header.size;
GLuint expected = 2 * header.width * header.height;
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) header.size));
fread(image->data, image->dataSize, 1, file);
fclose(file);
if(compressed) {
printf("Compressed - ");
if(twiddled) {
printf("Twiddled - ");
switch(format) {
case 0: {
if(mipmapped) {
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS;
} else {
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
}
} break;
case 1: {
if(mipmapped) {
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS;
} else {
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
}
} break;
case 2: {
if(mipmapped) {
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS;
} else {
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
}
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
} else {
switch(format) {
case 0: {
if(mipmapped) {
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS;
} else {
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
}
} break;
case 1: {
if(mipmapped) {
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS;
} else {
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_KOS;
}
} break;
case 2: {
if(mipmapped) {
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS;
} else {
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_KOS;
}
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
}
} else {
printf("Uncompressed - ");
//printf("Color:%u -", format);
switch(format) {
case 0:
image->internalFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS;
//image->internalFormat = GL_UNSIGNED_SHORT_1_5_5_5_REV;
break;
case 1:
image->internalFormat = GL_UNSIGNED_SHORT_5_6_5_REV;
break;
case 2:
image->internalFormat = GL_UNSIGNED_SHORT_4_4_4_4_REV;
break;
}
}
printf("\n");
// Create Texture
GLuint texture_id;
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE_2D, texture_id); // 2d texture (x and y size)
GLint newFormat = format;
GLint colorType = GL_RGB;
if (image->internalFormat == GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS ||
image->internalFormat == GL_UNSIGNED_SHORT_4_4_4_4_REV){
newFormat = GL_BGRA;
colorType = GL_RGBA;
printf("Reversing RGBA\n");
}
if (image->internalFormat == GL_UNSIGNED_SHORT_5_6_5_REV){
newFormat = GL_RGB;
colorType = GL_RGB;
printf("Reversing RGB\n");
}
glTexImage2D(GL_TEXTURE_2D, 0,
colorType, image->sizeX, image->sizeY, 0,
newFormat, image->internalFormat, image->data);
tex->id = texture_id;
tex->w = image->sizeX;
tex->h = image->sizeY;
tex->u = 0.f;
tex->v = 0.f;
tex->a = tex->light = 1;
tex->color[0] = tex->color[1] = tex->color[2] = 1.0f;
tex->uSize = tex->vSize = 1.0f;
tex->xScale = tex->yScale = 1.0f;
tex->format = image->internalFormat;
tex->min_filter = tex->mag_filter = GL_NEAREST;
tex->blend_source = GL_SRC_ALPHA;
tex->blend_dest = GL_ONE_MINUS_SRC_ALPHA;
strcpy(tex->path, filename);
printf("Texture size: %lu x %lu\n", image->sizeX, image->sizeY);
printf("Texture ratio: %d\n", ratio);
printf("Texture size: %lu x %lu\n", image->sizeX, image->sizeY);
printf("Texture %s loaded\n", tex->path);
return(1);
}
void draw_textured_quad(texture *tex) {
if(glIsTexture(tex->id)) {
GLfloat vertex_data[] = {
/* 2D Coordinate, texture coordinate */
0, 1, 0,
1, 1, 0,
1, 0, 0,
0, 0, 0
};
GLfloat uv_data[] = {
/* 2D Coordinate, texture coordinate */
0, 1,
1, 1,
1, 0,
0, 0
};
GLfloat normal_data[] = {
/* 2D Coordinate, texture coordinate */
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0
};
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex->id);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glVertexPointer (3, GL_FLOAT, 0, vertex_data);
glTexCoordPointer (2, GL_FLOAT, 0, uv_data);
glNormalPointer (GL_FLOAT, 0, normal_data);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisable(GL_TEXTURE_2D);
}
}

View File

@ -0,0 +1,42 @@
#ifndef __GL_PNG_H__
#define __GL_PNG_H__
#include <stdio.h>
#include <stdint.h>
#include <GL/gl.h>
typedef struct _texture {
GLuint id;
GLenum format;
GLenum min_filter;
GLenum mag_filter;
GLenum blend_source;
GLenum blend_dest;
int loaded;
uint16_t w, h; // width / height of texture image
int size[2];
float u, v; //uv COORD
float uSize, vSize; // uvSize
float xScale, yScale; //render scale
float a; //alpha
float light; //alpha
float color[3];
char path[32];
} texture;
/* DTEX Image type - contains height, width, and data */
typedef struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
GLenum internalFormat;
GLboolean mipmapped;
unsigned int dataSize;
} Image;
int dtex_to_gl_texture(texture *tex, char* filename);
void draw_textured_quad(texture *tex);
#endif

View File

@ -0,0 +1,142 @@
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
#include "gl_png.h"
//$KOS_BASE/utils/texconv/texconv --in disk.png --format ARGB4444 --preview disk_preview.png --out disk.dtex
#ifdef __DREAMCAST__
extern uint8_t romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMAGE_FILENAME "/rd/disk_1555.dtex"
#else
#define IMAGE_FILENAME "../samples/depth_funcs/alpha_testing/romdisk/disk_1555.dtex"
#endif
texture t;
int blendActive = -1;
/* floats for x rotation, y rotation, z rotation */
float xrot, yrot, zrot;
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
glOrtho(-3, 3, -3, 3, -10, 10);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-3, 3, -3, 3, -10, 10);
glMatrixMode(GL_MODELVIEW);
}
void DrawSquare(float width, float r, float g, float b, float z) {
width /= 2;
glColor3f(r, g, b);
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glVertex3f(-width, width, z); // Top Left
glVertex3f( width, width, z); // Top Right
glVertex3f( width,-width, z); // Bottom Right
glVertex3f(-width,-width, z); // Bottom Left
glEnd(); // done with the polygon
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
//First Batch is alpha blending
glTranslated(-1 ,0, -5);
for (int i = 0; i < 5; i++) {
glTranslated(0.5, 0, 0);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
draw_textured_quad(&t);
glDisable(GL_BLEND);
}
//Second batch is depth testing
//Changing the translate Z value doesn't change anything?
glLoadIdentity();
glTranslated(-1 , -1, -5);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_FUNC);
for (int i = 0; i < 5; i++) {
glTranslated(0.5, 0, -0.2);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
draw_textured_quad(&t);
glDisable(GL_BLEND);
}
glDisable(GL_DEPTH_TEST);
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
//loads a dtex texture. see the /romdisk folder for more files
dtex_to_gl_texture(&t, IMAGE_FILENAME);
ReSizeGLScene(640, 480);
DrawGLScene();
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

@ -0,0 +1,17 @@
#! /bin/sh
FILE=$1
FILE_FLIP="$1_flip.png"
FILE_PATH=${FILE%/*}
echo $FILE_PATH
convert $FILE -flip $FILE_FLIP
$KOS_BASE/utils/texconv/texconv --in $FILE_FLIP --format ARGB1555 --preview $FILE_PATH/preview_1555.png --out $FILE_PATH/disk_1555.dtex
$KOS_BASE/utils/texconv/texconv --in $FILE_FLIP --format RGB565 --preview $FILE_PATH/preview_565.png --out $FILE_PATH/disk_565.dtex
$KOS_BASE/utils/texconv/texconv --in $FILE_FLIP --format ARGB4444 --preview $FILE_PATH/preview_4444.png --out $FILE_PATH/disk_4444.dtex
rm $FILE_FLIP
#rm $FILE_FLIP

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1,109 @@
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
glOrtho(0.0, 640.0, 0.0, 480.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 640.0, 0.0, 480.0, 0.0, 1.0);
glMatrixMode(GL_MODELVIEW);
}
void DrawSquare(float width, float r, float g, float b, float z) {
width /= 2;
glColor3f(r, g, b);
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glVertex3f(-width, width, z); // Top Left
glVertex3f( width, width, z); // Top Right
glVertex3f( width,-width, z); // Bottom Right
glVertex3f(-width,-width, z); // Bottom Left
glEnd(); // done with the polygon
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
// Center fo the screen.
glTranslatef(320, 240, 0);
glDepthFunc(GL_LEQUAL);
//RED over GREEN over BLUE
DrawSquare(100.0, 1.0, 0.0, 0.0, 0.0);
glTranslatef(50, 0, -0.03f);
DrawSquare(100, 0, 1, 0, 0);
glTranslatef(50, 0, -0.03f);
DrawSquare(100, 0, 0, 1, 0);
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

@ -1,30 +0,0 @@
TARGET = lerabot01.elf
OBJS = main.o
KOS_CFLAGS += -std=c99
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

View File

@ -1,11 +1,26 @@
#include <stdio.h>
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
#ifdef __DREAMCAST__
extern uint8 romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMAGE_FILENAME "/rd/flag1.bmp"
#else
#define IMAGE_FILENAME "../samples/lerabot01/romdisk/flag1.bmp"
#endif
#include "../loadbmp.h"
/* floats for x rotation, y rotation, z rotation */
float xrot, yrot, zrot;
@ -13,96 +28,6 @@ float xrot, yrot, zrot;
/* storage for one texture */
int texture[1];
/* Image type - contains height, width, and data */
struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
typedef struct Image Image;
// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // size of the image in bytes.
unsigned long i; // standard counter.
unsigned short int planes; // number of planes in image (must be 1)
unsigned short int bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.
// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL)
{
printf("File Not Found : %s\n",filename);
return 0;
}
// seek through the bmp header, up to the width/height:
fseek(file, 18, SEEK_CUR);
// read the width
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename);
return 0;
}
printf("Width of %s: %lu\n", filename, image->sizeX);
// read the height
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
printf("Height of %s: %lu\n", filename, image->sizeY);
// calculate the size (assuming 24 bits or 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bpp
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, 24, SEEK_CUR);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf(stderr, "Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}
// Load Bitmaps And Convert To Textures
void LoadGLTextures() {
// Load Texture
@ -115,7 +40,7 @@ void LoadGLTextures() {
exit(0);
}
if (!ImageLoad("/rd/flag1.bmp", image1)) {
if (!ImageLoad(IMAGE_FILENAME, image1)) {
exit(1);
}
@ -129,6 +54,8 @@ void LoadGLTextures() {
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
free(image1);
};
/* A general OpenGL initialization function. Sets all of the initial parameters. */
@ -162,6 +89,19 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 0.0001);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 0.00001);
GLfloat l2_pos[] = {0.0, 15.0, 1.0, 1.0};
GLfloat l2_dir[] = {0.0, -1.0, 0.0};
GLfloat l2_diff[] = {0.5, 0.5, 0.0, 1.0};
GLfloat l2_amb[] = {0.5, 0.5, 0.5, 1.0};
glEnable(GL_LIGHT2);
glLightfv(GL_LIGHT2, GL_DIFFUSE, l2_diff);
glLightfv(GL_LIGHT2, GL_POSITION, l2_pos);
glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, l2_dir);
glLightf(GL_LIGHT2, GL_CONSTANT_ATTENUATION, 1.0f);
glLightf(GL_LIGHT2, GL_LINEAR_ATTENUATION, 0.0001);
glLightf(GL_LIGHT2, GL_QUADRATIC_ATTENUATION, 0.00001);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
@ -179,6 +119,24 @@ void ReSizeGLScene(int Width, int Height)
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
void DrawTexturedQuad(int tex, float x, float y, float z)
{
GLfloat texW = 10;
@ -232,7 +190,7 @@ void DrawTexturedQuad(int tex, float x, float y, float z)
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
//glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertex_data);
glTexCoordPointer(2, GL_FLOAT, 0, uv_data);
@ -245,11 +203,10 @@ void DrawTexturedQuad(int tex, float x, float y, float z)
glVertexPointer(3, GL_FLOAT, 0, vertex_data);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
//glDisableClientState(GL_COLOR_ARRAY);
}
@ -259,18 +216,18 @@ void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
//glTranslatef(-5.0f, -5.0f, -10.0f);
glTranslatef(-50.0f, 0.0f, -200.0f);
GLfloat l1_pos[] = {50 + sin(delta) * 100.0f, 25.0, 1.0, 1.0};
delta+= 0.03;
glTranslatef(-50.0f, 0.0f, -100.0f);
GLfloat l1_pos[] = {50 + sin(delta) * 100.0f, 6.0, 5.0, 1.0};
delta += 0.03;
glLightfv(GL_LIGHT1, GL_POSITION, l1_pos);
//glLightfv(GL_LIGHT1, GL_SPOT_EXPONENT, 3);
DrawTexturedQuad(texture[0], l1_pos[0], l1_pos[1], l1_pos[2]);
for (int i = 0; i < 5; i++)
DrawTexturedQuad(texture[0], i * 20, 0.0f, 0.0f); // Draw the textured quad.
DrawTexturedQuad(texture[0], i * 20, 0.0f, 0.1f); // Draw the textured quad.
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
@ -284,6 +241,9 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

247
samples/lights/main.c Normal file
View File

@ -0,0 +1,247 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glext.h"
#include "GL/glkos.h"
#ifdef __DREAMCAST__
#include <kos.h>
extern uint8_t romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMAGE_FILENAME "/rd/NeHe.bmp"
#else
#define IMAGE_FILENAME "../samples/lights/romdisk/NeHe.bmp"
#endif
#include "../loadbmp.h"
float xrot, yrot, zrot;
int texture[1];
void LoadGLTextures() {
Image *image1;
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!ImageLoad(IMAGE_FILENAME, image1)) {
exit(1);
}
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
glGenerateMipmapEXT(GL_TEXTURE_2D);
free(image1);
};
void InitGL(int Width, int Height)
{
LoadGLTextures();
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glClearColor(0.5, 0.5, 0.5, 0.5);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
// Create light components
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 1.0f, 0.0f, 0.0, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { -1.5f, -1.0f, 0.0f, 0.0f };
// Assign created components to GL_LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);
glDisable(GL_TEXTURE_2D);
diffuseLight[1] = 1.0f;
glEnable(GL_LIGHT1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT1, GL_SPECULAR, specularLight);
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0);
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 4.5 / 100);
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 75.0f / (100 * 100));
glEnable(GL_NORMALIZE);
}
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0)
Height = 1;
glViewport(0, 0, Width, Height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
void DrawCube(float x, float z) {
static float pos = 0.0f;
static const float radius = 30.0f;
pos += 0.001f;
GLfloat position[] = { cos(pos) * radius, 15.0f, sin(pos) * radius, 1.0f };
glLightfv(GL_LIGHT1, GL_POSITION, position);
glPushMatrix();
glTranslatef(x, 0, z);
glColor4f(1, 1, 1, 1);
glBegin(GL_QUADS);
glNormal3f(0, 0, -1);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glNormal3f(0, 0, 1);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glNormal3f(0, 1, 0);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glNormal3f(0, -1, 0);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glNormal3f(1, 0, 0);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glNormal3f(-1, 0, 0);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glPopMatrix();
}
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -55.0f);
glRotatef(45, 1, 0, 0);
glTranslatef(0, 0, -30);
glBindTexture(GL_TEXTURE_2D, texture[0]);
int x, z;
for(z = -100; z < 100; z += 10) {
for(x = -100; x < 100; x += 10) {
DrawCube(x, z);
}
}
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
GLdcConfig config;
glKosInitConfig(&config);
config.fsaa_enabled = GL_FALSE;
glKosInitEx(&config);
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

94
samples/loadbmp.c Normal file
View File

@ -0,0 +1,94 @@
// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "loadbmp.h"
int ImageLoad(char *filename, Image *image) {
FILE *file;
size_t size; // size of the image in bytes.
size_t i; // standard counter.
int32_t sizeX, sizeY; // width/height of the image - must be 4 bytes to match the file format
int16_t planes; // number of planes in image (must be 1)
int16_t bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.
// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL) {
printf("File Not Found : %s\n",filename);
return 0;
}
// seek through the bmp header, up to the width/height:
fseek(file, 10, SEEK_CUR);
uint32_t offset;
fread(&offset, 4, 1, file);
fseek(file, 4, SEEK_CUR);
// read the width
if ((i = fread(&sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename);
return 0;
}
image->sizeX = sizeX;
printf("Width of %s: %d\n", filename, sizeX);
// read the height
if ((i = fread(&sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
image->sizeY = sizeY;
printf("Height of %s: %d\n", filename, sizeY);
// calculate the size (assuming 24 bits or 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bpp
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, offset, SEEK_SET);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf("Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}

16
samples/loadbmp.h Normal file
View File

@ -0,0 +1,16 @@
// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
#ifndef __LOADBMP_H
#define __LOADBMP_H
/* Image type - contains height, width, and data */
struct Image {
unsigned int sizeX;
unsigned int sizeY;
char *data;
};
typedef struct Image Image;
int ImageLoad(char *, Image *);
#endif

179
samples/mipmap/main.c Normal file
View File

@ -0,0 +1,179 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glext.h"
#include "GL/glkos.h"
#ifdef __DREAMCAST__
extern uint8_t romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMAGE_FILENAME "/rd/NeHe.bmp"
#else
#define IMAGE_FILENAME "../samples/mipmap/romdisk/NeHe.bmp"
#endif
#include "../loadbmp.h"
/* storage for one texture */
int texture[1];
// Load Bitmaps And Convert To Textures
void LoadGLTextures() {
// Load Texture
Image *image1;
// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!ImageLoad(IMAGE_FILENAME, image1)) {
exit(1);
}
// Create Texture
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); // scale linearly when image smalled than texture
// 2d texture, 3 components (red, green, blue), x size from image, y size from image,
// rgb color data, unsigned byte data, and finally the data itself.
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
free(image1);
};
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
LoadGLTextures();
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
void DrawQuad() {
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left Of The Texture and Quad
glEnd(); // done with the polygon.
}
static GLboolean mipmap_enabled = GL_FALSE;
static GLuint timer = 0;
/* The main drawing function. */
void DrawGLScene()
{
timer++;
if(timer > 60) {
timer = 0;
mipmap_enabled = !mipmap_enabled;
if(mipmap_enabled) {
printf("Enabling mipmaps!\n");
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
} else {
printf("Disabling mipmaps!\n");
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glClearColor(0.5, 0.5, 0.5, 1.0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTranslatef(-1.5f, 0.0f, -4.5f);
DrawQuad();
glTranslatef(1.0f, 0.0f, -5.0f);
DrawQuad();
glTranslatef(1.5f, 0.0f, -5.0f);
DrawQuad();
glTranslatef(2.0f, 0.0f, -5.0f);
DrawQuad();
glTranslatef(3.5f, 0.0f, -5.0f);
DrawQuad();
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

View File

@ -0,0 +1,154 @@
/*
KallistiOS 2.0.0
main.c
(c)2014 Josh Pearson
Open GL Multi-Texture example using Vertex Array Submission.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
#include "GL/glext.h"
#ifdef __DREAMCAST__
extern uint8_t romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMAGE1_FILENAME "/rd/wp001vq.pvr"
#define IMAGE2_FILENAME "/rd/FlareWS_256.pvr"
#else
#define IMAGE1_FILENAME "../samples/multitexture_arrays/romdisk/wp001vq.pvr"
#define IMAGE2_FILENAME "../samples/multitexture_arrays/romdisk/FlareWS_256.pvr"
#endif
/* Load a PVR texture - located in pvr-texture.c */
extern GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap);
GLfloat VERTEX_ARRAY[4 * 3] = { -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
GLfloat TEXCOORD_ARRAY[4 * 2] = { 0, 0,
1, 0,
1, 1,
0, 1
};
GLuint ARGB_ARRAY[4] = { 0xFFFF0000, 0xFF0000FF, 0xFF00FF00, 0xFFFFFF00 };
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* Multi-Texture Example using Open GL Vertex Buffer Submission. */
void RenderCallback(GLuint texID0, GLuint texID1) {
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -3.0f);
/* Enable Client States for OpenGL Arrays Submission */
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
/* Bind texture to GL_TEXTURE0_ARB and set texture parameters */
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
/* Bind multi-texture to GL_TEXTURE1_ARB and set texture parameters */
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texID1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
/* Set Blending Mode */
glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
/* Bind texture coordinates to GL_TEXTURE0_ARB */
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORD_ARRAY);
/* Bind texture coordinates to GL_TEXTURE1_ARB */
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, TEXCOORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE0_ARB);
/* Bind the Color Array */
glColorPointer(GL_BGRA, GL_UNSIGNED_BYTE, 0, ARGB_ARRAY);
/* Bind the Vertex Array */
glVertexPointer(3, GL_FLOAT, 0, VERTEX_ARRAY);
/* Render the Vertices as Indexed Arrays using glDrawArrays */
glDrawArrays(GL_QUADS, 0, 4);
/* Disable GL_TEXTURE1 */
glActiveTextureARB(GL_TEXTURE1_ARB);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
/* Make sure to set glActiveTexture back to GL_TEXTURE0_ARB when finished */
glActiveTextureARB(GL_TEXTURE0_ARB);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
/* Disable Vertex, Color and Texture Coord Arrays */
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
int main(int argc, char **argv) {
/* Notice we do not init the PVR here, that is handled by Open GL */
glKosInit();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 640.0f / 480.0f, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* Load two PVR textures to OpenGL */
GLuint texID0 = glTextureLoadPVR(IMAGE1_FILENAME, 0, 0);
GLuint texID1 = glTextureLoadPVR(IMAGE2_FILENAME, 0, 0);
while(1) {
if(check_start())
break;
/* Draw the "scene" */
RenderCallback(texID0, texID1);
/* Finish the frame - Notice there is no glKosBegin/FinshFrame */
glKosSwapBuffers();
}
return 0;
}

View File

@ -0,0 +1,176 @@
/*
KallistiOS 2.0.0
pvr-texture.c
(c)2014 Josh PH3NOM Pearson
Load A PVR Texture to the PVR using Open GL
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
#include "GL/glext.h"
#define PVR_HDR_SIZE 0x20
#define MAX(x, y) ((x > y) ? x : y)
static GLuint PVR_TextureHeight(unsigned char *HDR);
static GLuint PVR_TextureWidth(unsigned char *HDR);
static GLuint PVR_TextureFormat(unsigned char *HDR);
static GLuint _glGetMipmapLevelCount(GLuint width, GLuint height) {
return 1 + floor(log2(MAX(width, height)));
}
static GLuint _glGetMipmapDataSize(GLuint width, GLuint height) {
GLuint size = 0;
GLuint i = 0;
for(; i < _glGetMipmapLevelCount(width, height); ++i) {
size += (width * height * 2);
if(width > 1) {
width /= 2;
}
if(height > 1) {
height /= 2;
}
}
return size;
}
/* Load a PVR texture file into memory, and then bind the texture to Open GL.
fname is the name of the PVR texture file to be opened and read.
isMipMapped should be passed as 1 if the texture contains MipMap levels, 0 otherwise.
glMipMap should be passed as 1 if Open GL should calculate the Mipmap levels, 0 otherwise */
GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap) {
FILE *tex = NULL;
uint16_t *TEX0 = NULL;
uint8_t HDR[PVR_HDR_SIZE];
GLuint texID, texSize, texW, texH, texFormat;
/* Open the PVR texture file, and get its file size */
tex = fopen(fname, "rb");
if(tex == NULL) {
printf("FILE READ ERROR: %s\n", fname);
return 1;
}
fseek(tex, 0, SEEK_END);
texSize = ftell(tex) - PVR_HDR_SIZE;
fseek(tex, 0, SEEK_SET);
/* Read in the PVR texture file header */
fread(HDR, 1, PVR_HDR_SIZE, tex);
/* Extract some information from the PVR texture file header */
texW = PVR_TextureWidth(HDR);
texH = PVR_TextureHeight(HDR);
texFormat = PVR_TextureFormat(HDR);
/* Allocate Some Memory for the texture. If we are using Open GL to build the MipMap,
we need to allocate enough space to hold the MipMap texture levels. */
if(!isMipMapped && glMipMap)
TEX0 = malloc(_glGetMipmapDataSize(texW, texH));
else
TEX0 = malloc(texSize);
fread(TEX0, 1, texSize, tex); /* Read in the PVR texture data */
/* Generate and bind a texture as normal for Open GL */
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
if(texFormat != GL_UNSIGNED_SHORT_5_6_5)
glCompressedTexImage2DARB(GL_TEXTURE_2D,
0,
texFormat,
texW,
texH,
0,
texSize,
TEX0);
else {
fprintf(stderr, "%x\n", texFormat);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
texW, texH,
0,
GL_RGB,
texFormat,
TEX0);
if(!isMipMapped && glMipMap)
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
free(TEX0);
return texID;
}
static GLuint PVR_TextureFormat(unsigned char *HDR) {
GLuint color = (GLuint)HDR[PVR_HDR_SIZE - 8];
GLuint format = (GLuint)HDR[PVR_HDR_SIZE - 7];
GLboolean twiddled = format == 0x01;
GLboolean compressed = (format == 0x10 || format == 0x03);
if(compressed) {
if(twiddled) {
switch(color) {
case 0x0: {
return GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
} break;
case 0x01: {
return GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
} break;
case 0x02: {
return GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
} else {
switch(color) {
case 0: {
return GL_COMPRESSED_ARGB_1555_VQ_KOS;
} break;
case 1: {
return GL_COMPRESSED_RGB_565_VQ_KOS;
} break;
case 2: {
return GL_COMPRESSED_ARGB_4444_VQ_KOS;
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
}
} else {
if(color == 1) {
return GL_UNSIGNED_SHORT_5_6_5;
}
return 0;
}
}
static GLuint PVR_TextureWidth(unsigned char *HDR) {
return (GLuint)HDR[PVR_HDR_SIZE - 4] | HDR[PVR_HDR_SIZE - 3] << 8;
}
static GLuint PVR_TextureHeight(unsigned char *HDR) {
return (GLuint)HDR[PVR_HDR_SIZE - 2] | HDR[PVR_HDR_SIZE - 1] << 8;
}

Binary file not shown.

Binary file not shown.

View File

@ -1,29 +0,0 @@
TARGET = nehe02.elf
OBJS = main.o
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

View File

@ -1,13 +1,17 @@
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearColor(0.0f, 0.0f, 1.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
@ -34,6 +38,23 @@ void ReSizeGLScene(int Width, int Height)
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
@ -41,25 +62,69 @@ void DrawGLScene()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-3.0f, 1.5f, -10.0f); // Move Left 1.5 Units And Into The Screen 6.0
// draw a triangle
glBegin(GL_POLYGON); // start drawing a polygon
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glBegin(GL_TRIANGLES); // start drawing a polygon
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // we're done with the polygon
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glTranslatef(3.0f, 0.0f, 0.0f); // Move Right 3 Units
// draw a square (quadrilateral)
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // done with the polygon
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON); // start drawing a polygon (4 sided)
glVertex3f(-0.0f, 1.0f, 0.0f); // Top Left
glVertex3f(-0.75f, 0.75f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f); // Top Right
glVertex3f(-0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f(-0.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f( 1.0f, 0.0f, 0.0f); // Top Right
glVertex3f( 0.75f, 0.75f, 0.0f);
glEnd(); // done with the polygon
glTranslatef(-6.0f, -3.0f, 0.0f);
// draw a triangle
glBegin(GL_POLYGON); // start drawing a polygon
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // we're done with the polygon
glTranslatef(3.0f, 0.0f, 0.0f); // Move Right 3 Units
// draw a square (quadrilateral)
glBegin(GL_POLYGON); // start drawing a polygon (4 sided)
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // done with the polygon
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON); // start drawing a polygon (4 sided)
glVertex3f(-0.0f, 1.0f, 0.0f); // Top Left
glVertex3f(-0.75f, 0.75f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f); // Top Right
glVertex3f(-0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f(-0.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f( 1.0f, 0.0f, 0.0f); // Top Right
glVertex3f( 0.75f, 0.75f, 0.0f);
glEnd(); // done with the polygon
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
@ -72,6 +137,9 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

118
samples/nehe02de/main.c Normal file
View File

@ -0,0 +1,118 @@
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glEnableClientState(GL_VERTEX_ARRAY); // Enable vertex arrays
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
{
const GLfloat triangle [] = {
0.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
const GLfloat square [] = {
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
const GLuint triangleIdx [] = {
0, 1, 2
};
const GLuint squareIdx [] = {
0, 1, 2, 3
};
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
glVertexPointer(3, GL_FLOAT, 0, triangle);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, triangleIdx);
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glVertexPointer(3, GL_FLOAT, 0, square);
glDrawElements(GL_QUADS, 4, GL_UNSIGNED_INT, squareIdx);
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

View File

@ -1,29 +0,0 @@
TARGET = nehe02va.elf
OBJS = main.o
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

View File

@ -1,6 +1,10 @@
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
@ -36,6 +40,23 @@ void ReSizeGLScene(int Width, int Height)
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
@ -79,6 +100,9 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

View File

@ -1,29 +0,0 @@
TARGET = nehe03.elf
OBJS = main.o
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

View File

@ -1,6 +1,10 @@
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
@ -34,6 +38,23 @@ void ReSizeGLScene(int Width, int Height)
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
@ -76,6 +97,9 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

118
samples/nehe04/main.c Normal file
View File

@ -0,0 +1,118 @@
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
GLfloat rtri;
GLfloat rquad;
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
// draw a triangle (in smooth coloring mode)
glRotatef(rtri, 0.0f,1.0f,0.0f);
glBegin(GL_TRIANGLES); // start drawing a polygon
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // we're done with the polygon (smooth color interpolation)
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
glLoadIdentity();
glTranslatef(1.5f,0.0f,-6.0f);
glRotatef(rquad,1.0f,0.0f,0.0f);
// draw a square (quadrilateral)
glColor3f(0.5f,0.5f,1.0f); // set color to a blue shade.
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // done with the polygon
rtri += 0.2f;
rquad -= 0.15f;
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

171
samples/nehe05/main.c Normal file
View File

@ -0,0 +1,171 @@
#ifdef __DREAMCAST__
#include <kos.h>
#endif
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
GLfloat rtri;
GLfloat rquad;
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
// draw a triangle (in smooth coloring mode)
glRotatef(rtri, 0.0f,1.0f,0.0f);
glBegin(GL_TRIANGLES); // start drawing a polygon
// Front Face
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(1.0f,-1.0f, 1.0f); // Bottom Left
// Right Face
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f( 1.0f,-1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Right Of Triangle (Right)
// Back face
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f( 1.0f,-1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f, -1.0f); // Right Of Triangle (Back)
// Left face
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f( 0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f,0.0f,1.0f); // Blue
glVertex3f(-1.0f,-1.0f,-1.0f); // Left Of Triangle (Left)
glColor3f(0.0f,1.0f,0.0f); // Green
glVertex3f(-1.0f,-1.0f, 1.0f); // Right Of Triangle (Left)
glEnd(); // Done Drawing The Pyramid
glLoadIdentity();
glTranslatef(1.5f,0.0f,-7.0f); // Move Right And Into The Screen
glRotatef(rquad,1.0f,1.0f,1.0f); // Rotate The Cube On X, Y & Z
glBegin(GL_QUADS); // Start Drawing The Cube
// Top
glColor3f(0.0f,1.0f,0.0f); // Set The Color To Green
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Top)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)
glColor3f(1.0f,0.5f,0.0f); // Set The Color To Orange
glVertex3f( 1.0f,-1.0f, 1.0f); // Top Right Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f, 1.0f); // Top Left Of The Quad (Bottom)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Bottom)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Bottom)
glColor3f(1.0f,0.0f,0.0f); // Set The Color To Red
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Front)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Front)
glColor3f(1.0f,1.0f,0.0f); // Set The Color To Yellow
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Back)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Back)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Back)
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Back)
glColor3f(0.0f,0.0f,1.0f); // Set The Color To Blue
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
glVertex3f(-1.0f, 1.0f,-1.0f); // Top Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f,-1.0f); // Bottom Left Of The Quad (Left)
glVertex3f(-1.0f,-1.0f, 1.0f); // Bottom Right Of The Quad (Left)
glColor3f(1.0f,0.0f,1.0f); // Set The Color To Violet
glVertex3f( 1.0f, 1.0f,-1.0f); // Top Right Of The Quad (Right)
glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f, 1.0f); // Bottom Left Of The Quad (Right)
glVertex3f( 1.0f,-1.0f,-1.0f); // Bottom Right Of The Quad (Right)
glEnd(); // Done Drawing The Quad
rtri += 0.2f;
rquad -= 0.15f;
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}
return 0;
}

View File

View File

@ -1,29 +0,0 @@
TARGET = nehe06.elf
OBJS = main.o
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

View File

@ -1,107 +1,32 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "gl.h"
#include "glu.h"
#include "glkos.h"
#ifdef __DREAMCAST__
#include <kos.h>
#endif
extern uint8 romdisk[];
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glext.h"
#include "GL/glkos.h"
#ifdef __DREAMCAST__
extern uint8_t romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMAGE_FILENAME "/rd/NeHe.bmp"
#else
#define IMAGE_FILENAME "../samples/nehe06/romdisk/NeHe.bmp"
#endif
#include "../loadbmp.h"
/* floats for x rotation, y rotation, z rotation */
float xrot, yrot, zrot;
/* storage for one texture */
int texture[1];
/* Image type - contains height, width, and data */
struct Image {
unsigned long sizeX;
unsigned long sizeY;
char *data;
};
typedef struct Image Image;
// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
int ImageLoad(char *filename, Image *image) {
FILE *file;
unsigned long size; // size of the image in bytes.
unsigned long i; // standard counter.
unsigned short int planes; // number of planes in image (must be 1)
unsigned short int bpp; // number of bits per pixel (must be 24)
char temp; // temporary color storage for bgr-rgb conversion.
// make sure the file is there.
if ((file = fopen(filename, "rb"))==NULL)
{
printf("File Not Found : %s\n",filename);
return 0;
}
// seek through the bmp header, up to the width/height:
fseek(file, 18, SEEK_CUR);
// read the width
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
printf("Error reading width from %s.\n", filename);
return 0;
}
printf("Width of %s: %lu\n", filename, image->sizeX);
// read the height
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
printf("Height of %s: %lu\n", filename, image->sizeY);
// calculate the size (assuming 24 bits or 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bpp
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, 24, SEEK_CUR);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf(stderr, "Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}
GLuint texture[1];
// Load Bitmaps And Convert To Textures
void LoadGLTextures() {
@ -115,7 +40,7 @@ void LoadGLTextures() {
exit(0);
}
if (!ImageLoad("/rd/NeHe.bmp", image1)) {
if (!ImageLoad(IMAGE_FILENAME, image1)) {
exit(1);
}
@ -124,12 +49,14 @@ void LoadGLTextures() {
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smaller than texture
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
};
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
free(image1);
}
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
@ -147,7 +74,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
@ -165,6 +92,23 @@ void ReSizeGLScene(int Width, int Height)
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
@ -236,6 +180,9 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 96 KiB

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