QuelSolaar/r_draw_buffer.c

1331 lines
46 KiB
C

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "forge.h"
#include "r_include.h"
#ifdef __APPLE__
boolean r_buffer_extension = TRUE;
#else
boolean r_buffer_extension = FALSE;
#endif
GLvoid (APIENTRY *r_glBindBufferARB)(uint target, uint buffer);
GLvoid (APIENTRY *r_glDeleteBuffersARB)(uint n, const uint *buffers);
GLvoid (APIENTRY *r_glGenBuffersARB)(uint n, uint *buffers);
GLvoid (APIENTRY *r_glBufferDataARB)(uint target, uint size, const void *data, uint usage);
GLvoid (APIENTRY *r_glBufferSubDataARB)(uint target, uint offset, uint size, const void *data);
GLvoid (APIENTRY *r_glGetBufferSubDataARB)(uint target, uint offset, uint size, void *data);
GLvoid (APIENTRY *r_glCopyBufferSubData)(GLenum readtarget, GLenum writetarget, void *readoffset, void *writeoffset, void *size);
GLvoid (APIENTRY *r_glEnableVertexAttribArrayARB)(GLuint index);
GLvoid (APIENTRY *r_glDisableVertexAttribArrayARB)(GLuint index);
GLvoid (APIENTRY *r_glVertexAttribPointerARB)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);
GLvoid (APIENTRY *r_glDrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, void *indices, GLint basevertex);
GLvoid (APIENTRY *r_glDrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count, GLenum type, GLvoid *indices, GLsizei primcount, GLint basevertex);
void (APIENTRY *r_glDrawArraysInstanced)( GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
GLvoid (APIENTRY *r_glMultiDrawArraysIndirect)(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
GLvoid (APIENTRY *r_glMultiDrawElementsIndirect)(GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
GLvoid (APIENTRY *r_glBindVertexArray)(uint array);
GLvoid (APIENTRY *r_glDeleteVertexArrays)(GLsizei n, const uint *arrays);
GLvoid (APIENTRY *r_glGenVertexArrays)(GLsizei n, uint *arrays);
void (APIENTRY *r_glBeginTransformFeedback)(GLenum primitiveMode);
void (APIENTRY *r_glEndTransformFeedback)(void);
extern GLuint (APIENTRY *r_glGetUniformBlockIndex)(GLuint program, const char *uniformBlockName);
extern void (APIENTRY *r_glBindBufferBase)(GLenum target, GLuint index, GLuint buffer);
typedef struct{
uint count;
uint instanceCount;
uint first;
uint baseInstance;
}RDrawArraysIndirectCommand;
typedef struct{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
}RDrawElementsIndirectCommand;
boolean r_array_attrib_mode[64] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
uint r_array_debug_allocated = 0;
uint r_array_bound = 0;
typedef enum{
R_AD_VERTEX,
R_AD_REFERENCE,
R_AD_COUNT
}RArrayDivision;
typedef struct{
uint start;
uint count;
void *prev;
void *next;
void *referencing;
}RArraySection;
typedef struct{
uint gl_buffer;
uint gl_array;
uint8 *data;
struct{
RArraySection *sections_start;
RArraySection *sections_end;
uint array_length;
uint array_used;
boolean defragged;
}divide[R_AD_COUNT];
uint vertex_size;
RFormats vertex_format_types[64];
uint vertex_format_size[64];
uint vertex_format_count;
}RArrayPool;
RArrayPool *r_array_pool_bound = NULL;
uint r_array_vertex_size(RFormats *vertex_format_types, uint *vertex_format_size, uint vertex_format_count)
{
uint type_sizes[] = {sizeof(int8), sizeof(uint8), sizeof(int16), sizeof(uint16), sizeof(int32), sizeof(uint32), sizeof(float), sizeof(double)}, i, size = 0;
for(i = 0; i < vertex_format_count; i++)
{
/* printf("vertex_format_types[%u] = %u\n", i, type_sizes[vertex_format_types[i]]);
printf("vertex_format_size[%u] = %u\n", i, vertex_format_size[i]);
printf("size %u\n", (type_sizes[vertex_format_types[i]] * vertex_format_size[i] + 3));
printf("div %u\n", (type_sizes[vertex_format_types[i]] * vertex_format_size[i] + 3) / 4);*/
size += (type_sizes[vertex_format_types[i]] * vertex_format_size[i] + 3) / 4;
}
return size * 4;
}
void r_array_debug_print_out(void *pool)
{
char *names[8] = {"INT8", "UINT8", "INT16", "UINT16", "INT32", "UINT32", "FLOAT", "DOUBLE"}, *divide[2] = {"Vertex", "Reference"};
RArrayPool *p;
RArraySection *s;
uint i, section;
p = pool;
printf("Reliquish POOL:\n");
printf("gl_buffer %u\n", p->gl_buffer);
printf("gl_array %u\n", p->gl_array);
printf("data %p\n", p->data);
for(i = 0; i < R_AD_COUNT; i++)
{
printf("%s divide:\n", divide[i]);
printf("\tsections_start %p\n", p->divide[i].sections_start);
printf("\tsections_end %p\n", p->divide[i].sections_end);
printf("\tarray_length %u\n", p->divide[i].array_length);
printf("\tarray_used %u\n", p->divide[i].array_used);
if(p->divide[i].defragged)
printf("\tDefragged TRUE\n");
else
printf("\tDefragged FALSE\n");
}
printf("vertex_size %u\n", p->vertex_size);
for(i = 0; i < p->vertex_format_count; i++)
{
if(p->vertex_format_types[i] < 8)
printf("Member[%u] Type: %s Count %u\n", i, names[p->vertex_format_types[i]], p->vertex_format_size[i]);
else
printf("Member[%u] Type: BROKEN Count %u\n", i, p->vertex_format_size[i]);
}
for(i = 0; i < R_AD_COUNT; i++)
{
section = 0;
printf("%s sections:\n", divide[i]);
for(s = p->divide[i].sections_start; s != NULL; s = s->next)
{
printf("\tSECTION[%u]: %p\n", section++, s);
printf("\tstart %u\n", s->start);
printf("\tcount %u\n", s->count);
printf("\tprev %p\n", s->prev);
printf("\tnext %p\n", s->next);
}
}
}
void *r_array_allocate(uint vertex_count, RFormats *vertex_format_types, uint *vertex_format_size, uint vertex_format_count, uint reference_count)
{
uint type_sizes[] = {1, 1, 2, 2, 4, 4, 4, 8}, i, size = 0;
RArrayPool *p;
p = malloc(sizeof *p);
p->vertex_format_count = vertex_format_count;
for(i = 0; i < vertex_format_count && i < 64; i++)
{
p->vertex_format_types[i] = vertex_format_types[i];
p->vertex_format_size[i] = vertex_format_size[i];
}
for(; i < 64; i++)
p->vertex_format_size[i] = 0;
p->vertex_size = size = r_array_vertex_size(vertex_format_types, vertex_format_size, vertex_format_count);
p->divide[R_AD_VERTEX].array_length = vertex_count;
p->divide[R_AD_REFERENCE].array_length = reference_count;
p->gl_array = 0;
if(r_buffer_extension)
{
r_glGenBuffersARB(1, &p->gl_buffer);
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
r_glBufferDataARB(GL_ARRAY_BUFFER_ARB, p->divide[R_AD_VERTEX].array_length * size * 2 + p->divide[R_AD_REFERENCE].array_length * sizeof(uint), NULL, GL_DYNAMIC_DRAW_ARB);
p->data = NULL;
if(r_glBindVertexArray != NULL)
{
#ifndef BETRAY_CONTEXT_OPENGLES
static uint types[] = {GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE};
uint type_sizes[] = {1, 1, 2, 2, 4, 4, 4, 8}, i, size = 0;
#else
static uint types[] = {GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_FLOAT};
uint type_sizes[] = {1, 1, 2, 2, 4, 4, 4, 4}, i, size = 0;
#endif
r_glGenVertexArrays(1, &p->gl_array);
r_glBindVertexArray(p->gl_array);
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
r_glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, p->gl_buffer);
for(i = 0; i < p->vertex_format_count; i++)
{
r_glEnableVertexAttribArrayARB(i);
r_glVertexAttribPointerARB(i, p->vertex_format_size[i], types[p->vertex_format_types[i]], FALSE, p->vertex_size, &p->data[size * 4]);
size += (type_sizes[p->vertex_format_types[i]] * p->vertex_format_size[i] + 3) / 4;
}
r_glBindVertexArray(0);
}
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
}else
{
p->gl_buffer = 0;
p->data = malloc(p->divide[R_AD_VERTEX].array_length * size + p->divide[R_AD_REFERENCE].array_length * sizeof(uint));
}
for(i = 0; i < 2; i++)
{
p->divide[i].sections_start = NULL;
p->divide[i].sections_end = NULL;
p->divide[i].array_used = 0;
p->divide[i].defragged = TRUE;
}
r_array_debug_allocated++;
return p;
}
void r_array_free(void *pool)
{
RArraySection *sections, *next;
RArrayPool *p;
uint i;
if(pool == NULL)
return;
if(r_array_pool_bound == pool)
r_array_pool_bound = NULL;
p = pool;
if(p->data != NULL)
free(p->data);
if(p->gl_buffer != 0)
r_glDeleteBuffersARB(1, &p->gl_buffer);
if(p->gl_array != 0)
r_glDeleteVertexArrays(1, &p->gl_array);
for(i = 0; i < 2; i++)
{
for(sections = p->divide[i].sections_start; sections != NULL; sections = next)
{
next = sections->next;
free(sections);
}
}
r_array_debug_allocated--;
free(p);
}
void r_array_section_move(RArrayPool *pool, uint last_pos, uint new_pos, uint size)
{
uint *from, *to, i;
if(pool->data != NULL)
{
from = (uint *)&pool->data[last_pos / 4];
to = (uint *)&pool->data[new_pos / 4];
size /= 4;
for(i = 0; i < size; i++)
to[i] = from[i];
}
if(pool->gl_buffer != 0)
{
void *copy_array;
copy_array = malloc(size);
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, pool->gl_buffer);
r_glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, last_pos, size, copy_array);
r_glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, new_pos, size, copy_array);
free(copy_array);
}
}
void r_array_section_rebase(RArrayPool *pool, RArraySection *sections, uint move)
{
uint *index, i, length;
length = sections->count;
if(pool->data != NULL)
{
index = (uint *)&pool->data[sections->start * sizeof(uint)];
for(i = 0; i < length; i++)
index[i] -= move;
}
if(pool->gl_buffer != 0)
{
index = malloc(length * sizeof(uint32));
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, pool->gl_buffer);
r_glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sections->start * sizeof(uint), length * sizeof(uint32), index);
for(i = 0; i < length; i++)
index[i] -= move;
r_glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sections->start * sizeof(uint), length * sizeof(uint32), index);
free(index);
}
}
boolean r_array_defrag(void *pool)
{
RArrayPool *p;
RArraySection *sections, *next, *ref;
uint move, size[2], i;
p = pool;
if(p->divide[R_AD_VERTEX].defragged && p->divide[R_AD_REFERENCE].defragged)
return FALSE;
// fprintf(stderr, "Working\n");
if(r_array_bound != p->gl_buffer && p->gl_buffer != 0)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
size[R_AD_VERTEX] = p->vertex_size;
size[R_AD_REFERENCE] = sizeof(uint);
for(i = 0; i < R_AD_COUNT; i++)
{
for(sections = p->divide[i].sections_start; sections != NULL; sections = sections->next)
{
next = sections->next;
if(next == NULL)
break;
if(sections->start + sections->count != next->start)
{
/* found a gap so we will move a block down to close the gap */
move = next->start - (sections->start + sections->count);
if(i == R_AD_VERTEX)
r_array_section_move(p, next->start * p->vertex_size, (sections->start + sections->count) * size[i], sections->count * p->vertex_size);
else
r_array_section_move(p, p->vertex_size * p->divide[R_AD_VERTEX].array_length + next->start * sizeof(uint32), p->vertex_size * p->divide[R_AD_VERTEX].array_length + (sections->start + sections->count) * size[i], sections->count * sizeof(uint32));
next->start = sections->start + sections->count;
if(sections->referencing != NULL && r_glDrawElementsBaseVertex == NULL)
for(ref = p->divide[R_AD_REFERENCE].sections_start; ref != NULL; ref = ref->next)
if(ref == sections->referencing)
r_array_section_rebase(pool, sections, move);
if(r_array_bound != p->gl_buffer && p->gl_buffer != 0)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
return TRUE;
}
}
p->divide[i].defragged = TRUE;
}
if(r_array_bound != p->gl_buffer && p->gl_buffer != 0)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
return FALSE;
}
void *r_array_section_allocate(RArrayPool *p, RArrayDivision division, uint size)
{
RArraySection *section, *s;
uint pos, unit_size;
if(division == R_AD_VERTEX)
unit_size = p->vertex_size;
else
unit_size = sizeof(uint);
if(p->divide[division].array_used + size > p->divide[division].array_length) /* there is no space no matter */
{
printf("there is no space no matter %u %u %u\n", p->divide[division].array_used, size, p->divide[division].array_length);
exit(0);
return NULL;
}
section = malloc(sizeof *section);
section->count = size;
section->referencing = NULL;
p->divide[division].array_used += size;
if(p->divide[division].sections_start == NULL) // no section exists
{
p->divide[division].sections_start = section;
p->divide[division].sections_end = section;
section->next = section->prev = NULL;
section->start = 0;
return section;
}else
{
s = p->divide[division].sections_end;
if(p->divide[division].array_length >= s->start + s->count + size) // add new section to end of array
{
s->next = section;
p->divide[division].sections_end = section;
section->next = NULL;
section->prev = s;
section->start = s->start + s->count;
return section;
}
/* try to find a hole in the array of sections where the new section fits */
pos = 0;
for(s = p->divide[division].sections_start; s != NULL; s = s->next)
{
if(pos + size <= s->start) /* Found a hole */
{
if(s->prev == NULL)
p->divide[division].sections_start = section;
else
((RArraySection *)s->prev)->next = section;
section->prev = s->prev;
section->next = s;
s->prev = section;
section->start = pos;
return section;
}
pos = s->start + s->count;
}
/* lets do it again, but this time we start to defrag the segments to eventiualy find a gap big enough */
pos = 0;
if(r_array_bound != p->gl_buffer && p->gl_buffer != 0)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
for(s = p->divide[division].sections_start; s != NULL; s = s->next)
{
if(pos + size <= s->start) /* Found a hole big enough */
{
if(s->prev == NULL)
p->divide[division].sections_start = section;
else
((RArraySection *)s->prev)->next = section;
section->prev = s->prev;
section->next = s;
s->prev = section;
section->start = pos;
return section;
}
if(pos != s->start) /* move back a section to close the gap. */
{
if(division == R_AD_VERTEX)
r_array_section_move(p, pos * p->vertex_size, s->start * p->vertex_size, s->count * p->vertex_size);
else
r_array_section_move(p, p->vertex_size * p->divide[R_AD_VERTEX].array_length + pos * sizeof(uint32), p->vertex_size * p->divide[R_AD_VERTEX].array_length + s->start * sizeof(uint32), s->count * sizeof(uint32));
s->start = pos;
}
pos = s->start + s->count;
}
if(r_array_bound != p->gl_buffer && p->gl_buffer != 0)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
/* add to the end */
s = p->divide[division].sections_end;
s->next = section;
p->divide[division].sections_end = section;
section->next = NULL;
section->prev = s;
section->start = s->start + s->count;
return section;
}
return NULL;
}
void *r_array_section_allocate_vertex(void *pool, uint size)
{
return r_array_section_allocate(pool, R_AD_VERTEX, size);
}
void *r_array_section_allocate_reference(void *pool, uint size)
{
return r_array_section_allocate(pool, R_AD_REFERENCE, size);
}
/*
typedef enum{
R_AD_VERTEX,
R_AD_REFERENCE,
R_AD_COUNT
}RArrayDivision;
*/
void r_array_section_free(void *pool, void *section)
{
RArrayPool *p;
RArraySection *s;
RArrayDivision divide = R_AD_VERTEX;
p = pool;
for(s = p->divide[R_AD_REFERENCE].sections_start; s != NULL; s = s->next)
{
if(s->referencing == section)
{
r_array_section_free(pool, s);
}
if(s == section)
divide = R_AD_REFERENCE;
}
s = section;
p->divide[divide].array_used -= s->count;
if(s->next == NULL)
p->divide[divide].sections_end = s->prev;
else
((RArraySection *)s->next)->prev = s->prev;
if(s->prev == NULL)
p->divide[divide].sections_start = s->next;
else
((RArraySection *)s->prev)->next = s->next;
free(s);
}
void r_test()
{
if(r_glDeleteBuffersARB == NULL)
exit(0);
}
void r_array_init(void)
{
uint i;
#ifdef RELINQUISH_CONTEXT_OPENGLES
r_glBindBufferARB = glBindBuffer;
r_glDeleteBuffersARB = glDeleteBuffers;
r_glGenBuffersARB = glGenBuffers;
r_glBufferDataARB = glBufferData;
r_glBufferSubDataARB = glBufferSubData;
r_glGetBufferSubDataARB = r_extension_get_address("glGetBufferSubData");
r_glBindVertexArray = r_extension_get_address("glBindVertexArray");
r_glDeleteVertexArrays = r_extension_get_address("glDeleteVertexArrays");
r_glGenVertexArrays = r_extension_get_address("glGenVertexArrays");
r_glVertexAttribPointerARB = glVertexAttribPointer;
r_glEnableVertexAttribArrayARB = glEnableVertexAttribArray;
r_glDisableVertexAttribArrayARB = glDisableVertexAttribArray;
r_buffer_extension = TRUE;
#endif
#ifdef RELINQUISH_CONTEXT_OPENGL
#ifdef __APPLE__
//FK: Macos OpenGL doesn't really list *all* extensions...
r_buffer_extension = TRUE;
#else
r_buffer_extension = r_extension_test("GL_ARB_vertex_buffer_object") ;
#endif
r_buffer_extension = r_extension_test("GL_ARB_vertex_buffer_object") ;
if(r_buffer_extension)
{
r_glBindBufferARB = r_extension_get_address("glBindBufferARB");
r_glDeleteBuffersARB = r_extension_get_address("glDeleteBuffersARB");
r_glGenBuffersARB = r_extension_get_address("glGenBuffersARB");
r_glBufferDataARB = r_extension_get_address("glBufferDataARB");
r_glBufferSubDataARB = r_extension_get_address("glBufferSubDataARB");
r_glGetBufferSubDataARB = r_extension_get_address("glGetBufferSubDataARB");
if(r_extension_test("GL_ARB_vertex_array_object"))
{
r_glBindVertexArray = r_extension_get_address("glBindVertexArray");
r_glDeleteVertexArrays = r_extension_get_address("glDeleteVertexArrays");
r_glGenVertexArrays = r_extension_get_address("glGenVertexArrays");
}
r_glGenBuffersARB(1, &i);
}
r_glGetUniformBlockIndex = r_extension_get_address("glGetUniformBlockIndex");
r_glBeginTransformFeedback = r_extension_get_address("glBeginTransformFeedback");
r_glEndTransformFeedback = r_extension_get_address("glEndTransformFeedback");
r_glVertexAttribPointerARB = r_extension_get_address("glVertexAttribPointerARB");
r_glEnableVertexAttribArrayARB = r_extension_get_address("glEnableVertexAttribArrayARB");
r_glDisableVertexAttribArrayARB = r_extension_get_address("glDisableVertexAttribArrayARB");
r_glDrawElementsBaseVertex = r_extension_get_address("glDrawElementsBaseVertex");
r_glDrawElementsInstancedBaseVertex = r_extension_get_address("glDrawElementsInstancedBaseVertex");
r_glMultiDrawArraysIndirect = r_extension_get_address("glMultiDrawArraysIndirect");
r_glMultiDrawElementsIndirect = r_extension_get_address("glMultiDrawElementsIndirect");
r_glCopyBufferSubData = r_extension_get_address("glCopyBufferSubData");
r_glDrawArraysInstanced = r_extension_get_address("glDrawArraysInstanced");
#endif
r_array_pool_bound = 0;
r_array_bound = 0;
for(i = 0; i < 64; i++)
r_array_attrib_mode[i] = FALSE;
}
float *sui_vertex_tmp = NULL;
void r_array_vertex_atrib_set(void *pool, boolean reference)
{
//FK: There's not GL_DOUBLE on OpenGL ES
#ifndef BETRAY_CONTEXT_OPENGLES
static uint types[] = {GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE};
uint type_sizes[] = {1, 1, 2, 2, 4, 4, 4, 8}, i, size = 0;
#else
static uint types[] = {GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_FLOAT};
uint type_sizes[] = {1, 1, 2, 2, 4, 4, 4, 4}, i, size = 0;
#endif
RArrayPool *p;
// if(r_array_pool_bound == pool)
// return;
p = pool;
r_array_pool_bound = pool;
if(r_glBindVertexArray != NULL)
{
r_glBindVertexArray(p->gl_array);
if(reference)
r_glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, p->gl_buffer);
}else
{
if(r_array_bound != p->gl_buffer && p->gl_buffer != 0)
{
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
if(reference)
r_glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, p->gl_buffer);
r_array_bound = p->gl_buffer;
}
for(i = 0; i < p->vertex_format_count; i++)
{
r_glVertexAttribPointerARB(i, p->vertex_format_size[i], types[p->vertex_format_types[i]], FALSE, p->vertex_size, &p->data[size * 4]);
if(!r_array_attrib_mode[i])
r_glEnableVertexAttribArrayARB(i);
r_array_attrib_mode[i] = TRUE;
size += (type_sizes[p->vertex_format_types[i]] * p->vertex_format_size[i] + 3) / 4;
}
for(; i < 64; i++)
{
if(r_array_attrib_mode[i])
{
r_array_attrib_mode[i] = FALSE;
r_glDisableVertexAttribArrayARB(i);
}
}
}
}
void r_array_deactivate()
{
uint i;
r_array_pool_bound = NULL;
if(r_array_bound != 0)
{
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
r_array_bound = 0;
}
if(r_glBindVertexArray != NULL)
r_glBindVertexArray(0);
else
for(i = 0; i < 64; i++)
r_glDisableVertexAttribArrayARB(i);
}
void r_array_load_vertex(void *pool, void *section, void *data, uint start, uint length)
{
RArrayPool *p;
p = pool;
/*{
uint i, j, read;
for(i = 0; i < length; i++)
read = ((uint8 *)data)[i * p->vertex_size];
}*/
if(section != NULL)
{
if(((RArraySection *)section)->count < length)
length = ((RArraySection *)section)->count;
if(p->data != NULL)
memcpy(&p->data[(((RArraySection *)section)->start + start) * p->vertex_size],
data,
length * p->vertex_size);
if(p->gl_buffer != 0)
{
if(r_array_bound != p->gl_buffer)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
r_glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (((RArraySection *)section)->start + start) * p->vertex_size, length * p->vertex_size, data);
if(r_array_bound != p->gl_buffer)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
}
}else
{
if(p->divide[R_AD_VERTEX].array_length + start < length)
length = p->divide[R_AD_VERTEX].array_length - start;
if(p->data != NULL)
{
memcpy(&p->data[start * p->vertex_size],
data,
length * p->vertex_size);
}
if(p->gl_buffer != 0)
{
if(r_array_bound != p->gl_buffer)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
r_glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, start * p->vertex_size, length * p->vertex_size, data);
if(r_array_bound != p->gl_buffer)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
}
}
}
void r_array_load_reference(void *pool, void *section, void *referencing_section, uint *reference, uint length)
{
RArrayPool *p;
uint size;
p = pool;
r_array_vertex_atrib_set(pool, TRUE);
((RArraySection *)section)->referencing = referencing_section;
size = ((RArraySection *)section)->start;
if(p->data != NULL)
{
if(((RArraySection *)referencing_section)->start == 0 || r_glDrawElementsBaseVertex != NULL)
memcpy(&p->data[(((RArraySection *)section)->start) * sizeof(uint32) + p->divide[R_AD_VERTEX].array_length * p->vertex_size], reference, length * sizeof(uint32));
else
{
uint32 *to, i, start;
start = ((RArraySection *)referencing_section)->start;
to = (uint32 *)&p->data[(((RArraySection *)section)->start) * sizeof(uint32) + p->divide[R_AD_VERTEX].array_length * p->vertex_size];
for(i = 0; i < length; i++)
to[i] = reference[i] + start;
}
}
if(p->gl_buffer != 0)
{
if(r_array_bound != p->gl_buffer)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, p->gl_buffer);
if(((RArraySection *)referencing_section)->start == 0 || r_glDrawElementsBaseVertex != NULL)
r_glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (((RArraySection *)section)->start) * sizeof(uint32) + p->divide[R_AD_VERTEX].array_length * p->vertex_size, length * sizeof(uint32), reference);
else
{
uint32 *temp, i, start;
start = ((RArraySection *)referencing_section)->start;
temp = malloc((sizeof *temp) * length);
for(i = 0; i < length; i++)
temp[i] = reference[i] + start;
r_glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, (((RArraySection *)section)->start) * sizeof(uint32) + p->divide[R_AD_VERTEX].array_length * p->vertex_size, length * sizeof(uint32), temp);
free(temp);
}
if(r_array_bound != p->gl_buffer)
r_glBindBufferARB(GL_ARRAY_BUFFER_ARB, r_array_bound);
}
((RArraySection *)section)->referencing = referencing_section;
}
uint r_array_get_size(void *pool)
{
return ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_length;
}
uint r_array_get_used(void *pool)
{
return ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_used;
}
uint r_array_get_left(void *pool)
{
return ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_length - ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_used;
}
uint r_array_get_vertex_size(void *pool)
{
return ((RArrayPool *)pool)->vertex_size;
}
uint r_array_section_get_vertex_count(void *section)
{
return ((RArraySection *)section)->count;
}
uint r_array_section_get_vertex_start(void *section)
{
return ((RArraySection *)section)->start;
}
/*
void r_array_section_draw(void *pool, void *section, uint primitive_type, uint vertex_start, uint vertex_count)
{
uint i, offset;
if(r_current_shader == NULL)
{
printf("Relinquish ERROR: no Shader set\n");
return;
}
r_array_vertex_atrib_set(pool, FALSE);
for(i = 0; i < r_current_shader->block_count; i++)
r_shader_uniform_matrix_set(r_current_shader, r_current_shader->uniform_data, i, (RMatrix *)r_matrix_state);
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, -1);
if(section != NULL)
{
RArraySection *s;
s = (RArraySection *)section;
if(vertex_count > s->vertex_count)
vertex_count = s->vertex_count;
glDrawArrays(primitive_type, s->vertex_start + vertex_start, vertex_count);
}else
{
RArrayPool *p;
p = pool;
if(vertex_count > p->array_length)
vertex_count = p->array_length;
glDrawArrays(primitive_type, vertex_start, vertex_count);
}
}*/
extern uint special_drawcall_active;
void r_array_draw(RArrayPool *pool, RArraySection *section, RPrimitive primitive_type, uint vertex_start, uint vertex_count, uint8 *uniforms, RArrayPool *array_pool, uint count)
{
uint i, bind_point, add;
uint progress;
uint8 *p = NULL;
r_array_vertex_atrib_set(pool, section != NULL && section->referencing != NULL);
for(i = 0; i < r_current_shader->block_count; i++)
r_shader_uniform_matrix_set(r_current_shader, r_current_shader->uniform_data, i, (RMatrix *)r_matrix_state);
if(uniforms == NULL && array_pool == NULL)
{
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, -1);
count = 1;
}else
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, r_current_shader->instance_block);
if(section == NULL)
{
if(vertex_start >= pool->divide[R_AD_VERTEX].array_length)
return;
if(vertex_start + vertex_count > pool->divide[R_AD_VERTEX].array_length)
vertex_count = pool->divide[R_AD_VERTEX].array_length - vertex_start;
}else
{
if(section->referencing != NULL)
{
if(vertex_count > section->count)
vertex_count = section->count;
p = &pool->data[(section->start + vertex_start) * sizeof(uint32) + ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_length * pool->vertex_size];
}else
{
if(vertex_start >= section->count)
return;
if(vertex_count > section->count - vertex_start)
vertex_count = section->count - vertex_start;
vertex_start += section->start;
}
}
/*
if(r_glMultiDrawArraysIndirect != NULL)
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
add = count;
else
{
add = r_current_shader->blocks[r_current_shader->instance_block].array_length;
if(add > count)
add = count;
}
}else
add = 1;*/
if(r_current_shader->blocks[r_current_shader->instance_block].object == -1)
{
// uniforms = &r_current_shader->uniform_data[r_current_shader->blocks[r_current_shader->instance_block].offset];
if(array_pool != NULL)
{
uniforms = malloc(r_current_shader->blocks[r_current_shader->instance_block].size * count);
r_glBindBufferARB(GL_COPY_READ_BUFFER, array_pool->gl_buffer);
r_glGetBufferSubDataARB(GL_COPY_READ_BUFFER, 0, r_current_shader->blocks[r_current_shader->instance_block].size * count, uniforms);
}
for(i = 0; i < count; i++)
{
r_current_shader->blocks[r_current_shader->instance_block].updated = FALSE;
if(uniforms != NULL)
r_shader_unifrom_data_set_block(r_current_shader, &(((uint8 *)uniforms)[r_current_shader->blocks[r_current_shader->instance_block].size * i]), r_current_shader->instance_block);
if(section != NULL)
{
if(section->referencing == NULL)
glDrawArrays(primitive_type, vertex_start, vertex_count);
else
{
if(r_glDrawElementsBaseVertex != NULL)
r_glDrawElementsBaseVertex(primitive_type, vertex_count, GL_UNSIGNED_INT, p, ((RArraySection *)section->referencing)->start);
else
glDrawElements(primitive_type, vertex_count, GL_UNSIGNED_INT, p);
}
}else
glDrawArrays(primitive_type, vertex_start, vertex_count);
}
if(array_pool != NULL)
free(uniforms);
}else
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT)
bind_point = GL_SHADER_STORAGE_BUFFER;
else
bind_point = GL_UNIFORM_BUFFER;
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
r_glBindBufferBase(bind_point, r_current_shader->blocks[r_current_shader->instance_block].id, array_pool->gl_buffer);
else
r_glBindBufferBase(bind_point, r_current_shader->blocks[r_current_shader->instance_block].id, r_current_shader->blocks[r_current_shader->instance_block].object);
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
r_glBindBufferARB(bind_point, array_pool->gl_buffer);
else
{
if(array_pool != NULL)
r_glBindBufferARB(GL_COPY_READ_BUFFER, array_pool->gl_buffer);
r_glBindBufferARB(bind_point, r_current_shader->blocks[r_current_shader->instance_block].object);
}
if(r_glDrawArraysInstanced != NULL)
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
add = count;
else
add = r_current_shader->blocks[r_current_shader->instance_block].array_length;
}else
add = 1;
for(progress = 0; progress < count; progress += add)
{
if(add + progress > count)
add = count - progress;
if(array_pool != NULL)
{
if(r_current_shader->mode == R_SIM_UNIFORM_BLOCK)
r_glCopyBufferSubData(GL_COPY_READ_BUFFER, bind_point, (void *)(progress * r_current_shader->blocks[r_current_shader->instance_block].size), 0, (void *)(add * r_current_shader->blocks[r_current_shader->instance_block].size));
}else if(uniforms != NULL)
r_glBufferDataARB(bind_point,
add * r_current_shader->blocks[r_current_shader->instance_block].size,
&uniforms[progress * r_current_shader->blocks[r_current_shader->instance_block].size],
GL_DYNAMIC_DRAW_ARB);
if(add != 1)
{
if(section != NULL && section->referencing != NULL)
{
r_glDrawElementsInstancedBaseVertex(primitive_type, vertex_count, GL_UNSIGNED_INT, p, add, ((RArraySection *)section->referencing)->start);
}else
r_glDrawArraysInstanced(primitive_type, 0, vertex_count, add);
}else
{
if(section != NULL && section->referencing != NULL)
{
if(r_glDrawElementsBaseVertex != NULL)
r_glDrawElementsBaseVertex(primitive_type, vertex_count, GL_UNSIGNED_INT, p, ((RArraySection *)section->referencing)->start);
else
glDrawElements(primitive_type, vertex_count, GL_UNSIGNED_INT, p);
}else
glDrawArrays(primitive_type, vertex_start, vertex_count);
}
}
}
}
void r_array_sections_draw(void *pool, void **sections, RPrimitive primitive_type, uint8 *uniforms, RArrayPool *array_pool, uint count)
{
uint i, bind_point;
if(r_current_shader == NULL)
{
printf("Relinquish ERROR: no Shader set\n");
return;
}
/* if(uniforms == NULL && array_pool == NULL)
{
printf("RELINQUISH Error: r_array_sections_draw uniform is NULL.\n");
exit(0);
}*/
if(array_pool != NULL)
{
if(count > array_pool->divide[R_AD_VERTEX].array_length)
count = array_pool->divide[R_AD_VERTEX].array_length;
if(array_pool->vertex_size != r_current_shader->blocks[r_current_shader->instance_block].size)
{
printf("RELINQUISH Error: r_array_sections_draw array_pool vertex format size does not match instance uniform block size.\n");
return;
}
}
r_array_vertex_atrib_set(pool, FALSE);
for(i = 0; i < r_current_shader->block_count; i++)
r_shader_uniform_matrix_set(r_current_shader, r_current_shader->uniform_data, i, (RMatrix *)r_matrix_state);
if(uniforms == NULL && array_pool == NULL)
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, -1);
else
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, r_current_shader->instance_block);
if(r_current_shader->blocks[r_current_shader->instance_block].object == -1)
{
RArraySection *s;
RArrayPool *p;
p = pool;
if(array_pool != NULL)
{
uniforms = malloc(r_current_shader->blocks[r_current_shader->instance_block].size * count);
r_glBindBufferARB(GL_COPY_READ_BUFFER, array_pool->gl_buffer);
r_glGetBufferSubDataARB(GL_COPY_READ_BUFFER, 0, r_current_shader->blocks[r_current_shader->instance_block].size * count, uniforms);
}
for(i = 0; i < count; i++)
{
r_current_shader->blocks[r_current_shader->instance_block].updated = FALSE;
r_shader_unifrom_data_set_block(r_current_shader, &(((uint8 *)uniforms)[r_current_shader->blocks[r_current_shader->instance_block].size * i]), r_current_shader->instance_block);
if(sections != NULL)
{
s = (RArraySection *)sections[i];
glDrawArrays(primitive_type, s->start, s->count);
}else
glDrawArrays(primitive_type, 0, p->divide[R_AD_VERTEX].array_length);
}
if(array_pool != NULL)
free(uniforms);
}else
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT)
bind_point = GL_SHADER_STORAGE_BUFFER;
else
bind_point = GL_UNIFORM_BUFFER;
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
r_glBindBufferBase(bind_point, r_current_shader->blocks[r_current_shader->instance_block].id, array_pool->gl_buffer);
else
r_glBindBufferBase(bind_point, r_current_shader->blocks[r_current_shader->instance_block].id, r_current_shader->blocks[r_current_shader->instance_block].object);
if(uniforms == NULL)
uniforms = &r_current_shader->uniform_data[r_current_shader->blocks[r_current_shader->instance_block].offset];
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
r_glBindBufferARB(bind_point, array_pool->gl_buffer);
else
{
if(array_pool != NULL)
r_glBindBufferARB(GL_COPY_READ_BUFFER, array_pool->gl_buffer);
r_glBindBufferARB(bind_point, r_current_shader->blocks[r_current_shader->instance_block].object);
}
if(sections != NULL)
{
static uint command_count = 0;
static RDrawArraysIndirectCommand *command = NULL;
uint progress, add, calls, j;
RArraySection *s;
if(r_glMultiDrawArraysIndirect != NULL)
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
add = count;
else
add = r_current_shader->blocks[r_current_shader->instance_block].array_length;
}else
add = 1;
if(add > command_count)
{
command = realloc(command, (sizeof *command) * add);
command_count = add;
}
for(progress = 0; progress < count; progress += add)
{
if(add + progress > count)
add = count - progress;
if(array_pool != NULL)
{
if(r_current_shader->mode == R_SIM_UNIFORM_BLOCK)
r_glCopyBufferSubData(GL_COPY_READ_BUFFER, bind_point, (void *)(progress * r_current_shader->blocks[r_current_shader->instance_block].size), 0, (void *)(add * r_current_shader->blocks[r_current_shader->instance_block].size));
}else
r_glBufferDataARB(bind_point,
add * r_current_shader->blocks[r_current_shader->instance_block].size,
&uniforms[progress * r_current_shader->blocks[r_current_shader->instance_block].size],
GL_DYNAMIC_DRAW_ARB);
if(add != 1)
{
for(i = calls = 0; i < add; i += j)
{
s = (RArraySection *)sections[i + progress];
command[calls].baseInstance = i;
command[calls].first = s->start;
command[calls].count = s->count;
// for(j = 1; sections[i + progress] == sections[i + progress + j] && i + j < add; j++); FIX ME!
j = 1;
command[calls].instanceCount = i + j;
calls++;
}
r_glMultiDrawArraysIndirect(primitive_type, command, calls, (sizeof *command));
}else
glDrawArrays(primitive_type, ((RArraySection *)sections)->start, ((RArraySection *)sections)->count);
}
}else
{
RArrayPool *p;
uint progress, add;
p = pool;
if(r_glDrawArraysInstanced != NULL)
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
add = count;
else
add = r_current_shader->blocks[r_current_shader->instance_block].array_length;
}else
add = 1;
for(progress = 0; progress < count; progress += add)
{
if(add + progress > count)
add = count - progress;
if(array_pool != NULL)
{
if(r_current_shader->mode == R_SIM_UNIFORM_BLOCK)
r_glCopyBufferSubData(GL_COPY_READ_BUFFER, bind_point, (void *)(progress * r_current_shader->blocks[r_current_shader->instance_block].size), 0, (void *)(add * r_current_shader->blocks[r_current_shader->instance_block].size));
}else
r_glBufferDataARB(bind_point,
add * r_current_shader->blocks[r_current_shader->instance_block].size,
&uniforms[progress * r_current_shader->blocks[r_current_shader->instance_block].size],
GL_DYNAMIC_DRAW_ARB);
if(add != 1)
r_glDrawArraysInstanced(primitive_type, 0, p->divide[R_AD_VERTEX].array_length, add);
else
glDrawArrays(primitive_type, 0, p->divide[R_AD_VERTEX].array_length);
}
}
}
}
/*
void r_array_reference_draw(void *pool, void *section, uint primitive_type, uint vertex_start, uint vertex_count)
{
uint i;
r_array_vertex_atrib_set(pool, TRUE);
if(r_current_shader != NULL)
{
for(i = 0; i < r_current_shader->block_count; i++)
r_shader_uniform_matrix_set(r_current_shader, r_current_shader->uniform_data, r_current_shader->instance_block, (RMatrix *)r_matrix_state);
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, -1);
}
if(section != NULL)
{
uint i, *p;
if(vertex_count > ((RArraySection *)section)->vertex_count * ((RArrayPool *)pool)->vertex_size / 4 - vertex_start)
vertex_count = ((RArraySection *)section)->vertex_count * ((RArrayPool *)pool)->vertex_size / 4 - vertex_start;
p = (uint *)((RArrayPool *)pool)->data;
p = &p[(((RArraySection *)section)->vertex_start + vertex_start) * ((RArrayPool *)pool)->vertex_size / 4];
if(r_glDrawElementsBaseVertex == NULL)
glDrawElements(primitive_type, vertex_count, GL_UNSIGNED_INT, p);
else
r_glDrawElementsBaseVertex(primitive_type, vertex_count, GL_UNSIGNED_INT, p, ((RArraySection *)((RArraySection *)section)->referencing)->vertex_start);
}
}*/
void r_array_references_draw(void *pool, void **sections, RPrimitive primitive_type, uint8 *uniforms, RArrayPool *array_pool, uint count)
{
uint i, vertex_count, bind_point;
uint8 *p;
if(r_current_shader == NULL)
{
printf("Relinquish ERROR: no Shader set\n");
return;
}
/* if(uniforms == NULL && array_pool == NULL)
{
printf("RELINQUISH Error: r_array_references_draw uniform is NULL.\n");
exit(0);
}*/
if(array_pool != NULL)
{
if(count > array_pool->divide[R_AD_VERTEX].array_length)
count = array_pool->divide[R_AD_VERTEX].array_length;
if(array_pool->vertex_size != r_current_shader->blocks[r_current_shader->instance_block].size)
{
printf("RELINQUISH Error: r_array_sections_draw array_pool vertex format size does not match instance uniform block size.\n");
return;
}
}
r_array_vertex_atrib_set(pool, TRUE);
for(i = 0; i < r_current_shader->block_count; i++)
if(r_current_shader->instance_block != i || (uniforms == NULL && array_pool == NULL))
r_shader_uniform_matrix_set(r_current_shader, r_current_shader->uniform_data, i, (RMatrix *)r_matrix_state);
if(uniforms == NULL && array_pool == NULL)
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, -1);
else
r_shader_unifrom_data_set_all(r_current_shader, r_current_shader->uniform_data, r_current_shader->instance_block);
if(uniforms == NULL)
uniforms = &r_current_shader->uniform_data[r_current_shader->blocks[r_current_shader->instance_block].offset];
if(r_current_shader->blocks[r_current_shader->instance_block].object == -1)
{
if(sections != NULL)
{
RArraySection *s;
if(array_pool != NULL)
{
uniforms = malloc(r_current_shader->blocks[r_current_shader->instance_block].size * count);
r_glBindBufferARB(GL_COPY_READ_BUFFER, array_pool->gl_buffer);
r_glGetBufferSubDataARB(GL_COPY_READ_BUFFER, 0, r_current_shader->blocks[r_current_shader->instance_block].size * count, uniforms);
}
for(i = 0; i < count; i++)
{
s = (RArraySection *)sections[i];
r_current_shader->blocks[r_current_shader->instance_block].updated = FALSE;
r_shader_unifrom_data_set_block(r_current_shader, &(((uint8 *)uniforms)[r_current_shader->blocks[r_current_shader->instance_block].size * i]), r_current_shader->instance_block);
vertex_count = ((RArraySection *)sections[i])->count;
p = ((RArrayPool *)pool)->data;
p = &p[((RArraySection *)sections[i])->start * sizeof(uint) + ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_length * ((RArrayPool *)pool)->vertex_size];
if(r_glDrawElementsBaseVertex == NULL)
glDrawElements(primitive_type, vertex_count, GL_UNSIGNED_INT, p);
else
r_glDrawElementsBaseVertex(primitive_type, vertex_count, GL_UNSIGNED_INT, p, ((RArraySection *)((RArraySection *)sections[i])->referencing)->start);
}
if(array_pool != NULL)
free(uniforms);
}
}else
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT)
bind_point = GL_SHADER_STORAGE_BUFFER;
else
bind_point = GL_UNIFORM_BUFFER;
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
r_glBindBufferBase(bind_point, r_current_shader->blocks[r_current_shader->instance_block].id, array_pool->gl_buffer);
else
r_glBindBufferBase(bind_point, r_current_shader->blocks[r_current_shader->instance_block].id, r_current_shader->blocks[r_current_shader->instance_block].object);
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
r_glBindBufferARB(bind_point, array_pool->gl_buffer);
else
{
if(array_pool != NULL)
r_glBindBufferARB(GL_COPY_READ_BUFFER, array_pool->gl_buffer);
r_glBindBufferARB(bind_point, r_current_shader->blocks[r_current_shader->instance_block].object);
}
if(sections != NULL)
{
static uint command_count = 0;
static RDrawElementsIndirectCommand *command = NULL;
uint progress, add, calls, j;
RArraySection *s;
if(r_glMultiDrawElementsIndirect != NULL)
{
if(r_current_shader->mode == R_SIM_BUFFER_OBJECT && array_pool != NULL)
add = count;
else
add = r_current_shader->blocks[r_current_shader->instance_block].array_length;
}else
add = 1;
if(add > command_count)
{
command = realloc(command, (sizeof *command) * add);
command_count = add;
}
// r_glBindBufferARB(bind_point, r_current_shader->blocks[0].object);
for(progress = 0; progress < count; progress += add)
{
if(add + progress > count)
add = count - progress;
if(array_pool != NULL)
{
if(r_current_shader->mode == R_SIM_UNIFORM_BLOCK)
r_glCopyBufferSubData(GL_COPY_READ_BUFFER, bind_point, (void *)(progress * r_current_shader->blocks[r_current_shader->instance_block].size), 0, (void *)(add * r_current_shader->blocks[r_current_shader->instance_block].size));
}else
r_glBufferDataARB(bind_point,
add * r_current_shader->blocks[r_current_shader->instance_block].size,
&uniforms[progress * r_current_shader->blocks[r_current_shader->instance_block].size],
GL_DYNAMIC_DRAW_ARB);
if(add != 1)
{
for(i = calls = 0; i < add; i += j)
{
s = (RArraySection *)sections[i + progress];
command[calls].baseInstance = i;
p = &((RArrayPool *)pool)->data[((RArraySection *)sections[i])->start + ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_length * ((RArrayPool *)pool)->vertex_size / sizeof(uint32)];
command[calls].firstIndex = (uint)p;
command[calls].count = s->count;
command[calls].baseVertex = ((RArraySection *)((RArraySection *)sections[i])->referencing)->start;
for(j = 1; sections[i + progress] == sections[i + progress + j] && i + j < add; j++);
command[calls].instanceCount = j;
calls++;
}
r_glMultiDrawElementsIndirect(primitive_type, GL_UNSIGNED_INT, command, calls, (sizeof *command));
}else
{
vertex_count = ((RArraySection *)sections[progress])->count;
p = ((RArrayPool *)pool)->data;
p = &p[((RArraySection *)sections[progress])->start * sizeof(uint) + ((RArrayPool *)pool)->divide[R_AD_VERTEX].array_length * ((RArrayPool *)pool)->vertex_size];
// p = &p[((RArraySection *)sections[progress])->vertex_start * ((RArrayPool *)pool)->vertex_size];
if(r_glDrawElementsBaseVertex == NULL)
glDrawElements(primitive_type, vertex_count, GL_UNSIGNED_INT, p);
else
r_glDrawElementsBaseVertex(primitive_type, vertex_count, GL_UNSIGNED_INT, p, ((RArraySection *)((RArraySection *)sections[progress])->referencing)->start);
}
}
}
}
i = 0;
}
void sui_array_section_draw_element(void *vertex_section, uint primitive_type, uint ref_type, void *ref_section, uint ref_count)
{
r_shader_uniform_matrix_set(r_current_shader, r_current_shader->uniform_data, r_current_shader->instance_block, (RMatrix *)r_matrix_state);
/* (((RArraySection *)section)->vertex_start + vertex_start) *
glDrawElements(primitive_type, ref_count, ref_type, ref_section);*/
}
#define GL_RASTERIZER_DISCARD 0x8C89
#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
void r_array_vertex_render(void *in_pool, void *out_pool)
{
RArrayPool *in_p, *out_p;
in_p = in_pool;
out_p = out_pool;
r_array_vertex_atrib_set(in_pool, FALSE);
glEnable(GL_RASTERIZER_DISCARD);
r_glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, out_p->gl_buffer);
r_glBeginTransformFeedback(GL_POINTS);
if(in_p->divide[R_AD_VERTEX].array_length < out_p->divide[R_AD_VERTEX].array_length)
glDrawArrays(GL_POINTS, 0, in_p->divide[R_AD_VERTEX].array_length);
else
glDrawArrays(GL_POINTS, 0, out_p->divide[R_AD_VERTEX].array_length);
r_glEndTransformFeedback();
glFlush();
glDisable(GL_RASTERIZER_DISCARD);
}
void r_array_section_draw(void *pool, void *section, RPrimitive primitive_type, uint vertex_start, uint vertex_count)
{
r_array_draw(pool, section, primitive_type, vertex_start, vertex_count, NULL, NULL, 1);
}
void r_array_reference_draw(void *pool, void *section, RPrimitive primitive_type, uint vertex_start, uint vertex_count)
{
r_array_draw(pool, section, primitive_type, vertex_start, vertex_count, NULL, NULL, 1);
}