Compare commits
No commits in common. "master" and "restore-color-material" have entirely different histories.
master
...
restore-co
6
.gitignore
vendored
@ -6,8 +6,4 @@
|
||||
*.img
|
||||
dc-build.sh
|
||||
.buildconfig
|
||||
build/*
|
||||
builddir/*
|
||||
version.[c|h]
|
||||
pcbuild/*
|
||||
dcbuild/*
|
||||
GL/version.h
|
||||
|
||||
@ -1,45 +1,10 @@
|
||||
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 libGL.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
|
||||
- make clean
|
||||
- make samples
|
||||
|
||||
225
CMakeLists.txt
@ -1,225 +0,0 @@
|
||||
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 14)
|
||||
|
||||
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/attributes.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/tnl_effects.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(GL STATIC ${SOURCES})
|
||||
|
||||
if(FLTO_SUPPORTED)
|
||||
set_property(TARGET GL PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
||||
if(NOT PLATFORM_DREAMCAST)
|
||||
set_target_properties(GL PROPERTIES
|
||||
COMPILE_OPTIONS "-m32"
|
||||
LINK_OPTIONS "-m32"
|
||||
)
|
||||
endif()
|
||||
|
||||
link_libraries(m)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
link_libraries(GL)
|
||||
|
||||
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(nehe16 samples/nehe16/main.c samples/nehe16/pvr-texture.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)
|
||||
gen_sample(primitive_modes samples/primitive_modes/main.c)
|
||||
gen_sample(tnl_effects samples/tnl_effects/main.c)
|
||||
|
||||
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()
|
||||
541
GL/alloc/alloc.c
@ -1,541 +0,0 @@
|
||||
#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;
|
||||
|
||||
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;
|
||||
|
||||
/* The pool size might be less than the passed size if the memory
|
||||
* wasn't aligned to 2048 */
|
||||
pool_header.pool_size = pool_header.block_count * 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);
|
||||
}
|
||||
|
||||
static void* alloc_malloc_internal(void* pool, size_t size, bool for_defrag) {
|
||||
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;
|
||||
}
|
||||
|
||||
// defrag allocations don't create new entries, they reuse old ones
|
||||
if(for_defrag) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
void* alloc_malloc(void* pool, size_t size) {
|
||||
return alloc_malloc_internal(pool, size, false);
|
||||
}
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
last = it;
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
assert("Freed pointer not found, heap corruption?" && 0);
|
||||
}
|
||||
|
||||
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 && potential_dest < it->pointer) {
|
||||
potential_dest = alloc_malloc_internal(pool, it->size, true);
|
||||
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;
|
||||
|
||||
size_t total_used = 0;
|
||||
|
||||
for(size_t i = 0; i < pool_header.block_count; ++i) {
|
||||
total_used += count_ones(pool_header.block_usage[i]) * 256;
|
||||
}
|
||||
|
||||
return pool_header.pool_size - total_used;
|
||||
}
|
||||
|
||||
size_t alloc_count_continuous(void* pool) {
|
||||
(void) pool;
|
||||
|
||||
size_t contiguous_free = 0;
|
||||
size_t most_contiguous = 0;
|
||||
|
||||
for(size_t i = 0; i < pool_header.block_count; ++i) {
|
||||
uint8_t t = pool_header.block_usage[i];
|
||||
|
||||
for(int i = 7; i >= 0; --i) {
|
||||
bool bitset = (t & (1 << i));
|
||||
if(!bitset) {
|
||||
++contiguous_free;
|
||||
} else {
|
||||
if(contiguous_free > most_contiguous) {
|
||||
most_contiguous = contiguous_free;
|
||||
}
|
||||
contiguous_free = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(contiguous_free > most_contiguous) {
|
||||
most_contiguous = contiguous_free;
|
||||
}
|
||||
return most_contiguous * 256;
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
#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
|
||||
881
GL/attributes.c
@ -1,881 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "platform.h"
|
||||
|
||||
AttribPointerList ATTRIB_LIST;
|
||||
static const float ONE_OVER_TWO_FIVE_FIVE = 1.0f / 255.0f;
|
||||
|
||||
GLushort _quantize( GLfloat v ) {
|
||||
union { GLfloat f; GLuint ui; } u = {v};
|
||||
GLuint ui = u.ui;
|
||||
|
||||
int s = (ui >> 16) & 0x8000;
|
||||
int em = ui & 0x7fffffff;
|
||||
|
||||
int h = (em - (112 << 23) + (1 << 12)) >> 13;
|
||||
h = (em < (113 << 23)) ? 0 : h;
|
||||
h = (em >= (143 << 23)) ? 0x7c00 : h;
|
||||
h = (em > (255 << 23)) ? 0x7e00 : h;
|
||||
|
||||
return (GLushort)(s | h);
|
||||
}
|
||||
GLfloat _dequantize( GLushort h ) {
|
||||
GLuint s = (GLuint) (h & 0x8000) << 16;
|
||||
int em = h & 0x7fff;
|
||||
int r = (em + (112 << 10)) << 13;
|
||||
r = (em < (1 << 10)) ? 0 : r;
|
||||
r += (em >= (31 << 10)) ? (112 << 23) : 0;
|
||||
|
||||
union { GLfloat f; GLuint ui; } u;
|
||||
u.ui = s | r;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLsizei byte_size(GLenum type) {
|
||||
switch(type) {
|
||||
case GL_BYTE: return sizeof(GLbyte);
|
||||
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
|
||||
case GL_SHORT: return sizeof(GLshort);
|
||||
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
|
||||
case GL_INT: return sizeof(GLint);
|
||||
case GL_UNSIGNED_INT: return sizeof(GLuint);
|
||||
case GL_DOUBLE: return sizeof(GLdouble);
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV: return sizeof(GLuint);
|
||||
case GL_HALF_FLOAT: return sizeof(GLhalf);
|
||||
case GL_FLOAT:
|
||||
default: return sizeof(GLfloat);
|
||||
}
|
||||
}
|
||||
|
||||
// Used to avoid checking and updating attribute related state unless necessary
|
||||
GL_FORCE_INLINE GLboolean _glStateUnchanged(AttribPointer* p, GLint size, GLenum type, GLsizei stride) {
|
||||
return (p->size == size && p->type == type && p->stride == stride);
|
||||
}
|
||||
|
||||
GLuint* _glGetEnabledAttributes(void) {
|
||||
return &ATTRIB_LIST.enabled;
|
||||
}
|
||||
|
||||
static void _readPosition3f3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
const float* input = (const float*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3d3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
const double* input = (const double*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3ub3f(const GLubyte* input, GLubyte* out) {
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float y = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float z = input[2] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3us3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3ui3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2f3f(const GLubyte* in, GLubyte* out) {
|
||||
const float* input = (const float*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2d3f(const GLubyte* in, GLubyte* out) {
|
||||
const double* input = (const double*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2ub3f(const GLubyte* input, GLubyte* out) {
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float y = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2us3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2ui3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
// dequantize to float
|
||||
static void _readPosition3usq3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = _dequantize(input[0]);
|
||||
float y = _dequantize(input[1]);
|
||||
float z = _dequantize(input[2]);
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
static void _readPosition2usq3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = _dequantize(input[0]);
|
||||
float y = _dequantize(input[1]);
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
// convert from float16 to float32
|
||||
static void _readPosition3f16_3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLhalf* input = (const GLhalf*) in;
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = (float) input[0];
|
||||
float y = (float) input[1];
|
||||
float z = (float) input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
static void _readPosition2f16_3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLhalf* input = (const GLhalf*) in;
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = (float) input[0];
|
||||
float y = (float) input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadPositionFunc(void) {
|
||||
switch(ATTRIB_LIST.vertex.type) {
|
||||
case GL_DOUBLE:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3d3f:
|
||||
_readPosition2d3f;
|
||||
default:
|
||||
case GL_FLOAT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3f3f:
|
||||
_readPosition2f3f;
|
||||
case GL_HALF_FLOAT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3f16_3f:
|
||||
_readPosition2f16_3f;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3ub3f:
|
||||
_readPosition2ub3f;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3us3f:
|
||||
_readPosition2us3f;
|
||||
case GL_QUANTIZED_SHORT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3usq3f:
|
||||
_readPosition2usq3f;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3ui3f:
|
||||
_readPosition2ui3f;
|
||||
}
|
||||
}
|
||||
|
||||
static void _fillWhiteARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
|
||||
_GL_UNUSED(input);
|
||||
*((uint32_t*) output) = ~0;
|
||||
}
|
||||
|
||||
static void _readColour4ubARGB(const GLubyte* input, GLubyte* output) {
|
||||
output[R8IDX] = input[0];
|
||||
output[G8IDX] = input[1];
|
||||
output[B8IDX] = input[2];
|
||||
output[A8IDX] = input[3];
|
||||
}
|
||||
|
||||
static void _readColour3ubARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
|
||||
output[R8IDX] = input[0];
|
||||
output[G8IDX] = input[1];
|
||||
output[B8IDX] = input[2];
|
||||
output[A8IDX] = 255;
|
||||
}
|
||||
|
||||
#define DEF_READ_COLOUR_4_ARGB_FP(prefix, intype) \
|
||||
static void _readColour##prefix##ARGB(const GLubyte* __restrict in, GLubyte* __restrict out) { \
|
||||
const intype* input = (const intype*) in; \
|
||||
out[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255); \
|
||||
out[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255); \
|
||||
out[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255); \
|
||||
out[A8IDX] = (GLubyte) clamp(input[3] * 255.0f, 0, 255); \
|
||||
}
|
||||
|
||||
#define DEF_READ_COLOUR_3_ARGB_FP(prefix, intype) \
|
||||
static void _readColour##prefix##ARGB(const GLubyte* __restrict in, GLubyte* __restrict out) { \
|
||||
const intype* input = (const intype*) in; \
|
||||
out[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255); \
|
||||
out[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255); \
|
||||
out[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255); \
|
||||
out[A8IDX] = 255; \
|
||||
}
|
||||
|
||||
DEF_READ_COLOUR_4_ARGB_FP(4f, float)
|
||||
|
||||
DEF_READ_COLOUR_3_ARGB_FP(3f, float)
|
||||
|
||||
|
||||
|
||||
static void _readColour4dARGB(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
const double* input = (const double*) in;
|
||||
|
||||
// Convert to float first
|
||||
float r = (float)input[0];
|
||||
float g = (float)input[1];
|
||||
float b = (float)input[2];
|
||||
float a = (float)input[3];
|
||||
|
||||
out[R8IDX] = (GLubyte) clamp(r * 255.0f, 0, 255);
|
||||
out[G8IDX] = (GLubyte) clamp(g * 255.0f, 0, 255);
|
||||
out[B8IDX] = (GLubyte) clamp(b * 255.0f, 0, 255);
|
||||
out[A8IDX] = (GLubyte) clamp(a * 255.0f, 0, 255);
|
||||
}
|
||||
|
||||
static void _readColour3dARGB(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
const double* input = (const double*) in;
|
||||
|
||||
// Convert to float first
|
||||
float r = (float)input[0];
|
||||
float g = (float)input[1];
|
||||
float b = (float)input[2];
|
||||
|
||||
out[R8IDX] = (GLubyte) clamp(r * 255.0f, 0, 255);
|
||||
out[G8IDX] = (GLubyte) clamp(g * 255.0f, 0, 255);
|
||||
out[B8IDX] = (GLubyte) clamp(b * 255.0f, 0, 255);
|
||||
out[A8IDX] = 255;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void _readColour4ubRevARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
|
||||
argbcpy(output, input);
|
||||
}
|
||||
|
||||
static void _readColour4fRevARGB(const GLubyte* __restrict__ in, GLubyte* __restrict__ output) {
|
||||
const float* input = (const float*) in;
|
||||
|
||||
output[0] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
|
||||
output[1] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
|
||||
output[2] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
|
||||
output[3] = (GLubyte) clamp(input[3] * 255.0f, 0, 255);
|
||||
}
|
||||
|
||||
static void _readColour4dRevARGB(const GLubyte* __restrict__ in, GLubyte* __restrict__ output) {
|
||||
const double* input = (const double*) in;
|
||||
|
||||
// Convert to float first
|
||||
float r = (float)input[0];
|
||||
float g = (float)input[1];
|
||||
float b = (float)input[2];
|
||||
float a = (float)input[3];
|
||||
|
||||
output[0] = (GLubyte) clamp(r * 255.0f, 0, 255);
|
||||
output[1] = (GLubyte) clamp(g * 255.0f, 0, 255);
|
||||
output[2] = (GLubyte) clamp(b * 255.0f, 0, 255);
|
||||
output[3] = (GLubyte) clamp(a * 255.0f, 0, 255);
|
||||
}
|
||||
|
||||
#define DEF_READ_COLOUR_N_ARGB_INT(prefix, intype, max, alpha, i0, i1, i2, i3) \
|
||||
static void _readColour##prefix##ARGB(const GLubyte* __restrict in, GLubyte* __restrict out) { \
|
||||
const intype* input = (const intype*) in; \
|
||||
out[i0] = (GLubyte) clamp((float)input[0] / (float)max * 255.0f, 0, 255); \
|
||||
out[i1] = (GLubyte) clamp((float)input[1] / (float)max * 255.0f, 0, 255); \
|
||||
out[i2] = (GLubyte) clamp((float)input[2] / (float)max * 255.0f, 0, 255); \
|
||||
out[i3] = alpha; \
|
||||
}
|
||||
|
||||
#define DEF_READ_COLOUR_3_ARGB_INT(prefix, intype, max) \
|
||||
DEF_READ_COLOUR_N_ARGB_INT(prefix, intype, max, 255, R8IDX, G8IDX, B8IDX, A8IDX)
|
||||
|
||||
#define DEF_READ_COLOUR_4_ARGB_INT(prefix, intype, max) \
|
||||
DEF_READ_COLOUR_N_ARGB_INT(prefix, intype, max, \
|
||||
((GLubyte)clamp((float)input[3] / (float)max * 255.0f, 0, 255)), \
|
||||
R8IDX, G8IDX, B8IDX, A8IDX)
|
||||
|
||||
#define DEF_READ_COLOUR_4_REV_ARGB_INT(prefix, intype, max) \
|
||||
DEF_READ_COLOUR_N_ARGB_INT(prefix##Rev, intype, max, \
|
||||
((GLubyte)clamp((float)input[3] / (float)max * 255.0f, 0, 255)), \
|
||||
0, 1, 2, 3)
|
||||
|
||||
DEF_READ_COLOUR_3_ARGB_INT(3us, GLushort, UINT16_MAX)
|
||||
DEF_READ_COLOUR_3_ARGB_INT(3ui, GLuint, UINT32_MAX)
|
||||
|
||||
DEF_READ_COLOUR_4_ARGB_INT(4us, GLushort, UINT16_MAX)
|
||||
DEF_READ_COLOUR_4_ARGB_INT(4ui, GLuint, UINT32_MAX)
|
||||
|
||||
DEF_READ_COLOUR_4_REV_ARGB_INT(4us, GLushort, UINT16_MAX)
|
||||
DEF_READ_COLOUR_4_REV_ARGB_INT(4ui, GLuint, UINT32_MAX)
|
||||
|
||||
static ReadAttributeFunc calcReadDiffuseFunc(void) {
|
||||
if((ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG) != DIFFUSE_ENABLED_FLAG) {
|
||||
/* Just fill the whole thing white if the attribute is disabled */
|
||||
return _fillWhiteARGB;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.colour.type) {
|
||||
case GL_DOUBLE:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3dARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4dARGB:
|
||||
_readColour4dRevARGB;
|
||||
default:
|
||||
case GL_FLOAT:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3fARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4fARGB:
|
||||
_readColour4fRevARGB;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3ubARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4ubARGB:
|
||||
_readColour4ubRevARGB;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3usARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4usARGB:
|
||||
_readColour4usRevARGB;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3uiARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4uiARGB:
|
||||
_readColour4uiRevARGB;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _fillZero2f(const GLubyte* __restrict__ input, GLubyte* __restrict__ out) {
|
||||
_GL_UNUSED(input);
|
||||
//memset(out, 0, sizeof(float) * 2);
|
||||
// memset does 8 individual byte writes - faster to manually write as uint32
|
||||
uint32_t* dst = (uint32_t*)out;
|
||||
dst[0] = 0;
|
||||
dst[1] = 0;
|
||||
}
|
||||
|
||||
static void _readTexcoord2f2f(const GLubyte* in, GLubyte* out) {
|
||||
vec2cpy(out, in);
|
||||
}
|
||||
|
||||
static void _readTexcoord2d2f(const GLubyte* in, GLubyte* out) {
|
||||
((float*)out)[0] = ((const double*)in)[0];
|
||||
((float*)out)[1] = ((const double*)in)[1];
|
||||
}
|
||||
|
||||
static void _readTexcoord2ub2f(const GLubyte* input, GLubyte* out) {
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
output[1] = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
}
|
||||
|
||||
static void _readTexcoord2us2f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = (float)input[0] / SHRT_MAX;
|
||||
output[1] = (float)input[1] / SHRT_MAX;
|
||||
}
|
||||
|
||||
static void _readTexcoord2ui2f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
}
|
||||
|
||||
// dequantize to float
|
||||
static void _readTexcoord2usq2f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = _dequantize(input[0]);
|
||||
output[1] = _dequantize(input[1]);
|
||||
}
|
||||
// convert from float16 to float32
|
||||
static void _readTexcoord2f16_2f(const GLubyte* in, GLubyte* out) {
|
||||
const GLhalf* input = (const GLhalf*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadUVFunc(void) {
|
||||
if((ATTRIB_LIST.enabled & UV_ENABLED_FLAG) != UV_ENABLED_FLAG) {
|
||||
return _fillZero2f;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.uv.type) {
|
||||
case GL_DOUBLE:
|
||||
return _readTexcoord2d2f;
|
||||
default:
|
||||
case GL_FLOAT:
|
||||
return _readTexcoord2f2f;
|
||||
case GL_HALF_FLOAT:
|
||||
return _readTexcoord2f16_2f;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return _readTexcoord2ub2f;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return _readTexcoord2us2f;
|
||||
case GL_QUANTIZED_SHORT:
|
||||
return _readTexcoord2usq2f;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return _readTexcoord2ui2f;
|
||||
}
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadSTFunc(void) {
|
||||
if((ATTRIB_LIST.enabled & ST_ENABLED_FLAG) != ST_ENABLED_FLAG) {
|
||||
return _fillZero2f;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.st.type) {
|
||||
case GL_DOUBLE:
|
||||
return _readTexcoord2d2f;
|
||||
default:
|
||||
case GL_FLOAT:
|
||||
return _readTexcoord2f2f;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return _readTexcoord2ub2f;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return _readTexcoord2us2f;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return _readTexcoord2ui2f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _fillWithNegZVE(const GLubyte* __restrict__ input, GLubyte* __restrict__ out) {
|
||||
_GL_UNUSED(input);
|
||||
typedef struct { float x, y, z; } V;
|
||||
|
||||
static const V NegZ = {0.0f, 0.0f, -1.0f};
|
||||
|
||||
*((V*) out) = NegZ;
|
||||
}
|
||||
|
||||
static void _readNormal3f3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
vec3cpy(out, in);
|
||||
}
|
||||
|
||||
static void _readNormal3d3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
((float*)out)[0] = ((const double*)in)[0];
|
||||
((float*)out)[1] = ((const double*)in)[1];
|
||||
((float*)out)[2] = ((const double*)in)[2];
|
||||
}
|
||||
|
||||
static void _readNormal3ub3f(const GLubyte* input, GLubyte* out) {
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
output[1] = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
output[2] = input[2] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
}
|
||||
|
||||
static void _readNormal3us3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
output[2] = input[2];
|
||||
}
|
||||
|
||||
static void _readNormal3ui3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
output[2] = input[2];
|
||||
}
|
||||
|
||||
static void _readNormal3usq3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = _dequantize(input[0]);
|
||||
output[1] = _dequantize(input[1]);
|
||||
output[2] = _dequantize(input[2]);
|
||||
}
|
||||
|
||||
static void _readNormal3f16_3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLhalf* input = (const GLhalf*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
output[2] = input[2];
|
||||
}
|
||||
|
||||
// 10:10:10:2REV format
|
||||
static void _readNormal1i3f(const GLubyte* in, GLubyte* out) {
|
||||
static const float MULTIPLIER = 1.0f / 1023.0f;
|
||||
|
||||
GLfloat* output = (GLfloat*) out;
|
||||
|
||||
union {
|
||||
int value;
|
||||
struct {
|
||||
signed int x: 10;
|
||||
signed int y: 10;
|
||||
signed int z: 10;
|
||||
signed int w: 2;
|
||||
} bits;
|
||||
} input;
|
||||
|
||||
input.value = *((const GLint*) in);
|
||||
|
||||
output[0] = (2.0f * (float) input.bits.x + 1.0f) * MULTIPLIER;
|
||||
output[1] = (2.0f * (float) input.bits.y + 1.0f) * MULTIPLIER;
|
||||
output[2] = (2.0f * (float) input.bits.z + 1.0f) * MULTIPLIER;
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadNormalFunc(void) {
|
||||
if((ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG) != NORMAL_ENABLED_FLAG) {
|
||||
return _fillWithNegZVE;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.normal.type) {
|
||||
case GL_DOUBLE:
|
||||
return _readNormal3d3f;
|
||||
case GL_FLOAT:
|
||||
default:
|
||||
return _readNormal3f3f;
|
||||
break;
|
||||
case GL_HALF_FLOAT:
|
||||
return _readNormal3f16_3f;
|
||||
break;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return _readNormal3ub3f;
|
||||
break;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return _readNormal3us3f;
|
||||
break;
|
||||
case GL_QUANTIZED_SHORT:
|
||||
return _readNormal3usq3f;
|
||||
break;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return _readNormal3ui3f;
|
||||
break;
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||
return _readNormal1i3f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glEnableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ATTRIB_LIST.enabled |= VERTEX_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= VERTEX_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
ATTRIB_LIST.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= DIFFUSE_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
ATTRIB_LIST.enabled |= NORMAL_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= NORMAL_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.enabled |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.enabled |= UV_ENABLED_FLAG);
|
||||
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.dirty |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.dirty |= UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glDisableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ATTRIB_LIST.enabled &= ~VERTEX_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= VERTEX_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
ATTRIB_LIST.enabled &= ~DIFFUSE_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= DIFFUSE_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
ATTRIB_LIST.enabled &= ~NORMAL_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= NORMAL_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.enabled &= ~ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.enabled &= ~UV_ENABLED_FLAG);
|
||||
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.dirty |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.dirty |= UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
|
||||
TRACE();
|
||||
|
||||
stride = (stride) ? stride : size * byte_size(type);
|
||||
AttribPointer* tointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &ATTRIB_LIST.uv : &ATTRIB_LIST.st;
|
||||
tointer->ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(tointer, size, type, stride)) return;
|
||||
|
||||
if(size < 1 || size > 4) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
tointer->stride = stride;
|
||||
tointer->type = type;
|
||||
tointer->size = size;
|
||||
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.dirty |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.dirty |= UV_ENABLED_FLAG);
|
||||
}
|
||||
|
||||
void APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
stride = (stride) ? stride : (size * byte_size(type));
|
||||
ATTRIB_LIST.vertex.ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(&ATTRIB_LIST.vertex, size, type, stride)) return;
|
||||
|
||||
if(size < 2 || size > 4) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ATTRIB_LIST.vertex.stride = stride;
|
||||
ATTRIB_LIST.vertex.type = type;
|
||||
ATTRIB_LIST.vertex.size = size;
|
||||
|
||||
ATTRIB_LIST.dirty |= VERTEX_ENABLED_FLAG;
|
||||
}
|
||||
|
||||
void APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
stride = (stride) ? stride : ((size == GL_BGRA) ? 4 : size) * byte_size(type);
|
||||
ATTRIB_LIST.colour.ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(&ATTRIB_LIST.colour, size, type, stride)) return;
|
||||
|
||||
if(size != 3 && size != 4 && size != GL_BGRA) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ATTRIB_LIST.colour.type = type;
|
||||
ATTRIB_LIST.colour.size = size;
|
||||
ATTRIB_LIST.colour.stride = stride;
|
||||
|
||||
ATTRIB_LIST.dirty |= DIFFUSE_ENABLED_FLAG;
|
||||
}
|
||||
|
||||
void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
GLint validTypes[] = {
|
||||
GL_DOUBLE,
|
||||
GL_FLOAT,
|
||||
GL_BYTE,
|
||||
GL_UNSIGNED_BYTE,
|
||||
GL_INT,
|
||||
GL_UNSIGNED_INT,
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
0
|
||||
};
|
||||
|
||||
stride = (stride) ? stride : ATTRIB_LIST.normal.size * byte_size(type);
|
||||
ATTRIB_LIST.normal.ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(&ATTRIB_LIST.normal, 3, type, stride)) return;
|
||||
|
||||
if(_glCheckValidEnum(type, validTypes, __func__) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ATTRIB_LIST.normal.size = (type == GL_UNSIGNED_INT_2_10_10_10_REV) ? 1 : 3;
|
||||
ATTRIB_LIST.normal.stride = stride;
|
||||
ATTRIB_LIST.normal.type = type;
|
||||
|
||||
ATTRIB_LIST.dirty |= NORMAL_ENABLED_FLAG;
|
||||
}
|
||||
|
||||
|
||||
void _glInitAttributePointers(void) {
|
||||
TRACE();
|
||||
ATTRIB_LIST.dirty = ~0; // all attributes dirty
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
|
||||
glColorPointer(4, GL_FLOAT, 0, NULL);
|
||||
glNormalPointer(GL_FLOAT, 0, NULL);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint _glIsVertexDataFastPathCompatible(void) {
|
||||
/* 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((ATTRIB_LIST.enabled & VERTEX_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.vertex.size != 3 || ATTRIB_LIST.vertex.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & UV_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.uv.size != 2 || ATTRIB_LIST.uv.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG)) {
|
||||
/* FIXME: Shouldn't this be a reversed format? */
|
||||
if(ATTRIB_LIST.colour.size != GL_BGRA || ATTRIB_LIST.colour.type != GL_UNSIGNED_BYTE) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & ST_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.st.size != 2 || ATTRIB_LIST.st.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.normal.size != 3 || ATTRIB_LIST.normal.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void _glUpdateAttributes(void) {
|
||||
if(ATTRIB_LIST.dirty & VERTEX_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.vertex_func = calcReadPositionFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & UV_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.uv_func = calcReadUVFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & DIFFUSE_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.colour_func = calcReadDiffuseFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & ST_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.st_func = calcReadSTFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & NORMAL_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.normal_func = calcReadNormalFunc();
|
||||
}
|
||||
|
||||
ATTRIB_LIST.fast_path = _glIsVertexDataFastPathCompatible();
|
||||
ATTRIB_LIST.dirty = 0;
|
||||
}
|
||||
398
GL/clip.c
Normal file
@ -0,0 +1,398 @@
|
||||
#include <float.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <dc/pvr.h>
|
||||
#else
|
||||
#define PVR_PACK_COLOR(a, r, g, b) {}
|
||||
#endif
|
||||
|
||||
#include "profiler.h"
|
||||
#include "private.h"
|
||||
#include "../containers/aligned_vector.h"
|
||||
|
||||
|
||||
static unsigned char ZCLIP_ENABLED = 1;
|
||||
|
||||
unsigned char _glIsClippingEnabled() {
|
||||
return ZCLIP_ENABLED;
|
||||
}
|
||||
|
||||
void _glEnableClipping(unsigned char v) {
|
||||
ZCLIP_ENABLED = v;
|
||||
}
|
||||
|
||||
void _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t) __attribute__((optimize("fast-math")));
|
||||
void _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t) {
|
||||
const float NEAR_PLANE = NEAR_PLANE_DISTANCE + 0.0001f;
|
||||
|
||||
*t = (NEAR_PLANE - v1->w) / (v2->w - v1->w);
|
||||
|
||||
float vec [] = {v2->xyz[0] - v1->xyz[0], v2->xyz[1] - v1->xyz[1], v2->xyz[2] - v1->xyz[2]};
|
||||
|
||||
vout->xyz[0] = v1->xyz[0] + (vec[0] * (*t));
|
||||
vout->xyz[1] = v1->xyz[1] + (vec[1] * (*t));
|
||||
vout->xyz[2] = v1->xyz[2] + (vec[2] * (*t));
|
||||
}
|
||||
|
||||
static inline void interpolateFloat(const float v1, const float v2, const float t, float* out) {
|
||||
float v = v2 - v1;
|
||||
*out = (v * t) + v1;
|
||||
}
|
||||
|
||||
static inline void interpolateVec2(const float* v1, const float* v2, const float t, float* out) {
|
||||
/* FIXME: SH4 has an asm instruction for this */
|
||||
interpolateFloat(v1[0], v2[0], t, &out[0]);
|
||||
interpolateFloat(v1[1], v2[1], t, &out[1]);
|
||||
}
|
||||
|
||||
static inline void interpolateVec3(const float* v1, const float* v2, const float t, float* out) {
|
||||
/* FIXME: SH4 has an asm instruction for this */
|
||||
|
||||
interpolateFloat(v1[0], v2[0], t, &out[0]);
|
||||
interpolateFloat(v1[1], v2[1], t, &out[1]);
|
||||
interpolateFloat(v1[2], v2[2], t, &out[2]);
|
||||
}
|
||||
|
||||
static inline void interpolateVec4(const float* v1, const float* v2, const float t, float* out) {
|
||||
/* FIXME: SH4 has an asm instruction for this */
|
||||
interpolateFloat(v1[0], v2[0], t, &out[0]);
|
||||
interpolateFloat(v1[1], v2[1], t, &out[1]);
|
||||
interpolateFloat(v1[2], v2[2], t, &out[2]);
|
||||
interpolateFloat(v1[3], v2[3], t, &out[3]);
|
||||
}
|
||||
|
||||
static inline void interpolateColour(const uint8_t* v1, const uint8_t* v2, const float t, uint8_t* out) {
|
||||
out[0] = v1[0] + (uint32_t) (((float) (v2[0] - v1[0])) * t);
|
||||
out[1] = v1[1] + (uint32_t) (((float) (v2[1] - v1[1])) * t);
|
||||
out[2] = v1[2] + (uint32_t) (((float) (v2[2] - v1[2])) * t);
|
||||
out[3] = v1[3] + (uint32_t) (((float) (v2[3] - v1[3])) * t);
|
||||
}
|
||||
|
||||
const uint32_t VERTEX_CMD_EOL = 0xf0000000;
|
||||
const uint32_t VERTEX_CMD = 0xe0000000;
|
||||
|
||||
typedef struct {
|
||||
Vertex vertex[3];
|
||||
VertexExtra extra[3];
|
||||
uint8_t visible;
|
||||
} Triangle;
|
||||
|
||||
void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) __attribute__((optimize("fast-math")));
|
||||
void _glClipTriangle(const Triangle* triangle, const uint8_t visible, SubmissionTarget* target, const uint8_t flatShade) {
|
||||
uint8_t i, c = 0;
|
||||
|
||||
uint8_t lastVisible = 255;
|
||||
Vertex* last = NULL;
|
||||
VertexExtra* veLast = NULL;
|
||||
|
||||
const Vertex* vertices = triangle->vertex;
|
||||
const VertexExtra* extras = triangle->extra;
|
||||
|
||||
char* bgra = (char*) vertices[2].bgra;
|
||||
|
||||
/* Used when flat shading is enabled */
|
||||
uint32_t finalColour = *((uint32_t*) bgra);
|
||||
|
||||
for(i = 0; i < 4; ++i) {
|
||||
uint8_t thisIndex = (i == 3) ? 0 : i;
|
||||
|
||||
Vertex next;
|
||||
VertexExtra veNext;
|
||||
|
||||
next.flags = VERTEX_CMD;
|
||||
|
||||
uint8_t thisVisible = (visible & (1 << (2 - thisIndex))) > 0;
|
||||
if(i > 0) {
|
||||
uint8_t lastIndex = (i == 3) ? 2 : thisIndex - 1;
|
||||
|
||||
if(lastVisible < 255 && lastVisible != thisVisible) {
|
||||
const Vertex* v1 = &vertices[lastIndex];
|
||||
const Vertex* v2 = &vertices[thisIndex];
|
||||
|
||||
const VertexExtra* ve1 = &extras[lastIndex];
|
||||
const VertexExtra* ve2 = &extras[thisIndex];
|
||||
|
||||
float t;
|
||||
|
||||
_glClipLineToNearZ(v1, v2, &next, &t);
|
||||
interpolateFloat(v1->w, v2->w, t, &next.w);
|
||||
interpolateVec2(v1->uv, v2->uv, t, next.uv);
|
||||
|
||||
interpolateVec3(ve1->nxyz, ve2->nxyz, t, veNext.nxyz);
|
||||
interpolateVec2(ve1->st, ve2->st, t, veNext.st);
|
||||
|
||||
if(flatShade) {
|
||||
char* next_bgra = (char*) next.bgra;
|
||||
*((uint32_t*) next_bgra) = finalColour;
|
||||
} else {
|
||||
interpolateColour(v1->bgra, v2->bgra, t, next.bgra);
|
||||
}
|
||||
|
||||
/* Push back the new vertices to the end of both the ClipVertex and VertexExtra lists */
|
||||
last = aligned_vector_push_back(&target->output->vector, &next, 1);
|
||||
last->flags = VERTEX_CMD;
|
||||
|
||||
veLast = aligned_vector_push_back(target->extras, &veNext, 1);
|
||||
|
||||
++c;
|
||||
}
|
||||
}
|
||||
|
||||
if(thisVisible && i != 3) {
|
||||
last = aligned_vector_push_back(&target->output->vector, &vertices[thisIndex], 1);
|
||||
last->flags = VERTEX_CMD;
|
||||
|
||||
veLast = aligned_vector_push_back(target->extras, &extras[thisIndex], 1);
|
||||
|
||||
++c;
|
||||
}
|
||||
|
||||
lastVisible = thisVisible;
|
||||
}
|
||||
|
||||
if(last) {
|
||||
if(c == 4) {
|
||||
/* Convert to two triangles */
|
||||
Vertex newVerts[3];
|
||||
newVerts[0] = *(last - 3);
|
||||
newVerts[1] = *(last - 1);
|
||||
newVerts[2] = *(last);
|
||||
|
||||
VertexExtra newExtras[3];
|
||||
newExtras[0] = *(veLast - 3);
|
||||
newExtras[1] = *(veLast - 1);
|
||||
newExtras[2] = *(veLast);
|
||||
|
||||
(last - 1)->flags = VERTEX_CMD_EOL;
|
||||
newVerts[0].flags = VERTEX_CMD;
|
||||
newVerts[1].flags = VERTEX_CMD;
|
||||
newVerts[2].flags = VERTEX_CMD_EOL;
|
||||
|
||||
aligned_vector_resize(&target->output->vector, target->output->vector.size - 1);
|
||||
aligned_vector_push_back(&target->output->vector, newVerts, 3);
|
||||
|
||||
aligned_vector_resize(target->extras, target->extras->size - 1);
|
||||
aligned_vector_push_back(target->extras, newExtras, 3);
|
||||
} else {
|
||||
last->flags = VERTEX_CMD_EOL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static inline void markDead(Vertex* vert) {
|
||||
vert->flags = VERTEX_CMD_EOL;
|
||||
|
||||
// If we're debugging, wipe out the xyz
|
||||
#ifndef NDEBUG
|
||||
typedef union {
|
||||
float* f;
|
||||
int* i;
|
||||
} cast;
|
||||
|
||||
cast v1, v2, v3;
|
||||
v1.f = &vert->xyz[0];
|
||||
v2.f = &vert->xyz[1];
|
||||
v3.f = &vert->xyz[2];
|
||||
|
||||
*v1.i = 0xDEADBEEF;
|
||||
*v2.i = 0xDEADBEEF;
|
||||
*v3.i = 0xDEADBEEF;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define B000 0
|
||||
#define B111 7
|
||||
#define B100 4
|
||||
#define B010 2
|
||||
#define B001 1
|
||||
#define B101 5
|
||||
#define B011 3
|
||||
#define B110 6
|
||||
|
||||
#define MAX_CLIP_TRIANGLES 255
|
||||
|
||||
void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade) {
|
||||
static Triangle TO_CLIP[MAX_CLIP_TRIANGLES];
|
||||
static uint8_t CLIP_COUNT = 0;
|
||||
|
||||
CLIP_COUNT = 0;
|
||||
|
||||
Vertex* vertex = _glSubmissionTargetStart(target);
|
||||
const Vertex* end = _glSubmissionTargetEnd(target);
|
||||
const Vertex* start = vertex;
|
||||
|
||||
int32_t triangle = -1;
|
||||
|
||||
/* Go to the (potential) end of the first triangle */
|
||||
vertex++;
|
||||
|
||||
uint32_t vi1, vi2, vi3;
|
||||
|
||||
while(vertex < end) {
|
||||
vertex++;
|
||||
triangle++;
|
||||
|
||||
uint8_t even = (triangle % 2) == 0;
|
||||
Vertex* v1 = (even) ? vertex - 2 : vertex - 1;
|
||||
Vertex* v2 = (even) ? vertex - 1 : vertex - 2;
|
||||
Vertex* v3 = vertex;
|
||||
|
||||
/* Skip ahead if we don't have a complete triangle yet */
|
||||
if(v1->flags != VERTEX_CMD || v2->flags != VERTEX_CMD) {
|
||||
triangle = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Indexes into extras array */
|
||||
vi1 = v1 - start;
|
||||
vi2 = v2 - start;
|
||||
vi3 = v3 - start;
|
||||
|
||||
uint8_t visible = ((v1->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v3->w > 0) ? 1 : 0);
|
||||
|
||||
switch(visible) {
|
||||
case B111:
|
||||
/* All visible? Do nothing */
|
||||
continue;
|
||||
break;
|
||||
case B000:
|
||||
/*
|
||||
It is not possible that this is any trangle except the first
|
||||
in a strip. That's because:
|
||||
- It's either the first triangle submitted
|
||||
- A previous triangle must have been clipped and the strip
|
||||
restarted behind the plane
|
||||
|
||||
So, we effectively reboot the strip. We mark the first vertex
|
||||
as the end (so it's ignored) then mark the next two as the
|
||||
start of a new strip. Then if the next triangle crosses
|
||||
back into view, we clip correctly. This will potentially
|
||||
result in a bunch of pointlessly submitted vertices.
|
||||
|
||||
FIXME: Skip submitting those verts
|
||||
*/
|
||||
|
||||
/* Even though this is always the first in the strip, it can also
|
||||
* be the last */
|
||||
if(v3->flags == VERTEX_CMD_EOL) {
|
||||
/* Wipe out the triangle */
|
||||
markDead(v1);
|
||||
markDead(v2);
|
||||
markDead(v3);
|
||||
} else {
|
||||
markDead(v1);
|
||||
swapVertex(v2, v3);
|
||||
triangle = -1;
|
||||
v2->flags = VERTEX_CMD;
|
||||
v3->flags = VERTEX_CMD;
|
||||
}
|
||||
break;
|
||||
case B100:
|
||||
case B010:
|
||||
case B001:
|
||||
case B101:
|
||||
case B011:
|
||||
case B110:
|
||||
assert(CLIP_COUNT < MAX_CLIP_TRIANGLES);
|
||||
|
||||
/* Store the triangle for clipping */
|
||||
TO_CLIP[CLIP_COUNT].vertex[0] = *v1;
|
||||
TO_CLIP[CLIP_COUNT].vertex[1] = *v2;
|
||||
TO_CLIP[CLIP_COUNT].vertex[2] = *v3;
|
||||
|
||||
VertexExtra* ve1 = (VertexExtra*) aligned_vector_at(target->extras, vi1);
|
||||
VertexExtra* ve2 = (VertexExtra*) aligned_vector_at(target->extras, vi2);
|
||||
VertexExtra* ve3 = (VertexExtra*) aligned_vector_at(target->extras, vi3);
|
||||
|
||||
TO_CLIP[CLIP_COUNT].extra[0] = *ve1;
|
||||
TO_CLIP[CLIP_COUNT].extra[1] = *ve2;
|
||||
TO_CLIP[CLIP_COUNT].extra[2] = *ve3;
|
||||
|
||||
TO_CLIP[CLIP_COUNT].visible = visible;
|
||||
++CLIP_COUNT;
|
||||
|
||||
/*
|
||||
OK so here's the clever bit. If any triangle except
|
||||
the first or last needs clipping, then the next one does aswell
|
||||
(you can't draw a plane through a single triangle in the middle of a
|
||||
strip, only 2+). This means we can clip in pairs which frees up two
|
||||
vertices in the middle of the strip, which is exactly the space
|
||||
we need to restart the triangle strip after the next triangle
|
||||
*/
|
||||
if(v3->flags == VERTEX_CMD_EOL) {
|
||||
/* Last triangle in strip so end a vertex early */
|
||||
if(triangle == 0) {
|
||||
// Wipe out the triangle completely
|
||||
markDead(v1);
|
||||
markDead(v2);
|
||||
} else {
|
||||
// End the strip
|
||||
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
||||
}
|
||||
|
||||
markDead(vertex);
|
||||
|
||||
triangle = -1;
|
||||
} else if(triangle == 0) {
|
||||
/* First triangle in strip, remove first vertex */
|
||||
markDead(v1);
|
||||
|
||||
v2->flags = VERTEX_CMD;
|
||||
v3->flags = VERTEX_CMD;
|
||||
|
||||
triangle = -1;
|
||||
} else {
|
||||
Vertex* v4 = v3 + 1;
|
||||
uint32_t vi4 = v4 - start;
|
||||
|
||||
TO_CLIP[CLIP_COUNT].vertex[0] = *v3;
|
||||
TO_CLIP[CLIP_COUNT].vertex[1] = *v2;
|
||||
TO_CLIP[CLIP_COUNT].vertex[2] = *v4;
|
||||
|
||||
VertexExtra* ve4 = (VertexExtra*) aligned_vector_at(target->extras, vi4);
|
||||
TO_CLIP[CLIP_COUNT].extra[0] = *(VertexExtra*) aligned_vector_at(target->extras, vi3);
|
||||
TO_CLIP[CLIP_COUNT].extra[1] = *(VertexExtra*) aligned_vector_at(target->extras, vi2);
|
||||
TO_CLIP[CLIP_COUNT].extra[2] = *ve4;
|
||||
|
||||
visible = ((v3->w > 0) ? 4 : 0) | ((v2->w > 0) ? 2 : 0) | ((v4->w > 0) ? 1 : 0);
|
||||
|
||||
TO_CLIP[CLIP_COUNT].visible = visible;
|
||||
++CLIP_COUNT;
|
||||
|
||||
// Restart strip
|
||||
triangle = -1;
|
||||
|
||||
// Mark the second vertex as the end of the strip
|
||||
(vertex - 1)->flags = VERTEX_CMD_EOL;
|
||||
|
||||
if(v4->flags == VERTEX_CMD_EOL) {
|
||||
markDead(v3);
|
||||
markDead(v4);
|
||||
} else {
|
||||
// Swap the next vertices to start a new strip
|
||||
swapVertex(v3, v4);
|
||||
v3->flags = VERTEX_CMD;
|
||||
v4->flags = VERTEX_CMD;
|
||||
|
||||
/* Swap the extra data too */
|
||||
VertexExtra t = *ve4;
|
||||
*ve3 = *ve4;
|
||||
*ve4 = t;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now, clip all the triangles and append them to the output */
|
||||
GLushort i;
|
||||
for(i = 0; i < CLIP_COUNT; ++i) {
|
||||
_glClipTriangle(&TO_CLIP[i], TO_CLIP[i].visible, target, fladeShade);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,9 @@
|
||||
#pragma once
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
/* This figure is derived from the needs of Quake 1 */
|
||||
#define MAX_TEXTURE_COUNT 1088
|
||||
|
||||
|
||||
#endif // CONFIG_H
|
||||
|
||||
@ -1,126 +0,0 @@
|
||||
/* 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)
|
||||
{
|
||||
if(!(ATTRIB_LIST.enabled & 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_LIST.uv.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & UV_ENABLED_FLAG) ? ATTRIB_LIST.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_LIST.colour.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG) ? ATTRIB_LIST.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_LIST.vertex.stride;
|
||||
ptr = ATTRIB_LIST.vertex.ptr + (offset * stride);
|
||||
it = (Vertex*) start;
|
||||
|
||||
PREFETCH(ptr);
|
||||
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
|
||||
PREFETCH(ptr + stride);
|
||||
TransformVertex(((float*) ptr)[0], ((float*) ptr)[1], ((float*) ptr)[2], 1.0f, it->xyz, &it->w);
|
||||
PROCESS_VERTEX_FLAGS(it, min + i);
|
||||
ptr += stride;
|
||||
}
|
||||
|
||||
start = aligned_vector_at(target->extras, min);
|
||||
|
||||
stride = ATTRIB_LIST.st.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & ST_ENABLED_FLAG) ? ATTRIB_LIST.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_LIST.normal.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG) ? ATTRIB_LIST.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
GL/error.c
@ -8,35 +8,12 @@
|
||||
KOS Open GL State Machine Error Code Implementation.
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
static GLenum LAST_ERROR = GL_NO_ERROR;
|
||||
static char ERROR_FUNCTION[64] = { '\0' };
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
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 void _glKosResetError() {
|
||||
LAST_ERROR = GL_NO_ERROR;
|
||||
}
|
||||
static GLenum last_error = GL_NO_ERROR;
|
||||
static char error_function[64] = { '\0' };
|
||||
|
||||
/* Quoth the GL Spec:
|
||||
When an error occurs, the error flag is set to the appropriate error code
|
||||
@ -47,9 +24,43 @@ GL_FORCE_INLINE void _glKosResetError() {
|
||||
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");
|
||||
}
|
||||
|
||||
static 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";
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosPrintError() {
|
||||
if(!_glKosHasError()) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "GL ERROR: %s when calling %s\n", _glErrorEnumAsString(last_error), error_function);
|
||||
}
|
||||
|
||||
GLenum glGetError(void) {
|
||||
GLenum rv = LAST_ERROR;
|
||||
GLenum rv = last_error;
|
||||
_glKosResetError();
|
||||
return rv;
|
||||
}
|
||||
|
||||
158
GL/flush.c
@ -1,28 +1,66 @@
|
||||
|
||||
|
||||
#include <kos.h>
|
||||
|
||||
#include "../include/glkos.h"
|
||||
#include "../containers/aligned_vector.h"
|
||||
#include "private.h"
|
||||
#include "profiler.h"
|
||||
#include "version.h"
|
||||
|
||||
PolyList OP_LIST;
|
||||
PolyList PT_LIST;
|
||||
PolyList TR_LIST;
|
||||
#define TA_SQ_ADDR (unsigned int *)(void *) \
|
||||
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
|
||||
|
||||
/**
|
||||
* FAST_MODE will use invW for all Z coordinates sent to the
|
||||
* GPU.
|
||||
*
|
||||
* This will break orthographic mode so default is FALSE
|
||||
**/
|
||||
static PolyList OP_LIST;
|
||||
static PolyList PT_LIST;
|
||||
static PolyList TR_LIST;
|
||||
|
||||
#define FAST_MODE GL_FALSE
|
||||
static void pvr_list_submit(void *src, int n) {
|
||||
GLuint *d = TA_SQ_ADDR;
|
||||
GLuint *s = src;
|
||||
|
||||
GLboolean AUTOSORT_ENABLED = 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;
|
||||
}
|
||||
|
||||
PolyList* _glOpaquePolyList() {
|
||||
return &OP_LIST;
|
||||
/* Wait for both store queues to complete */
|
||||
d = (GLuint *)0xe0000000;
|
||||
d[0] = d[8] = 0;
|
||||
}
|
||||
|
||||
PolyList* _glPunchThruPolyList() {
|
||||
return &PT_LIST;
|
||||
static void _glInitPVR(GLboolean autosort) {
|
||||
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 */
|
||||
(autosort) ? 0 : 1 /* Disable translucent auto-sorting to match traditional GL */
|
||||
};
|
||||
|
||||
pvr_init(¶ms);
|
||||
}
|
||||
|
||||
|
||||
PolyList* _glActivePolyList() {
|
||||
if(_glIsBlendingEnabled()) {
|
||||
return &TR_LIST;
|
||||
} else if(_glIsAlphaTestEnabled()) {
|
||||
return &PT_LIST;
|
||||
} else {
|
||||
return &OP_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
PolyList *_glTransparentPolyList() {
|
||||
@ -40,37 +78,20 @@ void APIENTRY glFinish() {
|
||||
|
||||
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->initial_op_capacity = 1024;
|
||||
config->initial_pt_capacity = 512;
|
||||
config->initial_tr_capacity = 1024;
|
||||
config->initial_immediate_capacity = 1024;
|
||||
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);
|
||||
_glInitPVR(config->autosort_enabled);
|
||||
|
||||
AUTOSORT_ENABLED = config->autosort_enabled;
|
||||
|
||||
_glInitSubmissionTarget();
|
||||
_glInitMatrices();
|
||||
_glInitAttributePointers();
|
||||
_glInitContext();
|
||||
@ -82,13 +103,9 @@ void APIENTRY glKosInitEx(GLdcConfig* config) {
|
||||
|
||||
_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;
|
||||
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(Vertex));
|
||||
aligned_vector_init(&PT_LIST.vector, sizeof(Vertex));
|
||||
@ -99,44 +116,49 @@ void APIENTRY glKosInitEx(GLdcConfig* config) {
|
||||
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() {
|
||||
GLdcConfig config;
|
||||
glKosInitConfig(&config);
|
||||
glKosInitEx(&config);
|
||||
}
|
||||
|
||||
#define QACRTA ((((unsigned int)0x10000000)>>26)<<2)&0x1c
|
||||
|
||||
void APIENTRY glKosSwapBuffers() {
|
||||
static int frame_count = 0;
|
||||
|
||||
TRACE();
|
||||
|
||||
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();
|
||||
}
|
||||
profiler_push(__func__);
|
||||
|
||||
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_wait_ready();
|
||||
|
||||
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();
|
||||
pvr_scene_begin();
|
||||
QACR0 = QACRTA;
|
||||
QACR1 = QACRTA;
|
||||
|
||||
pvr_list_begin(PVR_LIST_OP_POLY);
|
||||
pvr_list_submit(OP_LIST.vector.data, OP_LIST.vector.size);
|
||||
pvr_list_finish();
|
||||
|
||||
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();
|
||||
|
||||
aligned_vector_clear(&OP_LIST.vector);
|
||||
aligned_vector_clear(&PT_LIST.vector);
|
||||
aligned_vector_clear(&TR_LIST.vector);
|
||||
|
||||
_glApplyScissor(true);
|
||||
profiler_checkpoint("scene");
|
||||
profiler_pop();
|
||||
|
||||
if(frame_count++ > 100) {
|
||||
profiler_print_stats();
|
||||
frame_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
176
GL/fog.c
@ -1,138 +1,74 @@
|
||||
|
||||
/*
|
||||
TODO: glGetX() fog values
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include "private.h"
|
||||
|
||||
static struct {
|
||||
GLfloat START;
|
||||
GLfloat END;
|
||||
GLfloat DENSITY;
|
||||
GLenum MODE;
|
||||
GLfloat COLOR[4];
|
||||
} FOG = {
|
||||
0.0f, 1.0f, 1.0f, GL_EXP, { 0.0f, 0.0f, 0.0f, 0.0f }
|
||||
};
|
||||
static GLfloat FOG_START = 0.0f;
|
||||
static GLfloat FOG_END = 1.0f;
|
||||
static GLfloat FOG_DENSITY = 1.0f;
|
||||
static GLenum FOG_MODE = GL_EXP;
|
||||
static GLfloat FOG_COLOR [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
static void updatePVRFog(void) {
|
||||
switch(FOG.MODE) {
|
||||
case GL_LINEAR:
|
||||
GPUSetFogLinear(FOG.START, FOG.END);
|
||||
break;
|
||||
|
||||
case GL_EXP:
|
||||
GPUSetFogExp(FOG.DENSITY);
|
||||
break;
|
||||
|
||||
case GL_EXP2:
|
||||
GPUSetFogExp2(FOG.DENSITY);
|
||||
break;
|
||||
static void updatePVRFog() {
|
||||
if(FOG_MODE == GL_LINEAR) {
|
||||
pvr_fog_table_linear(FOG_START, FOG_END);
|
||||
} else if(FOG_MODE == GL_EXP) {
|
||||
pvr_fog_table_exp(FOG_DENSITY);
|
||||
} else if(FOG_MODE == GL_EXP2) {
|
||||
pvr_fog_table_exp2(FOG_DENSITY);
|
||||
}
|
||||
|
||||
GPUSetFogColor(FOG.COLOR[3], FOG.COLOR[0], FOG.COLOR[1], FOG.COLOR[2]);
|
||||
pvr_fog_table_color(FOG_COLOR[3], FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2]);
|
||||
}
|
||||
|
||||
void APIENTRY glFogf(GLenum pname, GLfloat param) {
|
||||
void APIENTRY glFogf(GLenum pname, GLfloat param) {
|
||||
switch(pname) {
|
||||
case GL_FOG_DENSITY:
|
||||
if(FOG.DENSITY != param) {
|
||||
if(param < 0.0f)
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
else {
|
||||
FOG.DENSITY = param;
|
||||
updatePVRFog();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_FOG_START:
|
||||
if(FOG.START != param) {
|
||||
FOG.START = param;
|
||||
updatePVRFog();
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_FOG_END:
|
||||
if(FOG.END != param) {
|
||||
FOG.END = param;
|
||||
updatePVRFog();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
case GL_FOG_MODE: {
|
||||
FOG_MODE = (GLenum) param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_DENSITY: {
|
||||
FOG_DENSITY = param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_START: {
|
||||
FOG_START = param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_END: {
|
||||
FOG_END = param;
|
||||
updatePVRFog();
|
||||
} break;
|
||||
case GL_FOG_INDEX:
|
||||
default: {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogi(GLenum pname, GLint param) {
|
||||
switch(pname) {
|
||||
case GL_FOG_DENSITY:
|
||||
case GL_FOG_START:
|
||||
case GL_FOG_END:
|
||||
glFogf(pname, (GLfloat)param);
|
||||
break;
|
||||
void APIENTRY glFogi(GLenum pname, GLint param) {
|
||||
glFogf(pname, (GLfloat) param);
|
||||
}
|
||||
|
||||
case GL_FOG_MODE:
|
||||
if(FOG.MODE != param) {
|
||||
switch(param) {
|
||||
case GL_LINEAR:
|
||||
case GL_EXP:
|
||||
case GL_EXP2:
|
||||
FOG.MODE = param;
|
||||
updatePVRFog();
|
||||
break;
|
||||
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_FOG_INDEX:
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
|
||||
if(pname == GL_FOG_COLOR) {
|
||||
FOG_COLOR[0] = params[0];
|
||||
FOG_COLOR[1] = params[1];
|
||||
FOG_COLOR[2] = params[2];
|
||||
FOG_COLOR[3] = params[3];
|
||||
updatePVRFog();
|
||||
} else {
|
||||
glFogf(pname, *params);
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
|
||||
switch(pname) {
|
||||
case GL_FOG_COLOR: {
|
||||
GLfloat color[] = {
|
||||
CLAMP(params[0], 0.0f, 1.0f),
|
||||
CLAMP(params[1], 0.0f, 1.0f),
|
||||
CLAMP(params[2], 0.0f, 1.0f),
|
||||
CLAMP(params[3], 0.0f, 1.0f)
|
||||
};
|
||||
|
||||
if(memcmp(color, FOG.COLOR, sizeof(float) * 4)) {
|
||||
memcpy(FOG.COLOR, color, sizeof(float) * 4);
|
||||
updatePVRFog();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
glFogf(pname, *params);
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
|
||||
switch(pname) {
|
||||
case GL_FOG_COLOR: {
|
||||
GLfloat color[] = {
|
||||
(GLfloat)params[0] / (GLfloat)INT_MAX,
|
||||
(GLfloat)params[1] / (GLfloat)INT_MAX,
|
||||
(GLfloat)params[2] / (GLfloat)INT_MAX,
|
||||
(GLfloat)params[3] / (GLfloat)INT_MAX,
|
||||
};
|
||||
|
||||
glFogfv(pname, color);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
glFogi(pname, *params);
|
||||
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
|
||||
if(pname == GL_FOG_COLOR) {
|
||||
FOG_COLOR[0] = ((GLfloat) params[0]) / (GLfloat) INT_MAX;
|
||||
FOG_COLOR[1] = ((GLfloat) params[1]) / (GLfloat) INT_MAX;
|
||||
FOG_COLOR[2] = ((GLfloat) params[2]) / (GLfloat) INT_MAX;
|
||||
FOG_COLOR[3] = ((GLfloat) params[3]) / (GLfloat) INT_MAX;
|
||||
updatePVRFog();
|
||||
} else {
|
||||
glFogi(pname, *params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "../include/glkos.h"
|
||||
#include "../include/glext.h"
|
||||
|
||||
typedef struct {
|
||||
GLuint index;
|
||||
@ -60,7 +63,6 @@ void APIENTRY glDeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers) {
|
||||
}
|
||||
|
||||
void APIENTRY glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
|
||||
_GL_UNUSED(target);
|
||||
TRACE();
|
||||
|
||||
if(framebuffer) {
|
||||
@ -74,79 +76,77 @@ 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;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint A1555(GLuint v) {
|
||||
static inline GLubyte A1555(GLushort v) {
|
||||
const GLuint MASK = (1 << 15);
|
||||
return (v & MASK) >> 8;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint R1555(GLuint v) {
|
||||
static inline GLubyte R1555(GLushort v) {
|
||||
const GLuint MASK = (31 << 10);
|
||||
return (v & MASK) >> 7;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint G1555(GLuint v) {
|
||||
static inline GLubyte G1555(GLushort v) {
|
||||
const GLuint MASK = (31 << 5);
|
||||
return (v & MASK) >> 2;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint B1555(GLuint v) {
|
||||
static inline GLubyte B1555(GLushort v) {
|
||||
const GLuint MASK = (31 << 0);
|
||||
return (v & MASK) << 3;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint A4444(GLuint v) {
|
||||
static inline GLubyte A4444(GLushort v) {
|
||||
const GLuint MASK = (0xF << 12);
|
||||
return (v & MASK) >> 12;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint R4444(GLuint v) {
|
||||
static inline GLubyte R4444(GLushort v) {
|
||||
const GLuint MASK = (0xF << 8);
|
||||
return (v & MASK) >> 8;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint G4444(GLuint v) {
|
||||
static inline GLubyte G4444(GLushort v) {
|
||||
const GLuint MASK = (0xF << 4);
|
||||
return (v & MASK) >> 4;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint B4444(GLuint v) {
|
||||
static inline GLubyte B4444(GLushort v) {
|
||||
const GLuint MASK = (0xF << 0);
|
||||
return (v & MASK) >> 0;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint R565(GLuint v) {
|
||||
static inline GLubyte R565(GLushort v) {
|
||||
const GLuint MASK = (31 << 11);
|
||||
return (v & MASK) >> 8;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint G565(GLuint v) {
|
||||
static inline GLubyte G565(GLushort v) {
|
||||
const GLuint MASK = (63 << 5);
|
||||
return (v & MASK) >> 3;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint B565(GLuint v) {
|
||||
static inline GLubyte B565(GLushort 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) {
|
||||
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;
|
||||
@ -155,7 +155,7 @@ static GL_NO_INSTRUMENT GLboolean _glCalculateAverageTexel(GLuint pvrFormat, con
|
||||
const GLubyte ARGB4444 = 1;
|
||||
const GLubyte RGB565 = 2;
|
||||
|
||||
if((pvrFormat & GPU_TXRFMT_PAL8BPP) == GPU_TXRFMT_PAL8BPP) {
|
||||
if((pvrFormat & PVR_TXRFMT_PAL8BPP) == PVR_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)
|
||||
@ -196,7 +196,7 @@ static GL_NO_INSTRUMENT GLboolean _glCalculateAverageTexel(GLuint pvrFormat, con
|
||||
|
||||
*d1 = PACK_ARGB4444(a, r, g, b);
|
||||
} else {
|
||||
gl_assert(format == ARGB1555);
|
||||
assert(format == ARGB1555);
|
||||
|
||||
GLushort* s1 = (GLushort*) src1;
|
||||
GLushort* s2 = (GLushort*) src2;
|
||||
@ -227,7 +227,7 @@ GLboolean _glGenerateMipmapTwiddled(const GLuint pvrFormat, const GLubyte* prevD
|
||||
uint32_t i, j;
|
||||
uint32_t stride = 0;
|
||||
|
||||
if((pvrFormat & GPU_TXRFMT_PAL8BPP) == GPU_TXRFMT_PAL8BPP) {
|
||||
if((pvrFormat & PVR_TXRFMT_PAL8BPP) == PVR_TXRFMT_PAL8BPP) {
|
||||
stride = 1;
|
||||
} else {
|
||||
stride = 2;
|
||||
@ -245,8 +245,8 @@ GLboolean _glGenerateMipmapTwiddled(const GLuint pvrFormat, const GLubyte* prevD
|
||||
const GLubyte* s4 = s3 + stride;
|
||||
GLubyte* t = &thisData[j * stride];
|
||||
|
||||
gl_assert(s4 < prevData + (lastHeight * lastWidth * stride));
|
||||
gl_assert(t < thisData + (thisHeight * thisWidth * stride));
|
||||
assert(s4 < prevData + (lastHeight * lastWidth * stride));
|
||||
assert(t < thisData + (thisHeight * thisWidth * stride));
|
||||
|
||||
_glCalculateAverageTexel(pvrFormat, s1, s2, s3, s4, t);
|
||||
}
|
||||
@ -254,37 +254,35 @@ GLboolean _glGenerateMipmapTwiddled(const GLuint pvrFormat, const GLubyte* prevD
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void APIENTRY glGenerateMipmap(GLenum target) {
|
||||
void APIENTRY glGenerateMipmapEXT(GLenum target) {
|
||||
if(target != GL_TEXTURE_2D) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
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__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
if((tex->color & GPU_TXRFMT_PAL4BPP) == GPU_TXRFMT_PAL4BPP) {
|
||||
fprintf(stderr, "[GL ERROR] Mipmap generation not supported for 4BPP paletted textures\n");
|
||||
if(!tex || !tex->data || !tex->mipmapCount) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
if((tex->color & GPU_TXRFMT_NONTWIDDLED) == GPU_TXRFMT_NONTWIDDLED) {
|
||||
if((tex->color & PVR_TXRFMT_NONTWIDDLED) == PVR_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__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -292,6 +290,7 @@ void APIENTRY glGenerateMipmap(GLenum target) {
|
||||
if(!complete && tex->isCompressed) {
|
||||
fprintf(stderr, "[GL ERROR] Generating mipmaps for compressed textures is not yet supported\n");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -322,12 +321,13 @@ void APIENTRY glGenerateMipmap(GLenum target) {
|
||||
prevHeight = thisHeight;
|
||||
}
|
||||
|
||||
gl_assert(_glIsMipmapComplete(tex));
|
||||
assert(_glIsMipmapComplete(tex));
|
||||
}
|
||||
|
||||
GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target) {
|
||||
if(target != GL_FRAMEBUFFER_EXT) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
|
||||
#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
|
||||
|
||||
20
GL/glu.c
@ -2,11 +2,11 @@
|
||||
#include "private.h"
|
||||
|
||||
/* Set the Perspective */
|
||||
void APIENTRY gluPerspective(GLdouble angle, GLdouble aspect,
|
||||
GLdouble znear, GLdouble zfar) {
|
||||
void APIENTRY gluPerspective(GLfloat angle, GLfloat aspect,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
GLdouble fW, fH;
|
||||
|
||||
fH = tan(angle * (M_PI / 360.0)) * znear;
|
||||
fH = tan(angle / 360 * F_PI) * znear;
|
||||
fW = fH * aspect;
|
||||
|
||||
glFrustum(-fW, fW, -fH, fH, znear, zfar);
|
||||
@ -15,17 +15,3 @@ void APIENTRY gluPerspective(GLdouble angle, GLdouble aspect,
|
||||
void APIENTRY gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) {
|
||||
glOrtho(left, right, bottom, top, -1.0f, 1.0f);
|
||||
}
|
||||
|
||||
/* generate mipmaps for any image provided by the user and then pass them to OpenGL */
|
||||
GLint 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);
|
||||
// FIXME return glu error codes
|
||||
return 0;
|
||||
}
|
||||
|
||||
327
GL/immediate.c
@ -10,74 +10,81 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../include/glext.h"
|
||||
#include "../include/glkos.h"
|
||||
#include "profiler.h"
|
||||
|
||||
#include "private.h"
|
||||
|
||||
GLboolean IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
static 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 AttribPointerList IM_ATTRIBS;
|
||||
static AlignedVector ST_COORDS;
|
||||
static AlignedVector NORMALS;
|
||||
|
||||
/* 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 GLubyte COLOR[4] = {255, 255, 255, 255};
|
||||
static GLfloat UV_COORD[2] = {0.0f, 0.0f};
|
||||
static GLfloat ST_COORD[2] = {0.0f, 0.0f};
|
||||
|
||||
static AttribPointer VERTEX_ATTRIB;
|
||||
static AttribPointer DIFFUSE_ATTRIB;
|
||||
static AttribPointer UV_ATTRIB;
|
||||
static AttribPointer ST_ATTRIB;
|
||||
static AttribPointer NORMAL_ATTRIB;
|
||||
|
||||
void _glInitImmediateMode(GLuint initial_size) {
|
||||
aligned_vector_init(&VERTICES, sizeof(IMVertex));
|
||||
aligned_vector_init(&VERTICES, sizeof(GLVertexKOS));
|
||||
aligned_vector_init(&ST_COORDS, sizeof(GLfloat));
|
||||
aligned_vector_init(&NORMALS, sizeof(GLuint));
|
||||
|
||||
aligned_vector_reserve(&VERTICES, initial_size);
|
||||
IM_ATTRIBS.fast_path = GL_TRUE;
|
||||
aligned_vector_reserve(&ST_COORDS, initial_size * 2);
|
||||
aligned_vector_reserve(&NORMALS, 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);
|
||||
VERTEX_ATTRIB.ptr = VERTICES.data + sizeof(uint32_t);
|
||||
VERTEX_ATTRIB.size = 3;
|
||||
VERTEX_ATTRIB.type = GL_FLOAT;
|
||||
VERTEX_ATTRIB.stride = 32;
|
||||
|
||||
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;
|
||||
UV_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 3);
|
||||
UV_ATTRIB.stride = 32;
|
||||
UV_ATTRIB.type = GL_FLOAT;
|
||||
UV_ATTRIB.size = 2;
|
||||
|
||||
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;
|
||||
DIFFUSE_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 5);
|
||||
DIFFUSE_ATTRIB.size = GL_BGRA; /* Flipped color order */
|
||||
DIFFUSE_ATTRIB.type = GL_UNSIGNED_BYTE;
|
||||
DIFFUSE_ATTRIB.stride = 32;
|
||||
|
||||
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);
|
||||
NORMAL_ATTRIB.ptr = NORMALS.data;
|
||||
NORMAL_ATTRIB.stride = 0;
|
||||
NORMAL_ATTRIB.type = GL_INT_2_10_10_10_REV;
|
||||
NORMAL_ATTRIB.size = 1;
|
||||
|
||||
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;
|
||||
ST_ATTRIB.ptr = ST_COORDS.data;
|
||||
ST_ATTRIB.stride = 0;
|
||||
ST_ATTRIB.type = GL_FLOAT;
|
||||
ST_ATTRIB.size = 2;
|
||||
}
|
||||
|
||||
GLubyte _glCheckImmediateModeInactive(const char* func) {
|
||||
/* Returns 1 on error */
|
||||
if(IMMEDIATE_MODE_ACTIVE) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, func);
|
||||
_glKosPrintError();
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void APIENTRY glBegin(GLenum mode) {
|
||||
if(IMMEDIATE_MODE_ACTIVE) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -86,102 +93,90 @@ void APIENTRY glBegin(GLenum mode) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
IM_ATTRIBS.enabled |= 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);
|
||||
COLOR[0] = (GLubyte)(r * 255);
|
||||
COLOR[1] = (GLubyte)(g * 255);
|
||||
COLOR[2] = (GLubyte)(b * 255);
|
||||
COLOR[3] = (GLubyte)(a * 255);
|
||||
}
|
||||
|
||||
void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = a;
|
||||
COLOR[R8IDX] = r;
|
||||
COLOR[G8IDX] = g;
|
||||
COLOR[B8IDX] = b;
|
||||
}
|
||||
|
||||
void APIENTRY glColor4ubv(const GLubyte *v) {
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = v[3];
|
||||
COLOR[R8IDX] = v[0];
|
||||
COLOR[G8IDX] = v[1];
|
||||
COLOR[B8IDX] = v[2];
|
||||
COLOR[0] = r;
|
||||
COLOR[1] = g;
|
||||
COLOR[2] = b;
|
||||
COLOR[3] = a;
|
||||
}
|
||||
|
||||
void APIENTRY glColor4fv(const GLfloat* v) {
|
||||
IM_ATTRIBS.enabled |= 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);
|
||||
COLOR[0] = (GLubyte)(v[0] * 255);
|
||||
COLOR[1] = (GLubyte)(v[1] * 255);
|
||||
COLOR[2] = (GLubyte)(v[2] * 255);
|
||||
COLOR[3] = (GLubyte)(v[3] * 255);
|
||||
}
|
||||
|
||||
void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) {
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[B8IDX] = (GLubyte)(b * 255.0f);
|
||||
COLOR[G8IDX] = (GLubyte)(g * 255.0f);
|
||||
COLOR[R8IDX] = (GLubyte)(r * 255.0f);
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[0] = (GLubyte)(r * 255);
|
||||
COLOR[1] = (GLubyte)(g * 255);
|
||||
COLOR[2] = (GLubyte)(b * 255);
|
||||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
void APIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue) {
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[R8IDX] = red;
|
||||
COLOR[G8IDX] = green;
|
||||
COLOR[B8IDX] = blue;
|
||||
COLOR[0] = red;
|
||||
COLOR[1] = green;
|
||||
COLOR[2] = blue;
|
||||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
void APIENTRY glColor3ubv(const GLubyte *v) {
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[R8IDX] = v[0];
|
||||
COLOR[G8IDX] = v[1];
|
||||
COLOR[B8IDX] = v[2];
|
||||
COLOR[0] = v[0];
|
||||
COLOR[1] = v[1];
|
||||
COLOR[2] = v[2];
|
||||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
void APIENTRY glColor3fv(const GLfloat* v) {
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[R8IDX] = (GLubyte)(v[0] * 255);
|
||||
COLOR[G8IDX] = (GLubyte)(v[1] * 255);
|
||||
COLOR[B8IDX] = (GLubyte)(v[2] * 255);
|
||||
COLOR[0] = (GLubyte)(v[0] * 255);
|
||||
COLOR[1] = (GLubyte)(v[1] * 255);
|
||||
COLOR[2] = (GLubyte)(v[2] * 255);
|
||||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
typedef union punned {
|
||||
GLubyte* byte;
|
||||
GLfloat* flt;
|
||||
uint32_t* u32;
|
||||
void* vptr;
|
||||
uintptr_t uptr;
|
||||
} punned_t;
|
||||
static inline uint32_t pack_vertex_attribute_vec3_1i(float x, float y, float z) {
|
||||
const float w = 0.0f;
|
||||
|
||||
const uint32_t xs = x < 0;
|
||||
const uint32_t ys = y < 0;
|
||||
const uint32_t zs = z < 0;
|
||||
const uint32_t ws = w < 0;
|
||||
|
||||
uint32_t vi =
|
||||
ws << 31 | ((uint32_t)(w + (ws << 1)) & 1) << 30 |
|
||||
zs << 29 | ((uint32_t)(z * 511 + (zs << 9)) & 511) << 20 |
|
||||
ys << 19 | ((uint32_t)(y * 511 + (ys << 9)) & 511) << 10 |
|
||||
xs << 9 | ((uint32_t)(x * 511 + (xs << 9)) & 511);
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
IM_ATTRIBS.enabled |= VERTEX_ENABLED_FLAG;
|
||||
GLVertexKOS* vert = aligned_vector_extend(&VERTICES, 1);
|
||||
GLfloat* st = aligned_vector_extend(&ST_COORDS, 2);
|
||||
GLuint* n = aligned_vector_extend(&NORMALS, 1);
|
||||
|
||||
IMVertex* vert = aligned_vector_extend(&VERTICES, 1);
|
||||
vert->x = x;
|
||||
vert->y = y;
|
||||
vert->z = z;
|
||||
vert->u = UV_COORD[0];
|
||||
vert->v = UV_COORD[1];
|
||||
|
||||
punned_t dest = { .flt = &vert->x };
|
||||
*(dest.flt++) = x;
|
||||
*(dest.flt++) = y;
|
||||
*(dest.flt++) = z;
|
||||
*(dest.flt++) = UV_COORD[0];
|
||||
*(dest.flt++) = UV_COORD[1];
|
||||
*(dest.flt++) = ST_COORD[0];
|
||||
*(dest.flt++) = ST_COORD[1];
|
||||
*(dest.u32++) = *((uint32_t*)(void*) COLOR);
|
||||
*(dest.flt++) = NORMAL[0];
|
||||
*(dest.flt++) = NORMAL[1];
|
||||
*(dest.flt++) = NORMAL[2];
|
||||
vert->bgra[R8IDX] = COLOR[0];
|
||||
vert->bgra[G8IDX] = COLOR[1];
|
||||
vert->bgra[B8IDX] = COLOR[2];
|
||||
vert->bgra[A8IDX] = COLOR[3];
|
||||
|
||||
*n = pack_vertex_attribute_vec3_1i(NORMAL[0], NORMAL[1], NORMAL[2]);
|
||||
|
||||
memcpy(st, ST_COORD, sizeof(GLfloat) * 2);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3fv(const GLfloat* v) {
|
||||
@ -197,7 +192,6 @@ void APIENTRY glVertex2fv(const GLfloat* v) {
|
||||
}
|
||||
|
||||
void APIENTRY glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
|
||||
_GL_UNUSED(w);
|
||||
glVertex3f(x, y, z);
|
||||
}
|
||||
|
||||
@ -207,31 +201,19 @@ void APIENTRY glVertex4fv(const GLfloat* v) {
|
||||
|
||||
void APIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
|
||||
if(target == GL_TEXTURE0) {
|
||||
IM_ATTRIBS.enabled |= UV_ENABLED_FLAG;
|
||||
UV_COORD[0] = s;
|
||||
UV_COORD[1] = t;
|
||||
} else if(target == GL_TEXTURE1) {
|
||||
IM_ATTRIBS.enabled |= ST_ENABLED_FLAG;
|
||||
ST_COORD[0] = s;
|
||||
ST_COORD[1] = t;
|
||||
} else {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoord1f(GLfloat u) {
|
||||
IM_ATTRIBS.enabled |= 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) {
|
||||
IM_ATTRIBS.enabled |= UV_ENABLED_FLAG;
|
||||
UV_COORD[0] = u;
|
||||
UV_COORD[1] = v;
|
||||
}
|
||||
@ -241,7 +223,6 @@ void APIENTRY glTexCoord2fv(const GLfloat* v) {
|
||||
}
|
||||
|
||||
void APIENTRY glNormal3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
IM_ATTRIBS.enabled |= NORMAL_ENABLED_FLAG;
|
||||
NORMAL[0] = x;
|
||||
NORMAL[1] = y;
|
||||
NORMAL[2] = z;
|
||||
@ -252,24 +233,76 @@ void APIENTRY glNormal3fv(const GLfloat* v) {
|
||||
}
|
||||
|
||||
void APIENTRY glEnd() {
|
||||
profiler_push(__func__);
|
||||
|
||||
IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
|
||||
/* 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;
|
||||
/* Resizing could have invalidated these pointers */
|
||||
VERTEX_ATTRIB.ptr = VERTICES.data + sizeof(uint32_t);
|
||||
UV_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 3);
|
||||
DIFFUSE_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 5);
|
||||
|
||||
/* Redirect attrib state */
|
||||
AttribPointerList stashed_state = ATTRIB_LIST;
|
||||
ATTRIB_LIST = IM_ATTRIBS;
|
||||
|
||||
glDrawArrays(ACTIVE_POLYGON_MODE, 0, aligned_vector_header(&VERTICES)->size);
|
||||
NORMAL_ATTRIB.ptr = NORMALS.data;
|
||||
ST_ATTRIB.ptr = ST_COORDS.data;
|
||||
|
||||
ATTRIB_LIST = stashed_state;
|
||||
GLuint* attrs = _glGetEnabledAttributes();
|
||||
|
||||
AttribPointer* vattr = _glGetVertexAttribPointer();
|
||||
AttribPointer* dattr = _glGetDiffuseAttribPointer();
|
||||
AttribPointer* nattr = _glGetNormalAttribPointer();
|
||||
AttribPointer* uattr = _glGetUVAttribPointer();
|
||||
AttribPointer* sattr = _glGetSTAttribPointer();
|
||||
|
||||
/* Stash existing values */
|
||||
AttribPointer vptr = *vattr;
|
||||
AttribPointer dptr = *dattr;
|
||||
AttribPointer nptr = *nattr;
|
||||
AttribPointer uvptr = *uattr;
|
||||
AttribPointer stptr = *sattr;
|
||||
|
||||
GLuint prevAttrs = *attrs;
|
||||
|
||||
/* Switch to our immediate mode arrays */
|
||||
*vattr = VERTEX_ATTRIB;
|
||||
*dattr = DIFFUSE_ATTRIB;
|
||||
*nattr = NORMAL_ATTRIB;
|
||||
*uattr = UV_ATTRIB;
|
||||
*sattr = ST_ATTRIB;
|
||||
|
||||
*attrs = ~0; // Enable everything
|
||||
|
||||
#ifndef NDEBUG
|
||||
_glRecalcFastPath();
|
||||
#else
|
||||
// Immediate mode should always activate the fast path
|
||||
GLboolean fastPathEnabled = _glRecalcFastPath();
|
||||
assert(fastPathEnabled);
|
||||
#endif
|
||||
|
||||
glDrawArrays(ACTIVE_POLYGON_MODE, 0, VERTICES.size);
|
||||
|
||||
/* Restore everything */
|
||||
*vattr = vptr;
|
||||
*dattr = dptr;
|
||||
*nattr = nptr;
|
||||
*uattr = uvptr;
|
||||
*sattr = stptr;
|
||||
|
||||
*attrs = prevAttrs;
|
||||
|
||||
/* Clear arrays for next polys */
|
||||
aligned_vector_clear(&VERTICES);
|
||||
aligned_vector_clear(&ST_COORDS);
|
||||
aligned_vector_clear(&NORMALS);
|
||||
|
||||
*vattr = vptr;
|
||||
*dattr = dptr;
|
||||
*nattr = nptr;
|
||||
*uattr = uvptr;
|
||||
*sattr = stptr;
|
||||
|
||||
profiler_checkpoint("restore");
|
||||
profiler_pop();
|
||||
}
|
||||
|
||||
void APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {
|
||||
|
||||
720
GL/lighting.c
@ -2,117 +2,62 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <dc/vec3f.h>
|
||||
#include "private.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define _MIN(x, y) (x < y) ? x : y
|
||||
|
||||
/* Lighting will not be calculated if the attenuation
|
||||
* multiplier ends up less than this value */
|
||||
#define ATTENUATION_THRESHOLD 100.0f
|
||||
#define ATTENUATION_THRESHOLD 0.01f
|
||||
|
||||
static GLfloat SCENE_AMBIENT [] = {0.2f, 0.2f, 0.2f, 1.0f};
|
||||
static GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE;
|
||||
static GLenum COLOR_CONTROL = GL_SINGLE_COLOR;
|
||||
static GLboolean TWO_SIDED_LIGHTING = GL_FALSE;
|
||||
static GLenum COLOR_MATERIAL_MODE = GL_AMBIENT_AND_DIFFUSE;
|
||||
|
||||
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] = scene_ambient[0] * material->ambient[0] + material->emissive[0];
|
||||
material->baseColour[1] = scene_ambient[1] * material->ambient[1] + material->emissive[1];
|
||||
material->baseColour[2] = scene_ambient[2] * material->ambient[2] + material->emissive[2];
|
||||
material->baseColour[3] = scene_ambient[3] * material->ambient[3] + material->emissive[3];
|
||||
}
|
||||
}
|
||||
static LightSource LIGHTS[MAX_LIGHTS];
|
||||
static Material MATERIAL;
|
||||
|
||||
void _glInitLights() {
|
||||
Material* material = _glActiveMaterial();
|
||||
|
||||
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_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);
|
||||
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);
|
||||
|
||||
if(i > 0) {
|
||||
memcpy(light->diffuse, ZERO, sizeof(GLfloat) * 4);
|
||||
memcpy(light->specular, ZERO, sizeof(GLfloat) * 4);
|
||||
memcpy(LIGHTS[i].diffuse, ZERO, sizeof(GLfloat) * 4);
|
||||
memcpy(LIGHTS[i].specular, ZERO, sizeof(GLfloat) * 4);
|
||||
}
|
||||
|
||||
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].position[0] = LIGHTS[i].position[1] = LIGHTS[i].position[3] = 0.0f;
|
||||
LIGHTS[i].position[2] = 1.0f;
|
||||
|
||||
light->spot_direction[0] = light->spot_direction[1] = 0.0f;
|
||||
light->spot_direction[2] = -1.0f;
|
||||
LIGHTS[i].spot_direction[0] = LIGHTS[i].spot_direction[1] = 0.0f;
|
||||
LIGHTS[i].spot_direction[2] = -1.0f;
|
||||
|
||||
light->spot_exponent = 0.0f;
|
||||
light->spot_cutoff = 180.0f;
|
||||
LIGHTS[i].spot_exponent = 0.0f;
|
||||
LIGHTS[i].spot_cutoff = 180.0f;
|
||||
|
||||
light->constant_attenuation = 1.0f;
|
||||
light->linear_attenuation = 0.0f;
|
||||
light->quadratic_attenuation = 0.0f;
|
||||
LIGHTS[i].constant_attenuation = 1.0f;
|
||||
LIGHTS[i].linear_attenuation = 0.0f;
|
||||
LIGHTS[i].quadratic_attenuation = 0.0f;
|
||||
}
|
||||
|
||||
_glPrecalcLightingValues(~0);
|
||||
_glRecalcEnabledLights();
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glLightModelf(GLenum pname, const GLfloat param) {
|
||||
glLightModelfv(pname, ¶m);
|
||||
}
|
||||
@ -123,87 +68,71 @@ void APIENTRY glLightModeli(GLenum pname, const GLint param) {
|
||||
|
||||
void APIENTRY glLightModelfv(GLenum pname, const GLfloat *params) {
|
||||
switch(pname) {
|
||||
case GL_LIGHT_MODEL_AMBIENT: {
|
||||
if(memcmp(_glGetLightModelSceneAmbient(), params, sizeof(float) * 4) != 0) {
|
||||
_glSetLightModelSceneAmbient(params);
|
||||
_glPrecalcLightingValues(SCENE_AMBIENT_MASK);
|
||||
}
|
||||
} break;
|
||||
case GL_LIGHT_MODEL_AMBIENT:
|
||||
memcpy(SCENE_AMBIENT, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_LIGHT_MODEL_LOCAL_VIEWER:
|
||||
_glSetLightModelViewerInEyeCoordinates((*params) ? GL_TRUE : GL_FALSE);
|
||||
VIEWER_IN_EYE_COORDINATES = (*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:
|
||||
_glSetLightModelColorControl(*params);
|
||||
COLOR_CONTROL = *params;
|
||||
break;
|
||||
case GL_LIGHT_MODEL_LOCAL_VIEWER:
|
||||
_glSetLightModelViewerInEyeCoordinates((*params) ? GL_TRUE : GL_FALSE);
|
||||
VIEWER_IN_EYE_COORDINATES = (*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_GLDC_LIGHTS) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
if(idx >= MAX_LIGHTS) {
|
||||
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:
|
||||
rebuild = memcmp(l->ambient, params, sizeof(GLfloat) * 4) != 0;
|
||||
if(rebuild) {
|
||||
memcpy(l->ambient, params, sizeof(GLfloat) * 4);
|
||||
}
|
||||
memcpy(LIGHTS[idx].ambient, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_DIFFUSE:
|
||||
rebuild = memcmp(l->diffuse, params, sizeof(GLfloat) * 4) != 0;
|
||||
if(rebuild) {
|
||||
memcpy(l->diffuse, params, sizeof(GLfloat) * 4);
|
||||
}
|
||||
memcpy(LIGHTS[idx].diffuse, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
rebuild = memcmp(l->specular, params, sizeof(GLfloat) * 4) != 0;
|
||||
if(rebuild) {
|
||||
memcpy(l->specular, params, sizeof(GLfloat) * 4);
|
||||
}
|
||||
memcpy(LIGHTS[idx].specular, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_POSITION: {
|
||||
memcpy(l->position, params, sizeof(GLfloat) * 4);
|
||||
_glMatrixLoadModelView();
|
||||
memcpy(LIGHTS[idx].position, params, sizeof(GLfloat) * 4);
|
||||
|
||||
l->isDirectional = params[3] == 0.0f;
|
||||
|
||||
if(l->isDirectional) {
|
||||
if(params[3] == 0.0f) {
|
||||
//FIXME: Do we need to rotate directional lights?
|
||||
} else {
|
||||
_glMatrixLoadModelView();
|
||||
TransformVec3(l->position);
|
||||
mat_trans_single4(
|
||||
LIGHTS[idx].position[0],
|
||||
LIGHTS[idx].position[1],
|
||||
LIGHTS[idx].position[2],
|
||||
LIGHTS[idx].position[3]
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GL_SPOT_DIRECTION: {
|
||||
l->spot_direction[0] = params[0];
|
||||
l->spot_direction[1] = params[1];
|
||||
l->spot_direction[2] = params[2];
|
||||
LIGHTS[idx].spot_direction[0] = params[0];
|
||||
LIGHTS[idx].spot_direction[1] = params[1];
|
||||
LIGHTS[idx].spot_direction[2] = params[2];
|
||||
} break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
@ -214,52 +143,47 @@ void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
return;
|
||||
_glKosPrintError();
|
||||
}
|
||||
|
||||
if(rebuild) {
|
||||
_glPrecalcLightingValues(mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void APIENTRY glLightf(GLenum light, GLenum pname, GLfloat param) {
|
||||
GLubyte idx = light & 0xF;
|
||||
|
||||
if(idx >= MAX_GLDC_LIGHTS) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
if(idx >= MAX_LIGHTS) {
|
||||
return;
|
||||
}
|
||||
|
||||
LightSource* l = _glLightAt(idx);
|
||||
switch(pname) {
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
l->constant_attenuation = param;
|
||||
LIGHTS[idx].constant_attenuation = param;
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
l->linear_attenuation = param;
|
||||
LIGHTS[idx].linear_attenuation = param;
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
l->quadratic_attenuation = param;
|
||||
LIGHTS[idx].quadratic_attenuation = param;
|
||||
break;
|
||||
case GL_SPOT_EXPONENT:
|
||||
l->spot_exponent = param;
|
||||
LIGHTS[idx].spot_exponent = param;
|
||||
break;
|
||||
case GL_SPOT_CUTOFF:
|
||||
l->spot_cutoff = param;
|
||||
LIGHTS[idx].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;
|
||||
}
|
||||
|
||||
_glActiveMaterial()->exponent = _MIN(param, 128); /* 128 is the max according to the GL spec */
|
||||
MATERIAL.exponent = _MIN(param, 128); /* 128 is the max according to the GL spec */
|
||||
}
|
||||
|
||||
void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param) {
|
||||
@ -267,76 +191,46 @@ void APIENTRY glMateriali(GLenum face, GLenum pname, const GLint param) {
|
||||
}
|
||||
|
||||
void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
|
||||
if(face == GL_BACK) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
if(pname == GL_SHININESS) {
|
||||
glMaterialf(face, pname, *params);
|
||||
return;
|
||||
}
|
||||
|
||||
Material* material = _glActiveMaterial();
|
||||
|
||||
GLboolean rebuild = GL_FALSE;
|
||||
if(face == GL_BACK) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
switch(pname) {
|
||||
case GL_SHININESS:
|
||||
glMaterialf(face, pname, *params);
|
||||
rebuild = GL_TRUE;
|
||||
case GL_AMBIENT:
|
||||
memcpy(MATERIAL.ambient, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_AMBIENT: {
|
||||
if(memcmp(material->ambient, params, sizeof(float) * 4) != 0) {
|
||||
vec4cpy(material->ambient, params);
|
||||
rebuild = GL_TRUE;
|
||||
}
|
||||
} break;
|
||||
case GL_DIFFUSE:
|
||||
if(memcmp(material->diffuse, params, sizeof(float) * 4) != 0) {
|
||||
vec4cpy(material->diffuse, params);
|
||||
rebuild = GL_TRUE;
|
||||
}
|
||||
memcpy(MATERIAL.diffuse, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_SPECULAR:
|
||||
if(memcmp(material->specular, params, sizeof(float) * 4) != 0) {
|
||||
vec4cpy(material->specular, params);
|
||||
rebuild = GL_TRUE;
|
||||
}
|
||||
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_EMISSION:
|
||||
if(memcmp(material->emissive, params, sizeof(float) * 4) != 0) {
|
||||
vec4cpy(material->emissive, params);
|
||||
rebuild = GL_TRUE;
|
||||
}
|
||||
memcpy(MATERIAL.emissive, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_AMBIENT_AND_DIFFUSE: {
|
||||
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);
|
||||
}
|
||||
glMaterialfv(face, GL_AMBIENT, params);
|
||||
glMaterialfv(face, GL_DIFFUSE, params);
|
||||
} break;
|
||||
case GL_COLOR_INDEXES:
|
||||
default: {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
return;
|
||||
_glKosPrintError();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glColorMaterial(GLenum face, GLenum mode) {
|
||||
if(face != GL_FRONT_AND_BACK) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -346,17 +240,160 @@ void APIENTRY glColorMaterial(GLenum face, GLenum mode) {
|
||||
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;
|
||||
COLOR_MATERIAL_MODE = mode;
|
||||
}
|
||||
|
||||
_glSetColorMaterialMask(mask);
|
||||
_glSetColorMaterialMode(mode);
|
||||
GL_FORCE_INLINE GLboolean isDiffuseColorMaterial() {
|
||||
return (COLOR_MATERIAL_MODE == GL_DIFFUSE || COLOR_MATERIAL_MODE == GL_AMBIENT_AND_DIFFUSE);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLboolean isAmbientColorMaterial() {
|
||||
return (COLOR_MATERIAL_MODE == GL_AMBIENT || COLOR_MATERIAL_MODE == GL_AMBIENT_AND_DIFFUSE);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLboolean isSpecularColorMaterial() {
|
||||
return (COLOR_MATERIAL_MODE == GL_SPECULAR);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void initVec3(struct vec3f* v, const GLfloat* src) {
|
||||
memcpy(v, src, sizeof(GLfloat) * 3);
|
||||
}
|
||||
|
||||
/* Fast POW Implementation - Less accurate, but much faster than math.h */
|
||||
#define EXP_A 184
|
||||
#define EXP_C 16249
|
||||
|
||||
GL_FORCE_INLINE 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;
|
||||
}
|
||||
|
||||
/* Inspired by: https://web.archive.org/web/20180423090243/www.dctsystems.co.uk/Software/power.html */
|
||||
#define SHIFT23 (1 << 23)
|
||||
#define INVSHIFT23 (1.0f / SHIFT23)
|
||||
#define LOGBODGE 0.346607f
|
||||
#define POWBODGE 0.33971f
|
||||
|
||||
const static float FINT_MAX = ((float) INT_MAX) + 1.0f;
|
||||
|
||||
GL_FORCE_INLINE float FFLOOR(float x) {
|
||||
return ((int)(x + FINT_MAX) + INT_MIN);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float FLOG2(float i) {
|
||||
float y;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} x;
|
||||
|
||||
x.i = i;
|
||||
|
||||
x.f *= INVSHIFT23;
|
||||
x.f = x.f - 127;
|
||||
|
||||
y = x.f - FFLOOR(x.f);
|
||||
y = (y - y * y) * LOGBODGE;
|
||||
|
||||
return x.f + y;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float FPOW2(float i) {
|
||||
float y = i - FFLOOR(i);
|
||||
y = (y - y * y) * POWBODGE;
|
||||
|
||||
union {
|
||||
float f;
|
||||
float i;
|
||||
} x;
|
||||
|
||||
x.f = i + 127 - y;
|
||||
x.f *= SHIFT23;
|
||||
return x.i;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float FPOW(float a, float b) {
|
||||
return FPOW2(b * FLOG2(a));
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float vec3_dot_limited(
|
||||
const float* x1, const float* y1, const float* z1,
|
||||
const float* x2, const float* y2, const float* z2) {
|
||||
|
||||
float ret;
|
||||
vec3f_dot(*x1, *y1, *z1, *x2, *y2, *z2, ret);
|
||||
return (ret < 0) ? 0 : ret;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glLightVertexDirectional(
|
||||
uint8_t* final, int8_t lid,
|
||||
float LdotN, float NdotH,
|
||||
const float* ambient, const float* diffuse, const float* specular) {
|
||||
|
||||
float F;
|
||||
uint8_t FO;
|
||||
float FI = (LdotN != 0.0f);
|
||||
FI = (MATERIAL.exponent) ? FPOW(FI * NdotH, MATERIAL.exponent) : 1.0f;
|
||||
|
||||
#define _PROCESS_COMPONENT(T, X) \
|
||||
F = (ambient[X] * LIGHTS[lid].ambient[X]); \
|
||||
F += (LdotN * diffuse[X] * LIGHTS[lid].diffuse[X]); \
|
||||
F += FI * specular[X] * LIGHTS[lid].specular[X]; \
|
||||
FO = (uint8_t) (_MIN(F * 255.0f, 255.0f)); \
|
||||
final[T] += _MIN(FO, 255 - final[T]);
|
||||
|
||||
_PROCESS_COMPONENT(R8IDX, 0);
|
||||
_PROCESS_COMPONENT(G8IDX, 1);
|
||||
_PROCESS_COMPONENT(B8IDX, 2);
|
||||
|
||||
#undef _PROCESS_COMPONENT
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glLightVertexPoint(
|
||||
uint8_t* final, int8_t lid,
|
||||
float LdotN, float NdotH, float att,
|
||||
const float* ambient, const float* diffuse, const float* specular) {
|
||||
|
||||
float F;
|
||||
uint8_t FO;
|
||||
float FI = (LdotN != 0.0f);
|
||||
FI = (MATERIAL.exponent) ? FPOW(FI * NdotH, MATERIAL.exponent) : 1.0f;
|
||||
|
||||
#define _PROCESS_COMPONENT(T, X) \
|
||||
F = (ambient[X] * LIGHTS[lid].ambient[X]); \
|
||||
F += (LdotN * diffuse[X] * LIGHTS[lid].diffuse[X]); \
|
||||
F += FI * specular[X] * LIGHTS[lid].specular[X]; \
|
||||
FO = (uint8_t) (_MIN(F * att * 255.0f, 255.0f)); \
|
||||
\
|
||||
final[T] += _MIN(FO, 255 - final[T]); \
|
||||
|
||||
_PROCESS_COMPONENT(R8IDX, 0);
|
||||
_PROCESS_COMPONENT(G8IDX, 1);
|
||||
_PROCESS_COMPONENT(B8IDX, 2);
|
||||
|
||||
#undef _PROCESS_COMPONENT
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float MATH_fsrra(float x) {
|
||||
__asm__ volatile ("fsrra %[one_div_sqrt]\n"
|
||||
: [one_div_sqrt] "+f" (x) // outputs, "+" means r/w
|
||||
: // no inputs
|
||||
: // no clobbers
|
||||
);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void bgra_to_float(const uint8_t* input, GLfloat* output) {
|
||||
static const float scale = 1.0f / 255.0f;
|
||||
const static float scale = 1.0f / 255.0f;
|
||||
|
||||
output[0] = ((float) input[R8IDX]) * scale;
|
||||
output[1] = ((float) input[G8IDX]) * scale;
|
||||
@ -364,277 +401,122 @@ GL_FORCE_INLINE void bgra_to_float(const uint8_t* input, GLfloat* output) {
|
||||
output[3] = ((float) input[A8IDX]) * scale;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 _glUpdateColourMaterialE(const GLubyte* argb) {
|
||||
Material* material = _glActiveMaterial();
|
||||
|
||||
float colour[4];
|
||||
bgra_to_float(argb, colour);
|
||||
vec4cpy(material->emissive, colour);
|
||||
|
||||
GLenum mask = _glColorMaterialMode();
|
||||
_glPrecalcLightingValues(mask);
|
||||
}
|
||||
|
||||
void _glUpdateColourMaterialAD(const GLubyte* argb) {
|
||||
Material* material = _glActiveMaterial();
|
||||
|
||||
float colour[4];
|
||||
bgra_to_float(argb, colour);
|
||||
vec4cpy(material->ambient, colour);
|
||||
vec4cpy(material->diffuse, colour);
|
||||
|
||||
GLenum mask = _glColorMaterialMode();
|
||||
_glPrecalcLightingValues(mask);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLboolean isDiffuseColorMaterial() {
|
||||
GLenum mode = _glColorMaterialMode();
|
||||
return (
|
||||
mode == GL_DIFFUSE ||
|
||||
mode == GL_AMBIENT_AND_DIFFUSE
|
||||
);
|
||||
}
|
||||
|
||||
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, VertexExtra* extra, const uint32_t count) {
|
||||
GLubyte i;
|
||||
GLuint j;
|
||||
|
||||
Material* material = _glActiveMaterial();
|
||||
void _glPerformLighting(Vertex* vertices, const EyeSpaceData* es, const int32_t count) {
|
||||
int8_t i;
|
||||
int32_t j;
|
||||
|
||||
Vertex* vertex = vertices;
|
||||
VertexExtra* data = extra;
|
||||
const EyeSpaceData* data = es;
|
||||
float base;
|
||||
|
||||
/* Calculate the colour material function once */
|
||||
void (*updateColourMaterial)(const GLubyte*) = NULL;
|
||||
/* This is the original vertex colour, before we replace it. It's
|
||||
* used for colour material */
|
||||
float vdiffuse[4];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
unsigned char isCM = _glIsColorMaterialEnabled();
|
||||
|
||||
if(!_glEnabledLightCount()) {
|
||||
return;
|
||||
}
|
||||
/* Update pointers as necessary depending on color material */
|
||||
GLfloat* ambient = (isCM && isAmbientColorMaterial()) ? vdiffuse : MATERIAL.ambient;
|
||||
GLfloat* diffuse = (isCM && isDiffuseColorMaterial()) ? vdiffuse : MATERIAL.diffuse;
|
||||
GLfloat* specular = (isCM && isSpecularColorMaterial()) ? vdiffuse : MATERIAL.specular;
|
||||
|
||||
for(j = 0; j < count; ++j, ++vertex, ++data) {
|
||||
/* Calculate the ambient lighting and set up colour material */
|
||||
if(updateColourMaterial) {
|
||||
updateColourMaterial(vertex->bgra);
|
||||
/* Unpack the colour for use in glColorMaterial */
|
||||
if(isCM) {
|
||||
bgra_to_float(vertex->bgra, vdiffuse);
|
||||
}
|
||||
|
||||
/* Copy the base colour across */
|
||||
float finalColour[4];
|
||||
vec4cpy(finalColour, material->baseColour);
|
||||
/* Initial, non-light related values */
|
||||
base = (SCENE_AMBIENT[0] * ambient[0]) + MATERIAL.emissive[0];
|
||||
vertex->bgra[R8IDX] = (uint8_t)(_MIN(base * 255.0f, 255.0f));
|
||||
|
||||
/* 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);
|
||||
base = (SCENE_AMBIENT[1] * ambient[1]) + MATERIAL.emissive[1];
|
||||
vertex->bgra[G8IDX] = (uint8_t)(_MIN(base * 255.0f, 255.0f));
|
||||
|
||||
const float Nx = data->nxyz[0];
|
||||
const float Ny = data->nxyz[1];
|
||||
const float Nz = data->nxyz[2];
|
||||
base = (SCENE_AMBIENT[2] * ambient[2]) + MATERIAL.emissive[2];
|
||||
vertex->bgra[B8IDX] = (uint8_t)(_MIN(base * 255.0f, 255.0f));
|
||||
vertex->bgra[A8IDX] = (uint8_t)(_MIN(MATERIAL.diffuse[3] * 255.0f, 255.0f));
|
||||
|
||||
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
|
||||
LightSource* light = _glLightAt(i);
|
||||
float Vx = -data->xyz[0];
|
||||
float Vy = -data->xyz[1];
|
||||
float Vz = -data->xyz[2];
|
||||
vec3f_normalize(Vx, Vy, Vz);
|
||||
|
||||
if(!light->isEnabled) {
|
||||
continue;
|
||||
}
|
||||
const float Nx = data->n[0];
|
||||
const float Ny = data->n[1];
|
||||
const float Nz = data->n[2];
|
||||
|
||||
float Lx = light->position[0] - vertex->xyz[0];
|
||||
float Ly = light->position[1] - vertex->xyz[1];
|
||||
float Lz = light->position[2] - vertex->xyz[2];
|
||||
for(i = 0; i < MAX_LIGHTS; ++i) {
|
||||
if(!_glIsLightEnabled(i)) continue;
|
||||
|
||||
if(light->isDirectional) {
|
||||
float Hx = (Lx + 0);
|
||||
float Hy = (Ly + 0);
|
||||
float Hz = (Lz + 1);
|
||||
if(LIGHTS[i].position[3] == 0.0f) {
|
||||
float Lx = -LIGHTS[i].position[0];
|
||||
float Ly = -LIGHTS[i].position[1];
|
||||
float Lz = -LIGHTS[i].position[2];
|
||||
float Hx = (Lx + Vx);
|
||||
float Hy = (Ly + Vy);
|
||||
float Hz = (Lz + Vz);
|
||||
|
||||
VEC3_NORMALIZE(Lx, Ly, Lz);
|
||||
VEC3_NORMALIZE(Hx, Hy, Hz);
|
||||
vec3f_normalize(Lx, Ly, Lz);
|
||||
vec3f_normalize(Hx, Hy, Hz);
|
||||
|
||||
float LdotN, NdotH;
|
||||
VEC3_DOT(
|
||||
Nx, Ny, Nz, Lx, Ly, Lz, LdotN
|
||||
const float LdotN = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Lx, &Ly, &Lz
|
||||
);
|
||||
|
||||
VEC3_DOT(
|
||||
Nx, Ny, Nz, Hx, Hy, Hz, NdotH
|
||||
const float NdotH = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Hx, &Hy, &Hz
|
||||
);
|
||||
|
||||
if(LdotN < 0.0f) LdotN = 0.0f;
|
||||
if(NdotH < 0.0f) NdotH = 0.0f;
|
||||
|
||||
_glLightVertexDirectional(
|
||||
finalColour,
|
||||
i, LdotN, NdotH
|
||||
vertex->bgra,
|
||||
i, LdotN, NdotH,
|
||||
ambient, diffuse, specular
|
||||
);
|
||||
} else {
|
||||
float Lx = LIGHTS[i].position[0] - data->xyz[0];
|
||||
float Ly = LIGHTS[i].position[1] - data->xyz[1];
|
||||
float Lz = LIGHTS[i].position[2] - data->xyz[2];
|
||||
float D;
|
||||
VEC3_LENGTH(Lx, Ly, Lz, D);
|
||||
|
||||
vec3f_length(Lx, Ly, Lz, D);
|
||||
|
||||
float att = (
|
||||
light->constant_attenuation + (
|
||||
light->linear_attenuation * D
|
||||
) + (light->quadratic_attenuation * D * D)
|
||||
LIGHTS[i].constant_attenuation + (
|
||||
LIGHTS[i].linear_attenuation * D
|
||||
) + (LIGHTS[i].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);
|
||||
att = MATH_fsrra(att * att);
|
||||
|
||||
if(att >= ATTENUATION_THRESHOLD) {
|
||||
float Hx = (Lx + Vx);
|
||||
float Hy = (Ly + Vy);
|
||||
float Hz = (Lz + Vz);
|
||||
|
||||
VEC3_NORMALIZE(Lx, Ly, Lz);
|
||||
VEC3_NORMALIZE(Hx, Hy, Hz);
|
||||
vec3f_normalize(Lx, Ly, Lz);
|
||||
vec3f_normalize(Hx, Hy, Hz);
|
||||
|
||||
float LdotN, NdotH;
|
||||
VEC3_DOT(
|
||||
Nx, Ny, Nz, Lx, Ly, Lz, LdotN
|
||||
const float LdotN = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Lx, &Ly, &Lz
|
||||
);
|
||||
|
||||
VEC3_DOT(
|
||||
Nx, Ny, Nz, Hx, Hy, Hz, NdotH
|
||||
const float NdotH = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Hx, &Hy, &Hz
|
||||
);
|
||||
|
||||
if(LdotN < 0.0f) LdotN = 0.0f;
|
||||
if(NdotH < 0.0f) NdotH = 0.0f;
|
||||
|
||||
_glLightVertexPoint(
|
||||
finalColour,
|
||||
i, LdotN, NdotH, att
|
||||
vertex->bgra,
|
||||
i, LdotN, NdotH, att,
|
||||
ambient, diffuse, specular
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vertex->bgra[R8IDX] = clamp(finalColour[0] * 255.0f, 0, 255);
|
||||
vertex->bgra[G8IDX] = clamp(finalColour[1] * 255.0f, 0, 255);
|
||||
vertex->bgra[B8IDX] = clamp(finalColour[2] * 255.0f, 0, 255);
|
||||
vertex->bgra[A8IDX] = clamp(finalColour[3] * 255.0f, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
563
GL/matrix.c
@ -1,28 +1,35 @@
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <dc/fmath.h>
|
||||
#include <dc/matrix.h>
|
||||
#include <dc/matrix3d.h>
|
||||
#include <dc/vec3f.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../containers/stack.h"
|
||||
|
||||
#define DEG2RAD (0.01745329251994329576923690768489f)
|
||||
#define DEG2RAD (0.01745329251994329576923690768489)
|
||||
|
||||
/* Viewport mapping */
|
||||
static GLfloat gl_viewport_scale[3], gl_viewport_offset[3];
|
||||
|
||||
/* Depth range */
|
||||
GLfloat DEPTH_RANGE_MULTIPLIER_L = (1 - 0) / 2;
|
||||
GLfloat DEPTH_RANGE_MULTIPLIER_H = (0 + 1) / 2;
|
||||
|
||||
static Stack __attribute__((aligned(32))) MATRIX_STACKS[4]; // modelview, projection, texture
|
||||
static Matrix4x4 __attribute__((aligned(32))) NORMAL_MATRIX;
|
||||
static Matrix4x4 __attribute__((aligned(32))) VIEWPORT_MATRIX;
|
||||
static Matrix4x4 __attribute__((aligned(32))) PROJECTION_MATRIX;
|
||||
/* Viewport size */
|
||||
static GLint gl_viewport_x1, gl_viewport_y1, gl_viewport_width, gl_viewport_height;
|
||||
|
||||
static Stack MATRIX_STACKS[3]; // modelview, projection, texture
|
||||
static Matrix4x4 NORMAL_MATRIX __attribute__((aligned(32)));
|
||||
static Matrix4x4 SCREENVIEW_MATRIX __attribute__((aligned(32)));
|
||||
|
||||
static GLenum MATRIX_MODE = GL_MODELVIEW;
|
||||
static Stack* MATRIX_CUR;
|
||||
static GLboolean NORMAL_DIRTY, PROJECTION_DIRTY;
|
||||
static GLubyte MATRIX_IDX = 0;
|
||||
|
||||
static const Matrix4x4 __attribute__((aligned(32))) IDENTITY = {
|
||||
static const Matrix4x4 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,
|
||||
@ -31,46 +38,48 @@ static const Matrix4x4 __attribute__((aligned(32))) IDENTITY = {
|
||||
|
||||
GLfloat NEAR_PLANE_DISTANCE = 0.0f;
|
||||
|
||||
Matrix4x4* _glGetModelViewMatrix() {
|
||||
return (Matrix4x4*) stack_top(&MATRIX_STACKS[0]);
|
||||
static void _glStoreNearPlane() {
|
||||
Matrix4x4* proj = (Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF));
|
||||
|
||||
GLfloat a = *(*proj + 10);
|
||||
GLfloat b = *(*proj + 14);
|
||||
|
||||
NEAR_PLANE_DISTANCE = -b / (1.0f - a);
|
||||
}
|
||||
|
||||
void APIENTRY glDepthRange(GLclampf n, GLclampf f);
|
||||
|
||||
static inline void upload_matrix(Matrix4x4* m) {
|
||||
mat_load((matrix_t*) m);
|
||||
}
|
||||
|
||||
static inline void multiply_matrix(Matrix4x4* m) {
|
||||
mat_apply((matrix_t*) m);
|
||||
}
|
||||
|
||||
static inline void download_matrix(Matrix4x4* m) {
|
||||
mat_store((matrix_t*) m);
|
||||
}
|
||||
|
||||
Matrix4x4* _glGetProjectionMatrix() {
|
||||
return (Matrix4x4*) stack_top(&MATRIX_STACKS[1]);
|
||||
}
|
||||
|
||||
Matrix4x4* _glGetTextureMatrix() {
|
||||
return (Matrix4x4*) stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF));
|
||||
}
|
||||
|
||||
Matrix4x4* _glGetColorMatrix() {
|
||||
return (Matrix4x4*) stack_top(MATRIX_STACKS + (GL_COLOR & 0xF));
|
||||
}
|
||||
|
||||
GLenum _glGetMatrixMode() {
|
||||
return MATRIX_MODE;
|
||||
}
|
||||
|
||||
GLboolean _glIsIdentity(const Matrix4x4* m) {
|
||||
return memcmp(m, IDENTITY, sizeof(Matrix4x4)) == 0;
|
||||
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);
|
||||
init_stack(&MATRIX_STACKS[3], sizeof(Matrix4x4), 32);
|
||||
|
||||
stack_push(&MATRIX_STACKS[0], IDENTITY);
|
||||
stack_push(&MATRIX_STACKS[1], IDENTITY);
|
||||
stack_push(&MATRIX_STACKS[2], IDENTITY);
|
||||
stack_push(&MATRIX_STACKS[3], IDENTITY);
|
||||
|
||||
MEMCPY4(NORMAL_MATRIX, IDENTITY, sizeof(Matrix4x4));
|
||||
|
||||
MATRIX_CUR = MATRIX_STACKS + (GL_MODELVIEW & 0xF);
|
||||
|
||||
const VideoMode* vid_mode = GetVideoMode();
|
||||
memcpy(NORMAL_MATRIX, IDENTITY, sizeof(Matrix4x4));
|
||||
memcpy(SCREENVIEW_MATRIX, IDENTITY, sizeof(Matrix4x4));
|
||||
|
||||
glDepthRange(0.0f, 1.0f);
|
||||
glViewport(0, 0, vid_mode->width, vid_mode->height);
|
||||
@ -113,113 +122,87 @@ static void transpose(GLfloat* m) {
|
||||
swap(m[11], m[14]);
|
||||
}
|
||||
|
||||
/* When projection matrix changes, need to pre-multiply with viewport transform matrix */
|
||||
static void UpdateProjectionMatrix() {
|
||||
PROJECTION_DIRTY = false;
|
||||
UploadMatrix4x4(&VIEWPORT_MATRIX);
|
||||
MultiplyMatrix4x4(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
|
||||
DownloadMatrix4x4(&PROJECTION_MATRIX);
|
||||
}
|
||||
|
||||
/* When modelview matrix changes, need to re-compute normal matrix */
|
||||
static void UpdateNormalMatrix() {
|
||||
NORMAL_DIRTY = false;
|
||||
MEMCPY4(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(Matrix4x4));
|
||||
static void recalculateNormalMatrix() {
|
||||
memcpy(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(Matrix4x4));
|
||||
inverse((GLfloat*) NORMAL_MATRIX);
|
||||
transpose((GLfloat*) NORMAL_MATRIX);
|
||||
}
|
||||
|
||||
static void OnMatrixChanged() {
|
||||
switch (MATRIX_MODE) {
|
||||
case GL_MODELVIEW:
|
||||
NORMAL_DIRTY = true;
|
||||
return;
|
||||
case GL_PROJECTION:
|
||||
PROJECTION_DIRTY = true;
|
||||
return;
|
||||
case GL_TEXTURE:
|
||||
_glTnlUpdateTextureMatrix();
|
||||
return;
|
||||
case GL_COLOR:
|
||||
_glTnlUpdateColorMatrix();
|
||||
return;
|
||||
void APIENTRY glMatrixMode(GLenum mode) {
|
||||
MATRIX_MODE = mode;
|
||||
MATRIX_IDX = mode & 0xF;
|
||||
}
|
||||
|
||||
void APIENTRY glPushMatrix() {
|
||||
stack_push(MATRIX_STACKS + MATRIX_IDX, stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
}
|
||||
|
||||
void APIENTRY glPopMatrix() {
|
||||
stack_pop(MATRIX_STACKS + MATRIX_IDX);
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glLoadIdentity() {
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, IDENTITY);
|
||||
}
|
||||
|
||||
void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
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] = x;
|
||||
trn[M13] = y;
|
||||
trn[M14] = z;
|
||||
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix(&trn);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glMatrixMode(GLenum mode) {
|
||||
MATRIX_MODE = mode;
|
||||
MATRIX_CUR = MATRIX_STACKS + (mode & 0xF);
|
||||
}
|
||||
|
||||
void APIENTRY glPushMatrix() {
|
||||
void* top = stack_top(MATRIX_CUR);
|
||||
assert(top);
|
||||
void* ret = stack_push(MATRIX_CUR, top);
|
||||
(void) ret;
|
||||
assert(ret);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void APIENTRY glPopMatrix() {
|
||||
stack_pop(MATRIX_CUR);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void APIENTRY glLoadIdentity() {
|
||||
stack_replace(MATRIX_CUR, IDENTITY);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void GL_FORCE_INLINE _glMultMatrix(const Matrix4x4* mat) {
|
||||
void* top = stack_top(MATRIX_CUR);
|
||||
|
||||
UploadMatrix4x4(top);
|
||||
MultiplyMatrix4x4(mat);
|
||||
DownloadMatrix4x4(top);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
const Matrix4x4 trn __attribute__((aligned(32))) = {
|
||||
void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
static Matrix4x4 scale __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
|
||||
};
|
||||
_glMultMatrix(&trn);
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
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
|
||||
};
|
||||
_glMultMatrix(&scale);
|
||||
|
||||
scale[M0] = x;
|
||||
scale[M5] = y;
|
||||
scale[M10] = z;
|
||||
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix(&scale);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
Matrix4x4 rotate __attribute__((aligned(32))) = {
|
||||
static 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
|
||||
};
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
float s, c;
|
||||
fsincos(angle, &s, &c);
|
||||
#else
|
||||
float r = DEG2RAD * angle;
|
||||
float c = cosf(r);
|
||||
float s = sinf(r);
|
||||
#endif
|
||||
|
||||
VEC3_NORMALIZE(x, y, z);
|
||||
|
||||
float c = cos(r);
|
||||
float s = sin(r);
|
||||
float invc = 1.0f - c;
|
||||
float xs = x * s;
|
||||
float zs = z * s;
|
||||
@ -228,6 +211,8 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
float xy = y * x;
|
||||
float yz = y * z;
|
||||
|
||||
vec3f_normalize(x, y, z);
|
||||
|
||||
rotate[M0] = (x * x) * invc + c;
|
||||
rotate[M1] = xy * invc + zs;
|
||||
rotate[M2] = xz * invc - ys;
|
||||
@ -240,48 +225,81 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
rotate[M9] = yz * invc - xs;
|
||||
rotate[M10] = (z * z) * invc + c;
|
||||
|
||||
_glMultMatrix(&rotate);
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix(&rotate);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an arbitrary matrix */
|
||||
void APIENTRY glLoadMatrixf(const GLfloat *m) {
|
||||
static Matrix4x4 __attribute__((aligned(32))) TEMP;
|
||||
static Matrix4x4 TEMP;
|
||||
|
||||
memcpy(TEMP, m, sizeof(float) * 16);
|
||||
stack_replace(MATRIX_CUR, TEMP);
|
||||
OnMatrixChanged();
|
||||
TEMP[M0] = m[0];
|
||||
TEMP[M1] = m[1];
|
||||
TEMP[M2] = m[2];
|
||||
TEMP[M3] = m[3];
|
||||
|
||||
TEMP[M4] = m[4];
|
||||
TEMP[M5] = m[5];
|
||||
TEMP[M6] = m[6];
|
||||
TEMP[M7] = m[7];
|
||||
|
||||
TEMP[M8] = m[8];
|
||||
TEMP[M9] = m[9];
|
||||
TEMP[M10] = m[10];
|
||||
TEMP[M11] = m[11];
|
||||
|
||||
TEMP[M12] = m[12];
|
||||
TEMP[M13] = m[13];
|
||||
TEMP[M14] = m[14];
|
||||
TEMP[M15] = m[15];
|
||||
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP);
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/* Ortho */
|
||||
void APIENTRY glOrtho(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar) {
|
||||
void APIENTRY glOrtho(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
|
||||
Matrix4x4 ortho __attribute__((aligned(32))) = {
|
||||
/* Ortho Matrix */
|
||||
static 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
|
||||
};
|
||||
|
||||
ortho[M0] = 2.0f / (right - left);
|
||||
ortho[M5] = 2.0f / (top - bottom);
|
||||
ortho[M10] = -2.0f / (zfar - znear);
|
||||
ortho[M12] = -(right + left) / (right - left);
|
||||
ortho[M13] = -(top + bottom) / (top - bottom);
|
||||
ortho[M14] = -(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);
|
||||
|
||||
_glMultMatrix(&ortho);
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix(&OrthoMatrix);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
}
|
||||
|
||||
|
||||
/* Set the GL frustum */
|
||||
void APIENTRY glFrustum(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar) {
|
||||
void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
|
||||
Matrix4x4 frustum __attribute__((aligned(32)));
|
||||
MEMSET(frustum, 0, sizeof(float) * 16);
|
||||
/* Frustum Matrix */
|
||||
static Matrix4x4 FrustumMatrix __attribute__((aligned(32)));
|
||||
|
||||
memset(FrustumMatrix, 0, sizeof(float) * 16);
|
||||
|
||||
const float near2 = 2.0f * znear;
|
||||
const float A = (right + left) / (right - left);
|
||||
@ -289,25 +307,60 @@ void APIENTRY glFrustum(GLdouble left, GLdouble right,
|
||||
const float C = -((zfar + znear) / (zfar - znear));
|
||||
const float D = -((2.0f * zfar * znear) / (zfar - znear));
|
||||
|
||||
frustum[M0] = near2 / (right - left);
|
||||
frustum[M5] = near2 / (top - bottom);
|
||||
FrustumMatrix[M0] = near2 / (right - left);
|
||||
FrustumMatrix[M5] = near2 / (top - bottom);
|
||||
|
||||
frustum[M8] = A;
|
||||
frustum[M9] = B;
|
||||
frustum[M10] = C;
|
||||
frustum[M11] = -1.0f;
|
||||
frustum[M14] = D;
|
||||
FrustumMatrix[M8] = A;
|
||||
FrustumMatrix[M9] = B;
|
||||
FrustumMatrix[M10] = C;
|
||||
FrustumMatrix[M11] = -1.0f;
|
||||
FrustumMatrix[M14] = D;
|
||||
|
||||
_glMultMatrix(&frustum);
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix(&FrustumMatrix);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_PROJECTION) {
|
||||
_glStoreNearPlane();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Multiply the current matrix by an arbitrary matrix */
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
Matrix4x4 tmp __attribute__((aligned(32)));
|
||||
MEMCPY4(tmp, m, sizeof(Matrix4x4));
|
||||
static Matrix4x4 TEMP;
|
||||
|
||||
_glMultMatrix(&tmp);
|
||||
TEMP[M0] = m[0];
|
||||
TEMP[M1] = m[1];
|
||||
TEMP[M2] = m[2];
|
||||
TEMP[M3] = m[3];
|
||||
|
||||
TEMP[M4] = m[4];
|
||||
TEMP[M5] = m[5];
|
||||
TEMP[M6] = m[6];
|
||||
TEMP[M7] = m[7];
|
||||
|
||||
TEMP[M8] = m[8];
|
||||
TEMP[M9] = m[9];
|
||||
TEMP[M10] = m[10];
|
||||
TEMP[M11] = m[11];
|
||||
|
||||
TEMP[M12] = m[12];
|
||||
TEMP[M13] = m[13];
|
||||
TEMP[M14] = m[14];
|
||||
TEMP[M15] = m[15];
|
||||
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix((Matrix4x4*) &TEMP);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
|
||||
if(MATRIX_MODE == GL_PROJECTION) {
|
||||
_glStoreNearPlane();
|
||||
}
|
||||
}
|
||||
|
||||
/* Load an arbitrary transposed matrix */
|
||||
@ -337,51 +390,82 @@ void glLoadTransposeMatrixf(const GLfloat *m) {
|
||||
TEMP[M14] = m[11];
|
||||
TEMP[M15] = m[15];
|
||||
|
||||
stack_replace(MATRIX_CUR, TEMP);
|
||||
OnMatrixChanged();
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP);
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
|
||||
if(MATRIX_MODE == GL_PROJECTION) {
|
||||
_glStoreNearPlane();
|
||||
}
|
||||
}
|
||||
|
||||
/* Multiply the current matrix by an arbitrary transposed matrix */
|
||||
void glMultTransposeMatrixf(const GLfloat *m) {
|
||||
static Matrix4x4 tmp __attribute__((aligned(32)));
|
||||
static Matrix4x4 TEMP __attribute__((aligned(32)));
|
||||
|
||||
tmp[M0] = m[0];
|
||||
tmp[M1] = m[4];
|
||||
tmp[M2] = m[8];
|
||||
tmp[M3] = m[12];
|
||||
TEMP[M0] = m[0];
|
||||
TEMP[M1] = m[4];
|
||||
TEMP[M2] = m[8];
|
||||
TEMP[M3] = m[12];
|
||||
|
||||
tmp[M4] = m[1];
|
||||
tmp[M5] = m[5];
|
||||
tmp[M6] = m[9];
|
||||
tmp[M7] = m[13];
|
||||
TEMP[M4] = m[1];
|
||||
TEMP[M5] = m[5];
|
||||
TEMP[M6] = m[9];
|
||||
TEMP[M7] = m[13];
|
||||
|
||||
tmp[M8] = m[3];
|
||||
tmp[M9] = m[6];
|
||||
tmp[M10] = m[10];
|
||||
tmp[M11] = m[14];
|
||||
TEMP[M8] = m[3];
|
||||
TEMP[M9] = m[6];
|
||||
TEMP[M10] = m[10];
|
||||
TEMP[M11] = m[14];
|
||||
|
||||
tmp[M12] = m[4];
|
||||
tmp[M13] = m[7];
|
||||
tmp[M14] = m[11];
|
||||
tmp[M15] = m[15];
|
||||
TEMP[M12] = m[4];
|
||||
TEMP[M13] = m[7];
|
||||
TEMP[M14] = m[11];
|
||||
TEMP[M15] = m[15];
|
||||
|
||||
_glMultMatrix(&tmp);
|
||||
upload_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
multiply_matrix(&TEMP);
|
||||
download_matrix(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
|
||||
if(MATRIX_MODE == GL_PROJECTION) {
|
||||
_glStoreNearPlane();
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the GL viewport */
|
||||
void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
VIEWPORT_MATRIX[M0] = width * 0.5f;
|
||||
VIEWPORT_MATRIX[M5] = height * -0.5f;
|
||||
VIEWPORT_MATRIX[M10] = 1.0f;
|
||||
VIEWPORT_MATRIX[M15] = 1.0f;
|
||||
|
||||
VIEWPORT_MATRIX[M12] = x + width * 0.5f;
|
||||
VIEWPORT_MATRIX[M13] = GetVideoMode()->height - (y + height * 0.5f);
|
||||
PROJECTION_DIRTY = true;
|
||||
gl_viewport_x1 = x;
|
||||
gl_viewport_y1 = y;
|
||||
gl_viewport_width = width;
|
||||
gl_viewport_height = height;
|
||||
|
||||
GLfloat rw = x + width;
|
||||
GLfloat lw = x;
|
||||
GLfloat tw = y + height;
|
||||
GLfloat bw = y;
|
||||
|
||||
GLfloat hw = ((GLfloat) width) / 2.0f;
|
||||
GLfloat hh = ((GLfloat) height) / 2.0f;
|
||||
|
||||
SCREENVIEW_MATRIX[M0] = hw;
|
||||
SCREENVIEW_MATRIX[M5] = -hh;
|
||||
SCREENVIEW_MATRIX[M10] = 1;
|
||||
SCREENVIEW_MATRIX[M12] = (rw + lw) / 2.0f;
|
||||
SCREENVIEW_MATRIX[M13] = (tw + bw) / 2.0f;
|
||||
}
|
||||
|
||||
GLfloat _glGetNearPlane() {
|
||||
return NEAR_PLANE_DISTANCE;
|
||||
}
|
||||
|
||||
/* Set the depth range */
|
||||
void APIENTRY glDepthRangef(GLclampf n, GLclampf f) {
|
||||
void APIENTRY glDepthRange(GLclampf n, GLclampf f) {
|
||||
if(n < 0.0f) n = 0.0f;
|
||||
else if(n > 1.0f) n = 1.0f;
|
||||
|
||||
@ -392,56 +476,58 @@ void APIENTRY glDepthRangef(GLclampf n, GLclampf f) {
|
||||
DEPTH_RANGE_MULTIPLIER_H = (n + f) / 2.0f;
|
||||
}
|
||||
|
||||
void APIENTRY glDepthRange(GLdouble n, GLdouble f){
|
||||
glDepthRangef(n,f);
|
||||
}
|
||||
|
||||
/* Vector Cross Product - Used by gluLookAt */
|
||||
/* Vector Cross Product - Used by glhLookAtf2 */
|
||||
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];
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void vec3f_normalize_sh4(float *v){
|
||||
float lengthSq, ilength;
|
||||
/* glhLookAtf2 adapted from http://www.opengl.org/wiki/GluLookAt_code */
|
||||
void glhLookAtf2(const GLfloat* eyePosition3D,
|
||||
const GLfloat* center3D,
|
||||
const GLfloat* upVector3D) {
|
||||
|
||||
lengthSq = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
||||
ilength = MATH_fsrra(lengthSq);
|
||||
/* Look-At Matrix */
|
||||
static Matrix4x4 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
|
||||
};
|
||||
|
||||
if (lengthSq)
|
||||
{
|
||||
v[0] *= ilength;
|
||||
v[1] *= ilength;
|
||||
v[2] *= ilength;
|
||||
}
|
||||
}
|
||||
GLfloat forward[3];
|
||||
GLfloat side[3];
|
||||
GLfloat up[3];
|
||||
|
||||
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
|
||||
GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
|
||||
GLdouble upz) {
|
||||
GLfloat m [16] __attribute__((aligned(32)));
|
||||
GLfloat f [3];
|
||||
GLfloat u [3];
|
||||
GLfloat s [3];
|
||||
vec3f_sub_normalize(center3D[0], center3D[1], center3D[2],
|
||||
eyePosition3D[0], eyePosition3D[1], eyePosition3D[2],
|
||||
forward[0], forward[1], forward[2]);
|
||||
|
||||
f[0] = centerx - eyex;
|
||||
f[1] = centery - eyey;
|
||||
f[2] = centerz - eyez;
|
||||
//Side = forward x up
|
||||
vec3f_cross(forward, upVector3D, side);
|
||||
vec3f_normalize(side[0], side[1], side[2]);
|
||||
|
||||
u[0] = upx;
|
||||
u[1] = upy;
|
||||
u[2] = upz;
|
||||
//Recompute up as: up = side x forward
|
||||
vec3f_cross(side, forward, up);
|
||||
|
||||
vec3f_normalize_sh4(f);
|
||||
vec3f_cross(f, u, s);
|
||||
vec3f_normalize_sh4(s);
|
||||
vec3f_cross(s, f, u);
|
||||
MatrixLookAt[M0] = side[0];
|
||||
MatrixLookAt[M4] = side[1];
|
||||
MatrixLookAt[M8] = side[2];
|
||||
MatrixLookAt[M12] = 0;
|
||||
|
||||
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;
|
||||
MatrixLookAt[M1] = up[0];
|
||||
MatrixLookAt[M5] = up[1];
|
||||
MatrixLookAt[M9] = up[2];
|
||||
MatrixLookAt[M13] = 0;
|
||||
|
||||
MatrixLookAt[M2] = -forward[0];
|
||||
MatrixLookAt[M6] = -forward[1];
|
||||
MatrixLookAt[M10] = -forward[2];
|
||||
MatrixLookAt[M14] = 0;
|
||||
|
||||
MatrixLookAt[M3] = MatrixLookAt[11] = MatrixLookAt[15] = 0;
|
||||
MatrixLookAt[M15] = 1;
|
||||
|
||||
static Matrix4x4 trn __attribute__((aligned(32))) = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
@ -450,33 +536,40 @@ void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
trn[M12] = -eyex;
|
||||
trn[M13] = -eyey;
|
||||
trn[M14] = -eyez;
|
||||
trn[M12] = -eyePosition3D[0];
|
||||
trn[M13] = -eyePosition3D[1];
|
||||
trn[M14] = -eyePosition3D[2];
|
||||
|
||||
// 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)));
|
||||
upload_matrix(&MatrixLookAt);
|
||||
multiply_matrix(&trn);
|
||||
multiply_matrix(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
download_matrix(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void _glApplyRenderMatrix() {
|
||||
upload_matrix(&SCREENVIEW_MATRIX);
|
||||
multiply_matrix(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
|
||||
multiply_matrix(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
void _glMatrixLoadTexture() {
|
||||
upload_matrix(stack_top(MATRIX_STACKS + (GL_TEXTURE & 0xF)));
|
||||
}
|
||||
|
||||
void _glMatrixLoadModelView() {
|
||||
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
void _glMatrixLoadProjection() {
|
||||
if (PROJECTION_DIRTY) UpdateProjectionMatrix();
|
||||
UploadMatrix4x4(&PROJECTION_MATRIX);
|
||||
}
|
||||
|
||||
void _glMatrixLoadModelViewProjection() {
|
||||
if (PROJECTION_DIRTY) UpdateProjectionMatrix();
|
||||
UploadMatrix4x4(&PROJECTION_MATRIX);
|
||||
MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
upload_matrix(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
void _glMatrixLoadNormal() {
|
||||
if (NORMAL_DIRTY) UpdateNormalMatrix();
|
||||
UploadMatrix4x4((const Matrix4x4*) &NORMAL_MATRIX);
|
||||
upload_matrix(&NORMAL_MATRIX);
|
||||
}
|
||||
|
||||
452
GL/platform.h
@ -1,452 +0,0 @@
|
||||
#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 _arch_dreamcast
|
||||
#include "platforms/sh4.h"
|
||||
#else
|
||||
#include "platforms/software.h"
|
||||
#endif
|
||||
@ -1,392 +0,0 @@
|
||||
#include <float.h>
|
||||
|
||||
#include <dc/sq.h>
|
||||
|
||||
#include "../platform.h"
|
||||
#include "sh4.h"
|
||||
|
||||
|
||||
#define CLIP_DEBUG 0
|
||||
|
||||
#define PVR_VERTEX_BUF_SIZE 2560 * 256
|
||||
#define PVR_OPB_COUNT 2
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 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 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_OPB_COUNT /* Number of tile object pointer overflow bins. */
|
||||
};
|
||||
|
||||
pvr_init(¶ms);
|
||||
|
||||
#ifndef _arch_sub_naomi
|
||||
/* 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();
|
||||
|
||||
if(cable != CT_VGA) {
|
||||
int region = flashrom_get_region();
|
||||
if (region == FLASHROM_REGION_EUROPE) {
|
||||
printf("PAL region without VGA - enabling 50hz");
|
||||
vid_set_mode(DM_640x480_PAL_IL, PM_RGB565);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float _glFastInvert(float x) {
|
||||
return (1.0f / __builtin_sqrtf(x * x));
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, int count) {
|
||||
TRACE();
|
||||
|
||||
for(int v = 0; v < count; ++v) {
|
||||
const float f = _glFastInvert(vertex[v].w);
|
||||
|
||||
/* Convert to screenspace */
|
||||
/* (note that vertices have already been viewport transformed) */
|
||||
vertex[v].xyz[0] *= f;
|
||||
vertex[v].xyz[1] *= f;
|
||||
|
||||
/* 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[v].w == 1.0f) {
|
||||
vertex[v].xyz[2] = _glFastInvert(1.0001f + vertex[v].xyz[2]);
|
||||
} else {
|
||||
vertex[v].xyz[2] = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uintptr_t sq_dest_addr = 0;
|
||||
|
||||
static inline void _glPushHeaderOrVertex(Vertex* v, size_t count) {
|
||||
TRACE();
|
||||
|
||||
#if CLIP_DEBUG
|
||||
fprintf(stderr, "{%f, %f, %f, %f}, // %x (%x)\n", v->xyz[0], v->xyz[1], v->xyz[2], v->w, v->flags, v);
|
||||
#endif
|
||||
|
||||
sq_fast_cpy((void *)sq_dest_addr, v, count);
|
||||
}
|
||||
|
||||
static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, Vertex* vout) {
|
||||
const float d0 = v1->w + v1->xyz[2];
|
||||
const float d1 = v2->w + v2->xyz[2];
|
||||
const float t = (fabsf(d0) * (1.0f / sqrtf((d1 - d0) * (d1 - d0))));
|
||||
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->xyz[2] = (vout->xyz[2] < FLT_EPSILON) ? FLT_EPSILON : vout->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;
|
||||
|
||||
vout->bgra[0] = invt * v1->bgra[0] + t * v2->bgra[0];
|
||||
vout->bgra[1] = invt * v1->bgra[1] + t * v2->bgra[1];
|
||||
vout->bgra[2] = invt * v1->bgra[2] + t * v2->bgra[2];
|
||||
vout->bgra[3] = invt * v1->bgra[3] + t * v2->bgra[3];
|
||||
}
|
||||
|
||||
#define SPAN_SORT_CFG 0x005F8030
|
||||
static volatile uint32_t* PVR_LMMODE0 = (uint32_t*) 0xA05F6884;
|
||||
static volatile uint32_t *PVR_LMMODE1 = (uint32_t*) 0xA05F6888;
|
||||
|
||||
enum Visible {
|
||||
NONE_VISIBLE = 0,
|
||||
FIRST_VISIBLE = 1,
|
||||
SECOND_VISIBLE = 2,
|
||||
THIRD_VISIBLE = 4,
|
||||
FIRST_AND_SECOND_VISIBLE = FIRST_VISIBLE | SECOND_VISIBLE,
|
||||
SECOND_AND_THIRD_VISIBLE = SECOND_VISIBLE | THIRD_VISIBLE,
|
||||
FIRST_AND_THIRD_VISIBLE = FIRST_VISIBLE | THIRD_VISIBLE,
|
||||
ALL_VISIBLE = 7
|
||||
};
|
||||
|
||||
static inline bool is_header(Vertex* v) {
|
||||
return !(v->flags == GPU_CMD_VERTEX || v->flags == GPU_CMD_VERTEX_EOL);
|
||||
}
|
||||
|
||||
void SceneListSubmit(Vertex* vertices, int n) {
|
||||
TRACE();
|
||||
|
||||
/* You need at least a header, and 3 vertices to render anything */
|
||||
if(n < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
PVR_SET(SPAN_SORT_CFG, 0x0);
|
||||
|
||||
//Set PVR DMA registers
|
||||
*PVR_LMMODE0 = 0;
|
||||
*PVR_LMMODE1 = 0;
|
||||
|
||||
#if CLIP_DEBUG
|
||||
fprintf(stderr, "----\n");
|
||||
|
||||
Vertex* vertex = (Vertex*) vertices;
|
||||
for(int i = 0; i < n; ++i) {
|
||||
fprintf(stderr, "IN: {%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]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is a bit cumbersome - in some cases (particularly case 2)
|
||||
we finish the vertex submission with a duplicated final vertex so
|
||||
that the tri-strip can be continued. However, if the next triangle in the
|
||||
strip is not visible then the duplicated vertex would've been sent without
|
||||
the EOL flag. We won't know if we need the EOL flag or not when processing
|
||||
case 2. To workaround this we may queue a vertex temporarily here, in the normal
|
||||
case it will be submitted by the next iteration with the same flags it had, but
|
||||
in the invisible case it will be overridden to submit with EOL */
|
||||
static Vertex __attribute__((aligned(32))) qv;
|
||||
Vertex* queued_vertex = NULL;
|
||||
|
||||
#define QUEUE_VERTEX(v) \
|
||||
do { queued_vertex = &qv; *queued_vertex = *(v); } while(0)
|
||||
|
||||
#define SUBMIT_QUEUED_VERTEX(sflags) \
|
||||
do { if(queued_vertex) { queued_vertex->flags = (sflags); _glPushHeaderOrVertex(queued_vertex, 1); queued_vertex = NULL; } } while(0)
|
||||
|
||||
int visible_mask = 0;
|
||||
sq_dest_addr = (uintptr_t)SQ_MASK_DEST(PVR_TA_INPUT);
|
||||
|
||||
Vertex* v0 = vertices;
|
||||
for(int i = 0; i < n - 1; ++i, ++v0) {
|
||||
if(is_header(v0)) {
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
visible_mask = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
Vertex* v1 = v0 + 1;
|
||||
Vertex* v2 = (i < n - 2) ? v0 + 2 : NULL;
|
||||
|
||||
assert(!is_header(v1));
|
||||
|
||||
// We are trailing if we're on the penultimate vertex, or the next but one vertex is
|
||||
// an EOL, or v1 is an EOL (FIXME: possibly unnecessary and coverted by the other case?)
|
||||
bool is_trailing = (v1->flags == GPU_CMD_VERTEX_EOL) || ((v2) ? is_header(v2) : true);
|
||||
|
||||
if(is_trailing) {
|
||||
// OK so we've hit a new context header
|
||||
// we need to finalize this strip and move on
|
||||
|
||||
// If the last triangle was all visible, we need
|
||||
// to submit the last two vertices, any clipped triangles
|
||||
// would've
|
||||
if(visible_mask == ALL_VISIBLE) {
|
||||
SUBMIT_QUEUED_VERTEX(qv.flags);
|
||||
|
||||
_glPerspectiveDivideVertex(v0, 2);
|
||||
v1->flags = GPU_CMD_VERTEX_EOL;
|
||||
_glPushHeaderOrVertex(v0, 2);
|
||||
} else {
|
||||
// If the previous triangle wasn't all visible, and we
|
||||
// queued a vertex - we force it to be EOL and submit
|
||||
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||
}
|
||||
|
||||
i++;
|
||||
v0++;
|
||||
visible_mask = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
visible_mask = (
|
||||
(v0->xyz[2] >= -v0->w) << 0 |
|
||||
(v1->xyz[2] >= -v1->w) << 1 |
|
||||
(v2->xyz[2] >= -v2->w) << 2
|
||||
);
|
||||
|
||||
/* If we've gone behind the plane, we finish the strip
|
||||
otherwise we submit however it was */
|
||||
if(visible_mask == NONE_VISIBLE) {
|
||||
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||
} else {
|
||||
SUBMIT_QUEUED_VERTEX(qv.flags);
|
||||
}
|
||||
|
||||
#if CLIP_DEBUG
|
||||
fprintf(stderr, "0x%x 0x%x 0x%x -> %d\n", v0, v1, v2, visible_mask);
|
||||
#endif
|
||||
|
||||
Vertex __attribute__((aligned(32))) scratch[4];
|
||||
Vertex* a = &scratch[0], *b = &scratch[1], *c = &scratch[2], *d = &scratch[3];
|
||||
|
||||
switch(visible_mask) {
|
||||
case ALL_VISIBLE:
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
QUEUE_VERTEX(v0);
|
||||
break;
|
||||
case NONE_VISIBLE:
|
||||
break;
|
||||
break;
|
||||
case FIRST_VISIBLE:
|
||||
_glClipEdge(v0, v1, a);
|
||||
a->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(a, 2);
|
||||
_glPushHeaderOrVertex(a, 2);
|
||||
|
||||
QUEUE_VERTEX(b);
|
||||
break;
|
||||
case SECOND_VISIBLE:
|
||||
memcpy_vertex(c, v1);
|
||||
|
||||
_glClipEdge(v0, v1, a);
|
||||
a->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
_glPushHeaderOrVertex(a, 1);
|
||||
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
QUEUE_VERTEX(b);
|
||||
break;
|
||||
case THIRD_VISIBLE:
|
||||
memcpy_vertex(c, v2);
|
||||
|
||||
_glClipEdge(v1, v2, a);
|
||||
a->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
_glPushHeaderOrVertex(a, 2);
|
||||
|
||||
QUEUE_VERTEX(c);
|
||||
break;
|
||||
case FIRST_AND_SECOND_VISIBLE:
|
||||
memcpy_vertex(c, v1);
|
||||
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
|
||||
_glClipEdge(v1, v2, a);
|
||||
a->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPushHeaderOrVertex(b, 2);
|
||||
|
||||
QUEUE_VERTEX(a);
|
||||
break;
|
||||
case SECOND_AND_THIRD_VISIBLE:
|
||||
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, 4);
|
||||
_glPushHeaderOrVertex(a, 1);
|
||||
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPushHeaderOrVertex(b, 2);
|
||||
|
||||
QUEUE_VERTEX(d);
|
||||
break;
|
||||
case FIRST_AND_THIRD_VISIBLE:
|
||||
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, 1);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
_glPushHeaderOrVertex(a, 1);
|
||||
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPushHeaderOrVertex(b, 1);
|
||||
|
||||
QUEUE_VERTEX(c);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "ERROR\n");
|
||||
}
|
||||
}
|
||||
|
||||
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||
|
||||
sq_wait();
|
||||
}
|
||||
|
||||
void SceneBegin() {
|
||||
pvr_wait_ready();
|
||||
pvr_scene_begin();
|
||||
}
|
||||
|
||||
static pvr_dr_state_t dr_state;
|
||||
void SceneListBegin(GPUList list) {
|
||||
pvr_list_begin(list);
|
||||
/* Direct rendering auto acquires/releases store queue */
|
||||
pvr_dr_init(&dr_state);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
@ -1,207 +0,0 @@
|
||||
#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"
|
||||
|
||||
#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
|
||||
|
||||
|
||||
// ---- sh4_math.h - SH7091 Math Module ----
|
||||
//
|
||||
// This file is part of the DreamHAL project, a hardware abstraction library
|
||||
// primarily intended for use on the SH7091 found in hardware such as the SEGA
|
||||
// Dreamcast game console.
|
||||
//
|
||||
// This math module is hereby released into the public domain in the hope that it
|
||||
// may prove useful. Now go hit 60 fps! :)
|
||||
//
|
||||
// --Moopthehedgehog
|
||||
|
||||
// 1/sqrt(x)
|
||||
GL_FORCE_INLINE float MATH_fsrra(float x)
|
||||
{
|
||||
asm volatile ("fsrra %[one_div_sqrt]\n"
|
||||
: [one_div_sqrt] "+f" (x) // outputs, "+" means r/w
|
||||
: // no inputs
|
||||
: // no clobbers
|
||||
);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// 1/x = 1 / sqrt(x^2)
|
||||
GL_FORCE_INLINE float MATH_Fast_Invert(float x)
|
||||
{
|
||||
int neg = x < 0.0f;
|
||||
|
||||
x = MATH_fsrra(x * x);
|
||||
|
||||
if (neg) x = -x;
|
||||
return x;
|
||||
}
|
||||
// end of ---- sh4_math.h ----
|
||||
|
||||
#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) memset((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(float x, float y, float z, float w, float* oxyz, float* ow) {
|
||||
register float __x __asm__("fr4") = x;
|
||||
register float __y __asm__("fr5") = y;
|
||||
register float __z __asm__("fr6") = z;
|
||||
register float __w __asm__("fr7") = w;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"ftrv xmtrx,fv4\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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -1,635 +0,0 @@
|
||||
#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 f = 1.0f / (vertex->w);
|
||||
|
||||
/* Convert to screenspace */
|
||||
/* (note that vertices have already been viewport transformed) */
|
||||
vertex->xyz[0] = vertex->xyz[0] * f;
|
||||
vertex->xyz[1] = vertex->xyz[1] * f;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(v1);
|
||||
_glPushHeaderOrVertex(v1);
|
||||
|
||||
_glPerspectiveDivideVertex(v2);
|
||||
_glPushHeaderOrVertex(v2);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
/* All visible, push the first vertex and move on */
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glClipEdge(v1, v2, a);
|
||||
a->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
if(counter % 2 == 1) {
|
||||
_glPushHeaderOrVertex(a);
|
||||
}
|
||||
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_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);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(d);
|
||||
_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 TransformVertex(float x, float y, float z, float w, float* oxyz, float* ow) {
|
||||
float vec[4], ret[4];
|
||||
vec[0] = x;
|
||||
vec[1] = y;
|
||||
vec[2] = z;
|
||||
vec[3] = w;
|
||||
|
||||
TransformVec4NoMod(vec, ret);
|
||||
|
||||
oxyz[0] = ret[0];
|
||||
oxyz[1] = ret[1];
|
||||
oxyz[2] = ret[2];
|
||||
*ow = ret[3];
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <math.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
#define __restrict
|
||||
|
||||
#define PREFETCH(addr) do {} while(0)
|
||||
|
||||
#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 = sqrtf((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 TransformVertex(float x, float y, float z, 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);
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
#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));
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
#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);
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
#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);
|
||||
372
GL/private.h
@ -2,31 +2,20 @@
|
||||
#define PRIVATE_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 <dc/matrix.h>
|
||||
#include <dc/pvr.h>
|
||||
#include <dc/vec3f.h>
|
||||
#include <dc/fmath.h>
|
||||
#include <dc/matrix3d.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../containers/aligned_vector.h"
|
||||
#include "../containers/named_array.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)
|
||||
#define GL_FORCE_INLINE __attribute__((always_inline)) static __inline__
|
||||
|
||||
|
||||
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_NO_INLINE __attribute__((noinline))
|
||||
#define _GL_UNUSED(x) (void)(x)
|
||||
#define FASTCPY(dst, src, bytes) \
|
||||
(bytes % 32 == 0) ? sq_cpy(dst, src, bytes) : memcpy(dst, src, bytes);
|
||||
|
||||
#define _PACK4(v) ((v * 0xF) / 0xFF)
|
||||
#define PACK_ARGB4444(a,r,g,b) (_PACK4(a) << 12) | (_PACK4(r) << 8) | (_PACK4(g) << 4) | (_PACK4(b))
|
||||
@ -38,7 +27,7 @@ extern void* memcpy4 (void *dest, const void *src, size_t count);
|
||||
((((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__);} (void) 0
|
||||
#define TRACE() if(TRACE_ENABLED) {fprintf(stderr, "%s\n", __func__);}
|
||||
|
||||
#define VERTEX_ENABLED_FLAG (1 << 0)
|
||||
#define UV_ENABLED_FLAG (1 << 1)
|
||||
@ -48,6 +37,7 @@ extern void* memcpy4 (void *dest, const void *src, size_t count);
|
||||
|
||||
#define MAX_TEXTURE_SIZE 1024
|
||||
|
||||
typedef float Matrix4x4[16];
|
||||
|
||||
/* This gives us an easy way to switch
|
||||
* internal matrix order if necessary */
|
||||
@ -90,6 +80,9 @@ extern void* memcpy4 (void *dest, const void *src, size_t count);
|
||||
#define M15 15
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
pvr_poly_hdr_t hdr;
|
||||
} PVRHeader;
|
||||
|
||||
typedef struct {
|
||||
unsigned int flags; /* Constant PVR_CMD_USERCLIP */
|
||||
@ -116,45 +109,36 @@ typedef struct {
|
||||
} 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;
|
||||
//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;
|
||||
GLuint color; /* This is the PVR texture format */
|
||||
GLubyte env;
|
||||
GLushort mipmap; /* Bitmask of supplied mipmap levels */
|
||||
GLubyte mipmapCount; /* The number of mipmap levels */
|
||||
GLubyte uv_wrap; /* clamp and flip settings for u and v */
|
||||
//40
|
||||
GLubyte uv_clamp;
|
||||
GLuint index;
|
||||
GLvoid *data;
|
||||
GLuint dataStride;
|
||||
GLuint baseDataSize; /* The data size of mipmap level 0 */
|
||||
|
||||
GLenum minFilter;
|
||||
GLenum magFilter;
|
||||
|
||||
GLboolean isCompressed;
|
||||
GLboolean isPaletted;
|
||||
|
||||
/* 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;
|
||||
|
||||
TexturePalette* palette;
|
||||
|
||||
/* When using the shared palette, this is the bank (0-3) */
|
||||
GLushort shared_bank;
|
||||
} TextureObject;
|
||||
|
||||
typedef struct {
|
||||
GLfloat emissive[4];
|
||||
@ -164,10 +148,6 @@ typedef struct {
|
||||
|
||||
/* Valid values are 0-128 */
|
||||
GLfloat exponent;
|
||||
|
||||
/* Base ambient + emission colour for
|
||||
* the current material + light */
|
||||
GLfloat baseColour[4];
|
||||
} Material;
|
||||
|
||||
typedef struct {
|
||||
@ -181,91 +161,42 @@ 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;
|
||||
|
||||
|
||||
#define argbcpy(dst, src) \
|
||||
*((GLuint*) dst) = *((const GLuint*) src) \
|
||||
|
||||
|
||||
typedef struct {
|
||||
float xy[2];
|
||||
} _glvec2;
|
||||
|
||||
typedef struct {
|
||||
/* Same 32 byte layout as pvr_vertex_t */
|
||||
uint32_t flags;
|
||||
float xyz[3];
|
||||
} _glvec3;
|
||||
float uv[2];
|
||||
uint8_t bgra[4];
|
||||
|
||||
typedef struct {
|
||||
float xyzw[4];
|
||||
} _glvec4;
|
||||
/* 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;
|
||||
} Vertex;
|
||||
|
||||
#define vec2cpy(dst, src) \
|
||||
*((_glvec2*) dst) = *((_glvec2*) src)
|
||||
/* FIXME: SH4 has a swap.w instruction, we should leverage it here! */
|
||||
#define _SWAP32(x, y) \
|
||||
do { \
|
||||
uint32_t t = *((uint32_t*) &x); \
|
||||
*((uint32_t*) &x) = *((uint32_t*) &y); \
|
||||
*((uint32_t*) &y) = t; \
|
||||
} while(0)
|
||||
|
||||
#define vec3cpy(dst, src) \
|
||||
*((_glvec3*) dst) = *((_glvec3*) src)
|
||||
/*
|
||||
*((uint32_t*) &x) = *((uint32_t*) &x) ^ *((uint32_t*) &y); \
|
||||
*((uint32_t*) &y) = *((uint32_t*) &x) ^ *((uint32_t*) &y); \
|
||||
*((uint32_t*) &x) = *((uint32_t*) &x) ^ *((uint32_t*) &y); */
|
||||
|
||||
#define vec4cpy(dst, src) \
|
||||
*((_glvec4*) dst) = *((_glvec4*) src)
|
||||
|
||||
GL_FORCE_INLINE float clamp(float d, float min, float max) {
|
||||
return (d < min) ? min : (d > max) ? max : d;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void memcpy_vertex(Vertex *dest, const Vertex *src) {
|
||||
#ifdef _arch_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); \
|
||||
Vertex c = *a; \
|
||||
*a = *b; \
|
||||
*b = c; \
|
||||
} while(0)
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#define fast_rsqrt(x) frsqrt(x)
|
||||
#else
|
||||
#define fast_rsqrt(x) (1.0f / __builtin_sqrtf(x))
|
||||
#endif
|
||||
|
||||
/* 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 {
|
||||
@ -277,7 +208,7 @@ typedef struct {
|
||||
* 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))) {
|
||||
typedef struct {
|
||||
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
|
||||
@ -287,6 +218,7 @@ typedef struct __attribute__((aligned(32))) {
|
||||
AlignedVector* extras;
|
||||
} SubmissionTarget;
|
||||
|
||||
PVRHeader* _glSubmissionTargetHeader(SubmissionTarget* target);
|
||||
Vertex* _glSubmissionTargetStart(SubmissionTarget* target);
|
||||
Vertex* _glSubmissionTargetEnd(SubmissionTarget* target);
|
||||
|
||||
@ -306,8 +238,10 @@ typedef enum {
|
||||
|
||||
struct SubmissionTarget;
|
||||
|
||||
PolyList* _glOpaquePolyList();
|
||||
PolyList* _glPunchThruPolyList();
|
||||
void _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t);
|
||||
void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade);
|
||||
|
||||
PolyList *_glActivePolyList();
|
||||
PolyList *_glTransparentPolyList();
|
||||
|
||||
void _glInitAttributePointers();
|
||||
@ -316,80 +250,52 @@ void _glInitLights();
|
||||
void _glInitImmediateMode(GLuint initial_size);
|
||||
void _glInitMatrices();
|
||||
void _glInitFramebuffers();
|
||||
void _glInitSubmissionTarget();
|
||||
|
||||
void _glMatrixLoadNormal();
|
||||
void _glMatrixLoadModelView();
|
||||
void _glMatrixLoadProjection();
|
||||
void _glMatrixLoadModelViewProjection();
|
||||
void _glMatrixLoadTexture();
|
||||
void _glApplyRenderMatrix();
|
||||
|
||||
extern GLfloat DEPTH_RANGE_MULTIPLIER_L;
|
||||
extern GLfloat DEPTH_RANGE_MULTIPLIER_H;
|
||||
|
||||
extern GLfloat HALF_LINE_WIDTH;
|
||||
extern GLfloat HALF_POINT_SIZE;
|
||||
|
||||
Matrix4x4* _glGetProjectionMatrix();
|
||||
Matrix4x4* _glGetModelViewMatrix();
|
||||
Matrix4x4* _glGetTextureMatrix();
|
||||
Matrix4x4* _glGetColorMatrix();
|
||||
GLenum _glGetMatrixMode();
|
||||
GLboolean _glIsIdentity(const Matrix4x4* m);
|
||||
|
||||
void _glWipeTextureOnFramebuffers(GLuint texture);
|
||||
GLubyte _glCheckImmediateModeInactive(const char* func);
|
||||
|
||||
pvr_poly_cxt_t* _glGetPVRContext();
|
||||
GLubyte _glInitTextures();
|
||||
|
||||
void _glUpdatePVRTextureContext(PolyContext* context, GLshort textureUnit);
|
||||
void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit);
|
||||
void _glAllocateSpaceForMipmaps(TextureObject* active);
|
||||
|
||||
extern GLfloat NEAR_PLANE_DISTANCE;
|
||||
|
||||
GLfloat _glGetNearPlane();
|
||||
|
||||
typedef struct {
|
||||
const void* ptr; // 4
|
||||
GLenum type; // 4
|
||||
GLsizei stride; // 4
|
||||
GLint size; // 4
|
||||
const void* ptr;
|
||||
GLenum type;
|
||||
GLsizei stride;
|
||||
GLint size;
|
||||
} AttribPointer;
|
||||
typedef void (*ReadAttributeFunc)(const GLubyte*, GLubyte*);
|
||||
|
||||
typedef struct {
|
||||
AttribPointer vertex; // 16
|
||||
AttribPointer colour; // 32
|
||||
AttribPointer uv; // 48
|
||||
AttribPointer st; // 64
|
||||
AttribPointer normal; // 80
|
||||
|
||||
GLuint enabled; // list of currently enabled/used attributes
|
||||
GLuint dirty; // list of attributes that need state recalculating
|
||||
GLboolean fast_path;
|
||||
|
||||
ReadAttributeFunc vertex_func;
|
||||
ReadAttributeFunc colour_func;
|
||||
ReadAttributeFunc uv_func;
|
||||
ReadAttributeFunc st_func;
|
||||
ReadAttributeFunc normal_func;
|
||||
} AttribPointerList;
|
||||
|
||||
extern AttribPointerList ATTRIB_LIST;
|
||||
|
||||
GLboolean _glCheckValidEnum(GLint param, GLint* values, const char* func);
|
||||
|
||||
GLuint* _glGetEnabledAttributes();
|
||||
GL_NO_INLINE void _glUpdateAttributes();
|
||||
|
||||
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[];
|
||||
extern GLubyte ACTIVE_CLIENT_TEXTURE;
|
||||
|
||||
GLubyte _glGetActiveTexture();
|
||||
GLint _glGetTextureInternalFormat();
|
||||
GLboolean _glGetTextureTwiddle();
|
||||
void _glSetTextureTwiddle(GLboolean v);
|
||||
|
||||
GLuint _glGetActiveClientTexture();
|
||||
TexturePalette* _glGetSharedPalette(GLshort bank);
|
||||
void _glSetInternalPaletteFormat(GLenum val);
|
||||
@ -399,106 +305,50 @@ 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 _glGetGpuBlendSrcFactor();
|
||||
GLenum _glGetGpuBlendDstFactor();
|
||||
|
||||
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();
|
||||
GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level);
|
||||
GLuint _glGetMipmapLevelCount(TextureObject* obj);
|
||||
|
||||
void _glEnableLight(GLubyte light, GLboolean value);
|
||||
GLboolean _glIsLightingEnabled();
|
||||
GLboolean _glIsLightEnabled(GLubyte light);
|
||||
GLboolean _glIsColorMaterialEnabled();
|
||||
|
||||
GLboolean _glIsNormalizeEnabled();
|
||||
|
||||
extern GLboolean IMMEDIATE_MODE_ACTIVE;
|
||||
GLboolean _glRecalcFastPath();
|
||||
|
||||
GL_NO_INLINE void _glKosThrowError(GLenum error, const char *function);
|
||||
typedef struct {
|
||||
float xyz[3];
|
||||
float n[3];
|
||||
} EyeSpaceData;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
extern void _glPerformLighting(Vertex* vertices, VertexExtra* extra, const uint32_t count);
|
||||
extern void _glPerformLighting(Vertex* vertices, const EyeSpaceData* es, const int32_t count);
|
||||
|
||||
unsigned char _glIsClippingEnabled();
|
||||
void _glEnableClipping(unsigned char v);
|
||||
|
||||
GLuint _glFreeTextureMemory();
|
||||
GLuint _glUsedTextureMemory();
|
||||
GLuint _glFreeContiguousTextureMemory();
|
||||
void _glKosThrowError(GLenum error, const char *function);
|
||||
void _glKosPrintError();
|
||||
GLubyte _glKosHasError();
|
||||
|
||||
void _glApplyScissor(bool force);
|
||||
void _glSetColorMaterialMask(GLenum mask);
|
||||
void _glSetColorMaterialMode(GLenum mode);
|
||||
GLenum _glColorMaterialMode();
|
||||
#define PVR_VERTEX_BUF_SIZE 2560 * 256
|
||||
#define MAX_TEXTURE_UNITS 2
|
||||
#define MAX_LIGHTS 8
|
||||
|
||||
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();
|
||||
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
|
||||
|
||||
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
|
||||
|
||||
|
||||
void _glTnlLoadMatrix(void);
|
||||
void _glTnlApplyEffects(SubmissionTarget* target);
|
||||
|
||||
void _glTnlUpdateLighting(void);
|
||||
void _glTnlUpdateTextureMatrix(void);
|
||||
void _glTnlUpdateColorMatrix(void);
|
||||
|
||||
/* 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)) )
|
||||
#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" ); \
|
||||
}
|
||||
|
||||
#endif // PRIVATE_H
|
||||
|
||||
143
GL/profiler.c
Normal file
@ -0,0 +1,143 @@
|
||||
#include <kos.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "profiler.h"
|
||||
#include "../containers/aligned_vector.h"
|
||||
|
||||
#define MAX_PATH 256
|
||||
|
||||
typedef struct {
|
||||
char name[MAX_PATH];
|
||||
|
||||
uint64_t total_time_us;
|
||||
uint64_t total_calls;
|
||||
} ProfilerResult;
|
||||
|
||||
typedef struct {
|
||||
AlignedVector stack;
|
||||
AlignedVector results;
|
||||
uint64_t start_time_in_us;
|
||||
} RootProfiler;
|
||||
|
||||
|
||||
static RootProfiler* root = NULL;
|
||||
|
||||
static char PROFILER_ENABLED = 0;
|
||||
|
||||
void profiler_enable() {
|
||||
PROFILER_ENABLED = 1;
|
||||
}
|
||||
|
||||
void profiler_disable() {
|
||||
PROFILER_ENABLED = 0;
|
||||
}
|
||||
|
||||
static ProfilerResult* profiler_get_or_create_result(const char* name) {
|
||||
if(!PROFILER_ENABLED) return NULL;
|
||||
|
||||
uint16_t i = 0;
|
||||
for(; i < root->results.size; ++i) {
|
||||
ProfilerResult* result = aligned_vector_at(&root->results, i);
|
||||
if(strcmp(result->name, name) == 0) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ProfilerResult newResult;
|
||||
strcpy(newResult.name, name);
|
||||
newResult.total_calls = 0;
|
||||
newResult.total_time_us = 0;
|
||||
aligned_vector_push_back(&root->results, &newResult, 1);
|
||||
return aligned_vector_back(&root->results);
|
||||
}
|
||||
|
||||
static uint64_t current_time_in_us() {
|
||||
return timer_us_gettime64();
|
||||
}
|
||||
|
||||
static void profiler_generate_path(const char* suffix, char* path) {
|
||||
uint16_t i = 0;
|
||||
for(; i < root->stack.size; ++i) {
|
||||
Profiler* prof = aligned_vector_at(&root->stack, i);
|
||||
strcat(path, prof->name);
|
||||
|
||||
if(i != root->stack.size - 1) {
|
||||
strcat(path, ".");
|
||||
}
|
||||
}
|
||||
|
||||
if(strlen(suffix)) {
|
||||
strcat(path, ":");
|
||||
strcat(path, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Profiler* profiler_push(const char* name) {
|
||||
if(!PROFILER_ENABLED) return NULL;
|
||||
|
||||
if(!root) {
|
||||
root = (RootProfiler*) malloc(sizeof(RootProfiler));
|
||||
aligned_vector_init(
|
||||
&root->stack,
|
||||
sizeof(Profiler)
|
||||
);
|
||||
|
||||
aligned_vector_init(
|
||||
&root->results,
|
||||
sizeof(ProfilerResult)
|
||||
);
|
||||
|
||||
aligned_vector_reserve(&root->stack, 32);
|
||||
aligned_vector_reserve(&root->results, 64);
|
||||
}
|
||||
|
||||
Profiler profiler;
|
||||
strncpy(profiler.name, name, 64);
|
||||
profiler.start_time_in_us = current_time_in_us();
|
||||
|
||||
aligned_vector_push_back(&root->stack, &profiler, 1);
|
||||
return aligned_vector_back(&root->stack);
|
||||
}
|
||||
|
||||
void profiler_checkpoint(const char* name) {
|
||||
if(!PROFILER_ENABLED) return;
|
||||
|
||||
Profiler* prof = aligned_vector_back(&root->stack);
|
||||
|
||||
char path[MAX_PATH];
|
||||
path[0] = '\0';
|
||||
|
||||
profiler_generate_path(name, path);
|
||||
|
||||
uint64_t now = current_time_in_us();
|
||||
uint64_t diff = now - prof->start_time_in_us;
|
||||
prof->start_time_in_us = now;
|
||||
|
||||
ProfilerResult* result = profiler_get_or_create_result(path);
|
||||
result->total_calls++;
|
||||
result->total_time_us += diff;
|
||||
}
|
||||
|
||||
void profiler_pop() {
|
||||
if(!PROFILER_ENABLED) return;
|
||||
|
||||
aligned_vector_resize(&root->stack, root->stack.size - 1);
|
||||
}
|
||||
|
||||
void profiler_print_stats() {
|
||||
if(!PROFILER_ENABLED) return;
|
||||
|
||||
fprintf(stderr, "%-60s%-20s%-20s%-20s\n", "Path", "Average", "Total", "Calls");
|
||||
|
||||
uint16_t i = 0;
|
||||
for(; i < root->results.size; ++i) {
|
||||
ProfilerResult* result = aligned_vector_at(&root->results, i);
|
||||
float ms = ((float) result->total_time_us) / 1000.0f;
|
||||
float avg = ms / (float) result->total_calls;
|
||||
|
||||
fprintf(stderr, "%-60s%-20f%-20f%" PRIu64 "\n", result->name, (double)avg, (double)ms, result->total_calls);
|
||||
}
|
||||
}
|
||||
18
GL/profiler.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
char name[64];
|
||||
uint64_t start_time_in_us;
|
||||
} Profiler;
|
||||
|
||||
|
||||
Profiler* profiler_push(const char* name);
|
||||
void profiler_checkpoint(const char* name);
|
||||
void profiler_pop();
|
||||
|
||||
void profiler_print_stats();
|
||||
|
||||
void profiler_enable();
|
||||
void profiler_disable();
|
||||
929
GL/state.c
2166
GL/texture.c
139
GL/tnl_effects.c
@ -1,139 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "platform.h"
|
||||
|
||||
static int TNL_EFFECTS, TNL_LIGHTING, TNL_TEXTURE, TNL_COLOR;
|
||||
|
||||
#define ITERATE(count) \
|
||||
GLuint i = count; \
|
||||
while(i--)
|
||||
|
||||
void _glTnlLoadMatrix(void) {
|
||||
/* If we're lighting, then we need to do some work in
|
||||
* eye-space, so we only transform vertices by the modelview
|
||||
* matrix, and then later multiply by projection.
|
||||
*
|
||||
* If we're not doing lighting though we can optimise by taking
|
||||
* vertices straight to clip-space */
|
||||
|
||||
if(TNL_LIGHTING) {
|
||||
_glMatrixLoadModelView();
|
||||
} else {
|
||||
_glMatrixLoadModelViewProjection();
|
||||
}
|
||||
}
|
||||
|
||||
static void updateEffects(void) {
|
||||
TNL_EFFECTS = TNL_LIGHTING | TNL_TEXTURE | TNL_COLOR;
|
||||
}
|
||||
|
||||
static void transformVertices(SubmissionTarget* target) {
|
||||
TRACE();
|
||||
|
||||
/* Perform modelview transform, storing W */
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
uint32_t count = target->count;
|
||||
|
||||
ITERATE(count) {
|
||||
TransformVertex(it->xyz[0], it->xyz[1], it->xyz[2], it->w,
|
||||
it->xyz, &it->w);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void mat_transform_normal3(VertexExtra* extra, const uint32_t count) {
|
||||
ITERATE(count) {
|
||||
TransformNormalNoMod(extra->nxyz, extra->nxyz);
|
||||
extra++;
|
||||
}
|
||||
}
|
||||
|
||||
static void lightingEffect(SubmissionTarget* target) {
|
||||
/* Perform lighting calculations and manipulate the colour */
|
||||
Vertex* vertex = _glSubmissionTargetStart(target);
|
||||
VertexExtra* extra = aligned_vector_at(target->extras, 0);
|
||||
|
||||
_glMatrixLoadNormal();
|
||||
mat_transform_normal3(extra, target->count);
|
||||
|
||||
_glPerformLighting(vertex, extra, target->count);
|
||||
}
|
||||
|
||||
void _glTnlUpdateLighting(void) {
|
||||
TNL_LIGHTING = _glIsLightingEnabled();
|
||||
updateEffects();
|
||||
}
|
||||
|
||||
|
||||
static void textureEffect(SubmissionTarget* target) {
|
||||
Matrix4x4* m = _glGetTextureMatrix();
|
||||
UploadMatrix4x4(m);
|
||||
float coords[4];
|
||||
float* ptr = (float*)m;
|
||||
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
uint32_t count = target->count;
|
||||
|
||||
ITERATE(count) {
|
||||
TransformVertex(it->uv[0], it->uv[1], 0.0f, 1.0f, coords, &coords[3]);
|
||||
it->uv[0] = coords[0];
|
||||
it->uv[1] = coords[1];
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void _glTnlUpdateTextureMatrix(void) {
|
||||
Matrix4x4* m = _glGetTextureMatrix();
|
||||
TNL_TEXTURE = !_glIsIdentity(m);
|
||||
updateEffects();
|
||||
}
|
||||
|
||||
|
||||
static void colorEffect(SubmissionTarget* target) {
|
||||
Matrix4x4* m = _glGetColorMatrix();
|
||||
UploadMatrix4x4(m);
|
||||
float coords[4];
|
||||
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
uint32_t count = target->count;
|
||||
|
||||
ITERATE(count) {
|
||||
TransformVertex(it->bgra[2], it->bgra[1], it->bgra[0], it->bgra[3], coords, &coords[3]);
|
||||
it->bgra[2] = clamp(coords[0], 0, 255);
|
||||
it->bgra[1] = clamp(coords[1], 0, 255);
|
||||
it->bgra[0] = clamp(coords[2], 0, 255);
|
||||
it->bgra[3] = clamp(coords[3], 0, 255);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
|
||||
void _glTnlUpdateColorMatrix(void) {
|
||||
Matrix4x4* m = _glGetColorMatrix();
|
||||
TNL_COLOR = !_glIsIdentity(m);
|
||||
updateEffects();
|
||||
}
|
||||
|
||||
|
||||
void _glTnlApplyEffects(SubmissionTarget* target) {
|
||||
if (!TNL_EFFECTS) return;
|
||||
|
||||
if (TNL_LIGHTING)
|
||||
lightingEffect(target);
|
||||
if (TNL_TEXTURE)
|
||||
textureEffect(target);
|
||||
if (TNL_COLOR)
|
||||
colorEffect(target);
|
||||
|
||||
if (TNL_LIGHTING) {
|
||||
/* OK eye-space work done, now move into clip space */
|
||||
_glMatrixLoadProjection();
|
||||
transformVertices(target);
|
||||
}
|
||||
}
|
||||
16
GL/types.h
@ -1,16 +0,0 @@
|
||||
#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;
|
||||
@ -1,4 +1,4 @@
|
||||
#include "private.h"
|
||||
#include "../include/glkos.h"
|
||||
|
||||
void APIENTRY glVertexPackColor3fKOS(GLVertexKOS* vertex, float r, float g, float b) {
|
||||
vertex->bgra[3] = 255;
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
|
||||
const char* GLDC_VERSION = "@GLDC_VERSION@";
|
||||
2
GL/version.h
Normal file
@ -0,0 +1,2 @@
|
||||
#pragma once
|
||||
#define GLDC_VERSION "1.1-master"
|
||||
36
Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
# KallistiOS ##version##
|
||||
#
|
||||
# kos-ports/libgl Makefile
|
||||
# Copyright (C) 2013, 2014 Josh Pearson
|
||||
# Copyright (C) 2014 Lawrence Sebald
|
||||
# Copyright (C) 2020 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 GL/version.h
|
||||
OBJS += GL/matrix.o GL/fog.o GL/error.o GL/clip.o containers/stack.o containers/named_array.o containers/aligned_vector.o GL/profiler.o
|
||||
|
||||
SUBDIRS =
|
||||
|
||||
KOS_CFLAGS += -ffast-math -Ofast -Iinclude
|
||||
|
||||
GL/version.h:
|
||||
rm -f $@
|
||||
@echo -e '#pragma once\n#define GLDC_VERSION "$(shell git describe --abbrev=4 --dirty --always --tags)"\n' > $@
|
||||
|
||||
link:
|
||||
$(KOS_AR) rcs $(TARGET) $(OBJS)
|
||||
|
||||
build: GL/version.h $(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
|
||||
33
README.md
@ -24,39 +24,6 @@ Things I'd like to do:
|
||||
- Define an extension for modifier volumes
|
||||
- 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!
|
||||
|
||||
|
||||
@ -4,77 +4,138 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include "../GL/private.h"
|
||||
#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) {
|
||||
return malloc(size);
|
||||
}
|
||||
#else
|
||||
#define FASTCPY memcpy
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#include "aligned_vector.h"
|
||||
|
||||
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_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;
|
||||
void aligned_vector_init(AlignedVector* vector, unsigned int element_size) {
|
||||
vector->size = vector->capacity = 0;
|
||||
vector->element_size = element_size;
|
||||
vector->data = NULL;
|
||||
|
||||
/* 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;
|
||||
/* Reserve some initial capacity */
|
||||
aligned_vector_reserve(vector, ALIGNED_VECTOR_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
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);
|
||||
static inline unsigned int round_to_chunk_size(unsigned int val) {
|
||||
const unsigned int n = val;
|
||||
const unsigned int m = ALIGNED_VECTOR_CHUNK_SIZE;
|
||||
|
||||
return ((n + m - 1) / m) * m;
|
||||
}
|
||||
|
||||
|
||||
void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count) {
|
||||
if(element_count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t original_byte_size = (hdr->size * hdr->element_size);
|
||||
if(element_count <= vector->capacity) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int original_byte_size = vector->size * vector->element_size;
|
||||
|
||||
/* We overallocate so that we don't make small allocations during push backs */
|
||||
element_count = ROUND_TO_CHUNK_SIZE(element_count);
|
||||
element_count = round_to_chunk_size(element_count);
|
||||
|
||||
uint32_t new_byte_size = (element_count * hdr->element_size);
|
||||
uint8_t* original_data = vector->data;
|
||||
unsigned int new_byte_size = element_count * vector->element_size;
|
||||
unsigned char* original_data = vector->data;
|
||||
|
||||
vector->data = (uint8_t*) memalign(0x20, new_byte_size);
|
||||
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
|
||||
assert(vector->data);
|
||||
|
||||
AV_MEMCPY4(vector->data, original_data, original_byte_size);
|
||||
free(original_data);
|
||||
if(original_data) {
|
||||
memcpy(vector->data, original_data, original_byte_size);
|
||||
free(original_data);
|
||||
}
|
||||
|
||||
hdr->capacity = element_count;
|
||||
return vector->data + original_byte_size;
|
||||
vector->capacity = element_count;
|
||||
}
|
||||
|
||||
void* aligned_vector_push_back(AlignedVector* vector, const void* objs, unsigned int count) {
|
||||
/* Resize enough room */
|
||||
assert(count);
|
||||
assert(vector->element_size);
|
||||
|
||||
unsigned int initial_size = vector->size;
|
||||
aligned_vector_resize(vector, vector->size + count);
|
||||
|
||||
assert(vector->size == initial_size + count);
|
||||
|
||||
unsigned char* dest = vector->data + (vector->element_size * initial_size);
|
||||
|
||||
/* Copy the objects in */
|
||||
memcpy(dest, objs, vector->element_size * count);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
void* aligned_vector_resize(AlignedVector* vector, const unsigned int element_count) {
|
||||
unsigned int previousCount = vector->size;
|
||||
|
||||
/* Don't change memory when resizing downwards, just change the size */
|
||||
if(element_count <= vector->size) {
|
||||
vector->size = element_count;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(vector->capacity < element_count) {
|
||||
aligned_vector_reserve(vector, element_count);
|
||||
}
|
||||
|
||||
vector->size = element_count;
|
||||
|
||||
if(previousCount < vector->size) {
|
||||
return aligned_vector_at(vector, previousCount);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void* aligned_vector_at(const AlignedVector* vector, const unsigned int index) {
|
||||
assert(index < vector->size);
|
||||
return &vector->data[index * vector->element_size];
|
||||
}
|
||||
|
||||
void* aligned_vector_back(AlignedVector* vector) {
|
||||
return aligned_vector_at(vector, vector->size - 1);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void aligned_vector_shrink_to_fit(AlignedVector* vector) {
|
||||
AlignedVectorHeader* const hdr = &vector->hdr;
|
||||
if(hdr->size == 0) {
|
||||
uint32_t element_size = hdr->element_size;
|
||||
if(vector->size == 0) {
|
||||
free(vector->data);
|
||||
|
||||
/* Reallocate the header */
|
||||
vector->data = NULL;
|
||||
hdr->size = hdr->capacity = 0;
|
||||
hdr->element_size = element_size;
|
||||
vector->capacity = 0;
|
||||
} else {
|
||||
uint32_t new_byte_size = (hdr->size * hdr->element_size);
|
||||
uint8_t* original_data = vector->data;
|
||||
unsigned int new_byte_size = vector->size * vector->element_size;
|
||||
unsigned char* original_data = vector->data;
|
||||
vector->data = (unsigned char*) memalign(0x20, new_byte_size);
|
||||
|
||||
if(original_data) {
|
||||
FASTCPY(vector->data, original_data, new_byte_size);
|
||||
memcpy(vector->data, original_data, new_byte_size);
|
||||
free(original_data);
|
||||
}
|
||||
hdr->capacity = hdr->size;
|
||||
|
||||
vector->capacity = vector->size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,201 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#ifndef ALIGNED_VECTOR_H
|
||||
#define ALIGNED_VECTOR_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
|
||||
#define AV_NO_INLINE __attribute__((noinline))
|
||||
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
|
||||
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 {
|
||||
uint32_t size;
|
||||
uint32_t capacity;
|
||||
uint32_t element_size;
|
||||
} __attribute__((aligned(32))) AlignedVectorHeader;
|
||||
|
||||
typedef struct {
|
||||
AlignedVectorHeader hdr;
|
||||
uint8_t* data;
|
||||
unsigned int size;
|
||||
unsigned int capacity;
|
||||
unsigned char* data;
|
||||
unsigned int element_size;
|
||||
} AlignedVector;
|
||||
|
||||
#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);
|
||||
|
||||
/* Resizes the backing array if necessary so that element_count elements can fit in the array */
|
||||
/* (note that only capacity is potentially changed, size is never changed) */
|
||||
AV_NO_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t element_count);
|
||||
|
||||
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 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(const 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);
|
||||
}
|
||||
void* aligned_vector_back(AlignedVector* vector);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ALIGNED_VECTOR_H
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
@ -17,7 +16,8 @@ void named_array_init(NamedArray* array, unsigned int element_size, unsigned int
|
||||
array->element_size = element_size;
|
||||
array->max_element_count = max_elements;
|
||||
|
||||
array->marker_count = (unsigned char)((max_elements+8-1)/8);
|
||||
float c = (float) max_elements / 8.0f;
|
||||
array->marker_count = (unsigned char) ceil(c);
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
// Use 32-bit aligned memory on the Dreamcast
|
||||
@ -30,6 +30,14 @@ void named_array_init(NamedArray* array, unsigned int element_size, unsigned int
|
||||
memset(array->used_markers, 0, sizeof(unsigned char) * array->marker_count);
|
||||
}
|
||||
|
||||
char named_array_used(NamedArray* array, unsigned int id) {
|
||||
unsigned int i = id / 8;
|
||||
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) {
|
||||
unsigned int i = 0, j = 0;
|
||||
for(i = 0; i < array->marker_count; ++i) {
|
||||
@ -68,6 +76,7 @@ void* named_array_reserve(NamedArray* array, unsigned int 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);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef NAMED_ARRAY_H
|
||||
#define NAMED_ARRAY_H
|
||||
|
||||
@ -16,13 +14,7 @@ typedef struct {
|
||||
} NamedArray;
|
||||
|
||||
void named_array_init(NamedArray* array, unsigned int element_size, unsigned int max_elements);
|
||||
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);
|
||||
}
|
||||
char named_array_used(NamedArray* array, unsigned int id);
|
||||
|
||||
void* named_array_alloc(NamedArray* array, unsigned int* new_id);
|
||||
void* named_array_reserve(NamedArray* array, unsigned int id);
|
||||
|
||||
@ -1,218 +0,0 @@
|
||||
#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
|
||||
|
||||
@ -19,10 +19,6 @@ __BEGIN_DECLS
|
||||
|
||||
#include <math.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 0x0000
|
||||
@ -40,45 +36,26 @@ __BEGIN_DECLS
|
||||
#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
|
||||
|
||||
/* Scissor box */
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#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
|
||||
#define GL_PROJECTION 0x1701
|
||||
#define GL_TEXTURE 0x1702
|
||||
#define GL_COLOR 0x1703 /* NOTE: Not the usual value */
|
||||
|
||||
#define GL_MODELVIEW_MATRIX 0x0BA6
|
||||
#define GL_PROJECTION_MATRIX 0x0BA7
|
||||
#define GL_TEXTURE_MATRIX 0x0BA8
|
||||
#define GL_COLOR_MATRIX 0x80B1
|
||||
|
||||
/* Depth buffer */
|
||||
#define GL_NEVER 0x0200
|
||||
@ -115,12 +92,11 @@ __BEGIN_DECLS
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
|
||||
/* Misc texture constants */
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_TEXTURE_2D 0x0001 /* capability bit */
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
#define GL_TEXTURE_MIN_FILTER 0x2801
|
||||
#define GL_MIRRORED_REPEAT 0x2902
|
||||
#define GL_REPEAT 0x2901
|
||||
#define GL_CLAMP 0x2900
|
||||
|
||||
@ -202,16 +178,8 @@ __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 0x0B60
|
||||
#define GL_FOG 0x0004 /* capability bit */
|
||||
#define GL_FOG_MODE 0x0B65
|
||||
#define GL_FOG_DENSITY 0x0B62
|
||||
#define GL_FOG_COLOR 0x0B66
|
||||
@ -233,7 +201,7 @@ __BEGIN_DECLS
|
||||
#define GL_FOG_HINT 0x0C54
|
||||
|
||||
/* Lighting constants */
|
||||
#define GL_LIGHTING 0x0b50
|
||||
#define GL_LIGHTING 0x0b50
|
||||
|
||||
#define GL_LIGHT0 0x4000
|
||||
#define GL_LIGHT1 0x4001
|
||||
@ -312,14 +280,12 @@ __BEGIN_DECLS
|
||||
#define GL_UNSIGNED_INT 0x1405
|
||||
#define GL_FLOAT 0x1406
|
||||
#define GL_DOUBLE 0x140A
|
||||
#define GL_HALF_FLOAT 0x140B
|
||||
#define GL_QUANTIZED_SHORT 0x140C
|
||||
#define GL_2_BYTES 0x1407
|
||||
#define GL_3_BYTES 0x1408
|
||||
#define GL_4_BYTES 0x1409
|
||||
|
||||
/* ErrorCode */
|
||||
#define GL_NO_ERROR ((GLenum) 0)
|
||||
#define GL_NO_ERROR 0
|
||||
#define GL_INVALID_ENUM 0x0500
|
||||
#define GL_INVALID_VALUE 0x0501
|
||||
#define GL_INVALID_OPERATION 0x0502
|
||||
@ -368,8 +334,9 @@ __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
|
||||
#define GL_INT_2_10_10_10_REV 0x8D9F
|
||||
|
||||
#define GL_COLOR_INDEX 0x1900
|
||||
#define GL_RED 0x1903
|
||||
@ -380,32 +347,6 @@ __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
|
||||
@ -422,40 +363,11 @@ __BEGIN_DECLS
|
||||
#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
|
||||
#define GLint int
|
||||
#define GLfloat float
|
||||
#define GLdouble double
|
||||
#define GLdouble float
|
||||
#define GLvoid void
|
||||
#define GLushort unsigned short
|
||||
#define GLuint unsigned int
|
||||
@ -463,54 +375,22 @@ __BEGIN_DECLS
|
||||
#define GLsizei unsigned int
|
||||
#define GLfixed const unsigned int
|
||||
#define GLclampf float
|
||||
#define GLclampd double
|
||||
#define GLubyte unsigned char
|
||||
#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_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 GL_MULTISAMPLE 0x809D
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
#define GL_SAMPLE_BUFFERS 0x80A8
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
|
||||
#define GL_MULTISAMPLE_BIT 0x20000000
|
||||
|
||||
#define GLAPI extern
|
||||
#define APIENTRY
|
||||
|
||||
GLAPI void APIENTRY glFlush(void);
|
||||
GLAPI void APIENTRY glFinish(void);
|
||||
GLAPI void APIENTRY glFlush();
|
||||
GLAPI void APIENTRY glFinish();
|
||||
|
||||
/* Start Submission of Primitive Data */
|
||||
/* Currently Supported Primitive Types:
|
||||
@ -522,18 +402,15 @@ GLAPI void APIENTRY glFinish(void);
|
||||
GLAPI void APIENTRY glBegin(GLenum mode);
|
||||
|
||||
/* Finish Submission of Primitive Data */
|
||||
GLAPI void APIENTRY glEnd(void);
|
||||
GLAPI void APIENTRY glEnd();
|
||||
|
||||
/* 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);
|
||||
@ -567,10 +444,6 @@ GLAPI GLvoid APIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2);
|
||||
GLAPI GLvoid APIENTRY glRectiv(const GLint *v1, const GLint *v2);
|
||||
#define glRectsv glRectiv
|
||||
|
||||
/* Primitive configuration */
|
||||
GLAPI void APIENTRY glLineWidth(GLfloat width);
|
||||
GLAPI void APIENTRY glPointSize(GLfloat size);
|
||||
|
||||
/* Enable / Disable Capability */
|
||||
/* Currently Supported Capabilities:
|
||||
GL_TEXTURE_2D
|
||||
@ -594,12 +467,11 @@ GLAPI void APIENTRY glReadBuffer(GLenum mode);
|
||||
GLAPI void APIENTRY glDrawBuffer(GLenum mode);
|
||||
|
||||
/* Depth Testing */
|
||||
GLAPI void APIENTRY glClearDepth(GLdouble depth);
|
||||
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(GLdouble n, GLdouble f);
|
||||
GLAPI void APIENTRY glDepthRangef(GLfloat n, GLfloat f);
|
||||
GLAPI void APIENTRY glDepthRange(GLclampf n, GLclampf f);
|
||||
|
||||
/* Hints */
|
||||
/* Currently Supported Capabilities:
|
||||
@ -618,7 +490,6 @@ 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);
|
||||
|
||||
@ -692,15 +563,15 @@ GLAPI void APIENTRY glDisableClientState(GLenum cap);
|
||||
|
||||
GLAPI void APIENTRY glMatrixMode(GLenum mode);
|
||||
|
||||
GLAPI void APIENTRY glLoadIdentity(void);
|
||||
GLAPI void APIENTRY glLoadIdentity();
|
||||
|
||||
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(void);
|
||||
GLAPI void APIENTRY glPopMatrix(void);
|
||||
GLAPI void APIENTRY glPushMatrix();
|
||||
GLAPI void APIENTRY glPopMatrix();
|
||||
|
||||
GLAPI void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z);
|
||||
#define glTranslated glTranslatef
|
||||
@ -711,9 +582,9 @@ GLAPI void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
GLAPI void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
#define glRotated glRotatef
|
||||
|
||||
GLAPI void APIENTRY glOrtho(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar);
|
||||
GLAPI void APIENTRY glOrtho(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar);
|
||||
|
||||
GLAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
@ -721,14 +592,13 @@ GLAPI void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
GLAPI void APIENTRY glKosGetMatrix(GLenum mode, GLfloat *params);
|
||||
|
||||
GLAPI void APIENTRY glFrustum(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar);
|
||||
GLAPI void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar);
|
||||
|
||||
/* 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 */
|
||||
@ -761,15 +631,11 @@ GLAPI GLenum APIENTRY glGetError(void);
|
||||
|
||||
/* Non Operational Stubs for portability */
|
||||
GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref);
|
||||
GLAPI void APIENTRY glPolygonMode(GLenum face, GLenum mode);
|
||||
GLAPI void APIENTRY glLineWidth(GLfloat width);
|
||||
GLAPI void APIENTRY glPolygonOffset(GLfloat factor, GLfloat units);
|
||||
GLAPI void APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat *params);
|
||||
GLAPI void APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint *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
|
||||
|
||||
@ -54,6 +54,16 @@ __BEGIN_DECLS
|
||||
#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
|
||||
@ -120,7 +130,7 @@ 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 void APIENTRY glGenerateMipmapEXT(GLenum target);
|
||||
GLAPI GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target);
|
||||
GLAPI GLboolean APIENTRY glIsFramebufferEXT(GLuint framebuffer);
|
||||
|
||||
@ -151,22 +161,6 @@ GLAPI void APIENTRY glGetColorTableEXT(GLenum target, GLenum format, GLenum type
|
||||
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
|
||||
@ -185,15 +179,6 @@ GLAPI void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||
GLsizei imageSize,
|
||||
const GLvoid *data);
|
||||
|
||||
GLAPI void APIENTRY glCompressedTexSubImage2DARB(GLenum target,
|
||||
GLint level,
|
||||
GLint xoffset,
|
||||
GLint yoffset,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLenum format,
|
||||
GLsizei imageSize,
|
||||
const GLvoid *data);
|
||||
|
||||
/* Core aliases */
|
||||
#define GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
|
||||
@ -202,29 +187,8 @@ GLAPI void APIENTRY glCompressedTexSubImage2DARB(GLenum target,
|
||||
#define glClientActiveTexture glClientActiveTextureARB
|
||||
#define glMultiTexCoord2f glMultiTexCoord2fARB
|
||||
|
||||
#define glGenerateMipmapEXT glGenerateMipmap
|
||||
#define glGenerateMipmap glGenerateMipmapEXT
|
||||
#define glCompressedTexImage2D glCompressedTexImage2DARB
|
||||
#define glCompressedTexSubImage2D glCompressedTexSubImage2DARB
|
||||
|
||||
#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
|
||||
|
||||
112
include/glkos.h
Normal file
@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include "gl.h"
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define GL_UNSIGNED_BYTE_TWID_KOS 0xEEFB
|
||||
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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;
|
||||
} 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();
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* Pass to glTexParameteri to set the shared bank */
|
||||
#define GL_SHARED_TEXTURE_BANK_KOS 0xEF00
|
||||
|
||||
__END_DECLS
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
__BEGIN_DECLS
|
||||
|
||||
#ifndef BUILD_LIBGL
|
||||
#include "gl.h"
|
||||
#include <GL/gl.h>
|
||||
#endif
|
||||
|
||||
#define GLU_FALSE 0
|
||||
@ -30,14 +30,9 @@ GLAPI void APIENTRY gluPerspective(GLdouble fovy, GLdouble aspect,
|
||||
GLdouble zNear, GLdouble zFar);
|
||||
|
||||
/* gluLookAt - Set Camera Position for Rendering. */
|
||||
GLAPI void APIENTRY gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
|
||||
GLdouble centerx, GLdouble centery, GLdouble centerz,
|
||||
GLdouble upx, GLdouble upy, GLdouble 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 void APIENTRY gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
|
||||
GLfloat centerx, GLfloat centery, GLfloat centerz,
|
||||
GLfloat upx, GLfloat upy, GLfloat upz);
|
||||
|
||||
GLAPI const GLubyte* APIENTRY gluErrorString(GLenum error);
|
||||
|
||||
32
samples/Makefile
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
# 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 nehe02de all
|
||||
$(KOS_MAKE) -C nehe03 all
|
||||
$(KOS_MAKE) -C nehe06 all
|
||||
$(KOS_MAKE) -C nehe06_vq all
|
||||
$(KOS_MAKE) -C ortho2d all
|
||||
$(KOS_MAKE) -C lerabot01 all
|
||||
$(KOS_MAKE) -C zclip all
|
||||
$(KOS_MAKE) -C zclip_triangle all
|
||||
$(KOS_MAKE) -C zclip_trianglestrip all
|
||||
$(KOS_MAKE) -C terrain all
|
||||
$(KOS_MAKE) -C quadmark all
|
||||
$(KOS_MAKE) -C trimark all
|
||||
$(KOS_MAKE) -C multitexture_arrays all
|
||||
$(KOS_MAKE) -C paletted all
|
||||
$(KOS_MAKE) -C paletted_pcx all
|
||||
$(KOS_MAKE) -C depth_funcs all
|
||||
$(KOS_MAKE) -C polymark all
|
||||
$(KOS_MAKE) -C polygon_offset all
|
||||
$(KOS_MAKE) -C blend_test all
|
||||
$(KOS_MAKE) -C mipmap all
|
||||
$(KOS_MAKE) -C lights all
|
||||
29
samples/blend_test/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET = blend_test.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)
|
||||
@ -1,17 +1,12 @@
|
||||
/*
|
||||
* 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
|
||||
* This sample is to demonstrate a bug where rendering an unblended
|
||||
* polygon, before a series of blended ones would result in no blended
|
||||
* output and incorrect depth testing
|
||||
*/
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "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.
|
||||
@ -47,23 +42,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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);
|
||||
@ -80,59 +58,28 @@ 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(0, 0, -10.0f); // Move Left 1.5 Units And Into The Screen 6.0
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-4.0, 0, -10);
|
||||
DrawQuad(RED);
|
||||
glPopMatrix();
|
||||
|
||||
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);
|
||||
/* Draw 3 overlapping quads, 2 of which should be totally transparent so the
|
||||
* output should be the third */
|
||||
DrawQuad(NONE);
|
||||
DrawQuad(NONE);
|
||||
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();
|
||||
@ -146,9 +93,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
@ -1,428 +0,0 @@
|
||||
#include <cstdio>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _arch_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
|
||||
|
||||
size_t numCubes = 0;
|
||||
|
||||
float timeElapsed = 0.0f;
|
||||
const float dt = 1.0f / 60.0f;
|
||||
|
||||
float angleDegrees = 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];
|
||||
float lutScaleFactors[MAX_CUBES];
|
||||
|
||||
|
||||
void debugLog(const char* msg)
|
||||
{
|
||||
#ifdef _arch_dreamcast
|
||||
dbglog(DBG_KDEBUG, "%s\n", msg);
|
||||
#else
|
||||
printf("%s\n", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void runningStats()
|
||||
{
|
||||
#ifdef _arch_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 _arch_dreamcast
|
||||
dbglog(DBG_DEBUG, "Average frame rate: ~%f fps\n", avgfps);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void stats()
|
||||
{
|
||||
#ifdef _arch_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(const float r, const float x, const float y, const float z, const float vx, const float vy, const 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 updateCubes(float dt)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_CUBES; i++)
|
||||
{
|
||||
Cube* pCube = &cubes[i];
|
||||
pCube->x += pCube->vx * dt;
|
||||
pCube->y += pCube->vy * dt;
|
||||
pCube->z += pCube->vz * dt;
|
||||
|
||||
if (pCube->x < -3 || pCube->x > +3) { pCube->vx *= -1; }
|
||||
if (pCube->y < -3 || pCube->y > +3) { pCube->vy *= -1; }
|
||||
if (pCube->z < -3 || pCube->z > +3) { pCube->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);
|
||||
|
||||
isDrawingArrays ? glDrawArrays(GL_QUADS, 0, 24) : glDrawElements(GL_QUADS, 24, GL_UNSIGNED_INT, cubeIndices);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
|
||||
void renderCubes(const float angleRotation)
|
||||
{
|
||||
for (size_t i = 0; i < MAX_CUBES; i++)
|
||||
{
|
||||
const float scaleFactor = lutScaleFactors[i];
|
||||
Cube* pCube = &cubes[i];
|
||||
|
||||
glPushMatrix(); // Save previous camera state
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glTranslatef(pCube->x, pCube->y, pCube->z);
|
||||
glRotatef(angleRotation, 1, 1, 1); // Rotate camera / object
|
||||
|
||||
glScalef(scaleFactor, scaleFactor, scaleFactor); // Apply scale factor
|
||||
|
||||
renderUnitCube();
|
||||
glPopMatrix(); // Restore previous camera state
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float rnd(float valueMin, float valueMax)
|
||||
{
|
||||
return (valueMax - valueMin) * (float)rand() / (float)RAND_MAX + valueMin;
|
||||
}
|
||||
|
||||
|
||||
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 (size_t 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];
|
||||
}
|
||||
|
||||
// Precalculate scale factors and store them in a LUT
|
||||
const float incFactor = 0.35f / (float)MAX_CUBES;
|
||||
for (size_t i = 0; i < MAX_CUBES; ++i)
|
||||
{
|
||||
lutScaleFactors[i] = 0.05f + (i * incFactor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateTimer()
|
||||
{
|
||||
timeElapsed += dt;
|
||||
|
||||
if (timeElapsed > 10.0f)
|
||||
{
|
||||
stats();
|
||||
timeElapsed = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void updateLogic()
|
||||
{
|
||||
updateTimer();
|
||||
|
||||
const int fullRot = (int)(angleDegrees * invAngle360);
|
||||
angleDegrees -= fullRot * 360.0f;
|
||||
angleDegrees += 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(angleDegrees);
|
||||
|
||||
// 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 _arch_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;
|
||||
|
||||
isDrawingArrays ? glClearColor(0.3f, 0.0f, 0.3f, 1.0f) : glClearColor(0.0f, 0.0f, 0.3f, 1.0f);
|
||||
}
|
||||
|
||||
if (state && (state->buttons & CONT_B) && !(prevButtons & CONT_B))
|
||||
{
|
||||
isBlendingEnabled = !isBlendingEnabled;
|
||||
|
||||
isBlendingEnabled ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
prevButtons = state->buttons;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void swapBuffers()
|
||||
{
|
||||
#ifdef _arch_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;
|
||||
}
|
||||
29
samples/depth_funcs/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET = depth_funcs.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)
|
||||
@ -1,17 +1,13 @@
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "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
|
||||
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
|
||||
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
|
||||
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
|
||||
|
||||
@ -38,23 +34,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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;
|
||||
@ -81,47 +60,22 @@ void DrawGLScene()
|
||||
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();
|
||||
}
|
||||
@ -134,9 +88,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
@ -1,229 +0,0 @@
|
||||
#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};
|
||||
|
||||
static int decode_dtex(Image* image, FILE* file) {
|
||||
struct {
|
||||
char id[4]; // 'DTEX'
|
||||
GLushort width;
|
||||
GLushort height;
|
||||
GLuint type;
|
||||
GLuint size;
|
||||
} header;
|
||||
|
||||
fread(&header, sizeof(header), 1, file);
|
||||
|
||||
image->twiddled = (header.type & (1 << 26)) < 1;
|
||||
image->compressed = (header.type & (1 << 30)) > 0;
|
||||
image->mipmapped = (header.type & (1 << 31)) > 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;
|
||||
|
||||
fread(image->data, image->dataSize, 1, file);
|
||||
fclose(file);
|
||||
|
||||
if(image->compressed && image->twiddled) {
|
||||
switch(format) {
|
||||
case 0:
|
||||
puts("Compressed & Twiddled - ARGB 1555");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
puts("Compressed & Twiddled - RGB 565");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
puts("Compressed & Twiddled - ARGB 4444");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
} else if (image->compressed) {
|
||||
switch(format) {
|
||||
case 0:
|
||||
puts("Compressed - ARGB 1555");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
puts("Compressed - RGB 565");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
puts("Compressed - ARGB 4444");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
switch (format) {
|
||||
case 0:
|
||||
puts("Uncompressed - ARGB 1555");
|
||||
image->internalFormat = GL_ARGB1555_TWID_KOS;
|
||||
image->transferFormat = GL_BGRA;
|
||||
image->transferType = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS;
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
puts("Uncompressed - RGB 565");
|
||||
image->internalFormat = GL_RGB565_TWID_KOS;
|
||||
image->transferFormat = GL_RGB;
|
||||
image->transferType = GL_UNSIGNED_SHORT_5_6_5_TWID_KOS;
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
puts("Uncompressed - ARGB 4444");
|
||||
image->internalFormat = GL_ARGB4444_TWID_KOS;
|
||||
image->transferFormat = GL_BGRA;
|
||||
image->transferType = GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Invalid texture format %u\n", header.type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dtex_to_gl_texture(texture *tex, char* filename) {
|
||||
// Load Texture
|
||||
Image image = { 0 };
|
||||
|
||||
FILE* file = NULL;
|
||||
|
||||
// make sure the file is there.
|
||||
if ((file = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
printf("File not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
decode_dtex(&image, file);
|
||||
|
||||
// Create Texture
|
||||
GLuint texture_id;
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id); // 2d texture (x and y size)
|
||||
|
||||
if (image.compressed) {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0,
|
||||
image.internalFormat, image.sizeX, image.sizeY,
|
||||
0, image.dataSize, image.data);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
image.internalFormat, image.sizeX, image.sizeY, 0,
|
||||
image.transferFormat, image.transferType, 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);
|
||||
|
||||
GLuint expected = 2 * image.sizeX * image.sizeY;
|
||||
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) image.dataSize));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
#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, transferFormat, transferType;
|
||||
unsigned int mipmapped, compressed, twiddled;
|
||||
unsigned int dataSize;
|
||||
} Image;
|
||||
|
||||
|
||||
int dtex_to_gl_texture(texture *tex, char* filename);
|
||||
void draw_textured_quad(texture *tex);
|
||||
|
||||
|
||||
#endif
|
||||
@ -1,142 +0,0 @@
|
||||
#ifdef _arch_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 _arch_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_TEST);
|
||||
|
||||
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 _arch_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;
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
#! /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
|
||||
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
@ -1,109 +0,0 @@
|
||||
#ifdef _arch_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 _arch_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;
|
||||
}
|
||||
30
samples/lerabot01/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
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)
|
||||
@ -1,32 +1,107 @@
|
||||
#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 _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
|
||||
#ifdef _arch_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;
|
||||
|
||||
/* storage for one texture */
|
||||
GLuint texture[1];
|
||||
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() {
|
||||
@ -40,7 +115,7 @@ void LoadGLTextures() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad(IMAGE_FILENAME, image1)) {
|
||||
if (!ImageLoad("/rd/flag1.bmp", image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -54,8 +129,6 @@ 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. */
|
||||
@ -81,7 +154,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
|
||||
|
||||
GLfloat l1_pos[] = {5.0, 0.0, 1.0, 1.0};
|
||||
GLfloat l1_diff[] = {1.0, 0.0, 0.0, 1.0};
|
||||
//GLfloat l1_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
GLfloat l1_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
|
||||
//glLightfv(GL_LIGHT1, GL_AMBIENT, l1_amb);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, l1_diff);
|
||||
@ -93,7 +166,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
|
||||
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};
|
||||
GLfloat l2_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
|
||||
glEnable(GL_LIGHT2);
|
||||
glLightfv(GL_LIGHT2, GL_DIFFUSE, l2_diff);
|
||||
@ -119,24 +192,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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;
|
||||
@ -145,7 +200,7 @@ void DrawTexturedQuad(int tex, float x, float y, float z)
|
||||
GLfloat y0 = y - texH / 2;
|
||||
GLfloat x1 = x + texW / 2;
|
||||
GLfloat y1 = y + texH / 2;
|
||||
//GLfloat color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat mat_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
GLfloat vertex_data[] = {
|
||||
@ -172,6 +227,14 @@ void DrawTexturedQuad(int tex, float x, float y, float z)
|
||||
0.0, 0.0, 1.0
|
||||
};
|
||||
|
||||
GLfloat color_data[] = {
|
||||
/* 2D Coordinate, texture coordinate */
|
||||
color[0], color[1], color[2], color[3],
|
||||
color[0], color[1], color[2], color[3],
|
||||
color[0], color[1], color[2], color[3],
|
||||
color[0], color[1], color[2], color[3]
|
||||
};
|
||||
|
||||
//GLint indices[] = {0,1,2,3,2,3};
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
@ -219,7 +282,7 @@ void DrawGLScene()
|
||||
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.1f); // Draw the textured quad.
|
||||
DrawTexturedQuad(texture[0], i * 20, 0.0f, 0.0f); // Draw the textured quad.
|
||||
// swap buffers to display, since we're double buffered.
|
||||
glKosSwapBuffers();
|
||||
|
||||
@ -233,9 +296,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
29
samples/lights/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET = lights.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)
|
||||
@ -1,30 +1,108 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glext.h"
|
||||
#include "GL/glkos.h"
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
extern uint8_t romdisk[];
|
||||
extern uint8 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;
|
||||
GLuint texture[1];
|
||||
|
||||
|
||||
int texture[1];
|
||||
|
||||
|
||||
struct Image {
|
||||
unsigned long sizeX;
|
||||
unsigned long sizeY;
|
||||
char *data;
|
||||
};
|
||||
typedef struct Image Image;
|
||||
|
||||
|
||||
|
||||
int ImageLoad(char *filename, Image *image) {
|
||||
FILE *file;
|
||||
unsigned long size;
|
||||
unsigned long i;
|
||||
unsigned short int planes;
|
||||
unsigned short int bpp;
|
||||
char temp;
|
||||
|
||||
|
||||
if ((file = fopen(filename, "rb"))==NULL)
|
||||
{
|
||||
printf("File Not Found : %s\n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
fseek(file, 18, SEEK_CUR);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
size = image->sizeX * image->sizeY * 3;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
fseek(file, 24, SEEK_CUR);
|
||||
|
||||
|
||||
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) {
|
||||
temp = image->data[i];
|
||||
image->data[i] = image->data[i+2];
|
||||
image->data[i+2] = temp;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void LoadGLTextures() {
|
||||
|
||||
@ -37,7 +115,7 @@ void LoadGLTextures() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad(IMAGE_FILENAME, image1)) {
|
||||
if (!ImageLoad("/rd/NeHe.bmp", image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -52,8 +130,6 @@ void LoadGLTextures() {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
|
||||
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||
|
||||
free(image1);
|
||||
};
|
||||
|
||||
|
||||
@ -124,27 +200,9 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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;
|
||||
const static float radius = 30.0f;
|
||||
|
||||
pos += 0.001f;
|
||||
|
||||
@ -225,20 +283,12 @@ void DrawGLScene()
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
GLdcConfig config;
|
||||
|
||||
glKosInitConfig(&config);
|
||||
config.fsaa_enabled = GL_FALSE;
|
||||
|
||||
glKosInitEx(&config);
|
||||
glKosInit();
|
||||
|
||||
InitGL(640, 480);
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
// 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: %ld\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: %ld\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;
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
// 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
|
||||
29
samples/mipmap/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET = mipmap.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)
|
||||
@ -1,26 +1,105 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glext.h"
|
||||
#include "GL/glkos.h"
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
extern uint8_t romdisk[];
|
||||
extern uint8 romdisk[];
|
||||
KOS_INIT_ROMDISK(romdisk);
|
||||
#define IMAGE_FILENAME "/rd/NeHe.bmp"
|
||||
#else
|
||||
#define IMAGE_FILENAME "../samples/mipmap/romdisk/NeHe.bmp"
|
||||
#endif
|
||||
|
||||
#include "../loadbmp.h"
|
||||
GLuint texture[1];
|
||||
/* 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() {
|
||||
@ -34,7 +113,7 @@ void LoadGLTextures() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad(IMAGE_FILENAME, image1)) {
|
||||
if (!ImageLoad("/rd/NeHe.bmp", image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -45,11 +124,11 @@ void LoadGLTextures() {
|
||||
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);
|
||||
// 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);
|
||||
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||
};
|
||||
|
||||
/* A general OpenGL initialization function. Sets all of the initial parameters. */
|
||||
@ -86,24 +165,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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
|
||||
@ -167,9 +228,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
29
samples/multitexture_arrays/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET = multitexture_arrays.elf
|
||||
OBJS = main.o pvr-texture.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)
|
||||
@ -8,27 +8,11 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "GL/glext.h"
|
||||
|
||||
#ifdef _arch_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
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
#include "glext.h"
|
||||
|
||||
/* Load a PVR texture - located in pvr-texture.c */
|
||||
extern GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap);
|
||||
@ -45,25 +29,8 @@ GLfloat TEXCOORD_ARRAY[4 * 2] = { 0, 0,
|
||||
0, 1
|
||||
};
|
||||
|
||||
GLuint ARGB_ARRAY[4] = { 0xFFFF0000, 0xFF0000FF, 0xFF00FF00, 0xFFFFFF00 };
|
||||
GLuint ARGB_ARRAY[4 * 1] = { 0xFFFF0000, 0xFF0000FF, 0xFF00FF00, 0xFFFFFF00 };
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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) {
|
||||
@ -124,6 +91,9 @@ void RenderCallback(GLuint texID0, GLuint texID1) {
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
}
|
||||
|
||||
extern uint8 romdisk[];
|
||||
KOS_INIT_ROMDISK(romdisk);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* Notice we do not init the PVR here, that is handled by Open GL */
|
||||
glKosInit();
|
||||
@ -135,13 +105,10 @@ int main(int argc, char **argv) {
|
||||
glLoadIdentity();
|
||||
|
||||
/* Load two PVR textures to OpenGL */
|
||||
GLuint texID0 = glTextureLoadPVR(IMAGE1_FILENAME, 0, 0);
|
||||
GLuint texID1 = glTextureLoadPVR(IMAGE2_FILENAME, 0, 0);
|
||||
GLuint texID0 = glTextureLoadPVR("/rd/wp001vq.pvr", 0, 0);
|
||||
GLuint texID1 = glTextureLoadPVR("/rd/FlareWS_256.pvr", 0, 0);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
/* Draw the "scene" */
|
||||
RenderCallback(texID0, texID1);
|
||||
|
||||
|
||||
@ -6,14 +6,13 @@
|
||||
|
||||
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"
|
||||
#include <kos.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
#include "glext.h"
|
||||
|
||||
#define PVR_HDR_SIZE 0x20
|
||||
#define MAX(x, y) ((x > y) ? x : y)
|
||||
@ -52,8 +51,8 @@ static GLuint _glGetMipmapDataSize(GLuint width, GLuint height) {
|
||||
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];
|
||||
uint16 *TEX0 = NULL;
|
||||
uint8 HDR[PVR_HDR_SIZE];
|
||||
GLuint texID, texSize, texW, texH, texFormat;
|
||||
|
||||
/* Open the PVR texture file, and get its file size */
|
||||
@ -62,7 +61,7 @@ GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char gl
|
||||
if(tex == NULL) {
|
||||
printf("FILE READ ERROR: %s\n", fname);
|
||||
|
||||
return 1;
|
||||
while(1);
|
||||
}
|
||||
|
||||
fseek(tex, 0, SEEK_END);
|
||||
@ -93,12 +92,12 @@ GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char gl
|
||||
if(texFormat != GL_UNSIGNED_SHORT_5_6_5)
|
||||
glCompressedTexImage2DARB(GL_TEXTURE_2D,
|
||||
0,
|
||||
texFormat,
|
||||
texW,
|
||||
texH,
|
||||
0,
|
||||
texSize,
|
||||
TEX0);
|
||||
texFormat,
|
||||
texW,
|
||||
texH,
|
||||
0,
|
||||
texSize,
|
||||
TEX0);
|
||||
else {
|
||||
fprintf(stderr, "%x\n", texFormat);
|
||||
glTexImage2D(GL_TEXTURE_2D,
|
||||
|
||||
29
samples/nehe02/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
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)
|
||||
@ -1,15 +1,11 @@
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "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, 1.0f, 0.0f); // This Will Clear The Background Color To Black
|
||||
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
|
||||
@ -38,23 +34,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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()
|
||||
@ -137,9 +116,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
29
samples/nehe02de/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
TARGET = nehe02de.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)
|
||||
@ -1,10 +1,6 @@
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "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.
|
||||
@ -40,23 +36,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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()
|
||||
@ -108,9 +87,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
29
samples/nehe02va/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
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)
|
||||
@ -1,10 +1,6 @@
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "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.
|
||||
@ -40,23 +36,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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()
|
||||
@ -100,9 +79,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
29
samples/nehe03/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
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)
|
||||
@ -1,10 +1,6 @@
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "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.
|
||||
@ -38,23 +34,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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()
|
||||
@ -97,9 +76,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
@ -1,118 +0,0 @@
|
||||
#ifdef _arch_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 _arch_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;
|
||||
}
|
||||
@ -1,171 +0,0 @@
|
||||
#ifdef _arch_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 _arch_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;
|
||||
}
|
||||
29
samples/nehe06/Makefile
Normal file
@ -0,0 +1,29 @@
|
||||
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)
|
||||
@ -1,32 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glext.h"
|
||||
#include "GL/glkos.h"
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
extern uint8_t romdisk[];
|
||||
extern uint8 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 */
|
||||
GLuint texture[1];
|
||||
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() {
|
||||
@ -40,7 +115,7 @@ void LoadGLTextures() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad(IMAGE_FILENAME, image1)) {
|
||||
if (!ImageLoad("/rd/NeHe.bmp", image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -49,17 +124,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 smaller than texture
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR); // scale linearly when image smalled 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.
|
||||
// Create an empty texture first
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
|
||||
// Update the texture with the image data
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
free(image1);
|
||||
}
|
||||
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||
};
|
||||
|
||||
/* 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.
|
||||
@ -77,7 +149,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) */
|
||||
@ -95,23 +167,6 @@ void ReSizeGLScene(int Width, int Height)
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_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()
|
||||
@ -183,9 +238,6 @@ int main(int argc, char **argv)
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 192 KiB |
@ -1,296 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glkos.h"
|
||||
#include "GL/glext.h"
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
extern uint8 romdisk[];
|
||||
KOS_INIT_ROMDISK(romdisk);
|
||||
#define IMG_PATH "/rd/NeHe.tex"
|
||||
#else
|
||||
#define IMG_PATH "../samples/nehe06_4444twid/romdisk/NeHe.tex"
|
||||
#endif
|
||||
|
||||
/* floats for x rotation, y rotation, z rotation */
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
/* storage for one texture */
|
||||
GLuint texture[1];
|
||||
|
||||
/* Image type - contains height, width, and data */
|
||||
struct Image {
|
||||
unsigned long sizeX;
|
||||
unsigned long sizeY;
|
||||
char *data;
|
||||
GLenum format;
|
||||
GLenum internal_format;
|
||||
GLenum type;
|
||||
GLboolean mipmapped;
|
||||
unsigned int dataSize;
|
||||
};
|
||||
|
||||
typedef struct Image Image;
|
||||
|
||||
int ImageLoad(char *filename, Image *image) {
|
||||
FILE* file = NULL;
|
||||
|
||||
// make sure the file is there.
|
||||
if ((file = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
printf("File Not Found : %s\n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct {
|
||||
char id[4]; // 'DTEX'
|
||||
GLshort width;
|
||||
GLshort height;
|
||||
GLint type;
|
||||
GLint 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);
|
||||
|
||||
printf("%d\n", compressed);
|
||||
printf("%d\n", twiddled);
|
||||
printf("%d\n", mipmapped);
|
||||
|
||||
image->format = (format == 1) ? GL_RGB : GL_BGRA;
|
||||
image->internal_format = (format == 1) ? GL_RGB : GL_RGBA;
|
||||
|
||||
GLuint COMPRESSED_MASK = 4;
|
||||
GLuint TWIDDLED_MASK = 2;
|
||||
GLuint MIPMAPPED_MASK = 1;
|
||||
|
||||
GLuint lookup[8] = {0};
|
||||
|
||||
switch(format) {
|
||||
case 0:
|
||||
lookup[COMPRESSED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||
lookup[COMPRESSED_MASK | TWIDDLED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||
lookup[COMPRESSED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS;
|
||||
lookup[COMPRESSED_MASK | TWIDDLED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS;
|
||||
lookup[TWIDDLED_MASK] = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS;
|
||||
lookup[TWIDDLED_MASK | MIPMAPPED_MASK] = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS;
|
||||
lookup[0] = GL_UNSIGNED_SHORT_1_5_5_5_REV;
|
||||
break;
|
||||
case 1:
|
||||
lookup[COMPRESSED_MASK] = GL_COMPRESSED_RGB_565_VQ_KOS;
|
||||
lookup[COMPRESSED_MASK | TWIDDLED_MASK] = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
||||
lookup[COMPRESSED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS;
|
||||
lookup[COMPRESSED_MASK | TWIDDLED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS;
|
||||
lookup[TWIDDLED_MASK] = GL_UNSIGNED_SHORT_5_6_5_TWID_KOS;
|
||||
lookup[TWIDDLED_MASK | MIPMAPPED_MASK] = GL_UNSIGNED_SHORT_5_6_5_TWID_KOS;
|
||||
lookup[0] = GL_UNSIGNED_SHORT_5_6_5;
|
||||
break;
|
||||
case 2:
|
||||
lookup[COMPRESSED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
||||
lookup[COMPRESSED_MASK | TWIDDLED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
||||
lookup[COMPRESSED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS;
|
||||
lookup[COMPRESSED_MASK | TWIDDLED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS;
|
||||
lookup[TWIDDLED_MASK] = GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS;
|
||||
lookup[TWIDDLED_MASK | MIPMAPPED_MASK] = GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS;
|
||||
lookup[0] = GL_UNSIGNED_SHORT_4_4_4_4_REV;
|
||||
break;
|
||||
default:
|
||||
printf("[ERROR] Unknown format\n");
|
||||
}
|
||||
|
||||
image->type = lookup[(compressed << 2) | (twiddled << 1) | mipmapped];
|
||||
|
||||
printf("%d\n", image->type);
|
||||
|
||||
assert(image->type);
|
||||
|
||||
// we're done.
|
||||
return 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(IMG_PATH, 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); // scale linearly when image smalled 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, image1->internal_format, image1->sizeX, image1->sizeY, 0,
|
||||
image1->format, image1->type, 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 _arch_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(0.0f,0.0f,-5.0f); // move 5 units into the screen.
|
||||
|
||||
glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis
|
||||
glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis
|
||||
glRotatef(zrot,0.0f,0.0f,1.0f); // Rotate On The Z Axis
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture[0]); // choose the texture to use.
|
||||
|
||||
glBegin(GL_QUADS); // begin drawing a cube
|
||||
|
||||
// Front Face (note that the texture's corners have to match the quad's corners)
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
|
||||
|
||||
// Back Face
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
|
||||
|
||||
// Top Face
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
|
||||
// Bottom Face
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
|
||||
// Right face
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
|
||||
// Left Face
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
|
||||
glEnd(); // done with the polygon.
|
||||
|
||||
xrot+=1.5f; // X Axis Rotation
|
||||
yrot+=1.5f; // Y Axis Rotation
|
||||
zrot+=1.5f; // Z Axis Rotation
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 192 KiB |
|
Before Width: | Height: | Size: 23 KiB |