Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/gawain/src/gwn_immediate.c')
-rw-r--r--intern/gawain/src/gwn_immediate.c923
1 files changed, 0 insertions, 923 deletions
diff --git a/intern/gawain/src/gwn_immediate.c b/intern/gawain/src/gwn_immediate.c
deleted file mode 100644
index d43e52cc525..00000000000
--- a/intern/gawain/src/gwn_immediate.c
+++ /dev/null
@@ -1,923 +0,0 @@
-
-// Gawain immediate mode work-alike
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 Mike Erwin
-//
-// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of
-// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-#include "gwn_immediate.h"
-#include "gwn_buffer_id.h"
-#include "gwn_attr_binding.h"
-#include "gwn_attr_binding_private.h"
-#include "gwn_vertex_format_private.h"
-#include "gwn_vertex_array_id.h"
-#include "gwn_primitive_private.h"
-#include <string.h>
-
-// necessary functions from matrix API
-extern void gpuBindMatrices(const Gwn_ShaderInterface*);
-extern bool gpuMatricesDirty(void);
-
-typedef struct {
- // TODO: organize this struct by frequency of change (run-time)
-
-#if IMM_BATCH_COMBO
- Gwn_Batch* batch;
-#endif
- Gwn_Context* context;
-
- // current draw call
- GLubyte* buffer_data;
- unsigned buffer_offset;
- unsigned buffer_bytes_mapped;
- unsigned vertex_len;
- bool strict_vertex_len;
- Gwn_PrimType prim_type;
-
- Gwn_VertFormat vertex_format;
-
- // current vertex
- unsigned vertex_idx;
- GLubyte* vertex_data;
- uint16_t unassigned_attrib_bits; // which attributes of current vertex have not been given values?
-
- GLuint vbo_id;
- GLuint vao_id;
-
- GLuint bound_program;
- const Gwn_ShaderInterface* shader_interface;
- Gwn_AttrBinding attrib_binding;
- uint16_t prev_enabled_attrib_bits; // <-- only affects this VAO, so we're ok
-} Immediate;
-
-// size of internal buffer -- make this adjustable?
-#define IMM_BUFFER_SIZE (4 * 1024 * 1024)
-
-static bool initialized = false;
-static Immediate imm;
-
-void immInit(void)
- {
-#if TRUST_NO_ONE
- assert(!initialized);
-#endif
-
- memset(&imm, 0, sizeof(Immediate));
-
- imm.vbo_id = GWN_buf_id_alloc();
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
-
- imm.prim_type = GWN_PRIM_NONE;
- imm.strict_vertex_len = true;
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- initialized = true;
- }
-
-void immActivate(void)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we're not between a Begin/End pair
- assert(imm.vao_id == 0);
-#endif
- imm.vao_id = GWN_vao_alloc();
- imm.context = GWN_context_active_get();
- }
-
-void immDeactivate(void)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we're not between a Begin/End pair
- assert(imm.vao_id != 0);
-#endif
- GWN_vao_free(imm.vao_id, imm.context);
- imm.vao_id = 0;
- imm.prev_enabled_attrib_bits = 0;
- }
-
-void immDestroy(void)
- {
- GWN_buf_id_free(imm.vbo_id);
- initialized = false;
- }
-
-Gwn_VertFormat* immVertexFormat(void)
- {
- GWN_vertformat_clear(&imm.vertex_format);
- return &imm.vertex_format;
- }
-
-void immBindProgram(GLuint program, const Gwn_ShaderInterface* shaderface)
- {
-#if TRUST_NO_ONE
- assert(imm.bound_program == 0);
- assert(glIsProgram(program));
-#endif
-
- imm.bound_program = program;
- imm.shader_interface = shaderface;
-
- if (!imm.vertex_format.packed)
- VertexFormat_pack(&imm.vertex_format);
-
- glUseProgram(program);
- get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, shaderface);
- gpuBindMatrices(shaderface);
- }
-
-void immUnbindProgram(void)
- {
-#if TRUST_NO_ONE
- assert(imm.bound_program != 0);
-#endif
-#if PROGRAM_NO_OPTI
- glUseProgram(0);
-#endif
- imm.bound_program = 0;
- }
-
-#if TRUST_NO_ONE
-static bool vertex_count_makes_sense_for_primitive(unsigned vertex_len, Gwn_PrimType prim_type)
- {
- // does vertex_len make sense for this primitive type?
- if (vertex_len == 0)
- return false;
-
- switch (prim_type)
- {
- case GWN_PRIM_POINTS:
- return true;
- case GWN_PRIM_LINES:
- return vertex_len % 2 == 0;
- case GWN_PRIM_LINE_STRIP:
- case GWN_PRIM_LINE_LOOP:
- return vertex_len >= 2;
- case GWN_PRIM_LINE_STRIP_ADJ:
- return vertex_len >= 4;
- case GWN_PRIM_TRIS:
- return vertex_len % 3 == 0;
- case GWN_PRIM_TRI_STRIP:
- case GWN_PRIM_TRI_FAN:
- return vertex_len >= 3;
- default:
- return false;
- }
- }
-#endif
-
-void immBegin(Gwn_PrimType prim_type, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we haven't already begun
- assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
-#endif
-
- imm.prim_type = prim_type;
- imm.vertex_len = vertex_len;
- imm.vertex_idx = 0;
- imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
-
- // how many bytes do we need for this draw call?
- const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len);
-
-#if TRUST_NO_ONE
- assert(bytes_needed <= IMM_BUFFER_SIZE);
-#endif
-
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
-
- // does the current buffer have enough room?
- const unsigned available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset;
- // ensure vertex data is aligned
- const unsigned pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); // might waste a little space, but it's safe
- if ((bytes_needed + pre_padding) <= available_bytes)
- imm.buffer_offset += pre_padding;
- else
- {
- // orphan this buffer & start with a fresh one
-#if 1
- // this method works on all platforms, old & new
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
-#else
- // TODO: use other (more recent) methods after thorough testing
- if (GLEW_VERSION_4_3 || GLEW_ARB_invalidate_subdata)
- glInvalidateBufferData(imm.vbo_id);
- else
- {
- // glitches!
-// glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, GL_MAP_INVALIDATE_BUFFER_BIT);
-
- // works
-// glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE,
-// GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
-// glUnmapBuffer(GL_ARRAY_BUFFER);
-
- // also works
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
- }
-#endif
-
- imm.buffer_offset = 0;
- }
-
-// printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1);
-
- imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed,
- GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT));
-
-#if TRUST_NO_ONE
- assert(imm.buffer_data != NULL);
-#endif
-
- imm.buffer_bytes_mapped = bytes_needed;
- imm.vertex_data = imm.buffer_data;
- }
-
-void immBeginAtMost(Gwn_PrimType prim_type, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(vertex_len > 0);
-#endif
-
- imm.strict_vertex_len = false;
- immBegin(prim_type, vertex_len);
- }
-
-#if IMM_BATCH_COMBO
-
-Gwn_Batch* immBeginBatch(Gwn_PrimType prim_type, unsigned vertex_len)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.prim_type == GWN_PRIM_NONE); // make sure we haven't already begun
- assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type));
-#endif
-
- imm.prim_type = prim_type;
- imm.vertex_len = vertex_len;
- imm.vertex_idx = 0;
- imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
-
- Gwn_VertBuf* verts = GWN_vertbuf_create_with_format(&imm.vertex_format);
- GWN_vertbuf_data_alloc(verts, vertex_len);
-
- imm.buffer_bytes_mapped = GWN_vertbuf_size_get(verts);
- imm.vertex_data = verts->data;
-
- imm.batch = GWN_batch_create_ex(prim_type, verts, NULL, GWN_BATCH_OWNS_VBO);
- imm.batch->phase = GWN_BATCH_BUILDING;
-
- return imm.batch;
- }
-
-Gwn_Batch* immBeginBatchAtMost(Gwn_PrimType prim_type, unsigned vertex_len)
- {
- imm.strict_vertex_len = false;
- return immBeginBatch(prim_type, vertex_len);
- }
-
-#endif // IMM_BATCH_COMBO
-
-static void immDrawSetup(void)
- {
- // set up VAO -- can be done during Begin or End really
- glBindVertexArray(imm.vao_id);
-
- // enable/disable vertex attribs as needed
- if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits)
- {
- for (unsigned loc = 0; loc < GWN_VERT_ATTR_MAX_LEN; ++loc)
- {
- bool is_enabled = imm.attrib_binding.enabled_bits & (1 << loc);
- bool was_enabled = imm.prev_enabled_attrib_bits & (1 << loc);
-
- if (is_enabled && !was_enabled)
- {
-// printf("enabling attrib %u\n", loc);
- glEnableVertexAttribArray(loc);
- }
- else if (was_enabled && !is_enabled)
- {
-// printf("disabling attrib %u\n", loc);
- glDisableVertexAttribArray(loc);
- }
- }
-
- imm.prev_enabled_attrib_bits = imm.attrib_binding.enabled_bits;
- }
-
- const unsigned stride = imm.vertex_format.stride;
-
- for (unsigned a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx)
- {
- const Gwn_VertAttr* a = imm.vertex_format.attribs + a_idx;
-
- const unsigned offset = imm.buffer_offset + a->offset;
- const GLvoid* pointer = (const GLubyte*)0 + offset;
-
- const unsigned loc = read_attrib_location(&imm.attrib_binding, a_idx);
-
-// printf("specifying attrib %u '%s' with offset %u, stride %u\n", loc, a->name, offset, stride);
-
- switch (a->fetch_mode)
- {
- case GWN_FETCH_FLOAT:
- case GWN_FETCH_INT_TO_FLOAT:
- glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer);
- break;
- case GWN_FETCH_INT_TO_FLOAT_UNIT:
- glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer);
- break;
- case GWN_FETCH_INT:
- glVertexAttribIPointer(loc, a->comp_len, a->gl_comp_type, stride, pointer);
- }
- }
-
- if (gpuMatricesDirty())
- gpuBindMatrices(imm.shader_interface);
- }
-
-void immEnd(void)
- {
-#if TRUST_NO_ONE
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- unsigned buffer_bytes_used;
- if (imm.strict_vertex_len)
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx == imm.vertex_len); // with all vertices defined
-#endif
- buffer_bytes_used = imm.buffer_bytes_mapped;
- }
- else
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx <= imm.vertex_len);
-#endif
- // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_len);
- if (imm.vertex_idx == imm.vertex_len)
- {
- buffer_bytes_used = imm.buffer_bytes_mapped;
- }
- else
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx == 0 || vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.prim_type));
-#endif
- imm.vertex_len = imm.vertex_idx;
- buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_len);
- // unused buffer bytes are available to the next immBegin
- // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped);
- }
-
- // tell OpenGL what range was modified so it doesn't copy the whole mapped range
- // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
- glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used);
- }
-
-#if IMM_BATCH_COMBO
- if (imm.batch)
- {
- if (buffer_bytes_used != imm.buffer_bytes_mapped)
- {
- GWN_vertbuf_data_resize(imm.batch->verts[0], imm.vertex_len);
- // TODO: resize only if vertex count is much smaller
- }
-
- GWN_batch_program_set(imm.batch, imm.bound_program, imm.shader_interface);
- imm.batch->phase = GWN_BATCH_READY_TO_DRAW;
- imm.batch = NULL; // don't free, batch belongs to caller
- }
- else
-#endif
- {
- glUnmapBuffer(GL_ARRAY_BUFFER);
-
- if (imm.vertex_len > 0)
- {
- immDrawSetup();
- glDrawArrays(convert_prim_type_to_gl(imm.prim_type), 0, imm.vertex_len);
- }
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
-
- // prep for next immBegin
- imm.buffer_offset += buffer_bytes_used;
- }
-
- // prep for next immBegin
- imm.prim_type = GWN_PRIM_NONE;
- imm.strict_vertex_len = true;
- }
-
-static void setAttribValueBit(unsigned attrib_id)
- {
- uint16_t mask = 1 << attrib_id;
-
-#if TRUST_NO_ONE
- assert(imm.unassigned_attrib_bits & mask); // not already set
-#endif
-
- imm.unassigned_attrib_bits &= ~mask;
- }
-
-
-// --- generic attribute functions ---
-
-void immAttrib1f(unsigned attrib_id, float x)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 1);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- }
-
-void immAttrib2f(unsigned attrib_id, float x, float y)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 2);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- data[1] = y;
- }
-
-void immAttrib3f(unsigned attrib_id, float x, float y, float z)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 3);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- data[1] = y;
- data[2] = z;
- }
-
-void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_F32);
- assert(attrib->comp_len == 4);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- float* data = (float*)(imm.vertex_data + attrib->offset);
-// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data);
-
- data[0] = x;
- data[1] = y;
- data[2] = z;
- data[3] = w;
- }
-
-void immAttrib1u(unsigned attrib_id, unsigned x)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_U32);
- assert(attrib->comp_len == 1);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- unsigned* data = (unsigned*)(imm.vertex_data + attrib->offset);
-
- data[0] = x;
- }
-
-void immAttrib2i(unsigned attrib_id, int x, int y)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_I32);
- assert(attrib->comp_len == 2);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- int* data = (int*)(imm.vertex_data + attrib->offset);
-
- data[0] = x;
- data[1] = y;
- }
-
-void immAttrib2s(unsigned attrib_id, short x, short y)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_I16);
- assert(attrib->comp_len == 2);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- short* data = (short*)(imm.vertex_data + attrib->offset);
-
- data[0] = x;
- data[1] = y;
- }
-
-void immAttrib2fv(unsigned attrib_id, const float data[2])
- {
- immAttrib2f(attrib_id, data[0], data[1]);
- }
-
-void immAttrib3fv(unsigned attrib_id, const float data[3])
- {
- immAttrib3f(attrib_id, data[0], data[1], data[2]);
- }
-
-void immAttrib4fv(unsigned attrib_id, const float data[4])
- {
- immAttrib4f(attrib_id, data[0], data[1], data[2], data[3]);
- }
-
-void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_U8);
- assert(attrib->comp_len == 3);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- GLubyte* data = imm.vertex_data + attrib->offset;
-// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data);
-
- data[0] = r;
- data[1] = g;
- data[2] = b;
- }
-
-void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
- {
- Gwn_VertAttr* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(attrib->comp_type == GWN_COMP_U8);
- assert(attrib->comp_len == 4);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
-
- GLubyte* data = imm.vertex_data + attrib->offset;
-// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data);
-
- data[0] = r;
- data[1] = g;
- data[2] = b;
- data[3] = a;
- }
-
-void immAttrib3ubv(unsigned attrib_id, const unsigned char data[3])
- {
- immAttrib3ub(attrib_id, data[0], data[1], data[2]);
- }
-
-void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4])
- {
- immAttrib4ub(attrib_id, data[0], data[1], data[2], data[3]);
- }
-
-void immSkipAttrib(unsigned attrib_id)
- {
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attr_len);
- assert(imm.vertex_idx < imm.vertex_len);
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- setAttribValueBit(attrib_id);
- }
-
-static void immEndVertex(void) // and move on to the next vertex
- {
-#if TRUST_NO_ONE
- assert(imm.prim_type != GWN_PRIM_NONE); // make sure we're between a Begin/End pair
- assert(imm.vertex_idx < imm.vertex_len);
-#endif
-
- // have all attribs been assigned values?
- // if not, copy value from previous vertex
- if (imm.unassigned_attrib_bits)
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx > 0); // first vertex must have all attribs specified
-#endif
-
- for (unsigned a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx)
- {
- if ((imm.unassigned_attrib_bits >> a_idx) & 1)
- {
- const Gwn_VertAttr* a = imm.vertex_format.attribs + a_idx;
-
-// printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx);
-
- GLubyte* data = imm.vertex_data + a->offset;
- memcpy(data, data - imm.vertex_format.stride, a->sz);
- // TODO: consolidate copy of adjacent attributes
- }
- }
- }
-
- imm.vertex_idx++;
- imm.vertex_data += imm.vertex_format.stride;
- imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits;
- }
-
-void immVertex2f(unsigned attrib_id, float x, float y)
- {
- immAttrib2f(attrib_id, x, y);
- immEndVertex();
- }
-
-void immVertex3f(unsigned attrib_id, float x, float y, float z)
- {
- immAttrib3f(attrib_id, x, y, z);
- immEndVertex();
- }
-
-void immVertex4f(unsigned attrib_id, float x, float y, float z, float w)
- {
- immAttrib4f(attrib_id, x, y, z, w);
- immEndVertex();
- }
-
-void immVertex2i(unsigned attrib_id, int x, int y)
- {
- immAttrib2i(attrib_id, x, y);
- immEndVertex();
- }
-
-void immVertex2s(unsigned attrib_id, short x, short y)
- {
- immAttrib2s(attrib_id, x, y);
- immEndVertex();
- }
-
-void immVertex2fv(unsigned attrib_id, const float data[2])
- {
- immAttrib2f(attrib_id, data[0], data[1]);
- immEndVertex();
- }
-
-void immVertex3fv(unsigned attrib_id, const float data[3])
- {
- immAttrib3f(attrib_id, data[0], data[1], data[2]);
- immEndVertex();
- }
-
-void immVertex2iv(unsigned attrib_id, const int data[2])
- {
- immAttrib2i(attrib_id, data[0], data[1]);
- immEndVertex();
- }
-
-
-// --- generic uniform functions ---
-
-#if 0
- #if TRUST_NO_ONE
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name); assert(uniform);
- #else
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name);
- #endif
-#else
- // NOTE: It is possible to have uniform fully optimized out from the shader.
- // In this case we can't assert failure or allow NULL-pointer dereference.
- // TODO(sergey): How can we detect existing-but-optimized-out uniform but still
- // catch typos in uniform names passed to immUniform*() functions?
- #define GET_UNIFORM const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform(imm.shader_interface, name); if (uniform == NULL) return;
-#endif
-
-void immUniform1f(const char* name, float x)
- {
- GET_UNIFORM
- glUniform1f(uniform->location, x);
- }
-
-void immUniform2f(const char* name, float x, float y)
- {
- GET_UNIFORM
- glUniform2f(uniform->location, x, y);
- }
-
-void immUniform2fv(const char* name, const float data[2])
- {
- GET_UNIFORM
- glUniform2fv(uniform->location, 1, data);
- }
-
-void immUniform3f(const char* name, float x, float y, float z)
- {
- GET_UNIFORM
- glUniform3f(uniform->location, x, y, z);
- }
-
-void immUniform3fv(const char* name, const float data[3])
- {
- GET_UNIFORM
- glUniform3fv(uniform->location, 1, data);
- }
-
-// can increase this limit or move to another file
-#define MAX_UNIFORM_NAME_LEN 60
-
-void immUniformArray3fv(const char* bare_name, const float *data, int count)
- {
- // look up "name[0]" when given "name"
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
- GET_UNIFORM
- glUniform3fv(uniform->location, count, data);
- }
-
-void immUniform4f(const char* name, float x, float y, float z, float w)
- {
- GET_UNIFORM
- glUniform4f(uniform->location, x, y, z, w);
- }
-
-void immUniform4fv(const char* name, const float data[4])
- {
- GET_UNIFORM
- glUniform4fv(uniform->location, 1, data);
- }
-
-void immUniformArray4fv(const char* bare_name, const float *data, int count)
- {
- // look up "name[0]" when given "name"
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
- GET_UNIFORM
- glUniform4fv(uniform->location, count, data);
- }
-
-void immUniformMatrix4fv(const char* name, const float data[4][4])
- {
- GET_UNIFORM
- glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data);
- }
-
-void immUniform1i(const char* name, int x)
- {
- GET_UNIFORM
- glUniform1i(uniform->location, x);
- }
-
-void immUniform4iv(const char* name, const int data[4])
- {
- GET_UNIFORM
- glUniform4iv(uniform->location, 1, data);
- }
-
-// --- convenience functions for setting "uniform vec4 color" ---
-
-void immUniformColor4f(float r, float g, float b, float a)
- {
- const Gwn_ShaderInput* uniform = GWN_shaderinterface_uniform_builtin(imm.shader_interface, GWN_UNIFORM_COLOR);
-
-#if TRUST_NO_ONE
- assert(uniform != NULL);
-#endif
-
- glUniform4f(uniform->location, r, g, b, a);
- }
-
-void immUniformColor4fv(const float rgba[4])
- {
- immUniformColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
- }
-
-void immUniformColor3f(float r, float g, float b)
- {
- immUniformColor4f(r, g, b, 1.0f);
- }
-
-void immUniformColor3fv(const float rgb[3])
- {
- immUniformColor4f(rgb[0], rgb[1], rgb[2], 1.0f);
- }
-
-void immUniformColor3fvAlpha(const float rgb[3], float a)
- {
- immUniformColor4f(rgb[0], rgb[1], rgb[2], a);
- }
-
-// TODO: v-- treat as sRGB? --v
-
-void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b)
- {
- const float scale = 1.0f / 255.0f;
- immUniformColor4f(scale * r, scale * g, scale * b, 1.0f);
- }
-
-void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
- {
- const float scale = 1.0f / 255.0f;
- immUniformColor4f(scale * r, scale * g, scale * b, scale * a);
- }
-
-void immUniformColor3ubv(const unsigned char rgb[3])
- {
- immUniformColor3ub(rgb[0], rgb[1], rgb[2]);
- }
-
-void immUniformColor3ubvAlpha(const unsigned char rgb[3], unsigned char alpha)
- {
- immUniformColor4ub(rgb[0], rgb[1], rgb[2], alpha);
- }
-
-void immUniformColor4ubv(const unsigned char rgba[4])
- {
- immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]);
- }