Compare commits

..

1 Commits

Author SHA1 Message Date
Luke Benstead
7dc2952b8d Start stubbing out profiling utils 2018-07-03 20:08:52 +01:00
171 changed files with 2694 additions and 29523 deletions

5
.gitignore vendored
View File

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

View File

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

View File

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

View File

@ -1,534 +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;
pool_header.pool_size = size;
intptr_t base_address = (intptr_t) pool_header.pool;
base_address = round_up(base_address, 2048);
pool_header.base_address = (uint8_t*) base_address;
pool_header.block_count = ((p + size) - pool_header.base_address) / 2048;
pool_header.allocations = NULL;
assert(((uintptr_t) pool_header.base_address) % 2048 == 0);
return 0;
}
void alloc_shutdown(void* pool) {
(void) pool;
if(!pool_header.pool) {
return;
}
struct AllocEntry* it = pool_header.allocations;
while(it) {
struct AllocEntry* next = it->next;
free(it);
it = next;
}
memset(&pool_header, 0, sizeof(pool_header));
pool_header.pool = NULL;
}
static inline uint32_t size_to_subblock_count(size_t size) {
uint32_t required_subblocks = (size / 256);
if(size % 256) required_subblocks += 1;
return required_subblocks;
}
static inline uint32_t subblock_from_pointer(void* p) {
uint8_t* ptr = (uint8_t*) p;
return (ptr - pool_header.base_address) / 256;
}
static inline void block_and_offset_from_subblock(size_t sb, size_t* b, uint8_t* off) {
*b = sb / 8;
*off = (sb % 8);
}
void* alloc_malloc(void* pool, size_t size) {
DBG_MSG("Allocating: %d\n", size);
size_t start_subblock, required_subblocks;
void* ret = alloc_next_available_ex(pool, size, &start_subblock, &required_subblocks);
if(ret) {
size_t block;
uint8_t offset;
block_and_offset_from_subblock(start_subblock, &block, &offset);
uint8_t mask = 0;
DBG_MSG("Alloc: size: %d, rs: %d, sb: %d, b: %d, off: %d\n", size, required_subblocks, start_subblock, start_subblock / 8, start_subblock % 8);
/* Toggle any bits for the first block */
int c = (required_subblocks < 8) ? required_subblocks : 8;
for(int i = 0; i < c; ++i) {
mask |= (1 << (7 - (offset + i)));
required_subblocks--;
}
if(mask) {
pool_header.block_usage[block++] |= mask;
}
/* Fill any full blocks in the middle of the allocation */
while(required_subblocks > 8) {
pool_header.block_usage[block++] = 255;
required_subblocks -= 8;
}
/* Fill out any trailing subblocks */
mask = 0;
for(size_t i = 0; i < required_subblocks; ++i) {
mask |= (1 << (7 - i));
}
if(mask) {
pool_header.block_usage[block++] |= mask;
}
/* Insert allocations in the list by size descending so that when we
* defrag we can move the larger blocks before the smaller ones without
* much effort */
struct AllocEntry* new_entry = (struct AllocEntry*) malloc(sizeof(struct AllocEntry));
new_entry->pointer = ret;
new_entry->size = size;
new_entry->next = NULL;
struct AllocEntry* it = pool_header.allocations;
struct AllocEntry* last = NULL;
if(!it) {
pool_header.allocations = new_entry;
} else {
while(it) {
if(it->size < size) {
if(last) {
last->next = new_entry;
} else {
pool_header.allocations = new_entry;
}
new_entry->next = it;
break;
} else if(!it->next) {
it->next = new_entry;
new_entry->next = NULL;
break;
}
last = it;
it = it->next;
}
}
}
DBG_MSG("Alloc done\n");
return ret;
}
static void alloc_release_blocks(struct AllocEntry* it) {
size_t used_subblocks = size_to_subblock_count(it->size);
size_t subblock = subblock_from_pointer(it->pointer);
size_t block;
uint8_t offset;
block_and_offset_from_subblock(subblock, &block, &offset);
uint8_t mask = 0;
DBG_MSG("Free: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset);
/* Wipe out any leading subblocks */
int c = (used_subblocks < 8) ? used_subblocks : 8;
for(int i = 0; i < c; ++i) {
mask |= (1 << (7 - (offset + i)));
used_subblocks--;
}
if(mask) {
pool_header.block_usage[block++] &= ~mask;
}
/* Clear any full blocks in the middle of the allocation */
while(used_subblocks > 8) {
pool_header.block_usage[block++] = 0;
used_subblocks -= 8;
}
/* Wipe out any trailing subblocks */
mask = 0;
for(size_t i = 0; i < used_subblocks; ++i) {
mask |= (1 << (7 - i));
}
if(mask) {
pool_header.block_usage[block++] &= ~mask;
}
}
void alloc_free(void* pool, void* p) {
(void) pool;
struct AllocEntry* it = pool_header.allocations;
struct AllocEntry* last = NULL;
while(it) {
if(it->pointer == p) {
alloc_release_blocks(it);
if(last) {
last->next = it->next;
} else {
assert(it == pool_header.allocations);
pool_header.allocations = it->next;
}
DBG_MSG("Freed: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset);
free(it);
break;
}
last = it;
it = it->next;
}
DBG_MSG("Free done\n");
}
void alloc_run_defrag(void* pool, defrag_address_move callback, int max_iterations, void* user_data) {
for(int i = 0; i < max_iterations; ++i) {
bool move_occurred = false;
struct AllocEntry* it = pool_header.allocations;
if(!it) {
return;
}
while(it) {
void* potential_dest = alloc_next_available(pool, it->size);
if(potential_dest < it->pointer) {
potential_dest = alloc_malloc(pool, it->size);
memcpy(potential_dest, it->pointer, it->size);
/* Mark this block as now free, but don't fiddle with the
* allocation list */
alloc_release_blocks(it);
callback(it->pointer, potential_dest, user_data);
it->pointer = potential_dest;
move_occurred = true;
}
it = it->next;
}
if(!move_occurred) {
return;
}
}
}
static inline uint8_t count_ones(uint8_t byte) {
static const uint8_t NIBBLE_LOOKUP [16] = {
0, 1, 1, 2, 1, 2, 2, 3,
1, 2, 2, 3, 2, 3, 3, 4
};
return NIBBLE_LOOKUP[byte & 0x0F] + NIBBLE_LOOKUP[byte >> 4];
}
size_t alloc_count_free(void* pool) {
(void) pool;
uint8_t* it = pool_header.block_usage;
uint8_t* end = it + pool_header.block_count;
size_t total_free = 0;
while(it < end) {
total_free += count_ones(*it) * 256;
++it;
}
return total_free;
}
size_t alloc_count_continuous(void* pool) {
(void) pool;
size_t largest_block = 0;
uint8_t* it = pool_header.block_usage;
uint8_t* end = it + pool_header.block_count;
size_t current_block = 0;
while(it < end) {
uint8_t t = *it++;
if(!t) {
current_block += 2048;
} else {
for(int i = 7; i >= 0; --i) {
bool bitset = (t & (1 << i));
if(bitset) {
current_block += (7 - i) * 256;
if(largest_block < current_block) {
largest_block = current_block;
current_block = 0;
}
}
}
}
}
return largest_block;
}

View File

@ -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

34
GL/clip.c Normal file
View File

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

22
GL/clip.h Normal file
View File

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

View File

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

1649
GL/draw.c

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -1,142 +1,106 @@
#include <kos.h>
#include "../containers/aligned_vector.h"
#include "private.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;
PolyList* _glOpaquePolyList() {
return &OP_LIST;
}
PolyList* _glPunchThruPolyList() {
return &PT_LIST;
}
PolyList *_glTransparentPolyList() {
return &TR_LIST;
}
void APIENTRY glFlush() {
}
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->internal_palette_format = GL_RGBA4;
config->texture_twiddle = GL_TRUE;
}
static bool _initialized = false;
void APIENTRY glKosInitEx(GLdcConfig* config) {
if(_initialized) {
return;
/* 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;
}
_initialized = true;
TRACE();
printf("\nWelcome to GLdc! Git revision: %s\n\n", GLDC_VERSION);
InitGPU(config->autosort_enabled, config->fsaa_enabled);
AUTOSORT_ENABLED = config->autosort_enabled;
_glInitSubmissionTarget();
_glInitMatrices();
_glInitAttributePointers();
_glInitContext();
_glInitLights();
_glInitImmediateMode(config->initial_immediate_capacity);
_glInitFramebuffers();
_glSetInternalPaletteFormat(config->internal_palette_format);
_glInitTextures();
if(config->texture_twiddle) {
glEnable(GL_TEXTURE_TWIDDLE_KOS);
}
OP_LIST.list_type = GPU_LIST_OP_POLY;
PT_LIST.list_type = GPU_LIST_PT_POLY;
TR_LIST.list_type = GPU_LIST_TR_POLY;
aligned_vector_init(&OP_LIST.vector, sizeof(Vertex));
aligned_vector_init(&PT_LIST.vector, sizeof(Vertex));
aligned_vector_init(&TR_LIST.vector, sizeof(Vertex));
aligned_vector_reserve(&OP_LIST.vector, config->initial_op_capacity);
aligned_vector_reserve(&PT_LIST.vector, config->initial_pt_capacity);
aligned_vector_reserve(&TR_LIST.vector, config->initial_tr_capacity);
/* Wait for both store queues to complete */
d = (GLuint *)0xe0000000;
d[0] = d[8] = 0;
}
void APIENTRY glKosShutdown() {
aligned_vector_clear(&OP_LIST.vector);
aligned_vector_clear(&PT_LIST.vector);
aligned_vector_clear(&TR_LIST.vector);
static void _initPVR() {
pvr_init_params_t params = {
/* Enable opaque and translucent polygons with size 32 and 32 */
{ PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32, PVR_BINSIZE_0, PVR_BINSIZE_32 },
PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
0, /* No DMA */
0, /* No FSAA */
1 /* Disable translucent auto-sorting to match traditional GL */
};
pvr_init(&params);
}
PolyList* activePolyList() {
if(isBlendingEnabled()) {
return &TR_LIST;
} else {
return &OP_LIST;
}
}
void APIENTRY glKosInit() {
GLdcConfig config;
glKosInitConfig(&config);
glKosInitEx(&config);
TRACE();
_initPVR();
initMatrices();
initAttributePointers();
initContext();
initLights();
initImmediateMode();
initFramebuffers();
_glKosInitTextures();
OP_LIST.list_type = PVR_LIST_OP_POLY;
PT_LIST.list_type = PVR_LIST_PT_POLY;
TR_LIST.list_type = PVR_LIST_TR_POLY;
aligned_vector_init(&OP_LIST.vector, sizeof(PVRCommand));
aligned_vector_init(&PT_LIST.vector, sizeof(PVRCommand));
aligned_vector_init(&TR_LIST.vector, sizeof(PVRCommand));
}
void APIENTRY glKosSwapBuffers() {
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();
}
pvr_wait_ready();
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_scene_begin();
pvr_list_begin(PVR_LIST_OP_POLY);
pvr_list_submit(OP_LIST.vector.data, OP_LIST.vector.size);
pvr_list_finish();
if(aligned_vector_header(&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_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);
}

View File

@ -10,13 +10,13 @@ static GLfloat FOG_COLOR [] = {0.0f, 0.0f, 0.0f, 0.0f};
static void updatePVRFog() {
if(FOG_MODE == GL_LINEAR) {
GPUSetFogLinear(FOG_START, FOG_END);
pvr_fog_table_linear(FOG_START, FOG_END);
} else if(FOG_MODE == GL_EXP) {
GPUSetFogExp(FOG_DENSITY);
pvr_fog_table_exp(FOG_DENSITY);
} else if(FOG_MODE == GL_EXP2) {
GPUSetFogExp2(FOG_DENSITY);
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) {
@ -40,6 +40,7 @@ void APIENTRY glFogf(GLenum pname, GLfloat param) {
case GL_FOG_INDEX:
default: {
_glKosThrowError(GL_INVALID_ENUM, __func__);
_glKosPrintError();
}
}
}

View File

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

View File

@ -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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 BACKEND_KOSPVR
#include "platforms/sh4.h"
#else
#include "platforms/software.h"
#endif

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -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));
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

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

68
GL/profile.c Normal file
View File

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

74
GL/profile.h Normal file
View File

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

1041
GL/state.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

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

View File

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

32
Makefile Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,5 +1,3 @@
#pragma once
#ifndef NAMED_ARRAY_H
#define NAMED_ARRAY_H
@ -16,17 +14,8 @@ 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);
void named_array_release(NamedArray* array, unsigned int new_id);
void* named_array_get(NamedArray* array, unsigned int id);
void named_array_cleanup(NamedArray* array);

View File

@ -1,13 +1,10 @@
#include <string.h>
#include <stdlib.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);
}
#ifndef __APPLE__
#include <malloc.h>
#else
#include <malloc.h>
/* Linux + Kos define this, OSX does not, so just use malloc there */
#define memalign(x, size) malloc((size))
#endif
#include "stack.h"

View File

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

View File

@ -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

View File

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

92
include/glext.h Normal file
View File

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

51
include/glkos.h Normal file
View File

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

View File

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

16
samples/Makefile Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
GLboolean mipmapped;
unsigned int dataSize;
} Image;
int dtex_to_gl_texture(texture *tex, char* filename);
void draw_textured_quad(texture *tex);
#endif

View File

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

View File

@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

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

View File

@ -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)

View File

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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

View File

@ -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: %d\n", filename, sizeX);
// read the height
if ((i = fread(&sizeY, 4, 1, file)) != 1) {
printf("Error reading height from %s.\n", filename);
return 0;
}
image->sizeY = sizeY;
printf("Height of %s: %d\n", filename, sizeY);
// calculate the size (assuming 24 bits or 3 bytes per pixel).
size = image->sizeX * image->sizeY * 3;
// read the planes
if ((fread(&planes, 2, 1, file)) != 1) {
printf("Error reading planes from %s.\n", filename);
return 0;
}
if (planes != 1) {
printf("Planes from %s is not 1: %u\n", filename, planes);
return 0;
}
// read the bpp
if ((i = fread(&bpp, 2, 1, file)) != 1) {
printf("Error reading bpp from %s.\n", filename);
return 0;
}
if (bpp != 24) {
printf("Bpp from %s is not 24: %u\n", filename, bpp);
return 0;
}
// seek past the rest of the bitmap header.
fseek(file, offset, SEEK_SET);
// read the data.
image->data = (char *) malloc(size);
if (image->data == NULL) {
printf("Error allocating memory for color-corrected image data");
return 0;
}
if ((i = fread(image->data, size, 1, file)) != 1) {
printf("Error reading image data from %s.\n", filename);
return 0;
}
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
temp = image->data[i];
image->data[i] = image->data[i+2];
image->data[i+2] = temp;
}
// we're done.
return 1;
}

View File

@ -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

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

View File

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

View File

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

29
samples/nehe02/Makefile Normal file
View 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)

View File

@ -1,17 +1,13 @@
#ifdef __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
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 __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()
@ -62,69 +41,25 @@ void DrawGLScene()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(-3.0f, 1.5f, -10.0f); // Move Left 1.5 Units And Into The Screen 6.0
// draw a triangle
glBegin(GL_TRIANGLES); // start drawing a polygon
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // we're done with the polygon
glTranslatef(3.0f, 0.0f, 0.0f); // Move Right 3 Units
// draw a square (quadrilateral)
glBegin(GL_QUADS); // start drawing a polygon (4 sided)
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // done with the polygon
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON); // start drawing a polygon (4 sided)
glVertex3f(-0.0f, 1.0f, 0.0f); // Top Left
glVertex3f(-0.75f, 0.75f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f); // Top Right
glVertex3f(-0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f(-0.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f( 1.0f, 0.0f, 0.0f); // Top Right
glVertex3f( 0.75f, 0.75f, 0.0f);
glEnd(); // done with the polygon
glTranslatef(-6.0f, -3.0f, 0.0f);
glTranslatef(-1.5f,0.0f,-6.0f); // Move Left 1.5 Units And Into The Screen 6.0
// draw a triangle
glBegin(GL_POLYGON); // start drawing a polygon
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 0.0f, 1.0f, 0.0f); // Top
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
glEnd(); // we're done with the polygon
glTranslatef(3.0f, 0.0f, 0.0f); // Move Right 3 Units
glTranslatef(3.0f,0.0f,0.0f); // Move Right 3 Units
// draw a square (quadrilateral)
glBegin(GL_POLYGON); // start drawing a polygon (4 sided)
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right
glVertex3f( 1.0f,-1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f,-1.0f, 0.0f); // Bottom Left
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
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON); // start drawing a polygon (4 sided)
glVertex3f(-0.0f, 1.0f, 0.0f); // Top Left
glVertex3f(-0.75f, 0.75f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f); // Top Right
glVertex3f(-0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f(-0.0f,-1.0f, 0.0f); // Bottom Left
glVertex3f( 0.75f,-0.75f, 0.0f); // Bottom Right
glVertex3f( 1.0f, 0.0f, 0.0f); // Top Right
glVertex3f( 0.75f, 0.75f, 0.0f);
glEnd(); // done with the polygon
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
@ -137,9 +72,6 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

View File

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

29
samples/nehe02va/Makefile Normal file
View 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)

View File

@ -1,10 +1,6 @@
#ifdef __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 __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
View 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)

View File

@ -1,10 +1,6 @@
#ifdef __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 __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();
}

View File

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

View File

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

29
samples/nehe06/Makefile Normal file
View 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)

View File

@ -1,32 +1,107 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef __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 __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,14 +124,12 @@ 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); // 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, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
free(image1);
}
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
};
/* 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.
@ -74,7 +147,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) */
@ -92,23 +165,6 @@ void ReSizeGLScene(int Width, int Height)
glMatrixMode(GL_MODELVIEW);
}
int check_start() {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
if(cont) {
state = (cont_state_t *)maple_dev_status(cont);
if(state)
return state->buttons & CONT_START;
}
#endif
return 0;
}
/* The main drawing function. */
void DrawGLScene()
@ -180,9 +236,6 @@ int main(int argc, char **argv)
ReSizeGLScene(640, 480);
while(1) {
if(check_start())
break;
DrawGLScene();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 192 KiB

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