Merge branch GLdc:master into master
This commit is contained in:
commit
810d0fdc19
@ -22,7 +22,7 @@ string(TOUPPER ${BACKEND} BACKEND_UPPER)
|
||||
add_definitions(-DBACKEND_${BACKEND_UPPER})
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
include_directories(include)
|
||||
|
||||
@ -68,6 +68,7 @@ set(
|
||||
containers/aligned_vector.c
|
||||
containers/named_array.c
|
||||
containers/stack.c
|
||||
GL/attributes.c
|
||||
GL/draw.c
|
||||
GL/error.c
|
||||
GL/flush.c
|
||||
@ -209,6 +210,7 @@ gen_sample(scissor samples/scissor/main.c)
|
||||
gen_sample(polymark samples/polymark/main.c)
|
||||
gen_sample(cubes samples/cubes/main.cpp)
|
||||
gen_sample(zclip_test tests/zclip/main.cpp)
|
||||
gen_sample(primitive_modes samples/primitive_modes/main.c)
|
||||
|
||||
if(PLATFORM_DREAMCAST)
|
||||
gen_sample(trimark samples/trimark/main.c)
|
||||
|
||||
@ -244,13 +244,17 @@ int alloc_init(void* pool, size_t size) {
|
||||
|
||||
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;
|
||||
|
||||
/* The pool size might be less than the passed size if the memory
|
||||
* wasn't aligned to 2048 */
|
||||
pool_header.pool_size = pool_header.block_count * 2048;
|
||||
|
||||
pool_header.allocations = NULL;
|
||||
|
||||
assert(((uintptr_t) pool_header.base_address) % 2048 == 0);
|
||||
@ -292,7 +296,7 @@ static inline void block_and_offset_from_subblock(size_t sb, size_t* b, uint8_t*
|
||||
*off = (sb % 8);
|
||||
}
|
||||
|
||||
void* alloc_malloc(void* pool, size_t size) {
|
||||
static void* alloc_malloc_internal(void* pool, size_t size, bool for_defrag) {
|
||||
DBG_MSG("Allocating: %d\n", size);
|
||||
|
||||
size_t start_subblock, required_subblocks;
|
||||
@ -335,6 +339,11 @@ void* alloc_malloc(void* pool, size_t size) {
|
||||
pool_header.block_usage[block++] |= mask;
|
||||
}
|
||||
|
||||
// defrag allocations don't create new entries, they reuse old ones
|
||||
if(for_defrag) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Insert allocations in the list by size descending so that when we
|
||||
* defrag we can move the larger blocks before the smaller ones without
|
||||
* much effort */
|
||||
@ -376,6 +385,10 @@ void* alloc_malloc(void* pool, size_t size) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void* alloc_malloc(void* pool, size_t size) {
|
||||
return alloc_malloc_internal(pool, size, false);
|
||||
}
|
||||
|
||||
static void alloc_release_blocks(struct AllocEntry* it) {
|
||||
size_t used_subblocks = size_to_subblock_count(it->size);
|
||||
size_t subblock = subblock_from_pointer(it->pointer);
|
||||
@ -433,14 +446,14 @@ void alloc_free(void* pool, void* p) {
|
||||
|
||||
DBG_MSG("Freed: size: %d, us: %d, sb: %d, off: %d\n", it->size, used_subblocks, block, offset);
|
||||
free(it);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
last = it;
|
||||
it = it->next;
|
||||
}
|
||||
|
||||
DBG_MSG("Free done\n");
|
||||
assert("Freed pointer not found, heap corruption?" && 0);
|
||||
}
|
||||
|
||||
void alloc_run_defrag(void* pool, defrag_address_move callback, int max_iterations, void* user_data) {
|
||||
@ -456,8 +469,8 @@ void alloc_run_defrag(void* pool, defrag_address_move callback, int max_iteratio
|
||||
|
||||
while(it) {
|
||||
void* potential_dest = alloc_next_available(pool, it->size);
|
||||
if(potential_dest < it->pointer) {
|
||||
potential_dest = alloc_malloc(pool, it->size);
|
||||
if(potential_dest && potential_dest < it->pointer) {
|
||||
potential_dest = alloc_malloc_internal(pool, it->size, true);
|
||||
memcpy(potential_dest, it->pointer, it->size);
|
||||
|
||||
/* Mark this block as now free, but don't fiddle with the
|
||||
@ -490,45 +503,39 @@ static inline uint8_t count_ones(uint8_t byte) {
|
||||
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_used = 0;
|
||||
|
||||
size_t total_free = 0;
|
||||
|
||||
while(it < end) {
|
||||
total_free += count_ones(*it) * 256;
|
||||
++it;
|
||||
for(size_t i = 0; i < pool_header.block_count; ++i) {
|
||||
total_used += count_ones(pool_header.block_usage[i]) * 256;
|
||||
}
|
||||
|
||||
return total_free;
|
||||
return pool_header.pool_size - total_used;
|
||||
}
|
||||
|
||||
size_t alloc_count_continuous(void* pool) {
|
||||
(void) pool;
|
||||
|
||||
size_t largest_block = 0;
|
||||
size_t contiguous_free = 0;
|
||||
size_t most_contiguous = 0;
|
||||
|
||||
uint8_t* it = pool_header.block_usage;
|
||||
uint8_t* end = it + pool_header.block_count;
|
||||
for(size_t i = 0; i < pool_header.block_count; ++i) {
|
||||
uint8_t t = pool_header.block_usage[i];
|
||||
|
||||
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;
|
||||
}
|
||||
for(int i = 7; i >= 0; --i) {
|
||||
bool bitset = (t & (1 << i));
|
||||
if(!bitset) {
|
||||
++contiguous_free;
|
||||
} else {
|
||||
if(contiguous_free > most_contiguous) {
|
||||
most_contiguous = contiguous_free;
|
||||
}
|
||||
contiguous_free = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return largest_block;
|
||||
if(contiguous_free > most_contiguous) {
|
||||
most_contiguous = contiguous_free;
|
||||
}
|
||||
return most_contiguous * 256;
|
||||
}
|
||||
|
||||
675
GL/attributes.c
Normal file
675
GL/attributes.c
Normal file
@ -0,0 +1,675 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "platform.h"
|
||||
|
||||
AttribPointerList ATTRIB_LIST;
|
||||
static const float ONE_OVER_TWO_FIVE_FIVE = 1.0f / 255.0f;
|
||||
|
||||
GL_FORCE_INLINE GLsizei byte_size(GLenum type) {
|
||||
switch(type) {
|
||||
case GL_BYTE: return sizeof(GLbyte);
|
||||
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
|
||||
case GL_SHORT: return sizeof(GLshort);
|
||||
case GL_UNSIGNED_SHORT: return sizeof(GLushort);
|
||||
case GL_INT: return sizeof(GLint);
|
||||
case GL_UNSIGNED_INT: return sizeof(GLuint);
|
||||
case GL_DOUBLE: return sizeof(GLdouble);
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV: return sizeof(GLuint);
|
||||
case GL_FLOAT:
|
||||
default: return sizeof(GLfloat);
|
||||
}
|
||||
}
|
||||
|
||||
// Used to avoid checking and updating attribute related state unless necessary
|
||||
GL_FORCE_INLINE GLboolean _glStateUnchanged(AttribPointer* p, GLint size, GLenum type, GLsizei stride) {
|
||||
return (p->size == size && p->type == type && p->stride == stride);
|
||||
}
|
||||
|
||||
GLuint* _glGetEnabledAttributes() {
|
||||
return &ATTRIB_LIST.enabled;
|
||||
}
|
||||
|
||||
|
||||
static void _readPosition3f3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
const float* input = (const float*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3ub3f(const GLubyte* input, GLubyte* out) {
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float y = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float z = input[2] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3us3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition3ui3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = input[2];
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2f3f(const GLubyte* in, GLubyte* out) {
|
||||
const float* input = (const float*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2ub3f(const GLubyte* input, GLubyte* out) {
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float y = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2us3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
Vertex* it = (Vertex*) out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static void _readPosition2ui3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
Vertex* it = (Vertex*)out;
|
||||
|
||||
float x = input[0];
|
||||
float y = input[1];
|
||||
float z = 0.0f;
|
||||
float w = 1.0f;
|
||||
TransformVertex(x, y, z, w, it->xyz, &it->w);
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadPositionFunc() {
|
||||
switch(ATTRIB_LIST.vertex.type) {
|
||||
default:
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3f3f:
|
||||
_readPosition2f3f;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3ub3f:
|
||||
_readPosition2ub3f;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3us3f:
|
||||
_readPosition2us3f;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3ui3f:
|
||||
_readPosition2ui3f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _fillWhiteARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
|
||||
_GL_UNUSED(input);
|
||||
*((uint32_t*) output) = ~0;
|
||||
}
|
||||
|
||||
static void _readColour4ubARGB(const GLubyte* input, GLubyte* output) {
|
||||
output[R8IDX] = input[0];
|
||||
output[G8IDX] = input[1];
|
||||
output[B8IDX] = input[2];
|
||||
output[A8IDX] = input[3];
|
||||
}
|
||||
|
||||
static void _readColour4fARGB(const GLubyte* in, GLubyte* output) {
|
||||
const float* input = (const float*) in;
|
||||
|
||||
output[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
|
||||
output[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
|
||||
output[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
|
||||
output[A8IDX] = (GLubyte) clamp(input[3] * 255.0f, 0, 255);
|
||||
}
|
||||
|
||||
static void _readColour3fARGB(const GLubyte* in, GLubyte* output) {
|
||||
const float* input = (const float*) in;
|
||||
|
||||
output[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
|
||||
output[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
|
||||
output[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
|
||||
output[A8IDX] = 255;
|
||||
}
|
||||
|
||||
static void _readColour3ubARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
|
||||
output[R8IDX] = input[0];
|
||||
output[G8IDX] = input[1];
|
||||
output[B8IDX] = input[2];
|
||||
output[A8IDX] = 255;
|
||||
}
|
||||
|
||||
static void _readColour4ubRevARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
|
||||
argbcpy(output, input);
|
||||
}
|
||||
|
||||
static void _readColour4fRevARGB(const GLubyte* __restrict__ in, GLubyte* __restrict__ output) {
|
||||
const float* input = (const float*) in;
|
||||
|
||||
output[0] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
|
||||
output[1] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
|
||||
output[2] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
|
||||
output[3] = (GLubyte) clamp(input[3] * 255.0f, 0, 255);
|
||||
}
|
||||
|
||||
static void _readColour3usARGB(const GLubyte* input, GLubyte* output) {
|
||||
_GL_UNUSED(input);
|
||||
_GL_UNUSED(output);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readColour3uiARGB(const GLubyte* input, GLubyte* output) {
|
||||
_GL_UNUSED(input);
|
||||
_GL_UNUSED(output);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readColour4usARGB(const GLubyte* input, GLubyte* output) {
|
||||
_GL_UNUSED(input);
|
||||
_GL_UNUSED(output);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readColour4uiARGB(const GLubyte* input, GLubyte* output) {
|
||||
_GL_UNUSED(input);
|
||||
_GL_UNUSED(output);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readColour4usRevARGB(const GLubyte* input, GLubyte* output) {
|
||||
_GL_UNUSED(input);
|
||||
_GL_UNUSED(output);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readColour4uiRevARGB(const GLubyte* input, GLubyte* output) {
|
||||
_GL_UNUSED(input);
|
||||
_GL_UNUSED(output);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadDiffuseFunc() {
|
||||
if((ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG) != DIFFUSE_ENABLED_FLAG) {
|
||||
/* Just fill the whole thing white if the attribute is disabled */
|
||||
return _fillWhiteARGB;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.colour.type) {
|
||||
default:
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3fARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4fARGB:
|
||||
_readColour4fRevARGB;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3ubARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4ubARGB:
|
||||
_readColour4ubRevARGB;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3usARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4usARGB:
|
||||
_readColour4usRevARGB;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return (ATTRIB_LIST.colour.size == 3) ? _readColour3uiARGB:
|
||||
(ATTRIB_LIST.colour.size == 4) ? _readColour4uiARGB:
|
||||
_readColour4uiRevARGB;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _fillZero2f(const GLubyte* __restrict__ input, GLubyte* __restrict__ out) {
|
||||
_GL_UNUSED(input);
|
||||
//memset(out, 0, sizeof(float) * 2);
|
||||
// memset does 8 byte writes - faster to manually write as uint32
|
||||
uint32_t* dst = (uint32_t*)out;
|
||||
dst[0] = 0;
|
||||
dst[1] = 0;
|
||||
}
|
||||
|
||||
static void _readTexcoord2f2f(const GLubyte* in, GLubyte* out) {
|
||||
vec2cpy(out, in);
|
||||
}
|
||||
|
||||
static void _readTexcoord2ub2f(const GLubyte* input, GLubyte* out) {
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
output[1] = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
}
|
||||
|
||||
static void _readTexcoord2us2f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = (float)input[0] / SHRT_MAX;
|
||||
output[1] = (float)input[1] / SHRT_MAX;
|
||||
}
|
||||
|
||||
static void _readTexcoord2ui2f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadUVFunc() {
|
||||
if((ATTRIB_LIST.enabled & UV_ENABLED_FLAG) != UV_ENABLED_FLAG) {
|
||||
return _fillZero2f;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.uv.type) {
|
||||
default:
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
return _readTexcoord2f2f;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return _readTexcoord2ub2f;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return _readTexcoord2us2f;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return _readTexcoord2ui2f;
|
||||
}
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadSTFunc() {
|
||||
if((ATTRIB_LIST.enabled & ST_ENABLED_FLAG) != ST_ENABLED_FLAG) {
|
||||
return _fillZero2f;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.st.type) {
|
||||
default:
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
return _readTexcoord2f2f;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return _readTexcoord2ub2f;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return _readTexcoord2us2f;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return _readTexcoord2ui2f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _fillWithNegZVE(const GLubyte* __restrict__ input, GLubyte* __restrict__ out) {
|
||||
_GL_UNUSED(input);
|
||||
typedef struct { float x, y, z; } V;
|
||||
|
||||
static const V NegZ = {0.0f, 0.0f, -1.0f};
|
||||
|
||||
*((V*) out) = NegZ;
|
||||
}
|
||||
|
||||
static void _readNormal3f3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
|
||||
vec3cpy(out, in);
|
||||
}
|
||||
|
||||
static void _readNormal3ub3f(const GLubyte* input, GLubyte* out) {
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
output[1] = input[1] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
output[2] = input[2] * ONE_OVER_TWO_FIVE_FIVE;
|
||||
}
|
||||
|
||||
static void _readNormal3us3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLushort* input = (const GLushort*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
output[2] = input[2];
|
||||
}
|
||||
|
||||
static void _readNormal3ui3f(const GLubyte* in, GLubyte* out) {
|
||||
const GLuint* input = (const GLuint*) in;
|
||||
float* output = (float*) out;
|
||||
|
||||
output[0] = input[0];
|
||||
output[1] = input[1];
|
||||
output[2] = input[2];
|
||||
}
|
||||
|
||||
// 10:10:10:2REV format
|
||||
static void _readNormal1i3f(const GLubyte* in, GLubyte* out) {
|
||||
static const float MULTIPLIER = 1.0f / 1023.0f;
|
||||
|
||||
GLfloat* output = (GLfloat*) out;
|
||||
|
||||
union {
|
||||
int value;
|
||||
struct {
|
||||
signed int x: 10;
|
||||
signed int y: 10;
|
||||
signed int z: 10;
|
||||
signed int w: 2;
|
||||
} bits;
|
||||
} input;
|
||||
|
||||
input.value = *((const GLint*) in);
|
||||
|
||||
output[0] = (2.0f * (float) input.bits.x + 1.0f) * MULTIPLIER;
|
||||
output[1] = (2.0f * (float) input.bits.y + 1.0f) * MULTIPLIER;
|
||||
output[2] = (2.0f * (float) input.bits.z + 1.0f) * MULTIPLIER;
|
||||
}
|
||||
|
||||
static ReadAttributeFunc calcReadNormalFunc() {
|
||||
if((ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG) != NORMAL_ENABLED_FLAG) {
|
||||
return _fillWithNegZVE;
|
||||
}
|
||||
|
||||
switch(ATTRIB_LIST.normal.type) {
|
||||
default:
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
return _readNormal3f3f;
|
||||
break;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return _readNormal3ub3f;
|
||||
break;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return _readNormal3us3f;
|
||||
break;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
return _readNormal3ui3f;
|
||||
break;
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV:
|
||||
return _readNormal1i3f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glEnableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ATTRIB_LIST.enabled |= VERTEX_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= VERTEX_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
ATTRIB_LIST.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= DIFFUSE_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
ATTRIB_LIST.enabled |= NORMAL_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= NORMAL_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.enabled |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.enabled |= UV_ENABLED_FLAG);
|
||||
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.dirty |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.dirty |= UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void APIENTRY glDisableClientState(GLenum cap) {
|
||||
TRACE();
|
||||
|
||||
switch(cap) {
|
||||
case GL_VERTEX_ARRAY:
|
||||
ATTRIB_LIST.enabled &= ~VERTEX_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= VERTEX_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_COLOR_ARRAY:
|
||||
ATTRIB_LIST.enabled &= ~DIFFUSE_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= DIFFUSE_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_NORMAL_ARRAY:
|
||||
ATTRIB_LIST.enabled &= ~NORMAL_ENABLED_FLAG;
|
||||
ATTRIB_LIST.dirty |= NORMAL_ENABLED_FLAG;
|
||||
break;
|
||||
case GL_TEXTURE_COORD_ARRAY:
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.enabled &= ~ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.enabled &= ~UV_ENABLED_FLAG);
|
||||
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.dirty |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.dirty |= UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
stride = (stride) ? stride : size * byte_size(type);
|
||||
AttribPointer* tointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &ATTRIB_LIST.uv : &ATTRIB_LIST.st;
|
||||
tointer->ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(tointer, size, type, stride)) return;
|
||||
|
||||
if(size < 1 || size > 4) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
tointer->stride = stride;
|
||||
tointer->type = type;
|
||||
tointer->size = size;
|
||||
|
||||
(ACTIVE_CLIENT_TEXTURE) ?
|
||||
(ATTRIB_LIST.dirty |= ST_ENABLED_FLAG):
|
||||
(ATTRIB_LIST.dirty |= UV_ENABLED_FLAG);
|
||||
}
|
||||
|
||||
void APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
stride = (stride) ? stride : (size * byte_size(type));
|
||||
ATTRIB_LIST.vertex.ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(&ATTRIB_LIST.vertex, size, type, stride)) return;
|
||||
|
||||
if(size < 2 || size > 4) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ATTRIB_LIST.vertex.stride = stride;
|
||||
ATTRIB_LIST.vertex.type = type;
|
||||
ATTRIB_LIST.vertex.size = size;
|
||||
|
||||
ATTRIB_LIST.dirty |= VERTEX_ENABLED_FLAG;
|
||||
}
|
||||
|
||||
void APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
stride = (stride) ? stride : ((size == GL_BGRA) ? 4 : size) * byte_size(type);
|
||||
ATTRIB_LIST.colour.ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(&ATTRIB_LIST.colour, size, type, stride)) return;
|
||||
|
||||
if(size != 3 && size != 4 && size != GL_BGRA) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ATTRIB_LIST.colour.type = type;
|
||||
ATTRIB_LIST.colour.size = size;
|
||||
ATTRIB_LIST.colour.stride = stride;
|
||||
|
||||
ATTRIB_LIST.dirty |= DIFFUSE_ENABLED_FLAG;
|
||||
}
|
||||
|
||||
void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
GLint validTypes[] = {
|
||||
GL_DOUBLE,
|
||||
GL_FLOAT,
|
||||
GL_BYTE,
|
||||
GL_UNSIGNED_BYTE,
|
||||
GL_INT,
|
||||
GL_UNSIGNED_INT,
|
||||
GL_UNSIGNED_INT_2_10_10_10_REV,
|
||||
0
|
||||
};
|
||||
|
||||
stride = (stride) ? stride : ATTRIB_LIST.normal.size * byte_size(type);
|
||||
ATTRIB_LIST.normal.ptr = pointer;
|
||||
|
||||
if(_glStateUnchanged(&ATTRIB_LIST.normal, 3, type, stride)) return;
|
||||
|
||||
if(_glCheckValidEnum(type, validTypes, __func__) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ATTRIB_LIST.normal.size = (type == GL_UNSIGNED_INT_2_10_10_10_REV) ? 1 : 3;
|
||||
ATTRIB_LIST.normal.stride = stride;
|
||||
ATTRIB_LIST.normal.type = type;
|
||||
|
||||
ATTRIB_LIST.dirty |= NORMAL_ENABLED_FLAG;
|
||||
}
|
||||
|
||||
|
||||
void _glInitAttributePointers() {
|
||||
TRACE();
|
||||
ATTRIB_LIST.dirty = ~0; // all attributes dirty
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, NULL);
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, NULL);
|
||||
glColorPointer(4, GL_FLOAT, 0, NULL);
|
||||
glNormalPointer(GL_FLOAT, 0, NULL);
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE GLuint _glIsVertexDataFastPathCompatible() {
|
||||
/* The fast path is enabled when all enabled elements of the vertex
|
||||
* match the output format. This means:
|
||||
*
|
||||
* xyz == 3f
|
||||
* uv == 2f
|
||||
* rgba == argb4444
|
||||
* st == 2f
|
||||
* normal == 3f
|
||||
*
|
||||
* When this happens we do inline straight copies of the enabled data
|
||||
* and transforms for positions and normals happen while copying.
|
||||
*/
|
||||
|
||||
if((ATTRIB_LIST.enabled & VERTEX_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.vertex.size != 3 || ATTRIB_LIST.vertex.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & UV_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.uv.size != 2 || ATTRIB_LIST.uv.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG)) {
|
||||
/* FIXME: Shouldn't this be a reversed format? */
|
||||
if(ATTRIB_LIST.colour.size != GL_BGRA || ATTRIB_LIST.colour.type != GL_UNSIGNED_BYTE) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & ST_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.st.size != 2 || ATTRIB_LIST.st.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if((ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG)) {
|
||||
if(ATTRIB_LIST.normal.size != 3 || ATTRIB_LIST.normal.type != GL_FLOAT) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
void _glUpdateAttributes() {
|
||||
if(ATTRIB_LIST.dirty & VERTEX_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.vertex_func = calcReadPositionFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & UV_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.uv_func = calcReadUVFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & DIFFUSE_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.colour_func = calcReadDiffuseFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & ST_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.st_func = calcReadSTFunc();
|
||||
}
|
||||
|
||||
if(ATTRIB_LIST.dirty & NORMAL_ENABLED_FLAG) {
|
||||
ATTRIB_LIST.normal_func = calcReadNormalFunc();
|
||||
}
|
||||
|
||||
ATTRIB_LIST.fast_path = _glIsVertexDataFastPathCompatible();
|
||||
ATTRIB_LIST.dirty = 0;
|
||||
}
|
||||
@ -5,8 +5,7 @@
|
||||
|
||||
MAKE_FUNC(POLYMODE)
|
||||
{
|
||||
static const float w = 1.0f;
|
||||
if(!(ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG)) {
|
||||
if(!(ATTRIB_LIST.enabled & VERTEX_ENABLED_FLAG)) {
|
||||
/* If we don't have vertices, do nothing */
|
||||
return;
|
||||
}
|
||||
@ -29,8 +28,8 @@ MAKE_FUNC(POLYMODE)
|
||||
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;
|
||||
stride = ATTRIB_LIST.uv.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & UV_ENABLED_FLAG) ? ATTRIB_LIST.uv.ptr + ((first + min) * stride) : NULL;
|
||||
it = (Vertex*) start;
|
||||
|
||||
if(ptr) {
|
||||
@ -48,8 +47,8 @@ MAKE_FUNC(POLYMODE)
|
||||
}
|
||||
}
|
||||
|
||||
stride = ATTRIB_POINTERS.colour.stride;
|
||||
ptr = (ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) ? ATTRIB_POINTERS.colour.ptr + (offset * stride) : NULL;
|
||||
stride = ATTRIB_LIST.colour.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG) ? ATTRIB_LIST.colour.ptr + (offset * stride) : NULL;
|
||||
it = (Vertex*) start;
|
||||
|
||||
if(ptr) {
|
||||
@ -68,22 +67,22 @@ MAKE_FUNC(POLYMODE)
|
||||
}
|
||||
}
|
||||
|
||||
stride = ATTRIB_POINTERS.vertex.stride;
|
||||
ptr = ATTRIB_POINTERS.vertex.ptr + (offset * stride);
|
||||
stride = ATTRIB_LIST.vertex.stride;
|
||||
ptr = ATTRIB_LIST.vertex.ptr + (offset * stride);
|
||||
it = (Vertex*) start;
|
||||
|
||||
PREFETCH(ptr);
|
||||
for(int_fast32_t i = 0; i < loop; ++i, ++it) {
|
||||
PREFETCH(ptr + stride);
|
||||
TransformVertex((const float*) ptr, &w, it->xyz, &it->w);
|
||||
TransformVertex(((float*) ptr)[0], ((float*) ptr)[1], ((float*) ptr)[2], 1.0f, it->xyz, &it->w);
|
||||
PROCESS_VERTEX_FLAGS(it, min + i);
|
||||
ptr += stride;
|
||||
}
|
||||
|
||||
start = aligned_vector_at(target->extras, min);
|
||||
|
||||
stride = ATTRIB_POINTERS.st.stride;
|
||||
ptr = (ENABLED_VERTEX_ATTRIBUTES & ST_ENABLED_FLAG) ? ATTRIB_POINTERS.st.ptr + (offset * stride) : NULL;
|
||||
stride = ATTRIB_LIST.st.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & ST_ENABLED_FLAG) ? ATTRIB_LIST.st.ptr + (offset * stride) : NULL;
|
||||
ve = (VertexExtra*) start;
|
||||
|
||||
if(ptr) {
|
||||
@ -102,8 +101,8 @@ MAKE_FUNC(POLYMODE)
|
||||
}
|
||||
}
|
||||
|
||||
stride = ATTRIB_POINTERS.normal.stride;
|
||||
ptr = (ENABLED_VERTEX_ATTRIBUTES & NORMAL_ENABLED_FLAG) ? ATTRIB_POINTERS.normal.ptr + (offset * stride) : NULL;
|
||||
stride = ATTRIB_LIST.normal.stride;
|
||||
ptr = (ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG) ? ATTRIB_LIST.normal.ptr + (offset * stride) : NULL;
|
||||
ve = (VertexExtra*) start;
|
||||
|
||||
if(ptr) {
|
||||
|
||||
27
GL/error.c
27
GL/error.c
@ -12,8 +12,31 @@
|
||||
|
||||
#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' };
|
||||
|
||||
GL_FORCE_INLINE const char* _glErrorEnumAsString(GLenum error) {
|
||||
switch(error) {
|
||||
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
|
||||
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
|
||||
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
|
||||
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
|
||||
default:
|
||||
return "GL_UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
void _glKosThrowError(GLenum error, const char *function) {
|
||||
if(LAST_ERROR == GL_NO_ERROR) {
|
||||
LAST_ERROR = error;
|
||||
sprintf(ERROR_FUNCTION, "%s\n", function);
|
||||
fprintf(stderr, "GL ERROR: %s when calling %s\n", _glErrorEnumAsString(LAST_ERROR), ERROR_FUNCTION);
|
||||
}
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glKosResetError() {
|
||||
LAST_ERROR = GL_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Quoth the GL Spec:
|
||||
When an error occurs, the error flag is set to the appropriate error code
|
||||
|
||||
8
GL/glu.c
8
GL/glu.c
@ -2,11 +2,11 @@
|
||||
#include "private.h"
|
||||
|
||||
/* Set the Perspective */
|
||||
void APIENTRY gluPerspective(GLfloat angle, GLfloat aspect,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
GLfloat fW, fH;
|
||||
void APIENTRY gluPerspective(GLdouble angle, GLdouble aspect,
|
||||
GLdouble znear, GLdouble zfar) {
|
||||
GLdouble fW, fH;
|
||||
|
||||
fH = tanf(angle * (M_PI / 360.0f)) * znear;
|
||||
fH = tan(angle * (M_PI / 360.0)) * znear;
|
||||
fW = fH * aspect;
|
||||
|
||||
glFrustum(-fW, fW, -fH, fH, znear, zfar);
|
||||
|
||||
108
GL/immediate.c
108
GL/immediate.c
@ -12,8 +12,6 @@
|
||||
|
||||
#include "private.h"
|
||||
|
||||
extern inline GLuint _glRecalcFastPath();
|
||||
|
||||
GLboolean IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
static GLenum ACTIVE_POLYGON_MODE = GL_TRIANGLES;
|
||||
|
||||
@ -49,6 +47,7 @@ typedef struct __attribute__((aligned(32))) {
|
||||
void _glInitImmediateMode(GLuint initial_size) {
|
||||
aligned_vector_init(&VERTICES, sizeof(IMVertex));
|
||||
aligned_vector_reserve(&VERTICES, initial_size);
|
||||
IM_ATTRIBS.fast_path = GL_TRUE;
|
||||
|
||||
IM_ATTRIBS.vertex.ptr = aligned_vector_front(&VERTICES);
|
||||
IM_ATTRIBS.vertex.size = 3;
|
||||
@ -87,7 +86,7 @@ void APIENTRY glBegin(GLenum mode) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = (GLubyte)(a * 255.0f);
|
||||
COLOR[R8IDX] = (GLubyte)(r * 255.0f);
|
||||
@ -96,7 +95,7 @@ void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = a;
|
||||
COLOR[R8IDX] = r;
|
||||
@ -105,7 +104,7 @@ void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor4ubv(const GLubyte *v) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = v[3];
|
||||
COLOR[R8IDX] = v[0];
|
||||
@ -114,7 +113,7 @@ void APIENTRY glColor4ubv(const GLubyte *v) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor4fv(const GLfloat* v) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[B8IDX] = (GLubyte)(v[2] * 255);
|
||||
COLOR[G8IDX] = (GLubyte)(v[1] * 255);
|
||||
@ -123,7 +122,7 @@ void APIENTRY glColor4fv(const GLfloat* v) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[B8IDX] = (GLubyte)(b * 255.0f);
|
||||
COLOR[G8IDX] = (GLubyte)(g * 255.0f);
|
||||
@ -132,7 +131,7 @@ void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[R8IDX] = red;
|
||||
@ -141,7 +140,7 @@ void APIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor3ubv(const GLubyte *v) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[R8IDX] = v[0];
|
||||
@ -150,7 +149,7 @@ void APIENTRY glColor3ubv(const GLubyte *v) {
|
||||
}
|
||||
|
||||
void APIENTRY glColor3fv(const GLfloat* v) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= DIFFUSE_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= DIFFUSE_ENABLED_FLAG;
|
||||
|
||||
COLOR[A8IDX] = 255;
|
||||
COLOR[R8IDX] = (GLubyte)(v[0] * 255);
|
||||
@ -158,30 +157,31 @@ void APIENTRY glColor3fv(const GLfloat* v) {
|
||||
COLOR[B8IDX] = (GLubyte)(v[2] * 255);
|
||||
}
|
||||
|
||||
typedef union punned {
|
||||
GLubyte* byte;
|
||||
GLfloat* flt;
|
||||
uint32_t* u32;
|
||||
void* vptr;
|
||||
uintptr_t uptr;
|
||||
} punned_t;
|
||||
|
||||
void APIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= VERTEX_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= VERTEX_ENABLED_FLAG;
|
||||
|
||||
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]);
|
||||
punned_t dest = { .flt = &vert->x };
|
||||
*(dest.flt++) = x;
|
||||
*(dest.flt++) = y;
|
||||
*(dest.flt++) = z;
|
||||
*(dest.flt++) = UV_COORD[0];
|
||||
*(dest.flt++) = UV_COORD[1];
|
||||
*(dest.flt++) = ST_COORD[0];
|
||||
*(dest.flt++) = ST_COORD[1];
|
||||
*(dest.u32++) = *((uint32_t*)(void*) COLOR);
|
||||
*(dest.flt++) = NORMAL[0];
|
||||
*(dest.flt++) = NORMAL[1];
|
||||
*(dest.flt++) = NORMAL[2];
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3fv(const GLfloat* v) {
|
||||
@ -207,11 +207,11 @@ void APIENTRY glVertex4fv(const GLfloat* v) {
|
||||
|
||||
void APIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
|
||||
if(target == GL_TEXTURE0) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= UV_ENABLED_FLAG;
|
||||
UV_COORD[0] = s;
|
||||
UV_COORD[1] = t;
|
||||
} else if(target == GL_TEXTURE1) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= ST_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= ST_ENABLED_FLAG;
|
||||
ST_COORD[0] = s;
|
||||
ST_COORD[1] = t;
|
||||
} else {
|
||||
@ -221,7 +221,7 @@ void APIENTRY glMultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) {
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoord1f(GLfloat u) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= UV_ENABLED_FLAG;
|
||||
UV_COORD[0] = u;
|
||||
UV_COORD[1] = 0.0f;
|
||||
}
|
||||
@ -231,7 +231,7 @@ void APIENTRY glTexCoord1fv(const GLfloat* v) {
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoord2f(GLfloat u, GLfloat v) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= UV_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= UV_ENABLED_FLAG;
|
||||
UV_COORD[0] = u;
|
||||
UV_COORD[1] = v;
|
||||
}
|
||||
@ -241,7 +241,7 @@ void APIENTRY glTexCoord2fv(const GLfloat* v) {
|
||||
}
|
||||
|
||||
void APIENTRY glNormal3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
IM_ENABLED_VERTEX_ATTRIBUTES |= NORMAL_ENABLED_FLAG;
|
||||
IM_ATTRIBS.enabled |= NORMAL_ENABLED_FLAG;
|
||||
NORMAL[0] = x;
|
||||
NORMAL[1] = y;
|
||||
NORMAL[2] = z;
|
||||
@ -254,38 +254,22 @@ void APIENTRY glNormal3fv(const GLfloat* v) {
|
||||
void APIENTRY glEnd() {
|
||||
IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
|
||||
GLuint* attrs = &ENABLED_VERTEX_ATTRIBUTES;
|
||||
|
||||
/* Redirect attrib pointers */
|
||||
AttribPointerList stashed_attrib_pointers = ATTRIB_POINTERS;
|
||||
ATTRIB_POINTERS = IM_ATTRIBS;
|
||||
|
||||
GLuint prevAttrs = *attrs;
|
||||
|
||||
*attrs = IM_ENABLED_VERTEX_ATTRIBUTES;
|
||||
|
||||
/* 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
|
||||
/* 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;
|
||||
|
||||
/* Redirect attrib state */
|
||||
AttribPointerList stashed_state = ATTRIB_LIST;
|
||||
ATTRIB_LIST = IM_ATTRIBS;
|
||||
|
||||
glDrawArrays(ACTIVE_POLYGON_MODE, 0, aligned_vector_header(&VERTICES)->size);
|
||||
|
||||
ATTRIB_POINTERS = stashed_attrib_pointers;
|
||||
|
||||
*attrs = prevAttrs;
|
||||
ATTRIB_LIST = stashed_state;
|
||||
|
||||
aligned_vector_clear(&VERTICES);
|
||||
|
||||
FAST_PATH_ENABLED = fp_was_enabled;
|
||||
}
|
||||
|
||||
void APIENTRY glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) {
|
||||
|
||||
@ -58,10 +58,10 @@ void _glPrecalcLightingValues(GLuint mask) {
|
||||
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]);
|
||||
material->baseColour[0] = scene_ambient[0] * material->ambient[0] + material->emissive[0];
|
||||
material->baseColour[1] = scene_ambient[1] * material->ambient[1] + material->emissive[1];
|
||||
material->baseColour[2] = scene_ambient[2] * material->ambient[2] + material->emissive[2];
|
||||
material->baseColour[3] = scene_ambient[3] * material->ambient[3] + material->emissive[3];
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,14 +499,14 @@ GL_FORCE_INLINE void _glLightVertexPoint(
|
||||
#undef _PROCESS_COMPONENT
|
||||
}
|
||||
|
||||
void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count) {
|
||||
void _glPerformLighting(Vertex* vertices, VertexExtra* extra, const uint32_t count) {
|
||||
GLubyte i;
|
||||
GLuint j;
|
||||
|
||||
Material* material = _glActiveMaterial();
|
||||
|
||||
Vertex* vertex = vertices;
|
||||
EyeSpaceData* data = es;
|
||||
VertexExtra* data = extra;
|
||||
|
||||
/* Calculate the colour material function once */
|
||||
void (*updateColourMaterial)(const GLubyte*) = NULL;
|
||||
@ -529,32 +529,29 @@ void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the ambient lighting and set up colour material */
|
||||
if(!_glEnabledLightCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(j = 0; j < count; ++j, ++vertex, ++data) {
|
||||
/* Calculate the ambient lighting and set up colour material */
|
||||
if(updateColourMaterial) {
|
||||
updateColourMaterial(vertex->bgra);
|
||||
}
|
||||
|
||||
/* Copy the base colour across */
|
||||
vec4cpy(data->finalColour, material->baseColour);
|
||||
}
|
||||
float finalColour[4];
|
||||
vec4cpy(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];
|
||||
const float Nx = data->nxyz[0];
|
||||
const float Ny = data->nxyz[1];
|
||||
const float Nz = data->nxyz[2];
|
||||
|
||||
for(i = 0; i < MAX_GLDC_LIGHTS; ++i) {
|
||||
LightSource* light = _glLightAt(i);
|
||||
@ -588,7 +585,7 @@ void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count
|
||||
if(NdotH < 0.0f) NdotH = 0.0f;
|
||||
|
||||
_glLightVertexDirectional(
|
||||
data->finalColour,
|
||||
finalColour,
|
||||
i, LdotN, NdotH
|
||||
);
|
||||
} else {
|
||||
@ -627,17 +624,17 @@ void _glPerformLighting(Vertex* vertices, EyeSpaceData* es, const uint32_t count
|
||||
if(NdotH < 0.0f) NdotH = 0.0f;
|
||||
|
||||
_glLightVertexPoint(
|
||||
data->finalColour,
|
||||
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);
|
||||
vertex->bgra[R8IDX] = clamp(finalColour[0] * 255.0f, 0, 255);
|
||||
vertex->bgra[G8IDX] = clamp(finalColour[1] * 255.0f, 0, 255);
|
||||
vertex->bgra[B8IDX] = clamp(finalColour[2] * 255.0f, 0, 255);
|
||||
vertex->bgra[A8IDX] = clamp(finalColour[3] * 255.0f, 0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
236
GL/matrix.c
236
GL/matrix.c
@ -15,13 +15,12 @@ GLfloat DEPTH_RANGE_MULTIPLIER_H = (0 + 1) / 2;
|
||||
|
||||
static Stack __attribute__((aligned(32))) MATRIX_STACKS[4]; // modelview, projection, texture
|
||||
static Matrix4x4 __attribute__((aligned(32))) NORMAL_MATRIX;
|
||||
|
||||
Viewport VIEWPORT = {
|
||||
0, 0, 640, 480, 320.0f, 240.0f, 320.0f, 240.0f
|
||||
};
|
||||
static Matrix4x4 __attribute__((aligned(32))) VIEWPORT_MATRIX;
|
||||
static Matrix4x4 __attribute__((aligned(32))) PROJECTION_MATRIX;
|
||||
|
||||
static GLenum MATRIX_MODE = GL_MODELVIEW;
|
||||
static GLubyte MATRIX_IDX = 0;
|
||||
static GLboolean NORMAL_DIRTY, PROJECTION_DIRTY;
|
||||
|
||||
static const Matrix4x4 __attribute__((aligned(32))) IDENTITY = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
@ -94,12 +93,28 @@ static void transpose(GLfloat* m) {
|
||||
swap(m[11], m[14]);
|
||||
}
|
||||
|
||||
static void recalculateNormalMatrix() {
|
||||
/* When projection matrix changes, need to pre-multiply with viewport transform matrix */
|
||||
static void UpdateProjectionMatrix() {
|
||||
PROJECTION_DIRTY = false;
|
||||
UploadMatrix4x4(&VIEWPORT_MATRIX);
|
||||
MultiplyMatrix4x4(stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
|
||||
DownloadMatrix4x4(&PROJECTION_MATRIX);
|
||||
}
|
||||
|
||||
/* When modelview matrix changes, need to re-compute normal matrix */
|
||||
static void UpdateNormalMatrix() {
|
||||
NORMAL_DIRTY = false;
|
||||
MEMCPY4(NORMAL_MATRIX, stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)), sizeof(Matrix4x4));
|
||||
inverse((GLfloat*) NORMAL_MATRIX);
|
||||
transpose((GLfloat*) NORMAL_MATRIX);
|
||||
}
|
||||
|
||||
static void OnMatrixChanged() {
|
||||
if(MATRIX_MODE == GL_MODELVIEW) NORMAL_DIRTY = true;
|
||||
if(MATRIX_MODE == GL_PROJECTION) PROJECTION_DIRTY = true;
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glMatrixMode(GLenum mode) {
|
||||
MATRIX_MODE = mode;
|
||||
MATRIX_IDX = mode & 0xF;
|
||||
@ -111,17 +126,26 @@ void APIENTRY glPushMatrix() {
|
||||
void* ret = stack_push(MATRIX_STACKS + MATRIX_IDX, top);
|
||||
(void) ret;
|
||||
assert(ret);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void APIENTRY glPopMatrix() {
|
||||
stack_pop(MATRIX_STACKS + MATRIX_IDX);
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void APIENTRY glLoadIdentity() {
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, IDENTITY);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void GL_FORCE_INLINE _glMultMatrix(const Matrix4x4* mat) {
|
||||
void* top = stack_top(MATRIX_STACKS + MATRIX_IDX);
|
||||
|
||||
UploadMatrix4x4(top);
|
||||
MultiplyMatrix4x4(mat);
|
||||
DownloadMatrix4x4(top);
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
@ -131,20 +155,7 @@ void APIENTRY glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
x, y, z, 1.0f
|
||||
};
|
||||
void* top = stack_top(MATRIX_STACKS + MATRIX_IDX);
|
||||
assert(top);
|
||||
|
||||
UploadMatrix4x4(top);
|
||||
MultiplyMatrix4x4(&trn);
|
||||
|
||||
top = stack_top(MATRIX_STACKS + MATRIX_IDX);
|
||||
assert(top);
|
||||
|
||||
DownloadMatrix4x4(top);
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
_glMultMatrix(&trn);
|
||||
}
|
||||
|
||||
|
||||
@ -155,14 +166,7 @@ void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
0.0f, 0.0f, z, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
MultiplyMatrix4x4(&scale);
|
||||
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
_glMultMatrix(&scale);
|
||||
}
|
||||
|
||||
void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
@ -174,8 +178,13 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
};
|
||||
|
||||
float r = DEG2RAD * angle;
|
||||
#ifdef __DREAMCAST__
|
||||
float s, c;
|
||||
fsincos(r, &s, &c);
|
||||
#else
|
||||
float c = cosf(r);
|
||||
float s = sinf(r);
|
||||
#endif
|
||||
|
||||
VEC3_NORMALIZE(x, y, z);
|
||||
|
||||
@ -199,13 +208,7 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
rotate[M9] = yz * invc - xs;
|
||||
rotate[M10] = (z * z) * invc + c;
|
||||
|
||||
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
MultiplyMatrix4x4((const Matrix4x4*) &rotate);
|
||||
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
_glMultMatrix(&rotate);
|
||||
}
|
||||
|
||||
/* Load an arbitrary matrix */
|
||||
@ -214,47 +217,39 @@ void APIENTRY glLoadMatrixf(const GLfloat *m) {
|
||||
|
||||
memcpy(TEMP, m, sizeof(float) * 16);
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP);
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
/* Ortho */
|
||||
void APIENTRY glOrtho(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
void APIENTRY glOrtho(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar) {
|
||||
|
||||
/* Ortho Matrix */
|
||||
Matrix4x4 OrthoMatrix __attribute__((aligned(32))) = {
|
||||
Matrix4x4 ortho __attribute__((aligned(32))) = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
OrthoMatrix[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);
|
||||
ortho[M0] = 2.0f / (right - left);
|
||||
ortho[M5] = 2.0f / (top - bottom);
|
||||
ortho[M10] = -2.0f / (zfar - znear);
|
||||
ortho[M12] = -(right + left) / (right - left);
|
||||
ortho[M13] = -(top + bottom) / (top - bottom);
|
||||
ortho[M14] = -(zfar + znear) / (zfar - znear);
|
||||
|
||||
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
MultiplyMatrix4x4((const Matrix4x4*) &OrthoMatrix);
|
||||
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
_glMultMatrix(&ortho);
|
||||
}
|
||||
|
||||
|
||||
/* Set the GL frustum */
|
||||
void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
void APIENTRY glFrustum(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar) {
|
||||
|
||||
/* Frustum Matrix */
|
||||
Matrix4x4 FrustumMatrix __attribute__((aligned(32)));
|
||||
|
||||
MEMSET(FrustumMatrix, 0, sizeof(float) * 16);
|
||||
Matrix4x4 frustum __attribute__((aligned(32)));
|
||||
MEMSET(frustum, 0, sizeof(float) * 16);
|
||||
|
||||
const float near2 = 2.0f * znear;
|
||||
const float A = (right + left) / (right - left);
|
||||
@ -262,33 +257,25 @@ void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
||||
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);
|
||||
frustum[M0] = near2 / (right - left);
|
||||
frustum[M5] = near2 / (top - bottom);
|
||||
|
||||
FrustumMatrix[M8] = A;
|
||||
FrustumMatrix[M9] = B;
|
||||
FrustumMatrix[M10] = C;
|
||||
FrustumMatrix[M11] = -1.0f;
|
||||
FrustumMatrix[M14] = D;
|
||||
frustum[M8] = A;
|
||||
frustum[M9] = B;
|
||||
frustum[M10] = C;
|
||||
frustum[M11] = -1.0f;
|
||||
frustum[M14] = D;
|
||||
|
||||
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
MultiplyMatrix4x4((const Matrix4x4*) &FrustumMatrix);
|
||||
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
_glMultMatrix(&frustum);
|
||||
}
|
||||
|
||||
|
||||
/* Multiply the current matrix by an arbitrary matrix */
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
Matrix4x4 TEMP __attribute__((aligned(32)));
|
||||
MEMCPY4(TEMP, m, sizeof(Matrix4x4));
|
||||
Matrix4x4 tmp __attribute__((aligned(32)));
|
||||
MEMCPY4(tmp, m, sizeof(Matrix4x4));
|
||||
|
||||
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
MultiplyMatrix4x4(&TEMP);
|
||||
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
_glMultMatrix(&tmp);
|
||||
}
|
||||
|
||||
/* Load an arbitrary transposed matrix */
|
||||
@ -319,55 +306,46 @@ void glLoadTransposeMatrixf(const GLfloat *m) {
|
||||
TEMP[M15] = m[15];
|
||||
|
||||
stack_replace(MATRIX_STACKS + MATRIX_IDX, TEMP);
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
OnMatrixChanged();
|
||||
}
|
||||
|
||||
/* Multiply the current matrix by an arbitrary transposed matrix */
|
||||
void glMultTransposeMatrixf(const GLfloat *m) {
|
||||
static Matrix4x4 TEMP __attribute__((aligned(32)));
|
||||
static Matrix4x4 tmp __attribute__((aligned(32)));
|
||||
|
||||
TEMP[M0] = m[0];
|
||||
TEMP[M1] = m[4];
|
||||
TEMP[M2] = m[8];
|
||||
TEMP[M3] = m[12];
|
||||
tmp[M0] = m[0];
|
||||
tmp[M1] = m[4];
|
||||
tmp[M2] = m[8];
|
||||
tmp[M3] = m[12];
|
||||
|
||||
TEMP[M4] = m[1];
|
||||
TEMP[M5] = m[5];
|
||||
TEMP[M6] = m[9];
|
||||
TEMP[M7] = m[13];
|
||||
tmp[M4] = m[1];
|
||||
tmp[M5] = m[5];
|
||||
tmp[M6] = m[9];
|
||||
tmp[M7] = m[13];
|
||||
|
||||
TEMP[M8] = m[3];
|
||||
TEMP[M9] = m[6];
|
||||
TEMP[M10] = m[10];
|
||||
TEMP[M11] = m[14];
|
||||
tmp[M8] = m[3];
|
||||
tmp[M9] = m[6];
|
||||
tmp[M10] = m[10];
|
||||
tmp[M11] = m[14];
|
||||
|
||||
TEMP[M12] = m[4];
|
||||
TEMP[M13] = m[7];
|
||||
TEMP[M14] = m[11];
|
||||
TEMP[M15] = m[15];
|
||||
tmp[M12] = m[4];
|
||||
tmp[M13] = m[7];
|
||||
tmp[M14] = m[11];
|
||||
tmp[M15] = m[15];
|
||||
|
||||
UploadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
MultiplyMatrix4x4((const Matrix4x4*) &TEMP);
|
||||
DownloadMatrix4x4(stack_top(MATRIX_STACKS + MATRIX_IDX));
|
||||
|
||||
if(MATRIX_MODE == GL_MODELVIEW) {
|
||||
recalculateNormalMatrix();
|
||||
}
|
||||
_glMultMatrix(&tmp);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
VIEWPORT_MATRIX[M0] = width * 0.5f;
|
||||
VIEWPORT_MATRIX[M5] = height * -0.5f;
|
||||
VIEWPORT_MATRIX[M10] = 1.0f;
|
||||
VIEWPORT_MATRIX[M15] = 1.0f;
|
||||
|
||||
VIEWPORT_MATRIX[M12] = x + width * 0.5f;
|
||||
VIEWPORT_MATRIX[M13] = GetVideoMode()->height - (y + height * 0.5f);
|
||||
PROJECTION_DIRTY = true;
|
||||
}
|
||||
|
||||
/* Set the depth range */
|
||||
@ -382,7 +360,7 @@ void APIENTRY glDepthRangef(GLclampf n, GLclampf f) {
|
||||
DEPTH_RANGE_MULTIPLIER_H = (n + f) / 2.0f;
|
||||
}
|
||||
|
||||
void APIENTRY glDepthRange(GLclampf n, GLclampf f){
|
||||
void APIENTRY glDepthRange(GLdouble n, GLdouble f){
|
||||
glDepthRangef(n,f);
|
||||
}
|
||||
|
||||
@ -394,11 +372,12 @@ static inline void vec3f_cross(const GLfloat* v1, const GLfloat* v2, GLfloat* re
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void vec3f_normalize_sh4(float *v){
|
||||
float length, ilength;
|
||||
float lengthSq, ilength;
|
||||
|
||||
ilength = MATH_fsrra(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
|
||||
length = MATH_Fast_Invert(ilength);
|
||||
if (length)
|
||||
lengthSq = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
|
||||
ilength = MATH_fsrra(lengthSq);
|
||||
|
||||
if (lengthSq)
|
||||
{
|
||||
v[0] *= ilength;
|
||||
v[1] *= ilength;
|
||||
@ -406,9 +385,9 @@ GL_FORCE_INLINE void vec3f_normalize_sh4(float *v){
|
||||
}
|
||||
}
|
||||
|
||||
void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
|
||||
GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
|
||||
GLfloat upz) {
|
||||
void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
|
||||
GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
|
||||
GLdouble upz) {
|
||||
GLfloat m [16] __attribute__((aligned(32)));
|
||||
GLfloat f [3];
|
||||
GLfloat u [3];
|
||||
@ -459,14 +438,17 @@ void _glMatrixLoadModelView() {
|
||||
}
|
||||
|
||||
void _glMatrixLoadProjection() {
|
||||
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
|
||||
if (PROJECTION_DIRTY) UpdateProjectionMatrix();
|
||||
UploadMatrix4x4(&PROJECTION_MATRIX);
|
||||
}
|
||||
|
||||
void _glMatrixLoadModelViewProjection() {
|
||||
UploadMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_PROJECTION & 0xF)));
|
||||
if (PROJECTION_DIRTY) UpdateProjectionMatrix();
|
||||
UploadMatrix4x4(&PROJECTION_MATRIX);
|
||||
MultiplyMatrix4x4((const Matrix4x4*) stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
}
|
||||
|
||||
void _glMatrixLoadNormal() {
|
||||
if (NORMAL_DIRTY) UpdateNormalMatrix();
|
||||
UploadMatrix4x4((const Matrix4x4*) &NORMAL_MATRIX);
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#include <float.h>
|
||||
|
||||
#include <dc/sq.h>
|
||||
|
||||
#include "../platform.h"
|
||||
#include "sh4.h"
|
||||
|
||||
@ -7,12 +9,11 @@
|
||||
#define CLIP_DEBUG 0
|
||||
|
||||
#define PVR_VERTEX_BUF_SIZE 2560 * 256
|
||||
#define PVR_OPB_COUNT 2
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define SQ_BASE_ADDRESS (void*) 0xe0000000
|
||||
|
||||
|
||||
GL_FORCE_INLINE bool glIsVertex(const float flags) {
|
||||
return flags == GPU_CMD_VERTEX_EOL || flags == GPU_CMD_VERTEX;
|
||||
@ -29,18 +30,10 @@ void InitGPU(_Bool autosort, _Bool fsaa) {
|
||||
PVR_VERTEX_BUF_SIZE, /* Vertex buffer size */
|
||||
0, /* No DMA */
|
||||
fsaa, /* No FSAA */
|
||||
(autosort) ? 0 : 1 /* Disable translucent auto-sorting to match traditional GL */
|
||||
(autosort) ? 0 : 1, /* Disable translucent auto-sorting to match traditional GL */
|
||||
PVR_OPB_COUNT /* Number of tile object pointer overflow bins. */
|
||||
};
|
||||
|
||||
/* Newer versions of KOS add an extra parameter to pvr_init_params_t
|
||||
* called opb_overflow_count. To remain compatible we set that last
|
||||
* parameter to something only if it exists */
|
||||
const int opb_offset = offsetof(pvr_init_params_t, autosort_disabled) + 4;
|
||||
if(sizeof(pvr_init_params_t) > opb_offset) {
|
||||
int* opb_count = (int*)(((char*)¶ms) + opb_offset);
|
||||
*opb_count = 2; // Two should be enough for anybody.. right?
|
||||
}
|
||||
|
||||
pvr_init(¶ms);
|
||||
|
||||
#ifndef _arch_sub_naomi
|
||||
@ -60,69 +53,44 @@ void InitGPU(_Bool autosort, _Bool fsaa) {
|
||||
#endif
|
||||
}
|
||||
|
||||
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));
|
||||
return (1.0f / __builtin_sqrtf(x * x));
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) {
|
||||
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, int count) {
|
||||
TRACE();
|
||||
|
||||
const float f = _glFastInvert(vertex->w);
|
||||
for(int v = 0; v < count; ++v) {
|
||||
const float f = _glFastInvert(vertex[v].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;
|
||||
/* Convert to screenspace */
|
||||
/* (note that vertices have already been viewport transformed) */
|
||||
vertex[v].xyz[0] *= f;
|
||||
vertex[v].xyz[1] *= f;
|
||||
|
||||
/* Orthographic projections need to use invZ otherwise we lose
|
||||
the depth information. As w == 1, and clip-space range is -w to +w
|
||||
we add 1.0 to the Z to bring it into range. We add a little extra to
|
||||
avoid a divide by zero.
|
||||
*/
|
||||
if(vertex->w == 1.0f) {
|
||||
vertex->xyz[2] = _glFastInvert(1.0001f + vertex->xyz[2]);
|
||||
} else {
|
||||
vertex->xyz[2] = f;
|
||||
/* Orthographic projections need to use invZ otherwise we lose
|
||||
the depth information. As w == 1, and clip-space range is -w to +w
|
||||
we add 1.0 to the Z to bring it into range. We add a little extra to
|
||||
avoid a divide by zero.
|
||||
*/
|
||||
if(vertex[v].w == 1.0f) {
|
||||
vertex[v].xyz[2] = _glFastInvert(1.0001f + vertex[v].xyz[2]);
|
||||
} else {
|
||||
vertex[v].xyz[2] = f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uintptr_t sq_dest_addr = 0;
|
||||
|
||||
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) {
|
||||
static inline void _glPushHeaderOrVertex(Vertex* v, size_t count) {
|
||||
TRACE();
|
||||
|
||||
#if CLIP_DEBUG
|
||||
fprintf(stderr, "{%f, %f, %f, %f}, // %x (%x)\n", v->xyz[0], v->xyz[1], v->xyz[2], v->w, v->flags, v);
|
||||
#endif
|
||||
|
||||
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;
|
||||
sq_fast_cpy((void *)sq_dest_addr, v, count);
|
||||
}
|
||||
|
||||
static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, Vertex* vout) {
|
||||
@ -150,7 +118,6 @@ static inline void _glClipEdge(const Vertex* const v1, const Vertex* const v2, V
|
||||
#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;
|
||||
|
||||
enum Visible {
|
||||
NONE_VISIBLE = 0,
|
||||
@ -175,17 +142,12 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
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
|
||||
fprintf(stderr, "----\n");
|
||||
|
||||
@ -210,16 +172,15 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
do { queued_vertex = &qv; *queued_vertex = *(v); } while(0)
|
||||
|
||||
#define SUBMIT_QUEUED_VERTEX(sflags) \
|
||||
do { if(queued_vertex) { queued_vertex->flags = (sflags); _glPushHeaderOrVertex(queued_vertex); queued_vertex = NULL; } } while(0)
|
||||
do { if(queued_vertex) { queued_vertex->flags = (sflags); _glPushHeaderOrVertex(queued_vertex, 1); queued_vertex = NULL; } } while(0)
|
||||
|
||||
int visible_mask = 0;
|
||||
|
||||
sq = SQ_BASE_ADDRESS;
|
||||
sq_dest_addr = (uintptr_t)SQ_MASK_DEST(PVR_TA_INPUT);
|
||||
|
||||
Vertex* v0 = vertices;
|
||||
for(int i = 0; i < n - 1; ++i, ++v0) {
|
||||
if(is_header(v0)) {
|
||||
_glPushHeaderOrVertex(v0);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
visible_mask = 0;
|
||||
continue;
|
||||
}
|
||||
@ -229,7 +190,7 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
|
||||
assert(!is_header(v1));
|
||||
|
||||
// We are trailing if we're on the penultimate vertex, or the next but one vertex is
|
||||
// We are trailing if we're on the penultimate vertex, or the next but one vertex is
|
||||
// an EOL, or v1 is an EOL (FIXME: possibly unnecessary and coverted by the other case?)
|
||||
bool is_trailing = (v1->flags == GPU_CMD_VERTEX_EOL) || ((v2) ? is_header(v2) : true);
|
||||
|
||||
@ -239,25 +200,21 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
|
||||
// If the last triangle was all visible, we need
|
||||
// to submit the last two vertices, any clipped triangles
|
||||
// would've
|
||||
// would've
|
||||
if(visible_mask == ALL_VISIBLE) {
|
||||
SUBMIT_QUEUED_VERTEX(qv.flags);
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(v0, 2);
|
||||
v1->flags = GPU_CMD_VERTEX_EOL;
|
||||
|
||||
_glPerspectiveDivideVertex(v1, h);
|
||||
_glPushHeaderOrVertex(v1);
|
||||
_glPushHeaderOrVertex(v0, 2);
|
||||
} else {
|
||||
// If the previous triangle wasn't all visible, and we
|
||||
// If the previous triangle wasn't all visible, and we
|
||||
// queued a vertex - we force it to be EOL and submit
|
||||
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||
}
|
||||
|
||||
i++;
|
||||
v0++;
|
||||
v0++;
|
||||
visible_mask = 0;
|
||||
continue;
|
||||
}
|
||||
@ -285,7 +242,7 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
|
||||
switch(visible_mask) {
|
||||
case ALL_VISIBLE:
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
QUEUE_VERTEX(v0);
|
||||
break;
|
||||
case NONE_VISIBLE:
|
||||
@ -298,14 +255,11 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPerspectiveDivideVertex(a, 2);
|
||||
_glPushHeaderOrVertex(a, 2);
|
||||
|
||||
QUEUE_VERTEX(b);
|
||||
break;
|
||||
@ -318,13 +272,11 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPushHeaderOrVertex(a);
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
_glPushHeaderOrVertex(a, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
QUEUE_VERTEX(b);
|
||||
break;
|
||||
case THIRD_VISIBLE:
|
||||
@ -336,14 +288,9 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
//_glPushHeaderOrVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
_glPushHeaderOrVertex(a, 2);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPushHeaderOrVertex(b);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
QUEUE_VERTEX(c);
|
||||
break;
|
||||
case FIRST_AND_SECOND_VISIBLE:
|
||||
@ -352,20 +299,17 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
|
||||
_glClipEdge(v1, v2, a);
|
||||
a->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPushHeaderOrVertex(b, 2);
|
||||
|
||||
QUEUE_VERTEX(a);
|
||||
break;
|
||||
@ -379,17 +323,13 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPushHeaderOrVertex(a);
|
||||
_glPerspectiveDivideVertex(a, 4);
|
||||
_glPushHeaderOrVertex(a, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPushHeaderOrVertex(b, 2);
|
||||
|
||||
_glPerspectiveDivideVertex(d, h);
|
||||
QUEUE_VERTEX(d);
|
||||
break;
|
||||
case FIRST_AND_THIRD_VISIBLE:
|
||||
@ -402,16 +342,16 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
_glPerspectiveDivideVertex(v0, 1);
|
||||
_glPushHeaderOrVertex(v0, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPushHeaderOrVertex(a);
|
||||
_glPerspectiveDivideVertex(a, 3);
|
||||
_glPushHeaderOrVertex(a, 1);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(c, 1);
|
||||
|
||||
_glPushHeaderOrVertex(b, 1);
|
||||
|
||||
QUEUE_VERTEX(c);
|
||||
break;
|
||||
default:
|
||||
@ -421,7 +361,19 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
|
||||
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||
|
||||
_glFlushBuffer();
|
||||
sq_wait();
|
||||
}
|
||||
|
||||
void SceneBegin() {
|
||||
pvr_wait_ready();
|
||||
pvr_scene_begin();
|
||||
}
|
||||
|
||||
static pvr_dr_state_t dr_state;
|
||||
void SceneListBegin(GPUList list) {
|
||||
pvr_list_begin(list);
|
||||
/* Direct rendering auto acquires/releases store queue */
|
||||
pvr_dr_init(&dr_state);
|
||||
}
|
||||
|
||||
void SceneListFinish() {
|
||||
|
||||
@ -10,8 +10,6 @@
|
||||
#include "../types.h"
|
||||
#include "../private.h"
|
||||
|
||||
#include "sh4_math.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define PERF_WARNING(msg) printf("[PERF] %s\n", msg)
|
||||
#else
|
||||
@ -24,6 +22,42 @@
|
||||
#define GL_FORCE_INLINE static GL_INLINE_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
// ---- sh4_math.h - SH7091 Math Module ----
|
||||
//
|
||||
// This file is part of the DreamHAL project, a hardware abstraction library
|
||||
// primarily intended for use on the SH7091 found in hardware such as the SEGA
|
||||
// Dreamcast game console.
|
||||
//
|
||||
// This math module is hereby released into the public domain in the hope that it
|
||||
// may prove useful. Now go hit 60 fps! :)
|
||||
//
|
||||
// --Moopthehedgehog
|
||||
|
||||
// 1/sqrt(x)
|
||||
GL_FORCE_INLINE float MATH_fsrra(float x)
|
||||
{
|
||||
asm volatile ("fsrra %[one_div_sqrt]\n"
|
||||
: [one_div_sqrt] "+f" (x) // outputs, "+" means r/w
|
||||
: // no inputs
|
||||
: // no clobbers
|
||||
);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
// 1/x = 1 / sqrt(x^2)
|
||||
GL_FORCE_INLINE float MATH_Fast_Invert(float x)
|
||||
{
|
||||
int neg = x < 0.0f;
|
||||
|
||||
x = MATH_fsrra(x * x);
|
||||
|
||||
if (neg) x = -x;
|
||||
return x;
|
||||
}
|
||||
// end of ---- sh4_math.h ----
|
||||
|
||||
#define PREFETCH(addr) __builtin_prefetch((addr))
|
||||
|
||||
GL_FORCE_INLINE void* memcpy_fast(void *dest, const void *src, size_t len) {
|
||||
@ -69,7 +103,7 @@ GL_FORCE_INLINE void* memcpy_fast(void *dest, const void *src, size_t len) {
|
||||
|
||||
#define MEMCPY4(dst, src, bytes) memcpy_fast(dst, src, bytes)
|
||||
|
||||
#define MEMSET4(dst, v, size) memset4((dst), (v), (size))
|
||||
#define MEMSET4(dst, v, size) memset((dst), (v), (size))
|
||||
|
||||
#define VEC3_NORMALIZE(x, y, z) vec3f_normalize((x), (y), (z))
|
||||
#define VEC3_LENGTH(x, y, z, l) vec3f_length((x), (y), (z), (l))
|
||||
@ -106,15 +140,14 @@ 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);
|
||||
GL_FORCE_INLINE void TransformVertex(float x, float y, float z, float w, float* oxyz, float* ow) {
|
||||
register float __x __asm__("fr4") = x;
|
||||
register float __y __asm__("fr5") = y;
|
||||
register float __z __asm__("fr6") = z;
|
||||
register float __w __asm__("fr7") = w;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"fldi1 fr15\n"
|
||||
"ftrv xmtrx,fv12\n"
|
||||
"ftrv xmtrx,fv4\n"
|
||||
: "=f" (__x), "=f" (__y), "=f" (__z), "=f" (__w)
|
||||
: "0" (__x), "1" (__y), "2" (__z), "3" (__w)
|
||||
);
|
||||
@ -125,28 +158,6 @@ GL_FORCE_INLINE void TransformVertex(const float* xyz, const float* w, float* ox
|
||||
*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() {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -75,17 +75,13 @@ void SceneListBegin(GPUList list) {
|
||||
vertex_counter = 0;
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, const float h) {
|
||||
GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex) {
|
||||
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
|
||||
);
|
||||
/* Convert to screenspace */
|
||||
/* (note that vertices have already been viewport transformed) */
|
||||
vertex->xyz[0] = vertex->xyz[0] * f;
|
||||
vertex->xyz[1] = vertex->xyz[1] * f;
|
||||
|
||||
if(vertex->w == 1.0f) {
|
||||
vertex->xyz[2] = 1.0f / (1.0001f + vertex->xyz[2]);
|
||||
@ -143,8 +139,6 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float h = GetVideoMode()->height;
|
||||
|
||||
uint8_t visible_mask = 0;
|
||||
uint8_t counter = 0;
|
||||
|
||||
@ -182,19 +176,19 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
switch(visible_mask) {
|
||||
case 15: /* All visible, but final vertex in strip */
|
||||
{
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(v1, h);
|
||||
_glPerspectiveDivideVertex(v1);
|
||||
_glPushHeaderOrVertex(v1);
|
||||
|
||||
_glPerspectiveDivideVertex(v2, h);
|
||||
_glPerspectiveDivideVertex(v2);
|
||||
_glPushHeaderOrVertex(v2);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
/* All visible, push the first vertex and move on */
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
break;
|
||||
case 9:
|
||||
@ -210,13 +204,13 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX_EOL;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
}
|
||||
break;
|
||||
@ -233,13 +227,13 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
}
|
||||
@ -262,13 +256,13 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
}
|
||||
break;
|
||||
@ -285,19 +279,19 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glClipEdge(v1, v2, a);
|
||||
a->flags = v2->flags;
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPushHeaderOrVertex(a);
|
||||
}
|
||||
@ -319,17 +313,17 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
if(counter % 2 == 1) {
|
||||
_glPushHeaderOrVertex(a);
|
||||
}
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
}
|
||||
break;
|
||||
@ -349,15 +343,15 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
|
||||
c->flags = GPU_CMD_VERTEX_EOL;
|
||||
@ -380,15 +374,15 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v1, v2, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(v0, h);
|
||||
_glPerspectiveDivideVertex(v0);
|
||||
_glPushHeaderOrVertex(v0);
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(c);
|
||||
}
|
||||
@ -411,17 +405,17 @@ void SceneListSubmit(Vertex* v2, int n) {
|
||||
_glClipEdge(v2, v0, b);
|
||||
b->flags = GPU_CMD_VERTEX;
|
||||
|
||||
_glPerspectiveDivideVertex(a, h);
|
||||
_glPerspectiveDivideVertex(a);
|
||||
_glPushHeaderOrVertex(a);
|
||||
|
||||
_glPerspectiveDivideVertex(c, h);
|
||||
_glPerspectiveDivideVertex(c);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(b, h);
|
||||
_glPerspectiveDivideVertex(b);
|
||||
_glPushHeaderOrVertex(b);
|
||||
_glPushHeaderOrVertex(c);
|
||||
|
||||
_glPerspectiveDivideVertex(d, h);
|
||||
_glPerspectiveDivideVertex(d);
|
||||
_glPushHeaderOrVertex(d);
|
||||
}
|
||||
break;
|
||||
@ -625,34 +619,17 @@ void TransformVec4(float* v) {
|
||||
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;
|
||||
void TransformVertex(float x, float y, float z, float w, float* oxyz, float* ow) {
|
||||
float vec[4], ret[4];
|
||||
vec[0] = x;
|
||||
vec[1] = y;
|
||||
vec[2] = z;
|
||||
vec[3] = w;
|
||||
|
||||
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);
|
||||
TransformVec4NoMod(vec, ret);
|
||||
|
||||
oxyz[0] = ret[0];
|
||||
oxyz[1] = ret[1];
|
||||
oxyz[2] = ret[2];
|
||||
*ow = ret[3];
|
||||
*ow = ret[3];
|
||||
}
|
||||
|
||||
@ -7,9 +7,6 @@
|
||||
|
||||
#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))
|
||||
|
||||
@ -28,7 +25,7 @@
|
||||
} while(0)
|
||||
|
||||
#define VEC3_LENGTH(x, y, z, d) \
|
||||
d = MATH_Fast_Sqrt((x) * (x) + (y) * (y) + (z) * (z))
|
||||
d = sqrtf((x) * (x) + (y) * (y) + (z) * (z))
|
||||
|
||||
#define VEC3_DOT(x1, y1, z1, x2, y2, z2, d) \
|
||||
d = (x1 * x2) + (y1 * y2) + (z1 * z2)
|
||||
@ -52,8 +49,7 @@ static inline void TransformNormalNoMod(const float* xIn, float* xOut) {
|
||||
(void) xOut;
|
||||
}
|
||||
|
||||
void TransformVertices(Vertex* vertices, const int count);
|
||||
void TransformVertex(const float* xyz, const float* w, float* oxyz, float* ow);
|
||||
void TransformVertex(float x, float y, float z, float w, float* oxyz, float* ow);
|
||||
|
||||
void InitGPU(_Bool autosort, _Bool fsaa);
|
||||
|
||||
|
||||
150
GL/private.h
150
GL/private.h
@ -25,6 +25,7 @@ extern void* memcpy4 (void *dest, const void *src, size_t count);
|
||||
#define GL_NO_INSTRUMENT inline __attribute__((no_instrument_function))
|
||||
#define GL_INLINE_DEBUG GL_NO_INSTRUMENT __attribute__((always_inline))
|
||||
#define GL_FORCE_INLINE static GL_INLINE_DEBUG
|
||||
#define GL_NO_INLINE __attribute__((noinline))
|
||||
#define _GL_UNUSED(x) (void)(x)
|
||||
|
||||
#define _PACK4(v) ((v * 0xF) / 0xFF)
|
||||
@ -104,20 +105,6 @@ typedef struct {
|
||||
AlignedVector vector;
|
||||
} 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 */
|
||||
@ -273,6 +260,12 @@ do { \
|
||||
memcpy_vertex(b, &c); \
|
||||
} while(0)
|
||||
|
||||
#ifdef __DREAMCAST__
|
||||
#define fast_rsqrt(x) frsqrt(x)
|
||||
#else
|
||||
#define fast_rsqrt(x) (1.0f / __builtin_sqrtf(x))
|
||||
#endif
|
||||
|
||||
/* ClipVertex doesn't have room for these, so we need to parse them
|
||||
* out separately. Potentially 'w' will be housed here if we support oargb */
|
||||
typedef struct {
|
||||
@ -334,6 +327,9 @@ void _glMatrixLoadModelViewProjection();
|
||||
extern GLfloat DEPTH_RANGE_MULTIPLIER_L;
|
||||
extern GLfloat DEPTH_RANGE_MULTIPLIER_H;
|
||||
|
||||
extern GLfloat HALF_LINE_WIDTH;
|
||||
extern GLfloat HALF_POINT_SIZE;
|
||||
|
||||
Matrix4x4* _glGetProjectionMatrix();
|
||||
Matrix4x4* _glGetModelViewMatrix();
|
||||
|
||||
@ -350,6 +346,7 @@ typedef struct {
|
||||
GLsizei stride; // 4
|
||||
GLint size; // 4
|
||||
} AttribPointer;
|
||||
typedef void (*ReadAttributeFunc)(const GLubyte*, GLubyte*);
|
||||
|
||||
typedef struct {
|
||||
AttribPointer vertex; // 16
|
||||
@ -357,25 +354,33 @@ typedef struct {
|
||||
AttribPointer uv; // 48
|
||||
AttribPointer st; // 64
|
||||
AttribPointer normal; // 80
|
||||
AttribPointer padding; // 96
|
||||
|
||||
GLuint enabled; // list of currently enabled/used attributes
|
||||
GLuint dirty; // list of attributes that need state recalculating
|
||||
GLboolean fast_path;
|
||||
|
||||
ReadAttributeFunc vertex_func;
|
||||
ReadAttributeFunc colour_func;
|
||||
ReadAttributeFunc uv_func;
|
||||
ReadAttributeFunc st_func;
|
||||
ReadAttributeFunc normal_func;
|
||||
} AttribPointerList;
|
||||
|
||||
extern AttribPointerList ATTRIB_LIST;
|
||||
|
||||
GLboolean _glCheckValidEnum(GLint param, GLint* values, const char* func);
|
||||
|
||||
GLuint* _glGetEnabledAttributes();
|
||||
AttribPointer* _glGetVertexAttribPointer();
|
||||
AttribPointer* _glGetDiffuseAttribPointer();
|
||||
AttribPointer* _glGetNormalAttribPointer();
|
||||
AttribPointer* _glGetUVAttribPointer();
|
||||
AttribPointer* _glGetSTAttribPointer();
|
||||
GLenum _glGetShadeModel();
|
||||
GL_NO_INLINE void _glUpdateAttributes();
|
||||
|
||||
GLenum _glGetShadeModel();
|
||||
TextureObject* _glGetTexture0();
|
||||
TextureObject* _glGetTexture1();
|
||||
TextureObject* _glGetBoundTexture();
|
||||
|
||||
extern GLubyte ACTIVE_TEXTURE;
|
||||
extern GLboolean TEXTURES_ENABLED[];
|
||||
extern GLubyte ACTIVE_CLIENT_TEXTURE;
|
||||
|
||||
GLubyte _glGetActiveTexture();
|
||||
GLint _glGetTextureInternalFormat();
|
||||
@ -399,8 +404,8 @@ GLboolean _glIsFogEnabled();
|
||||
GLenum _glGetDepthFunc();
|
||||
GLenum _glGetCullFace();
|
||||
GLenum _glGetFrontFace();
|
||||
GLenum _glGetBlendSourceFactor();
|
||||
GLenum _glGetBlendDestFactor();
|
||||
GLenum _glGetGpuBlendSrcFactor();
|
||||
GLenum _glGetGpuBlendDstFactor();
|
||||
|
||||
extern PolyList OP_LIST;
|
||||
extern PolyList PT_LIST;
|
||||
@ -426,98 +431,9 @@ 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_NO_INLINE void _glKosThrowError(GLenum error, const char *function);
|
||||
|
||||
GL_FORCE_INLINE GLboolean _glCheckImmediateModeInactive(const char* func) {
|
||||
/* Returns 1 on error */
|
||||
@ -529,13 +445,7 @@ GL_FORCE_INLINE GLboolean _glCheckImmediateModeInactive(const char* func) {
|
||||
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);
|
||||
extern void _glPerformLighting(Vertex* vertices, VertexExtra* extra, const uint32_t count);
|
||||
|
||||
unsigned char _glIsClippingEnabled();
|
||||
void _glEnableClipping(unsigned char v);
|
||||
|
||||
87
GL/state.c
87
GL/state.c
@ -3,7 +3,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
GLfloat HALF_LINE_WIDTH = 1.0f / 2.0f;
|
||||
GLfloat HALF_POINT_SIZE = 1.0f / 2.0f;
|
||||
|
||||
static struct {
|
||||
GLboolean is_dirty;
|
||||
@ -80,9 +81,7 @@ static struct {
|
||||
.color_control = GL_SINGLE_COLOR,
|
||||
.color_material_mode = GL_AMBIENT_AND_DIFFUSE,
|
||||
.color_material_mask = AMBIENT_MASK | DIFFUSE_MASK,
|
||||
.lights = {0},
|
||||
.enabled_light_count = 0,
|
||||
.material = {0},
|
||||
.shade_model = GL_SMOOTH
|
||||
};
|
||||
|
||||
@ -218,12 +217,54 @@ GLboolean _glIsNormalizeEnabled() {
|
||||
return GPUState.normalize_enabled;
|
||||
}
|
||||
|
||||
GLenum _glGetBlendSourceFactor() {
|
||||
return GPUState.blend_sfactor;
|
||||
GLenum _glGetGpuBlendSrcFactor() {
|
||||
switch(GPUState.blend_sfactor) {
|
||||
case GL_ZERO:
|
||||
return GPU_BLEND_ZERO;
|
||||
case GL_SRC_ALPHA:
|
||||
return GPU_BLEND_SRCALPHA;
|
||||
case GL_DST_COLOR:
|
||||
return GPU_BLEND_DESTCOLOR;
|
||||
case GL_DST_ALPHA:
|
||||
return GPU_BLEND_DESTALPHA;
|
||||
case GL_ONE_MINUS_DST_COLOR:
|
||||
return GPU_BLEND_INVDESTCOLOR;
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
return GPU_BLEND_INVSRCALPHA;
|
||||
case GL_ONE_MINUS_DST_ALPHA:
|
||||
return GPU_BLEND_INVDESTALPHA;
|
||||
case GL_ONE:
|
||||
return GPU_BLEND_ONE;
|
||||
default:
|
||||
fprintf(stderr, "Invalid src blend mode: %u\n", (unsigned int)GPUState.blend_sfactor);
|
||||
return GPU_BLEND_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
GLenum _glGetBlendDestFactor() {
|
||||
return GPUState.blend_dfactor;
|
||||
GLenum _glGetGpuBlendDstFactor() {
|
||||
switch(GPUState.blend_dfactor) {
|
||||
case GL_ZERO:
|
||||
return GPU_BLEND_ZERO;
|
||||
case GL_SRC_ALPHA:
|
||||
return GPU_BLEND_SRCALPHA;
|
||||
case GL_SRC_COLOR:
|
||||
// actually 'src' color in PVR2 when used as dst blend factor
|
||||
return GPU_BLEND_DESTCOLOR;
|
||||
case GL_DST_ALPHA:
|
||||
return GPU_BLEND_DESTALPHA;
|
||||
case GL_ONE_MINUS_SRC_COLOR:
|
||||
// actually 'src' color in PVR2 when used as dst blend factor
|
||||
return GPU_BLEND_INVDESTCOLOR;
|
||||
case GL_ONE_MINUS_SRC_ALPHA:
|
||||
return GPU_BLEND_INVSRCALPHA;
|
||||
case GL_ONE_MINUS_DST_ALPHA:
|
||||
return GPU_BLEND_INVDESTALPHA;
|
||||
case GL_ONE:
|
||||
return GPU_BLEND_ONE;
|
||||
default:
|
||||
fprintf(stderr, "Invalid dst blend mode: %u\n", (unsigned int)GPUState.blend_dfactor);
|
||||
return GPU_BLEND_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -497,9 +538,12 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
|
||||
case GL_TEXTURE_TWIDDLE_KOS:
|
||||
_glSetTextureTwiddle(GL_TRUE);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
break;
|
||||
case GL_MULTISAMPLE:
|
||||
// Not supported, but not an error
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -603,9 +647,12 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
|
||||
case GL_TEXTURE_TWIDDLE_KOS:
|
||||
_glSetTextureTwiddle(GL_FALSE);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
break;
|
||||
case GL_MULTISAMPLE:
|
||||
// Not supported, but not an error
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,14 +679,14 @@ GLAPI void APIENTRY glClearColor(GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
|
||||
|
||||
/* Depth Testing */
|
||||
GLAPI void APIENTRY glClearDepthf(GLfloat depth) {
|
||||
glClearDepth(depth);
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glClearDepth(GLfloat depth) {
|
||||
/* We reverse because using invW means that farther Z == lower number */
|
||||
GPUSetClearDepth(MIN(1.0f - depth, PVR_MIN_Z));
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glClearDepth(GLdouble depth) {
|
||||
glClearDepthf(depth);
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glDrawBuffer(GLenum mode) {
|
||||
_GL_UNUSED(mode);
|
||||
|
||||
@ -727,7 +774,11 @@ GLAPI void APIENTRY glAlphaFunc(GLenum func, GLclampf ref) {
|
||||
}
|
||||
|
||||
void glLineWidth(GLfloat width) {
|
||||
_GL_UNUSED(width);
|
||||
HALF_LINE_WIDTH = width / 2.0f;
|
||||
}
|
||||
|
||||
void glPointSize(GLfloat size) {
|
||||
HALF_POINT_SIZE = size / 2.0f;
|
||||
}
|
||||
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units) {
|
||||
|
||||
342
GL/texture.c
342
GL/texture.c
@ -78,15 +78,16 @@ void build_twiddle_table(int32_t w, int32_t h) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Given a 0-based texel location, and an image width/height. Return the
|
||||
* new 0-based texel location */
|
||||
GL_FORCE_INLINE uint32_t twid_location(uint32_t i, uint32_t w, uint32_t h) {
|
||||
static void twid_prepare_table(uint32_t w, uint32_t h) {
|
||||
if(TWIDDLE_TABLE.width != w || TWIDDLE_TABLE.height != h || !TWIDDLE_TABLE.table) {
|
||||
build_twiddle_table(w, h);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ret = TWIDDLE_TABLE.table[i];
|
||||
return ret;
|
||||
/* Given a 0-based texel location, returns new 0-based texel location */
|
||||
/* NOTE: twid_prepare_table must have been called beforehand for correct behaviour */
|
||||
GL_FORCE_INLINE uint32_t twid_location(uint32_t i) {
|
||||
return TWIDDLE_TABLE.table[i];
|
||||
}
|
||||
|
||||
|
||||
@ -1228,55 +1229,69 @@ static int _determineConversion(GLint internalFormat, GLenum format, GLenum type
|
||||
bool twiddle;
|
||||
bool pack; // If true, each value is packed after conversion into half-bytes
|
||||
} conversions [] = {
|
||||
{_a8_to_argb4444, GL_ARGB4444_KOS, GL_ALPHA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba4444_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false, false},
|
||||
{_rgba4444_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, true, false},
|
||||
{NULL, GL_ARGB4444_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false, false},
|
||||
{NULL, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS, false, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_ARGB1555_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false, false},
|
||||
{_argb1555_to_argb4444, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, true, false},
|
||||
{NULL, GL_ARGB1555_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS, false, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false, false},
|
||||
{NULL, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_TWID_KOS, false, false},
|
||||
{NULL, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, true, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false, true},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_BYTE, false, true},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_BYTE, true, false},
|
||||
{_a8_to_argb4444, GL_ARGB4444_KOS, GL_ALPHA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_a8_to_argb4444, GL_ARGB4444_TWID_KOS, GL_ALPHA, GL_UNSIGNED_BYTE, true, false},
|
||||
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX4_EXT, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, true},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, true},
|
||||
{_rgba4444_to_argb4444, GL_ARGB4444_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, false, false},
|
||||
{_rgba4444_to_argb4444, GL_ARGB4444_TWID_KOS, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, true, false},
|
||||
{NULL, GL_ARGB4444_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, false, false},
|
||||
{NULL, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, true, false},
|
||||
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_BYTE, true, false},
|
||||
{NULL, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS, false, false},
|
||||
|
||||
{_argb1555_to_argb4444, GL_ARGB4444_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false, false},
|
||||
{_argb1555_to_argb4444, GL_ARGB4444_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, true, false},
|
||||
|
||||
{NULL, GL_ARGB1555_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false, false},
|
||||
{NULL, GL_ARGB1555_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, true, false},
|
||||
|
||||
{NULL, GL_ARGB1555_TWID_KOS, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS, false, false},
|
||||
|
||||
{_r8_to_rgb565, GL_RGB565_KOS, GL_RED, GL_UNSIGNED_BYTE, false, false},
|
||||
{_r8_to_rgb565, GL_RGB565_TWID_KOS, GL_RED, GL_UNSIGNED_BYTE, true, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_rgb565, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_BYTE, true, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_KOS, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_rgb565, GL_RGB565_TWID_KOS, GL_RGBA, GL_UNSIGNED_BYTE, true, false},
|
||||
|
||||
{NULL, GL_RGB565_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false, false},
|
||||
{NULL, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, true, false},
|
||||
{NULL, GL_RGB565_TWID_KOS, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_TWID_KOS, false, false},
|
||||
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, false},
|
||||
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_EXT, GL_BYTE, true, false},
|
||||
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_TWID_KOS, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_TWID_KOS, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_EXT, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_EXT, GL_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX8_TWID_KOS, GL_COLOR_INDEX8_TWID_KOS, GL_BYTE, false, false},
|
||||
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_BYTE, false, false},
|
||||
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_BYTE, false, false},
|
||||
{_rgb888_to_argb4444, GL_RGBA4, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_argb4444, GL_RGBA4, GL_RGB, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, false, true},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX, GL_BYTE, false, true},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, true, true},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX, GL_BYTE, true, true},
|
||||
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX4_EXT, GL_COLOR_INDEX4_EXT, GL_BYTE, false, false},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, true, false},
|
||||
{NULL, GL_COLOR_INDEX4_TWID_KOS, GL_COLOR_INDEX4_EXT, GL_BYTE, true, false},
|
||||
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{NULL, GL_RGBA8, GL_RGBA, GL_BYTE, false, false},
|
||||
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_rgba8888, GL_RGBA8, GL_RGB, GL_BYTE, false, false},
|
||||
|
||||
{_rgb888_to_argb4444, GL_RGBA4, GL_RGB, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgb888_to_argb4444, GL_RGBA4, GL_RGB, GL_BYTE, false, false},
|
||||
{_rgba8888_to_argb4444, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE, false, false},
|
||||
{_rgba8888_to_argb4444, GL_RGBA4, GL_RGBA, GL_BYTE, false, false},
|
||||
{_rgba8888_to_argb4444, GL_RGBA4, GL_RGBA, GL_BYTE, false, false},
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < sizeof(conversions) / sizeof(struct Entry); ++i) {
|
||||
@ -1465,6 +1480,79 @@ static bool _glTexImage2DValidate(GLenum target, GLint level, GLint internalForm
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _glTexSubImage2DValidate(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLenum format, GLenum type,
|
||||
GLsizei textureWidth, GLsizei textureHeight) {
|
||||
if (target != GL_TEXTURE_2D) {
|
||||
INFO_MSG("Invalid target. Only GL_TEXTURE_2D is supported.");
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (width > 1024 || height > 1024) {
|
||||
INFO_MSG("Invalid subimage size. Maximum 1024x1024.");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure format is valid
|
||||
GLint validFormats[] = {
|
||||
GL_ALPHA,
|
||||
GL_LUMINANCE,
|
||||
GL_INTENSITY,
|
||||
GL_LUMINANCE_ALPHA,
|
||||
GL_RED,
|
||||
GL_RGB,
|
||||
GL_RGBA,
|
||||
GL_BGRA,
|
||||
GL_COLOR_INDEX,
|
||||
GL_COLOR_INDEX4_EXT, /* Extension, for glCompressedTexImage pass-thru */
|
||||
GL_COLOR_INDEX8_EXT, /* Extension, for glCompressedTexImage pass-thru */
|
||||
GL_COLOR_INDEX4_TWID_KOS, /* Extension, for glCompressedTexImage pass-thru */
|
||||
GL_COLOR_INDEX8_TWID_KOS, /* Extension, for glCompressedTexImage pass-thru */
|
||||
0
|
||||
};
|
||||
|
||||
if (_glCheckValidEnum(format, validFormats, __func__) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate type
|
||||
if (format != GL_COLOR_INDEX4_EXT && format != GL_COLOR_INDEX4_TWID_KOS) {
|
||||
/* Use determineStride to see if type is valid */
|
||||
if (_determineStride(GL_RGBA, type) == -1) {
|
||||
INFO_MSG("Invalid pixel data type.");
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate offsets and dimensions using the underlying texture size
|
||||
if (xoffset < 0 || yoffset < 0 ||
|
||||
(xoffset + width) > textureWidth ||
|
||||
(yoffset + height) > textureHeight) {
|
||||
INFO_MSG("Subimage exceeds the dimensions of the texture.");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (level < 0) {
|
||||
INFO_MSG("Invalid mipmap level.");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure no border (since glTexSubImage2D doesn't allow it)
|
||||
GLint border = 0; // No border allowed
|
||||
if (border != 0) {
|
||||
INFO_MSG("Border must be zero for glTexSubImage2D.");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline GLboolean is4BPPFormat(GLenum format) {
|
||||
return format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS;
|
||||
}
|
||||
@ -1620,8 +1708,10 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
if(is4BPPFormat(internalFormat) && is4BPPFormat(format)) {
|
||||
// Special case twiddling. We have to unpack each src value
|
||||
// and repack into the right place
|
||||
twid_prepare_table(width, height);
|
||||
|
||||
for(uint32_t i = 0; i < (width * height); ++i) {
|
||||
uint32_t newLocation = twid_location(i, width, height);
|
||||
uint32_t newLocation = twid_location(i);
|
||||
|
||||
assert(newLocation < (width * height));
|
||||
assert((newLocation / 2) < destBytes);
|
||||
@ -1641,8 +1731,10 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
twid_prepare_table(width, height);
|
||||
|
||||
for(uint32_t i = 0; i < (width * height); ++i) {
|
||||
uint32_t newLocation = twid_location(i, width, height);
|
||||
uint32_t newLocation = twid_location(i);
|
||||
dst = conversionBuffer + (destStride * newLocation);
|
||||
|
||||
for(int j = 0; j < destStride; ++j)
|
||||
@ -1653,8 +1745,10 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
}
|
||||
} else if(needs_conversion == 3) {
|
||||
// Convert + twiddle
|
||||
twid_prepare_table(width, height);
|
||||
|
||||
for(uint32_t i = 0; i < (width * height); ++i) {
|
||||
uint32_t newLocation = twid_location(i, width, height);
|
||||
uint32_t newLocation = twid_location(i);
|
||||
dst = conversionBuffer + (destStride * newLocation);
|
||||
src = data + (sourceStride * i);
|
||||
conversion(src, dst);
|
||||
@ -1977,19 +2071,139 @@ GLAPI void APIENTRY glGetColorTableParameterfvEXT(GLenum target, GLenum pname, G
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glTexSubImage2D(
|
||||
GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {
|
||||
_GL_UNUSED(target);
|
||||
_GL_UNUSED(level);
|
||||
_GL_UNUSED(xoffset);
|
||||
_GL_UNUSED(yoffset);
|
||||
_GL_UNUSED(width);
|
||||
_GL_UNUSED(height);
|
||||
_GL_UNUSED(format);
|
||||
_GL_UNUSED(type);
|
||||
_GL_UNUSED(pixels);
|
||||
gl_assert(0 && "Not Implemented");
|
||||
void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||
GLsizei width, GLsizei height, GLenum format,
|
||||
GLenum type, const GLvoid *data) {
|
||||
TRACE();
|
||||
|
||||
gl_assert(ACTIVE_TEXTURE < MAX_GLDC_TEXTURE_UNITS);
|
||||
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||
|
||||
if (!active || !active->data) {
|
||||
INFO_MSG("Called glTexSubImage2D on unbound or uninitialized texture");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve the dimensions of the currently bound texture
|
||||
GLsizei textureWidth = active->width;
|
||||
GLsizei textureHeight = active->height;
|
||||
|
||||
if (!_glTexSubImage2DValidate(target, level, xoffset, yoffset, width, height, format, type, textureWidth, textureHeight)) {
|
||||
INFO_MSG("Error: _glTexSubImage2DValidate failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GLboolean isPaletted = (
|
||||
active->internalFormat == GL_COLOR_INDEX8_EXT ||
|
||||
active->internalFormat == GL_COLOR_INDEX4_EXT ||
|
||||
active->internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
|
||||
active->internalFormat == GL_COLOR_INDEX8_TWID_KOS
|
||||
) ? GL_TRUE : GL_FALSE;
|
||||
|
||||
GLenum cleanInternalFormat = _cleanInternalFormat(active->internalFormat);
|
||||
|
||||
// Determine source stride
|
||||
GLint sourceStride = _determineStride(format, type);
|
||||
GLuint srcBytes = (width * height * sourceStride);
|
||||
|
||||
// Calculate destination stride (this accounts for both POT and NPOT)
|
||||
GLint destStride = _determineStrideInternal(cleanInternalFormat);
|
||||
|
||||
// Calculate destBytes using the texture's full dimensions
|
||||
GLuint destBytes = (textureWidth * textureHeight * destStride);
|
||||
|
||||
TextureConversionFunc conversion;
|
||||
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
|
||||
|
||||
// Adjust source bytes for 4bpp formats
|
||||
if (format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS) {
|
||||
srcBytes /= 2;
|
||||
}
|
||||
|
||||
if ((needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK) {
|
||||
destBytes /= 2;
|
||||
} else if (active->internalFormat == GL_COLOR_INDEX4_EXT || active->internalFormat == GL_COLOR_INDEX4_TWID_KOS) {
|
||||
destBytes /= 2;
|
||||
}
|
||||
|
||||
if (needs_conversion < 0) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
INFO_MSG("Couldn't find necessary texture conversion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the starting point for the subregion in the texture data
|
||||
GLubyte* targetData = active->data;
|
||||
if (needs_conversion > 0) {
|
||||
GLubyte* conversionBuffer = (GLubyte*) memalign(32, destBytes);
|
||||
|
||||
const GLubyte* src = data;
|
||||
GLubyte* dst = conversionBuffer;
|
||||
|
||||
bool pack = (needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK;
|
||||
needs_conversion &= ~CONVERSION_TYPE_PACK;
|
||||
|
||||
// Only initialize the buffer with zeros if it's a partial update
|
||||
if (xoffset != 0 || yoffset != 0 || width != textureWidth || height != textureHeight) {
|
||||
memset(conversionBuffer, 0, destBytes);
|
||||
}
|
||||
if (needs_conversion == CONVERSION_TYPE_CONVERT) {
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
dst = conversionBuffer + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
||||
for (uint32_t x = 0; x < width; ++x) {
|
||||
conversion(src, dst);
|
||||
dst += destStride;
|
||||
src += sourceStride;
|
||||
}
|
||||
}
|
||||
} else if (needs_conversion == 2 || needs_conversion == 3) {
|
||||
twid_prepare_table(textureWidth, textureHeight);
|
||||
|
||||
for (uint32_t y = yoffset; y < yoffset + height; ++y) {
|
||||
for (uint32_t x = xoffset; x < xoffset + width; ++x) {
|
||||
uint32_t srcIndex = (y - yoffset) * width + (x - xoffset);
|
||||
uint32_t newLocation = twid_location(y * textureWidth + x);
|
||||
dst = conversionBuffer + (destStride * newLocation);
|
||||
|
||||
if (needs_conversion == 3) {
|
||||
conversion(src + srcIndex * sourceStride, dst);
|
||||
} else {
|
||||
memcpy(dst, src + srcIndex * sourceStride, destStride);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pack) {
|
||||
assert(isPaletted);
|
||||
size_t dst_byte = 0;
|
||||
for (size_t src_byte = 0; src_byte < destBytes; ++src_byte) {
|
||||
uint8_t v = conversionBuffer[src_byte];
|
||||
|
||||
if (src_byte % 2 == 0) {
|
||||
conversionBuffer[dst_byte] = (conversionBuffer[dst_byte] & 0xF) | ((v & 0xF) << 4);
|
||||
} else {
|
||||
conversionBuffer[dst_byte] = (conversionBuffer[dst_byte] & 0xF0) | (v & 0xF);
|
||||
dst_byte++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the converted data to the texture
|
||||
FASTCPY(targetData, conversionBuffer, destBytes);
|
||||
|
||||
free(conversionBuffer);
|
||||
} else {
|
||||
// No conversion necessary, we can update data directly
|
||||
for (GLsizei y = 0; y < height; ++y) {
|
||||
GLsizei srcRowWidth = width * sourceStride;
|
||||
GLubyte* destRow = targetData + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
||||
FASTCPY(destRow, (GLubyte*)data + y * srcRowWidth, srcRowWidth);
|
||||
}
|
||||
}
|
||||
|
||||
_glGPUStateMarkDirty();
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
|
||||
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) {
|
||||
@ -31,6 +30,31 @@ void aligned_vector_init(AlignedVector* vector, uint32_t element_size) {
|
||||
(void) ptr;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void aligned_vector_shrink_to_fit(AlignedVector* vector) {
|
||||
AlignedVectorHeader* const hdr = &vector->hdr;
|
||||
if(hdr->size == 0) {
|
||||
|
||||
@ -27,10 +27,10 @@ static inline void* memalign(size_t alignment, size_t size) {
|
||||
#define AV_INLINE_DEBUG AV_NO_INSTRUMENT __attribute__((always_inline))
|
||||
#define AV_FORCE_INLINE static AV_INLINE_DEBUG
|
||||
#endif
|
||||
#define AV_NO_INLINE __attribute__((noinline))
|
||||
|
||||
|
||||
#ifdef __DREAMCAST__
|
||||
#include <kos/string.h>
|
||||
|
||||
AV_FORCE_INLINE void *AV_MEMCPY4(void *dest, const void *src, size_t len)
|
||||
{
|
||||
@ -86,37 +86,16 @@ typedef struct {
|
||||
|
||||
void aligned_vector_init(AlignedVector* vector, uint32_t element_size);
|
||||
|
||||
/* Resizes the backing array if necessary so that element_count elements can fit in the array */
|
||||
/* (note that only capacity is potentially changed, size is never changed) */
|
||||
AV_NO_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t element_count);
|
||||
|
||||
AV_FORCE_INLINE void* aligned_vector_at(const AlignedVector* vector, const uint32_t index) {
|
||||
const AlignedVectorHeader* hdr = &vector->hdr;
|
||||
assert(index < hdr->size);
|
||||
return vector->data + (index * hdr->element_size);
|
||||
}
|
||||
|
||||
AV_FORCE_INLINE 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;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ __BEGIN_DECLS
|
||||
#define GL_FRONT_FACE 0x0B46
|
||||
|
||||
/* Scissor box */
|
||||
#define GL_SCISSOR_TEST 0x0008 /* capability bit */
|
||||
#define GL_SCISSOR_TEST 0x0C11
|
||||
#define GL_SCISSOR_BOX 0x0C10
|
||||
|
||||
/* Stencil actions */
|
||||
@ -109,7 +109,7 @@ __BEGIN_DECLS
|
||||
#define GL_SRC_ALPHA_SATURATE 0x0308
|
||||
|
||||
/* Misc texture constants */
|
||||
#define GL_TEXTURE_2D 0x0001 /* capability bit */
|
||||
#define GL_TEXTURE_2D 0x0DE1
|
||||
#define GL_TEXTURE_WRAP_S 0x2802
|
||||
#define GL_TEXTURE_WRAP_T 0x2803
|
||||
#define GL_TEXTURE_MAG_FILTER 0x2800
|
||||
@ -204,7 +204,7 @@ __BEGIN_DECLS
|
||||
#define GL_CLIP_PLANE5 0x3005
|
||||
|
||||
/* Fog */
|
||||
#define GL_FOG 0x0004 /* capability bit */
|
||||
#define GL_FOG 0x0B60
|
||||
#define GL_FOG_MODE 0x0B65
|
||||
#define GL_FOG_DENSITY 0x0B62
|
||||
#define GL_FOG_COLOR 0x0B66
|
||||
@ -226,7 +226,7 @@ __BEGIN_DECLS
|
||||
#define GL_FOG_HINT 0x0C54
|
||||
|
||||
/* Lighting constants */
|
||||
#define GL_LIGHTING 0x0b50
|
||||
#define GL_LIGHTING 0x0b50
|
||||
|
||||
#define GL_LIGHT0 0x4000
|
||||
#define GL_LIGHT1 0x4001
|
||||
@ -446,7 +446,7 @@ __BEGIN_DECLS
|
||||
#define GLshort short
|
||||
#define GLint int
|
||||
#define GLfloat float
|
||||
#define GLdouble float
|
||||
#define GLdouble double
|
||||
#define GLvoid void
|
||||
#define GLushort unsigned short
|
||||
#define GLuint unsigned int
|
||||
@ -454,7 +454,7 @@ __BEGIN_DECLS
|
||||
#define GLsizei unsigned int
|
||||
#define GLfixed const unsigned int
|
||||
#define GLclampf float
|
||||
#define GLclampd float
|
||||
#define GLclampd double
|
||||
#define GLubyte unsigned char
|
||||
#define GLbitfield unsigned int
|
||||
#define GLboolean unsigned char
|
||||
@ -481,6 +481,16 @@ __BEGIN_DECLS
|
||||
#define GL_PACK_SKIP_PIXELS 0x0D04
|
||||
#define GL_PACK_ALIGNMENT 0x0D05
|
||||
|
||||
#define GL_MULTISAMPLE 0x809D
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
#define GL_SAMPLE_BUFFERS 0x80A8
|
||||
#define GL_SAMPLES 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
|
||||
#define GL_MULTISAMPLE_BIT 0x20000000
|
||||
|
||||
#define GLAPI extern
|
||||
#define APIENTRY
|
||||
|
||||
@ -542,6 +552,10 @@ GLAPI GLvoid APIENTRY glRecti(GLint x1, GLint y1, GLint x2, GLint y2);
|
||||
GLAPI GLvoid APIENTRY glRectiv(const GLint *v1, const GLint *v2);
|
||||
#define glRectsv glRectiv
|
||||
|
||||
/* Primitive configuration */
|
||||
GLAPI void APIENTRY glLineWidth(GLfloat width);
|
||||
GLAPI void APIENTRY glPointSize(GLfloat size);
|
||||
|
||||
/* Enable / Disable Capability */
|
||||
/* Currently Supported Capabilities:
|
||||
GL_TEXTURE_2D
|
||||
@ -565,12 +579,12 @@ GLAPI void APIENTRY glReadBuffer(GLenum mode);
|
||||
GLAPI void APIENTRY glDrawBuffer(GLenum mode);
|
||||
|
||||
/* Depth Testing */
|
||||
GLAPI void APIENTRY glClearDepth(GLfloat depth);
|
||||
GLAPI void APIENTRY glClearDepth(GLdouble 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);
|
||||
GLAPI void APIENTRY glDepthRange(GLdouble n, GLdouble f);
|
||||
GLAPI void APIENTRY glDepthRangef(GLfloat n, GLfloat f);
|
||||
|
||||
/* Hints */
|
||||
/* Currently Supported Capabilities:
|
||||
@ -682,9 +696,9 @@ GLAPI void APIENTRY glScalef(GLfloat x, GLfloat y, GLfloat z);
|
||||
GLAPI void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
|
||||
#define glRotated glRotatef
|
||||
|
||||
GLAPI void APIENTRY glOrtho(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar);
|
||||
GLAPI void APIENTRY glOrtho(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar);
|
||||
|
||||
GLAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
@ -692,9 +706,9 @@ GLAPI void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
|
||||
GLAPI void APIENTRY glKosGetMatrix(GLenum mode, GLfloat *params);
|
||||
|
||||
GLAPI void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
||||
GLfloat bottom, GLfloat top,
|
||||
GLfloat znear, GLfloat zfar);
|
||||
GLAPI void APIENTRY glFrustum(GLdouble left, GLdouble right,
|
||||
GLdouble bottom, GLdouble top,
|
||||
GLdouble znear, GLdouble zfar);
|
||||
|
||||
/* Fog Functions - client must enable GL_FOG for this to take effect */
|
||||
GLAPI void APIENTRY glFogi(GLenum pname, GLint param);
|
||||
@ -732,7 +746,6 @@ 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);
|
||||
|
||||
@ -54,16 +54,6 @@ __BEGIN_DECLS
|
||||
#define GL_TRANSPOSE_TEXTURE_MATRIX_ARB 0x84E5
|
||||
#define GL_TRANSPOSE_COLOR_MATRIX_ARB 0x84E6
|
||||
|
||||
#define GL_MULTISAMPLE_ARB 0x809D
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
|
||||
#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
|
||||
#define GL_SAMPLE_COVERAGE_ARB 0x80A0
|
||||
#define GL_SAMPLE_BUFFERS_ARB 0x80A8
|
||||
#define GL_SAMPLES_ARB 0x80A9
|
||||
#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
|
||||
#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
|
||||
#define GL_MULTISAMPLE_BIT_ARB 0x20000000
|
||||
|
||||
#define GL_NORMAL_MAP_ARB 0x8511
|
||||
#define GL_REFLECTION_MAP_ARB 0x8512
|
||||
#define GL_TEXTURE_CUBE_MAP_ARB 0x8513
|
||||
|
||||
@ -30,9 +30,9 @@ GLAPI void APIENTRY gluPerspective(GLdouble fovy, GLdouble aspect,
|
||||
GLdouble zNear, GLdouble zFar);
|
||||
|
||||
/* gluLookAt - Set Camera Position for Rendering. */
|
||||
GLAPI void APIENTRY gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
|
||||
GLfloat centerx, GLfloat centery, GLfloat centerz,
|
||||
GLfloat upx, GLfloat upy, GLfloat upz);
|
||||
GLAPI void APIENTRY gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
|
||||
GLdouble centerx, GLdouble centery, GLdouble centerz,
|
||||
GLdouble upx, GLdouble upy, GLdouble upz);
|
||||
|
||||
/* generate mipmaps for any image provided by the user and then pass them to OpenGL */
|
||||
GLAPI GLint APIENTRY gluBuild2DMipmaps(GLenum target, GLint internalFormat,
|
||||
|
||||
@ -80,7 +80,6 @@ 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
|
||||
|
||||
|
||||
@ -14,179 +14,172 @@
|
||||
GLfloat global_diffuse[] = {1.0, 1.0, 1.0, 1.0};
|
||||
GLfloat global_ambient[] = {1.0, 1.0, 1.0, 1.0};
|
||||
|
||||
static int decode_dtex(Image* image, FILE* file) {
|
||||
struct {
|
||||
char id[4]; // 'DTEX'
|
||||
GLushort width;
|
||||
GLushort height;
|
||||
GLuint type;
|
||||
GLuint size;
|
||||
} header;
|
||||
|
||||
fread(&header, sizeof(header), 1, file);
|
||||
|
||||
image->twiddled = (header.type & (1 << 26)) < 1;
|
||||
image->compressed = (header.type & (1 << 30)) > 0;
|
||||
image->mipmapped = (header.type & (1 << 31)) > 0;
|
||||
GLuint format = (header.type >> 27) & 0b111;
|
||||
|
||||
image->data = (char *) malloc (header.size);
|
||||
image->sizeX = header.width;
|
||||
image->sizeY = header.height;
|
||||
image->dataSize = header.size;
|
||||
|
||||
fread(image->data, image->dataSize, 1, file);
|
||||
fclose(file);
|
||||
|
||||
if(image->compressed && image->twiddled) {
|
||||
switch(format) {
|
||||
case 0:
|
||||
puts("Compressed & Twiddled - ARGB 1555");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
puts("Compressed & Twiddled - RGB 565");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
puts("Compressed & Twiddled - ARGB 4444");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
} else if (image->compressed) {
|
||||
switch(format) {
|
||||
case 0:
|
||||
puts("Compressed - ARGB 1555");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_1555_VQ_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
puts("Compressed - RGB 565");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_RGB_565_VQ_KOS;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
puts("Compressed - ARGB 4444");
|
||||
if(image->mipmapped) {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS;
|
||||
} else {
|
||||
image->internalFormat = GL_COMPRESSED_ARGB_4444_VQ_KOS;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
switch (format) {
|
||||
case 0:
|
||||
puts("Uncompressed - ARGB 1555");
|
||||
image->internalFormat = GL_ARGB1555_TWID_KOS;
|
||||
image->transferFormat = GL_BGRA;
|
||||
image->transferType = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS;
|
||||
return 1;
|
||||
|
||||
case 1:
|
||||
puts("Uncompressed - RGB 565");
|
||||
image->internalFormat = GL_RGB565_TWID_KOS;
|
||||
image->transferFormat = GL_RGB;
|
||||
image->transferType = GL_UNSIGNED_SHORT_5_6_5_TWID_KOS;
|
||||
return 1;
|
||||
|
||||
case 2:
|
||||
puts("Uncompressed - ARGB 4444");
|
||||
image->internalFormat = GL_ARGB4444_TWID_KOS;
|
||||
image->transferFormat = GL_BGRA;
|
||||
image->transferType = GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Invalid texture format %u\n", header.type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dtex_to_gl_texture(texture *tex, char* filename) {
|
||||
// Load Texture
|
||||
Image *image;
|
||||
Image image = { 0 };
|
||||
|
||||
// allocate space for texture
|
||||
image = (Image *) malloc(sizeof(Image));
|
||||
if (image == NULL) {
|
||||
printf("No memory for .DTEX file\n");
|
||||
return(0);
|
||||
}
|
||||
FILE* file = NULL;
|
||||
|
||||
FILE* file = NULL;
|
||||
// make sure the file is there.
|
||||
if ((file = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
printf("File not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// make sure the file is there.
|
||||
if ((file = fopen(filename, "rb")) == NULL)
|
||||
{
|
||||
printf("File not found");
|
||||
return 0;
|
||||
}
|
||||
decode_dtex(&image, file);
|
||||
|
||||
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");
|
||||
}
|
||||
// Create Texture
|
||||
GLuint texture_id;
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id); // 2d texture (x and y size)
|
||||
|
||||
if (image.compressed) {
|
||||
glCompressedTexImage2D(GL_TEXTURE_2D, 0,
|
||||
image.internalFormat, image.sizeX, image.sizeY,
|
||||
0, image.dataSize, image.data);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0,
|
||||
colorType, image->sizeX, image->sizeY, 0,
|
||||
newFormat, image->internalFormat, image->data);
|
||||
image.internalFormat, image.sizeX, image.sizeY, 0,
|
||||
image.transferFormat, image.transferType, image.data);
|
||||
}
|
||||
|
||||
tex->id = texture_id;
|
||||
tex->w = image->sizeX;
|
||||
tex->h = image->sizeY;
|
||||
tex->u = 0.f;
|
||||
tex->v = 0.f;
|
||||
tex->a = tex->light = 1;
|
||||
tex->color[0] = tex->color[1] = tex->color[2] = 1.0f;
|
||||
tex->uSize = tex->vSize = 1.0f;
|
||||
tex->xScale = tex->yScale = 1.0f;
|
||||
tex->format = image->internalFormat;
|
||||
tex->min_filter = tex->mag_filter = GL_NEAREST;
|
||||
tex->blend_source = GL_SRC_ALPHA;
|
||||
tex->blend_dest = GL_ONE_MINUS_SRC_ALPHA;
|
||||
strcpy(tex->path, filename);
|
||||
tex->id = texture_id;
|
||||
tex->w = image.sizeX;
|
||||
tex->h = image.sizeY;
|
||||
tex->u = 0.f;
|
||||
tex->v = 0.f;
|
||||
tex->a = tex->light = 1;
|
||||
tex->color[0] = tex->color[1] = tex->color[2] = 1.0f;
|
||||
tex->uSize = tex->vSize = 1.0f;
|
||||
tex->xScale = tex->yScale = 1.0f;
|
||||
tex->format = image.internalFormat;
|
||||
tex->min_filter = tex->mag_filter = GL_NEAREST;
|
||||
tex->blend_source = GL_SRC_ALPHA;
|
||||
tex->blend_dest = GL_ONE_MINUS_SRC_ALPHA;
|
||||
strcpy(tex->path, filename);
|
||||
|
||||
GLuint expected = 2 * image.sizeX * image.sizeY;
|
||||
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) image.dataSize));
|
||||
|
||||
printf("Texture size: %lu x %lu\n", image->sizeX, image->sizeY);
|
||||
printf("Texture ratio: %d\n", ratio);
|
||||
printf("Texture size: %lu x %lu\n", image->sizeX, image->sizeY);
|
||||
printf("Texture %s loaded\n", tex->path);
|
||||
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);
|
||||
return(1);
|
||||
}
|
||||
|
||||
void draw_textured_quad(texture *tex) {
|
||||
|
||||
@ -29,8 +29,8 @@ typedef struct Image {
|
||||
unsigned long sizeX;
|
||||
unsigned long sizeY;
|
||||
char *data;
|
||||
GLenum internalFormat;
|
||||
GLboolean mipmapped;
|
||||
GLenum internalFormat, transferFormat, transferType;
|
||||
unsigned int mipmapped, compressed, twiddled;
|
||||
unsigned int dataSize;
|
||||
} Image;
|
||||
|
||||
|
||||
@ -88,7 +88,7 @@ void DrawGLScene()
|
||||
glLoadIdentity();
|
||||
glTranslated(-1 , -1, -5);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_DEPTH_FUNC);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
glTranslated(0.5, 0, -0.2);
|
||||
|
||||
@ -26,7 +26,7 @@ KOS_INIT_ROMDISK(romdisk);
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
/* storage for one texture */
|
||||
int texture[1];
|
||||
GLuint texture[1];
|
||||
|
||||
// Load Bitmaps And Convert To Textures
|
||||
void LoadGLTextures() {
|
||||
@ -81,7 +81,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
|
||||
|
||||
GLfloat l1_pos[] = {5.0, 0.0, 1.0, 1.0};
|
||||
GLfloat l1_diff[] = {1.0, 0.0, 0.0, 1.0};
|
||||
GLfloat l1_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
//GLfloat l1_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
|
||||
//glLightfv(GL_LIGHT1, GL_AMBIENT, l1_amb);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, l1_diff);
|
||||
@ -93,7 +93,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
|
||||
GLfloat l2_pos[] = {0.0, 15.0, 1.0, 1.0};
|
||||
GLfloat l2_dir[] = {0.0, -1.0, 0.0};
|
||||
GLfloat l2_diff[] = {0.5, 0.5, 0.0, 1.0};
|
||||
GLfloat l2_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
//GLfloat l2_amb[] = {0.5, 0.5, 0.5, 1.0};
|
||||
|
||||
glEnable(GL_LIGHT2);
|
||||
glLightfv(GL_LIGHT2, GL_DIFFUSE, l2_diff);
|
||||
@ -145,7 +145,7 @@ void DrawTexturedQuad(int tex, float x, float y, float z)
|
||||
GLfloat y0 = y - texH / 2;
|
||||
GLfloat x1 = x + texW / 2;
|
||||
GLfloat y1 = y + texH / 2;
|
||||
GLfloat color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
//GLfloat color[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
GLfloat mat_ambient[] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
GLfloat vertex_data[] = {
|
||||
@ -172,14 +172,6 @@ void DrawTexturedQuad(int tex, float x, float y, float z)
|
||||
0.0, 0.0, 1.0
|
||||
};
|
||||
|
||||
GLfloat color_data[] = {
|
||||
/* 2D Coordinate, texture coordinate */
|
||||
color[0], color[1], color[2], color[3],
|
||||
color[0], color[1], color[2], color[3],
|
||||
color[0], color[1], color[2], color[3],
|
||||
color[0], color[1], color[2], color[3]
|
||||
};
|
||||
|
||||
//GLint indices[] = {0,1,2,3,2,3};
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
@ -24,8 +24,7 @@ KOS_INIT_ROMDISK(romdisk);
|
||||
#include "../loadbmp.h"
|
||||
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
int texture[1];
|
||||
GLuint texture[1];
|
||||
|
||||
void LoadGLTextures() {
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ int ImageLoad(char *filename, Image *image) {
|
||||
return 0;
|
||||
}
|
||||
image->sizeX = sizeX;
|
||||
printf("Width of %s: %d\n", filename, sizeX);
|
||||
printf("Width of %s: %ld\n", filename, sizeX);
|
||||
|
||||
// read the height
|
||||
if ((i = fread(&sizeY, 4, 1, file)) != 1) {
|
||||
@ -43,7 +43,7 @@ int ImageLoad(char *filename, Image *image) {
|
||||
return 0;
|
||||
}
|
||||
image->sizeY = sizeY;
|
||||
printf("Height of %s: %d\n", filename, sizeY);
|
||||
printf("Height of %s: %ld\n", filename, sizeY);
|
||||
|
||||
// calculate the size (assuming 24 bits or 3 bytes per pixel).
|
||||
size = image->sizeX * image->sizeY * 3;
|
||||
|
||||
@ -20,9 +20,7 @@ KOS_INIT_ROMDISK(romdisk);
|
||||
#endif
|
||||
|
||||
#include "../loadbmp.h"
|
||||
|
||||
/* storage for one texture */
|
||||
int texture[1];
|
||||
GLuint texture[1];
|
||||
|
||||
// Load Bitmaps And Convert To Textures
|
||||
void LoadGLTextures() {
|
||||
|
||||
@ -53,8 +53,11 @@ 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, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
// Create an empty texture first
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
||||
|
||||
// Update the texture with the image data
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
free(image1);
|
||||
}
|
||||
|
||||
|
||||
@ -62,7 +62,7 @@ int ImageLoad(char *filename, Image *image) {
|
||||
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;
|
||||
//GLboolean strided = (header.type & (1 << 25)) > 0;
|
||||
GLuint format = (header.type >> 27) & 0b111;
|
||||
|
||||
image->data = (char *) malloc (header.size);
|
||||
@ -70,8 +70,8 @@ int ImageLoad(char *filename, Image *image) {
|
||||
image->sizeY = header.height;
|
||||
image->dataSize = header.size;
|
||||
|
||||
GLuint expected = 2 * header.width * header.height;
|
||||
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) 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);
|
||||
|
||||
@ -22,7 +22,7 @@ KOS_INIT_ROMDISK(romdisk);
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
/* storage for one texture */
|
||||
int texture[1];
|
||||
GLuint texture[1];
|
||||
|
||||
/* Image type - contains height, width, and data */
|
||||
struct Image {
|
||||
@ -59,7 +59,7 @@ int ImageLoad(char *filename, Image *image) {
|
||||
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;
|
||||
//GLboolean strided = (header.type & (1 << 25)) > 0;
|
||||
GLuint format = (header.type >> 27) & 0b111;
|
||||
|
||||
image->data = (char *) malloc (header.size);
|
||||
@ -67,8 +67,8 @@ int ImageLoad(char *filename, Image *image) {
|
||||
image->sizeY = header.height;
|
||||
image->dataSize = header.size;
|
||||
|
||||
GLuint expected = 2 * header.width * header.height;
|
||||
GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) 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);
|
||||
|
||||
@ -11,10 +11,10 @@
|
||||
#ifdef __DREAMCAST__
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glkos.h>
|
||||
#include <GL/glu.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Simple OpenGL example to demonstrate blending and lighting.
|
||||
|
||||
|
||||
@ -11,6 +11,11 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __DREAMCAST__
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#define FPS 60
|
||||
uint32_t waittime = 1000.0f/FPS;
|
||||
uint32_t framestarttime = 0;
|
||||
@ -58,8 +63,9 @@ KOS_INIT_ROMDISK(romdisk);
|
||||
#include <GL/glu.h> // Header File For The GLu32 Library
|
||||
#include <GL/glkos.h>
|
||||
#else
|
||||
#include <GL/gl.h> // Header File For The OpenGL32 Library
|
||||
#include <GL/glu.h> // Header File For The GLu32 Library
|
||||
#include <GL/gl.h> // Header File For The OpenGL32 Library
|
||||
#include <GL/glkos.h>
|
||||
#include <GL/glu.h> // Header File For The GLu32 Library
|
||||
#endif
|
||||
|
||||
#define BOOL int
|
||||
@ -227,8 +233,6 @@ int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
BOOL done=FALSE; // Bool Variable To Exit Loop
|
||||
|
||||
glKosInit();
|
||||
|
||||
InitGL();
|
||||
|
||||
@ -22,8 +22,7 @@ KOS_INIT_ROMDISK(romdisk);
|
||||
|
||||
/* floats for x rotation, y rotation, z rotation */
|
||||
float xrot, yrot, zrot;
|
||||
/* storage for one texture */
|
||||
int texture[1];
|
||||
GLuint texture[1];
|
||||
|
||||
typedef struct {
|
||||
unsigned int height;
|
||||
|
||||
@ -41,7 +41,7 @@
|
||||
/* floats for x rotation, y rotation, z rotation */
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
int textures[3];
|
||||
GLuint textures[3];
|
||||
|
||||
typedef struct {
|
||||
uint32_t height;
|
||||
@ -272,7 +272,7 @@ int BMP_GetPalette(FILE *pFile)
|
||||
bitCount = BmpInfoHeader.ClrImportant * sizeof(RGB_QUAD);
|
||||
|
||||
if (fread(BmpRgbQuad, 1, bitCount, pFile) != bitCount){
|
||||
fprintf(stderr, "Failed to read palette: %d\n", bitCount);
|
||||
fprintf(stderr, "Failed to read palette: %ld\n", bitCount);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -293,7 +293,7 @@ int BMP_GetPalette(FILE *pFile)
|
||||
int BMP_Depack(FILE *pFile,char *pZone)
|
||||
{
|
||||
char PadRead[4];
|
||||
int32_t i, j, Offset, PadSize, pix, c;
|
||||
int32_t i, j, Offset, PadSize, c;
|
||||
|
||||
if (BmpInfoHeader.Compression != BMP_BI_RGB)
|
||||
return 0;
|
||||
@ -356,7 +356,7 @@ int LoadPalettedBMP(const char* filename, Image* image)
|
||||
}
|
||||
|
||||
/* store palette information */
|
||||
image->palette = BmpPal;
|
||||
image->palette = (char*)BmpPal;
|
||||
image->palette_width = 16;
|
||||
|
||||
|
||||
|
||||
203
samples/primitive_modes/main.c
Normal file
203
samples/primitive_modes/main.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glkos.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __DREAMCAST__
|
||||
#include <SDL2/SDL.h>
|
||||
static SDL_Window* win_handle;
|
||||
#else
|
||||
#include <kos.h>
|
||||
#include <GL/glkos.h>
|
||||
#endif
|
||||
|
||||
static void DrawLineLoop(float y) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(410.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(490.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(490.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(410.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawLineStrip(float y) {
|
||||
glBegin(GL_LINE_STRIP);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(310.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(390.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(390.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(310.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawLine(float y) {
|
||||
glBegin(GL_LINES);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(210.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(290.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(290.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(210.0f, y + 90.0f);
|
||||
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(230.0f, y + 25.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(250.0f, y + 75.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(260.0f, y + 75.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(280.0f, y + 45.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawPoint(float y) {
|
||||
glBegin(GL_POINTS);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(110.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(190.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(190.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(110.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawQuad(float y) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(10.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(90.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(90.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(10.0f, y + 90.0f);
|
||||
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(110.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(190.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(190.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(110.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawQuadStrip(float y) {
|
||||
glBegin(GL_QUAD_STRIP);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(210.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(290.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(290.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(210.0f, y + 90.0f);
|
||||
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(310.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(390.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(390.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(310.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawTriList(float y) {
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f( 10.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f( 90.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f( 90.0f, y + 90.0f);
|
||||
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(110.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(190.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(190.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void DrawTriStrip(float y) {
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(210.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(290.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(290.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(210.0f, y + 90.0f);
|
||||
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(310.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(390.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(390.0f, y + 90.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(310.0f, y + 90.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
static void DrawTriFan(float y) {
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glColor3f(1.0f, 0.0f, 0.0f); glVertex2f(410.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(490.0f, y + 10.0f);
|
||||
glColor3f(0.0f, 0.0f, 1.0f); glVertex2f(445.0f, y + 90.0f);
|
||||
|
||||
glColor3f(0.0f, 1.0f, 0.0f); glVertex2f(590.0f, y + 10.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f); glVertex2f(510.0f, y + 45.0f);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void sample_init() {
|
||||
#ifndef __DREAMCAST__
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
win_handle = SDL_CreateWindow("Shapes", 0, 0, 640, 480, SDL_WINDOW_OPENGL);
|
||||
SDL_GL_CreateContext(win_handle);
|
||||
#else
|
||||
glKosInit();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int sample_should_exit() {
|
||||
#ifndef __DREAMCAST__
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
if(event.type == SDL_QUIT) return 1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
maple_device_t *cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||
if (!cont) return 0;
|
||||
|
||||
cont_state_t *state = (cont_state_t *)maple_dev_status(cont);
|
||||
if (!state) return 0;
|
||||
|
||||
return state->buttons & CONT_START;
|
||||
#endif
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sample_init();
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 1);
|
||||
glViewport(0, 0, 640, 480);
|
||||
|
||||
float mat[4][4] = { 0 };
|
||||
float L = 0, T = 0, R = 640, B = 480, N = -100, F = 100;
|
||||
mat[0][0] = 2.0f / (R - L);
|
||||
mat[1][1] = 2.0f / (T - B);
|
||||
mat[2][2] = -2.0f / (F - N);
|
||||
mat[3][0] = -(R + L) / (R - L);
|
||||
mat[3][1] = -(T + B) / (T - B);
|
||||
mat[3][2] = -(F + N) / (F - N);
|
||||
mat[3][3] = 1;
|
||||
glLoadMatrixf(*mat);
|
||||
|
||||
while (!sample_should_exit()) {
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
DrawTriStrip(300);
|
||||
DrawTriFan(300);
|
||||
DrawTriList(300);
|
||||
|
||||
DrawQuadStrip(200);
|
||||
DrawQuad(200);
|
||||
|
||||
glPointSize(5);
|
||||
DrawPoint(100);
|
||||
glLineWidth(2);
|
||||
DrawLineLoop(100);
|
||||
glLineWidth(4);
|
||||
DrawLineStrip(100);
|
||||
glLineWidth(10);
|
||||
DrawLine(100);
|
||||
|
||||
glPointSize(1);
|
||||
glLineWidth(1);
|
||||
DrawPoint(0);
|
||||
DrawLineLoop(0);
|
||||
DrawLineStrip(0);
|
||||
DrawLine(0);
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
DrawQuad(400);
|
||||
DrawTriStrip(400);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
#ifdef SDL2_BUILD
|
||||
SDL_GL_SwapWindow(win_handle);
|
||||
#else
|
||||
glKosSwapBuffers();
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -287,7 +287,7 @@ static bool write_samples(const char* path) {
|
||||
root = ARCS;
|
||||
for(int i = 0; i < BUCKET_SIZE; ++i) {
|
||||
if(root->pc) {
|
||||
printf("Incrementing %d for %x. ", (root->pc - lowest_address) / bin_size, (unsigned int) root->pc);
|
||||
printf("Incrementing %ld for %x. ", (root->pc - lowest_address) / bin_size, (unsigned int) root->pc);
|
||||
bins[(root->pc - lowest_address) / bin_size]++;
|
||||
printf("Now: %d\n", (int) bins[(root->pc - lowest_address) / bin_size]);
|
||||
|
||||
|
||||
@ -39,6 +39,42 @@ public:
|
||||
self->defrag_moves.push_back(std::make_pair(src, dst));
|
||||
}
|
||||
|
||||
void test_count_free() {
|
||||
alloc_init(pool, POOL_SIZE);
|
||||
|
||||
assert_equal(alloc_count_free(pool), POOL_SIZE);
|
||||
|
||||
void* a1 = alloc_malloc(pool, 2048);
|
||||
assert_equal(alloc_count_free(pool), POOL_SIZE - 2048);
|
||||
|
||||
void* a2 = alloc_malloc(pool, 2048);
|
||||
assert_equal(alloc_count_free(pool), POOL_SIZE - 4096);
|
||||
|
||||
alloc_free(pool, a1);
|
||||
assert_equal(alloc_count_free(pool), POOL_SIZE - 2048);
|
||||
|
||||
alloc_free(pool, a2);
|
||||
assert_equal(alloc_count_free(pool), POOL_SIZE);
|
||||
}
|
||||
|
||||
void test_count_contiguous() {
|
||||
alloc_init(pool, POOL_SIZE);
|
||||
|
||||
assert_equal(alloc_count_continuous(pool), POOL_SIZE);
|
||||
|
||||
void* a1 = alloc_malloc(pool, 2048);
|
||||
assert_equal(alloc_count_continuous(pool), POOL_SIZE - 2048);
|
||||
|
||||
void* a2 = alloc_malloc(pool, 2048);
|
||||
assert_equal(alloc_count_continuous(pool), POOL_SIZE - 4096);
|
||||
|
||||
alloc_free(pool, a1);
|
||||
assert_equal(alloc_count_continuous(pool), POOL_SIZE - 4096);
|
||||
|
||||
alloc_free(pool, a2);
|
||||
assert_equal(alloc_count_continuous(pool), POOL_SIZE);
|
||||
}
|
||||
|
||||
void test_defrag() {
|
||||
alloc_init(pool, POOL_SIZE);
|
||||
|
||||
|
||||
@ -435,7 +435,7 @@ bool test_clip_case_001() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 5);
|
||||
check_equal(sent.size(), 5u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
@ -461,7 +461,7 @@ bool test_clip_case_010() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 4);
|
||||
check_equal(sent.size(), 4u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
@ -481,7 +481,7 @@ bool test_clip_case_100() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 5);
|
||||
check_equal(sent.size(), 5u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
@ -507,7 +507,7 @@ bool test_clip_case_110() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 6);
|
||||
check_equal(sent.size(), 6u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
@ -530,7 +530,7 @@ bool test_clip_case_011() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 6);
|
||||
check_equal(sent.size(), 6u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
@ -553,7 +553,7 @@ bool test_clip_case_101() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 6);
|
||||
check_equal(sent.size(), 6u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
@ -576,7 +576,7 @@ bool test_clip_case_111() {
|
||||
|
||||
SceneListSubmit(&data[0], data.size());
|
||||
|
||||
check_equal(sent.size(), 4);
|
||||
check_equal(sent.size(), 4u);
|
||||
check_equal(sent[0].flags, GPU_CMD_POLYHDR);
|
||||
check_equal(sent[1].flags, GPU_CMD_VERTEX);
|
||||
check_equal(sent[2].flags, GPU_CMD_VERTEX);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user