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:
authorMike Erwin <significant.bit@gmail.com>2016-09-13 09:18:33 +0300
committerMike Erwin <significant.bit@gmail.com>2016-09-13 09:18:33 +0300
commitb6bd2993598712240bd354e4400d057732cda459 (patch)
treeb6ebbad35ddb8513dd430b5c15eefd0cfcb3819f /source/blender/gpu/intern/gpu_immediate.c
parent18d49a8283f2490b0751798685770533cc814d29 (diff)
Gawain: reorganize source code
Put Gawain source code in a subfolder to make the boundary between the library and the rest of Blender clear. Changed Gawain’s license from Apache to Mozilla Public License. Has more essence of copyleft — closer to GPL but not as restrictive. Split immediate.c into several files so parts can be reused (adding more files soon…)
Diffstat (limited to 'source/blender/gpu/intern/gpu_immediate.c')
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c776
1 files changed, 0 insertions, 776 deletions
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
deleted file mode 100644
index 98568d14482..00000000000
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ /dev/null
@@ -1,776 +0,0 @@
-
-// Gawain immediate mode work-alike, take 2
-//
-// This code is part of the Gawain library, with modifications
-// specific to integration with Blender.
-//
-// Copyright 2016 Mike Erwin
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-
-#include "GPU_immediate.h"
-#include <assert.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#define PACK_DEBUG 0
-
-#if PACK_DEBUG
- #include <stdio.h>
-#endif
-
-#define APPLE_LEGACY (defined(__APPLE__) && defined(WITH_GL_PROFILE_COMPAT))
-
-#if APPLE_LEGACY
- #undef glGenVertexArrays
- #define glGenVertexArrays glGenVertexArraysAPPLE
-
- #undef glDeleteVertexArrays
- #define glDeleteVertexArrays glDeleteVertexArraysAPPLE
-
- #undef glBindVertexArray
- #define glBindVertexArray glBindVertexArrayAPPLE
-#endif
-
-#define PRIM_NONE 0xF
-
-void clear_VertexFormat(VertexFormat* format)
- {
- for (unsigned a = 0; a < format->attrib_ct; ++a)
- free(format->attribs[a].name);
-
-#if TRUST_NO_ONE
- memset(format, 0, sizeof(VertexFormat));
-#else
- format->attrib_ct = 0;
- format->packed = false;
-#endif
- }
-
-static unsigned comp_sz(GLenum type)
- {
-#if TRUST_NO_ONE
- assert(type >= GL_BYTE && type <= GL_FLOAT);
-#endif
-
- const GLubyte sizes[] = {1,1,2,2,4,4,4};
- return sizes[type - GL_BYTE];
- }
-
-static unsigned attrib_sz(const Attrib *a)
- {
- return a->comp_ct * comp_sz(a->comp_type);
- }
-
-static unsigned attrib_align(const Attrib *a)
- {
- unsigned c = comp_sz(a->comp_type);
- if (a->comp_ct == 3 && c <= 2)
- return 4 * c; // AMD HW can't fetch these well, so pad it out (other vendors too?)
- else
- return c; // most fetches are ok if components are naturally aligned
- }
-
-static unsigned vertex_buffer_size(const VertexFormat* format, unsigned vertex_ct)
- {
-#if TRUST_NO_ONE
- assert(format->packed && format->stride > 0);
-#endif
-
- return format->stride * vertex_ct;
- }
-
-unsigned add_attrib(VertexFormat* format, const char* name, GLenum comp_type, unsigned comp_ct, VertexFetchMode fetch_mode)
- {
-#if TRUST_NO_ONE
- assert(format->attrib_ct < MAX_VERTEX_ATTRIBS); // there's room for more
- assert(!format->packed); // packed means frozen/locked
-#endif
-
- const unsigned attrib_id = format->attrib_ct++;
- Attrib* attrib = format->attribs + attrib_id;
-
- attrib->name = strdup(name);
- attrib->comp_type = comp_type;
- attrib->comp_ct = comp_ct;
- attrib->sz = attrib_sz(attrib);
- attrib->offset = 0; // offsets & stride are calculated later (during pack)
- attrib->fetch_mode = fetch_mode;
-
- return attrib_id;
- }
-
-static unsigned padding(unsigned offset, unsigned alignment)
- {
- const unsigned mod = offset % alignment;
- return (mod == 0) ? 0 : (alignment - mod);
- }
-
-#if PACK_DEBUG
-static void show_pack(unsigned a_idx, unsigned sz, unsigned pad)
- {
- const char c = 'A' + a_idx;
- for (unsigned i = 0; i < pad; ++i)
- putchar('-');
- for (unsigned i = 0; i < sz; ++i)
- putchar(c);
- }
-#endif
-
-void pack(VertexFormat* format)
- {
- // for now, attributes are packed in the order they were added,
- // making sure each attrib is naturally aligned (add padding where necessary)
-
- // later we can implement more efficient packing w/ reordering
-
- Attrib* a0 = format->attribs + 0;
- a0->offset = 0;
- unsigned offset = a0->sz;
-
-#if PACK_DEBUG
- show_pack(0, a0->sz, 0);
-#endif
-
- for (unsigned a_idx = 1; a_idx < format->attrib_ct; ++a_idx)
- {
- Attrib* a = format->attribs + a_idx;
- unsigned mid_padding = padding(offset, attrib_align(a));
- offset += mid_padding;
- a->offset = offset;
- offset += a->sz;
-
-#if PACK_DEBUG
- show_pack(a_idx, a->sz, mid_padding);
-#endif
- }
-
- unsigned end_padding = padding(offset, attrib_align(a0));
-
-#if PACK_DEBUG
- show_pack(0, 0, end_padding);
- putchar('\n');
-#endif
-
- format->stride = offset + end_padding;
- format->packed = true;
- }
-
-void bind_attrib_locations(const VertexFormat* format, GLuint program)
- {
-#if TRUST_NO_ONE
- assert(glIsProgram(program));
-#endif
-
- for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
- {
- const Attrib* a = format->attribs + a_idx;
- glBindAttribLocation(program, a_idx, a->name);
- }
- }
-
-typedef struct {
- uint64_t loc_bits; // store 4 bits for each of the 16 attribs
- uint16_t enabled_bits; // 1 bit for each attrib
-} AttribBinding;
-
-void clear_AttribBinding(AttribBinding* binding)
- {
- binding->loc_bits = 0;
- binding->enabled_bits = 0;
- }
-
-unsigned read_attrib_location(const AttribBinding* binding, unsigned a_idx)
- {
-#if TRUST_NO_ONE
- assert(MAX_VERTEX_ATTRIBS == 16);
- assert(a_idx < MAX_VERTEX_ATTRIBS);
- assert(binding->enabled_bits & (1 << a_idx));
-#endif
-
- return (binding->loc_bits >> (4 * a_idx)) & 0xF;
- }
-
-void write_attrib_location(AttribBinding* binding, unsigned a_idx, unsigned location)
- {
-#if TRUST_NO_ONE
- assert(MAX_VERTEX_ATTRIBS == 16);
- assert(a_idx < MAX_VERTEX_ATTRIBS);
- assert(location < MAX_VERTEX_ATTRIBS);
-#endif
-
- const unsigned shift = 4 * a_idx;
- const uint64_t mask = ((uint64_t)0xF) << shift;
- // overwrite this attrib's previous location
- binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift);
- // mark this attrib as enabled
- binding->enabled_bits |= 1 << a_idx;
- }
-
-void get_attrib_locations(const VertexFormat* format, AttribBinding* binding, GLuint program)
- {
-#if TRUST_NO_ONE
- assert(glIsProgram(program));
-#endif
-
- clear_AttribBinding(binding);
-
- for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx)
- {
- const Attrib* a = format->attribs + a_idx;
- GLint loc = glGetAttribLocation(program, a->name);
-
-#if TRUST_NO_ONE
- assert(loc != -1);
-#endif
-
- write_attrib_location(binding, a_idx, loc);
- }
- }
-
-// --- immediate mode work-alike --------------------------------
-
-typedef struct {
- // TODO: organize this struct by frequency of change (run-time)
-
- // current draw call
- GLubyte* buffer_data;
- unsigned buffer_offset;
- unsigned buffer_bytes_mapped;
- unsigned vertex_ct;
- bool strict_vertex_ct;
- GLenum primitive;
-
- VertexFormat vertex_format;
-
- // current vertex
- unsigned vertex_idx;
- GLubyte* vertex_data;
- unsigned short attrib_value_bits; // which attributes of current vertex have been given values?
-
- GLuint vbo_id;
- GLuint vao_id;
-
- GLuint bound_program;
- AttribBinding attrib_binding;
- uint16_t prev_enabled_attrib_bits;
-} Immediate;
-
-// size of internal buffer -- make this adjustable?
-#define IMM_BUFFER_SIZE (4 * 1024 * 1024)
-
-static PER_THREAD bool initialized = false;
-static PER_THREAD Immediate imm;
-
-void immInit()
- {
-#if TRUST_NO_ONE
- assert(!initialized);
-#endif
-
- memset(&imm, 0, sizeof(Immediate));
-
- glGenVertexArrays(1, &imm.vao_id);
- glBindVertexArray(imm.vao_id);
- glGenBuffers(1, &imm.vbo_id);
- glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id);
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
-
-#if APPLE_LEGACY
- glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE);
- glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE);
-#endif
-
- imm.primitive = PRIM_NONE;
- imm.strict_vertex_ct = true;
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
- initialized = true;
- }
-
-void immDestroy()
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.primitive == PRIM_NONE); // make sure we're not between a Begin/End pair
-#endif
-
- clear_VertexFormat(&imm.vertex_format);
- glDeleteVertexArrays(1, &imm.vao_id);
- glDeleteBuffers(1, &imm.vbo_id);
- initialized = false;
- }
-
-VertexFormat* immVertexFormat()
- {
- clear_VertexFormat(&imm.vertex_format);
- return &imm.vertex_format;
- }
-
-void immBindProgram(GLuint program)
- {
-#if TRUST_NO_ONE
- assert(imm.bound_program == 0);
-#endif
-
- if (!imm.vertex_format.packed)
- pack(&imm.vertex_format);
-
- glUseProgram(program);
- get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, program);
- imm.bound_program = program;
- }
-
-void immUnbindProgram()
- {
-#if TRUST_NO_ONE
- assert(imm.bound_program != 0);
-#endif
-
- glUseProgram(0);
- imm.bound_program = 0;
- }
-
-static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, GLenum primitive)
- {
- // does vertex_ct make sense for this primitive type?
- if (vertex_ct == 0)
- return false;
-
- switch (primitive)
- {
- case GL_POINTS:
- return true;
- case GL_LINES:
- return vertex_ct % 2 == 0;
- case GL_LINE_STRIP:
- case GL_LINE_LOOP:
- return vertex_ct > 2; // otherwise why bother?
- case GL_TRIANGLES:
- return vertex_ct % 3 == 0;
- #ifdef WITH_GL_PROFILE_COMPAT
- case GL_QUADS:
- return vertex_ct % 4 == 0;
- #endif
- default:
- return false;
- }
- }
-
-void immBegin(GLenum primitive, unsigned vertex_ct)
- {
-#if TRUST_NO_ONE
- assert(initialized);
- assert(imm.primitive == PRIM_NONE); // make sure we haven't already begun
- assert(vertex_count_makes_sense_for_primitive(vertex_ct, primitive));
-#endif
-
- imm.primitive = primitive;
- imm.vertex_ct = vertex_ct;
- imm.vertex_idx = 0;
- imm.attrib_value_bits = 0;
-
- // how many bytes do we need for this draw call?
- const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_ct);
-
-#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 APPLE_LEGACY
- glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW);
-#else
- if (GLEW_VERSION_4_3 || GLEW_ARB_invalidate_subdata)
- glInvalidateBufferData(imm.vbo_id);
- else
- glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, GL_MAP_INVALIDATE_BUFFER_BIT);
-#endif
-
- imm.buffer_offset = 0;
- }
-
-// printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1);
-
-#if APPLE_LEGACY
- imm.buffer_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY) + imm.buffer_offset;
-#else
- imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
-#endif
-
-#if TRUST_NO_ONE
- assert(imm.buffer_data != NULL);
-#endif
-
- imm.buffer_bytes_mapped = bytes_needed;
- imm.vertex_data = imm.buffer_data;
- }
-
-void immBeginAtMost(GLenum primitive, unsigned vertex_ct)
- {
- imm.strict_vertex_ct = false;
- immBegin(primitive, vertex_ct);
- }
-
-void immEnd()
- {
-#if TRUST_NO_ONE
- assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
-#endif
-
- unsigned buffer_bytes_used;
- if (imm.strict_vertex_ct)
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined
-#endif
- buffer_bytes_used = imm.buffer_bytes_mapped;
- }
- else
- {
-#if TRUST_NO_ONE
- assert(imm.vertex_idx <= imm.vertex_ct);
- assert(vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.primitive));
-#endif
- // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct);
- imm.vertex_ct = imm.vertex_idx;
- buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct);
- // unused buffer bytes are available to the next immBegin
- // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped);
- }
-
-#if APPLE_LEGACY
- // tell OpenGL what range was modified so it doesn't copy the whole buffer
- glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used);
-// printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1);
-#endif
- glUnmapBuffer(GL_ARRAY_BUFFER);
-
- // 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 < MAX_VERTEX_ATTRIBS; ++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.attrib_ct; ++a_idx)
- {
- const Attrib* 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 KEEP_FLOAT:
- case CONVERT_INT_TO_FLOAT:
- glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer);
- break;
- case NORMALIZE_INT_TO_FLOAT:
- glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer);
- break;
- case KEEP_INT:
- glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer);
- }
- }
-
- glDrawArrays(imm.primitive, 0, imm.vertex_ct);
-
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- glBindVertexArray(0);
-
- // prep for next immBegin
- imm.buffer_offset += buffer_bytes_used;
- imm.primitive = PRIM_NONE;
- imm.strict_vertex_ct = true;
-
- // further optional cleanup
- imm.buffer_bytes_mapped = 0;
- imm.buffer_data = NULL;
- imm.vertex_data = NULL;
- }
-
-static void setAttribValueBit(unsigned attrib_id)
- {
- unsigned short mask = 1 << attrib_id;
-
-#if TRUST_NO_ONE
- assert((imm.attrib_value_bits & mask) == 0); // not already set
-#endif
-
- imm.attrib_value_bits |= mask;
- }
-
-void immAttrib1f(unsigned attrib_id, float x)
- {
- Attrib* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attrib_ct);
- assert(attrib->comp_type == GL_FLOAT);
- assert(attrib->comp_ct == 1);
- assert(imm.vertex_idx < imm.vertex_ct);
- assert(imm.primitive != 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)
- {
- Attrib* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attrib_ct);
- assert(attrib->comp_type == GL_FLOAT);
- assert(attrib->comp_ct == 2);
- assert(imm.vertex_idx < imm.vertex_ct);
- assert(imm.primitive != 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)
- {
- Attrib* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attrib_ct);
- assert(attrib->comp_type == GL_FLOAT);
- assert(attrib->comp_ct == 3);
- assert(imm.vertex_idx < imm.vertex_ct);
- assert(imm.primitive != 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)
- {
- Attrib* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attrib_ct);
- assert(attrib->comp_type == GL_FLOAT);
- assert(attrib->comp_ct == 4);
- assert(imm.vertex_idx < imm.vertex_ct);
- assert(imm.primitive != 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 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)
- {
- Attrib* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attrib_ct);
- assert(attrib->comp_type == GL_UNSIGNED_BYTE);
- assert(attrib->comp_ct == 3);
- assert(imm.vertex_idx < imm.vertex_ct);
- assert(imm.primitive != 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)
- {
- Attrib* attrib = imm.vertex_format.attribs + attrib_id;
-
-#if TRUST_NO_ONE
- assert(attrib_id < imm.vertex_format.attrib_ct);
- assert(attrib->comp_type == GL_UNSIGNED_BYTE);
- assert(attrib->comp_ct == 4);
- assert(imm.vertex_idx < imm.vertex_ct);
- assert(imm.primitive != 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 immEndVertex()
- {
-#if TRUST_NO_ONE
- assert(imm.primitive != PRIM_NONE); // make sure we're between a Begin/End pair
- assert(imm.vertex_idx < imm.vertex_ct);
-#endif
-
- // have all attribs been assigned values?
- // if not, copy value from previous vertex
- const unsigned short all_bits = ~(0xFFFFU << imm.vertex_format.attrib_ct);
- if (imm.attrib_value_bits != all_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.attrib_ct; ++a_idx)
- {
- const uint16_t mask = 1 << a_idx;
- if ((imm.attrib_value_bits & mask) == 0)
- {
- const Attrib* 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);
- }
- }
- }
-
- imm.vertex_idx++;
- imm.vertex_data += imm.vertex_format.stride;
- imm.attrib_value_bits = 0;
- }
-
-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 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 immUniform4f(const char* name, float x, float y, float z, float w)
- {
- int loc = glGetUniformLocation(imm.bound_program, name);
-
-#if TRUST_NO_ONE
- assert(loc != -1);
-#endif
-
- glUniform4f(loc, x, y, z, w);
- }
-
-void immUniformColor3ubv(const unsigned char rgb[3])
- {
- const float scale = 1.0f / 255.0f;
- immUniform4f("color", scale * rgb[0], scale * rgb[1], scale * rgb[2], 1.0f);
- }
-
-void immUniformColor4ubv(const unsigned char rgba[4])
- {
- const float scale = 1.0f / 255.0f;
- immUniform4f("color", scale * rgba[0], scale * rgba[1], scale * rgba[2], rgba[3]);
- }