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 'source/blender/gpu/intern/gpu_immediate.c')
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c1665
1 files changed, 1665 insertions, 0 deletions
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
new file mode 100644
index 00000000000..7f5127408aa
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -0,0 +1,1665 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_immediate.c
+ * \ingroup gpu
+ */
+
+/* my interface */
+#include "intern/gpu_immediate_intern.h"
+
+/* my library */
+#include "GPU_extensions.h"
+
+/* internal */
+#include "intern/gpu_profile.h"
+
+/* external */
+#include "MEM_guardedalloc.h"
+
+/* standard */
+#include <string.h>
+
+
+
+#if GPU_SAFETY
+
+/* Define some useful, but potentially slow, checks for correct API usage. */
+
+/* Each block contains variables that can be inspected by a
+ debugger in the event that a break point is triggered. */
+
+#define GPU_CHECK_CAN_SETUP() \
+ { \
+ GLboolean immediateOK; \
+ GLboolean noLockOK; \
+ GLboolean noBeginOK; \
+ GPU_CHECK_BASE(immediateOK); \
+ GPU_CHECK_NO_LOCK(noLockOK) \
+ GPU_CHECK_NO_BEGIN(noBeginOK) \
+ }
+
+#define GPU_CHECK_CAN_PUSH() \
+ { \
+ GLboolean immediateStackOK; \
+ GLboolean noLockOK; \
+ GLboolean noBeginOK; \
+ GPU_SAFE_RETURN(immediateStack == NULL, immediateStackOK,); \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->mappedBuffer == NULL, noLockOK,); \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->lockCount == 0, noBeginOK,); \
+ }
+
+#define GPU_CHECK_CAN_POP() \
+ { \
+ GLboolean immediateOK; \
+ GLboolean noLockOK; \
+ GLboolean noBeginOK; \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE != NULL, immediateOK, NULL); \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->mappedBuffer == NULL, noLockOK, NULL); \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->lockCount == 0, noBeginOK, NULL); \
+ }
+
+#define GPU_CHECK_CAN_LOCK() \
+ { \
+ GLboolean immediateOK; \
+ GLboolean noBeginOK; \
+ GLboolean noLockOK; \
+ GPU_CHECK_BASE(immediateOK); \
+ GPU_CHECK_NO_BEGIN(noBeginOK); \
+ GPU_CHECK_NO_LOCK(noLockOK); \
+ }
+
+#define GPU_CHECK_CAN_UNLOCK() \
+ { \
+ GLboolean immediateOK; \
+ GLboolean isLockedOK; \
+ GLboolean noBeginOK; \
+ GPU_CHECK_BASE(immediateOK); \
+ GPU_CHECK_IS_LOCKED(isLockedOK) \
+ GPU_CHECK_NO_BEGIN(noBeginOK) \
+ }
+
+// XXX jwilkins: make this assert prettier
+#define GPU_SAFE_STMT(var, test, stmt) \
+ var = (GLboolean)(test); \
+ GPU_ASSERT(((void)#test, var)); \
+ if (var) { \
+ stmt; \
+ }
+
+#else
+
+#define GPU_CHECK_CAN_SETUP()
+#define GPU_CHECK_CAN_PUSH()
+#define GPU_CHECK_CAN_POP()
+#define GPU_CHECK_CAN_LOCK()
+#define GPU_CHECK_CAN_UNLOCK()
+
+#define GPU_CHECK_CAN_CURRENT()
+#define GPU_CHECK_CAN_GET_COLOR()
+#define GPU_CHECK_CAN_GET_NORMAL()
+
+#define GPU_SAFE_STMT(var, test, stmt) { (void)(var); stmt; }
+
+#endif
+
+
+
+/* global symbol needed because the immediate drawing functons are inline */
+GPUimmediate *__restrict GPU_IMMEDIATE = NULL;
+
+
+
+void gpuBegin(GLenum mode)
+{
+ int primMod;
+ int primOff;
+
+ GPU_CHECK_CAN_BEGIN();
+
+#if GPU_SAFETY
+ GPU_IMMEDIATE->hasOverflowed = GL_FALSE;
+#endif
+
+ GPU_IMMEDIATE->mode = mode;
+ GPU_IMMEDIATE->offset = 0;
+ GPU_IMMEDIATE->count = 0;
+
+ switch (mode) {
+ case GL_LINES:
+ primMod = 2;
+ primOff = 0;
+ break;
+
+ case GL_QUAD_STRIP:
+ case GL_TRIANGLE_STRIP:
+ primMod = 2;
+ primOff = 2;
+ break;
+
+ case GL_TRIANGLES:
+ primMod = 3;
+ primOff = 0;
+ break;
+
+ case GL_QUADS:
+ primMod = 4;
+ primOff = 2;
+ break;
+
+ default:
+ primMod = 1;
+ primOff = 0;
+ break;
+ }
+
+ GPU_IMMEDIATE->lastPrimVertex = GPU_IMMEDIATE->maxVertexCount - (GPU_IMMEDIATE->maxVertexCount % primMod);
+
+ gpu_begin_buffer_gl();
+}
+
+
+
+void gpuEnd(void)
+{
+ GPU_CHECK_CAN_END();
+ GPU_ASSERT(GPU_IMMEDIATE->mode != GL_NOOP || !(GPU_IMMEDIATE->hasOverflowed));
+
+ gpu_end_buffer_gl();
+
+ GPU_IMMEDIATE->mappedBuffer = NULL;
+}
+
+
+
+void gpuImmediateFormatReset(void)
+{
+ /* reset vertex format */
+ memset(&(GPU_IMMEDIATE->format), 0, sizeof(GPU_IMMEDIATE->format));
+ GPU_IMMEDIATE->format.vertexSize = 3;
+}
+
+
+
+void gpuImmediateLock(void)
+{
+ GPU_CHECK_CAN_LOCK();
+
+ if (GPU_IMMEDIATE->lockCount == 0)
+ gpu_lock_buffer_gl();
+
+ GPU_IMMEDIATE->lockCount++;
+}
+
+void gpuImmediateUnlock(void)
+{
+ GPU_CHECK_CAN_UNLOCK();
+
+ GPU_IMMEDIATE->lockCount--;
+
+ if (GPU_IMMEDIATE->lockCount == 0)
+ gpu_unlock_buffer_gl();
+}
+
+
+
+GLint gpuImmediateLockCount(void)
+{
+ GPU_ASSERT(GPU_IMMEDIATE);
+
+ if (!GPU_IMMEDIATE) {
+ return GL_FALSE;
+ }
+
+ return GPU_IMMEDIATE->lockCount;
+}
+
+
+
+static void gpu_copy_vertex(void);
+
+
+
+GPUimmediate* gpuNewImmediate(void)
+{
+ GPUimmediate* immediate =
+ (GPUimmediate*)MEM_callocN(sizeof(GPUimmediate), "GPUimmediate");
+
+ immediate->copyVertex = gpu_copy_vertex;
+
+#if GPU_SAFETY
+ immediate->lastTexture = GPU_max_textures() - 1;
+#endif
+
+ return immediate;
+}
+
+
+
+void gpuImmediateMakeCurrent(GPUimmediate *__restrict immediate)
+{
+ GPU_IMMEDIATE = immediate;
+}
+
+
+
+void gpuDeleteImmediate(GPUimmediate *__restrict immediate)
+{
+ if (!immediate)
+ return;
+
+ if (GPU_IMMEDIATE == immediate)
+ gpuImmediateMakeCurrent(NULL);
+
+ gpu_shutdown_buffer_gl(immediate);
+
+ MEM_freeN(immediate);
+}
+
+
+
+void gpuImmediateElementSizes(
+ GLint vertexSize,
+ GLint normalSize,
+ GLint colorSize)
+{
+ GLboolean vertexOK;
+ GLboolean normalOK;
+ GLboolean colorOK;
+
+ GPU_CHECK_CAN_SETUP();
+
+ GPU_SAFE_STMT(
+ vertexOK,
+ vertexSize > 0 && vertexSize <= 4,
+ GPU_IMMEDIATE->format.vertexSize = vertexSize);
+
+ GPU_SAFE_STMT(
+ normalOK,
+ normalSize == 0 || normalSize == 3,
+ GPU_IMMEDIATE->format.normalSize = normalSize);
+
+ GPU_SAFE_STMT(
+ colorOK,
+ colorSize == 0 || colorSize == 4, //-V112
+ GPU_IMMEDIATE->format.colorSize = colorSize);
+}
+
+
+
+void gpuImmediateMaxVertexCount(GLsizei maxVertexCount)
+{
+ GLboolean maxVertexCountOK;
+
+ GPU_CHECK_CAN_SETUP();
+
+ GPU_SAFE_STMT(
+ maxVertexCountOK,
+ maxVertexCount >= 0,
+ GPU_IMMEDIATE->maxVertexCount = maxVertexCount);
+}
+
+
+
+void gpuImmediateTexCoordCount(size_t count)
+{
+ GLboolean countOK;
+
+ GPU_CHECK_CAN_SETUP();
+
+ GPU_SAFE_STMT(
+ countOK,
+ count <= GPU_MAX_COMMON_TEXCOORDS,
+ GPU_IMMEDIATE->format.texCoordCount = count);
+}
+
+
+
+void gpuImmediateTexCoordSizes(const GLint *__restrict sizes)
+{
+ size_t i;
+
+ GPU_CHECK_CAN_SETUP();
+
+ for (i = 0; i < GPU_IMMEDIATE->format.texCoordCount; i++) {
+ GLboolean texCoordSizeOK;
+
+ GPU_SAFE_STMT(
+ texCoordSizeOK,
+ sizes[i] > 0 && sizes[i] <= 4,
+ GPU_IMMEDIATE->format.texCoordSize[i] = sizes[i]);
+ }
+}
+
+
+
+void gpuImmediateSamplerCount(size_t count)
+{
+ GLboolean countOK;
+
+ GPU_CHECK_CAN_SETUP();
+
+ GPU_SAFE_STMT(
+ countOK,
+ count <= GPU_MAX_COMMON_SAMPLERS,
+ GPU_IMMEDIATE->format.samplerCount = count);
+}
+
+
+
+void gpuImmediateSamplerMap(const GLint *__restrict map)
+{
+ size_t i;
+
+ GPU_CHECK_CAN_SETUP();
+
+ for (i = 0; i < GPU_IMMEDIATE->format.samplerCount; i++) {
+ GLboolean mapOK;
+
+ GPU_SAFE_STMT(
+ mapOK,
+ map[i] >= 0 && map[i] <= GPU_IMMEDIATE->lastTexture,
+ GPU_IMMEDIATE->format.samplerMap[i] = map[i]);
+ }
+}
+
+
+
+void gpuImmediateFloatAttribCount(size_t count)
+{
+ GLboolean countOK;
+
+ GPU_CHECK_CAN_SETUP();
+
+ GPU_SAFE_STMT(
+ countOK,
+ count <= GPU_MAX_FLOAT_ATTRIBS,
+ GPU_IMMEDIATE->format.attribCount_f = count);
+}
+
+
+
+void gpuImmediateFloatAttribSizes(const GLint *__restrict sizes)
+{
+ size_t i;
+
+ GPU_CHECK_CAN_SETUP();
+
+ for (i = 0; i < GPU_IMMEDIATE->format.attribCount_f; i++) {
+ GLboolean sizeOK;
+
+ GPU_SAFE_STMT(
+ sizeOK,
+ sizes[i] > 0 && sizes[i] <= 4,
+ GPU_IMMEDIATE->format.attribSize_f[i] = sizes[i]);
+ }
+}
+
+
+
+void gpuImmediateFloatAttribIndexMap(const GLuint *__restrict map)
+{
+ size_t i;
+
+ GPU_CHECK_CAN_SETUP();
+
+ for (i = 0; i < GPU_IMMEDIATE->format.attribCount_f; i++) {
+ GPU_IMMEDIATE->format.attribIndexMap_f[i] = map[i];
+ }
+}
+
+
+
+void gpuImmediateUbyteAttribCount(size_t count)
+{
+ GLboolean countOK;
+
+ GPU_CHECK_CAN_SETUP();
+
+ GPU_SAFE_STMT(
+ countOK,
+ count <= GPU_MAX_UBYTE_ATTRIBS,
+ GPU_IMMEDIATE->format.attribCount_ub = count);
+}
+
+void gpuImmediateUbyteAttribSizes(const GLint *__restrict sizes)
+{
+ size_t i;
+
+ GPU_CHECK_CAN_SETUP();
+
+ for (i = 0; i < GPU_IMMEDIATE->format.attribCount_ub; i++) {
+ GLboolean sizeOK;
+
+ GPU_SAFE_STMT(
+ sizeOK,
+ sizes[i] > 0 && sizes[i] <= 4, //-V112
+ GPU_IMMEDIATE->format.attribSize_ub[i] = sizes[i]);
+ }
+}
+
+
+
+void gpuImmediateUbyteAttribIndexMap(const GLuint *__restrict map)
+{
+ size_t i;
+
+ GPU_CHECK_CAN_SETUP();
+
+ for (i = 0; i < GPU_IMMEDIATE->format.attribCount_ub; i++) {
+ GPU_IMMEDIATE->format.attribIndexMap_ub[i] = map[i];
+ }
+}
+
+
+
+static GLboolean end_begin(void)
+{
+#if GPU_SAFETY
+ GPU_IMMEDIATE->hasOverflowed = GL_TRUE;
+#endif
+
+ if (!ELEM(
+ GPU_IMMEDIATE->mode,
+ GL_NOOP,
+ GL_LINE_LOOP,
+ GL_POLYGON,
+ GL_QUAD_STRIP,
+ GL_LINE_STRIP,
+ GL_TRIANGLE_STRIP)) // XXX jwilkins: can restart some of these, but need to put in the logic (could be problematic with mapped VBOs?)
+ {
+ gpu_end_buffer_gl();
+
+ GPU_IMMEDIATE->mappedBuffer = NULL;
+ GPU_IMMEDIATE->offset = 0;
+ GPU_IMMEDIATE->count = 1; /* count the vertex that triggered this */
+
+ gpu_begin_buffer_gl();
+
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+static void gpu_copy_vertex(void)
+{
+ size_t i;
+ size_t size;
+ size_t offset;
+ GLubyte *__restrict mappedBuffer;
+
+#if GPU_SAFETY
+ {
+ int maxVertexCountOK;
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->maxVertexCount != 0, maxVertexCountOK,);
+ }
+#endif
+
+ if (GPU_IMMEDIATE->count == GPU_IMMEDIATE->lastPrimVertex) {
+ GLboolean restarted;
+
+ restarted = end_begin(); /* draw and clear buffer */
+
+ GPU_ASSERT(restarted);
+
+ if (!restarted)
+ return;
+ }
+ else {
+ GPU_IMMEDIATE->count++;
+ }
+
+ mappedBuffer = GPU_IMMEDIATE->mappedBuffer;
+ offset = GPU_IMMEDIATE->offset;
+
+ /* vertex */
+
+ size = (size_t)(GPU_IMMEDIATE->format.vertexSize) * sizeof(GLfloat);
+ memcpy(mappedBuffer + offset, GPU_IMMEDIATE->vertex, size);
+ offset += size;
+
+ /* normal */
+
+ if (GPU_IMMEDIATE->format.normalSize != 0) {
+ /* normals are always have 3 components */
+ memcpy(mappedBuffer + offset, GPU_IMMEDIATE->normal, 3*sizeof(GLfloat));
+ offset += 3*sizeof(GLfloat);
+ }
+
+ /* color */
+
+ if (GPU_IMMEDIATE->format.colorSize != 0) {
+ /* 4 bytes are always reserved for color, for efficient memory alignment */
+ memcpy(mappedBuffer + offset, GPU_IMMEDIATE->color, 4*sizeof(GLubyte));
+ offset += 4*sizeof(GLubyte);
+ }
+
+ /* texture coordinate(s) */
+
+ for (i = 0; i < GPU_IMMEDIATE->format.texCoordCount; i++) {
+ size = (size_t)(GPU_IMMEDIATE->format.texCoordSize[i]) * sizeof(GLfloat);
+ memcpy(mappedBuffer + offset, GPU_IMMEDIATE->texCoord[i], size);
+ offset += size;
+ }
+
+ /* float vertex attribute(s) */
+
+ for (i = 0; i < GPU_IMMEDIATE->format.attribCount_f; i++) {
+ size = (size_t)(GPU_IMMEDIATE->format.attribSize_f[i]) * sizeof(GLfloat);
+ memcpy(mappedBuffer + offset, GPU_IMMEDIATE->attrib_f[i], size);
+ offset += size;
+ }
+
+ /* unsigned byte vertex attribute(s) */
+
+ for (i = 0; i < GPU_IMMEDIATE->format.attribCount_ub; i++) {
+ /* 4 bytes are always reserved for byte attributes, for efficient memory alignment */
+ memcpy(mappedBuffer + offset, GPU_IMMEDIATE->attrib_ub[i], 4*sizeof(GLubyte));
+ offset += 4*sizeof(GLubyte);
+ }
+
+ GPU_IMMEDIATE->offset = offset;
+}
+
+
+
+/* vertex formats */
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_V2(const char* file, int line)
+#else
+void gpuImmediateFormat_V2(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_V2\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(2, 0, 0);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_C4_V2(const char* file, int line)
+#else
+void gpuImmediateFormat_C4_V2(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_C4_V2\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(2, 0, 4); //-V112
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_T2_V2(const char* file, int line)
+#else
+void gpuImmediateFormat_T2_V2(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_T2_V2\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ GLint texCoordSizes[1] = { 2 };
+ GLint samplerMap [1] = { 0 };
+
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(2, 0, 0);
+
+ gpuImmediateTexCoordCount(1);
+ gpuImmediateTexCoordSizes(texCoordSizes);
+
+ gpuImmediateSamplerCount(1);
+ gpuImmediateSamplerMap(samplerMap);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_T2_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_T2_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_T2_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ GLint texCoordSizes[1] = { 2 };
+ GLint samplerMap [1] = { 0 };
+
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 0, 0);
+
+ gpuImmediateTexCoordCount(1);
+ gpuImmediateTexCoordSizes(texCoordSizes);
+
+ gpuImmediateSamplerCount(1);
+ gpuImmediateSamplerMap(samplerMap);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_T2_C4_V2(const char* file, int line)
+#else
+void gpuImmediateFormat_T2_C4_V2(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_T2_C4_V2\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ GLint texCoordSizes[1] = { 2 };
+ GLint samplerMap [1] = { 0 };
+
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(2, 0, 4); //-V112
+
+ gpuImmediateTexCoordCount(1);
+ gpuImmediateTexCoordSizes(texCoordSizes);
+
+ gpuImmediateSamplerCount(1);
+ gpuImmediateSamplerMap(samplerMap);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 0, 0);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_N3_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_N3_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_N3_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 3, 0);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_C4_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_C4_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_C4_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 0, 4); //-V112
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_C4_N3_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_C4_N3_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_C4_N3_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 3, 4); //-V112
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_T2_C4_N3_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_T2_C4_N3_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_T2_C4_N3_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ GLint texCoordSizes[1] = { 2 };
+ GLint samplerMap [1] = { 0 };
+
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 3, 4); //-V112
+
+ gpuImmediateTexCoordCount(1);
+ gpuImmediateTexCoordSizes(texCoordSizes);
+
+ gpuImmediateSamplerCount(1);
+ gpuImmediateSamplerMap(samplerMap);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateFormat_T3_C4_V3(const char* file, int line)
+#else
+void gpuImmediateFormat_T3_C4_V3(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateFormat_T3_C4_V3\n", file, line);
+#endif
+
+ if (gpuImmediateLockCount() == 0) {
+ GLint texCoordSizes[1] = { 3 };
+ GLint samplerMap [1] = { 0 };
+
+ gpuImmediateFormatReset();
+
+ gpuImmediateElementSizes(3, 0, 4); //-V112
+
+ gpuImmediateTexCoordCount(1);
+ gpuImmediateTexCoordSizes(texCoordSizes);
+
+ gpuImmediateSamplerCount(1);
+ gpuImmediateSamplerMap(samplerMap);
+ }
+
+ gpuImmediateLock();
+}
+
+#if GPU_SAFETY
+void gpuSafetyImmediateUnformat(const char* file, int line)
+#else
+void gpuImmediateUnformat(void)
+#endif
+{
+#if GPU_SAFETY
+ printf("%s(%d): gpuImmediateUnformat\n", file, line);
+#endif
+
+ gpuImmediateUnlock();
+}
+
+
+
+static GPUimmediate* immediateStack = NULL; /* stack size of one */
+
+
+
+void gpuPushImmediate(void)
+{
+ GPUimmediate* newImmediate;
+
+ GPU_CHECK_CAN_PUSH();
+
+ newImmediate = gpuNewImmediate();
+ immediateStack = GPU_IMMEDIATE;
+ GPU_IMMEDIATE = newImmediate;
+}
+
+GPUimmediate* gpuPopImmediate(void)
+{
+ GPUimmediate* newImmediate;
+
+ GPU_CHECK_CAN_POP();
+
+ newImmediate = GPU_IMMEDIATE;
+ GPU_IMMEDIATE = immediateStack;
+ immediateStack = NULL;
+
+ return newImmediate;
+}
+
+
+
+static void gpu_append_client_arrays(
+ const GPUarrays *__restrict arrays,
+ GLint first,
+ GLsizei count)
+{
+ GLsizei i;
+ size_t size;
+ size_t offset;
+
+ GLubyte *__restrict mappedBuffer;
+
+ char *__restrict colorPointer;
+ char *__restrict normalPointer;
+ char *__restrict vertexPointer;
+
+#if GPU_SAFETY
+ {
+ int newVertexCountOK;
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->count + count <= GPU_IMMEDIATE->maxVertexCount, newVertexCountOK,);
+ }
+#endif
+
+ vertexPointer = (char *__restrict)(arrays->vertexPointer) + (first * arrays->vertexStride);
+ normalPointer = (char *__restrict)(arrays->normalPointer) + (first * arrays->normalStride);
+ colorPointer = (char *__restrict)(arrays->colorPointer ) + (first * arrays->colorStride );
+
+ mappedBuffer = GPU_IMMEDIATE->mappedBuffer;
+
+ offset = GPU_IMMEDIATE->offset;
+
+ for (i = 0; i < count; i++) {
+ size = arrays->vertexSize * sizeof(GLfloat);
+ memcpy(mappedBuffer + offset, vertexPointer, size);
+ offset += size;
+ vertexPointer += arrays->vertexStride;
+
+ if (normalPointer) {
+ memcpy(mappedBuffer + offset, normalPointer, 3*sizeof(GLfloat));
+ offset += 3*sizeof(GLfloat);
+ normalPointer += arrays->normalStride;
+ }
+
+ if (colorPointer) {
+ if (arrays->colorType == GL_FLOAT) {
+ GLubyte color[4];
+
+ color[0] = (GLubyte)(colorPointer[0] * 255.0f);
+ color[1] = (GLubyte)(colorPointer[1] * 255.0f);
+ color[2] = (GLubyte)(colorPointer[2] * 255.0f);
+
+ if (arrays->colorSize == 4) {
+ color[3] = (GLubyte)(colorPointer[3] * 255.0f);
+ }
+ else {
+ color[3] = 255;;
+ }
+
+ memcpy(mappedBuffer + offset, color, 4);
+ }
+ else /* assume four GL_UNSIGNED_BYTE */ {
+ memcpy(mappedBuffer + offset, colorPointer, 4);
+ }
+
+ offset += 4;
+ colorPointer += arrays->colorStride;
+ }
+ }
+
+ GPU_IMMEDIATE->offset = offset;
+ GPU_IMMEDIATE->count += count;
+}
+
+
+
+const GPUarrays GPU_ARRAYS_V2F = {
+ 0, /* GLenum colorType; */
+ 0, /* GLint colorSize; */
+ 0, /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ 0, /* GLenum normalType; */
+ 0, /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 2, /* GLint vertexSize; */
+ 2 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_C4UB_V2F = {
+ GL_UNSIGNED_BYTE, /* GLenum colorType; */
+ 4, /* GLint colorSize; */
+ 4, /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ 0, /* GLenum normalType; */
+ 0, /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 2, /* GLint vertexSize; */
+ 2 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_C4UB_V3F = {
+ GL_UNSIGNED_BYTE, /* GLenum colorType; */
+ 4, /* GLint colorSize; */
+ 4, /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ 0, /* GLenum normalType; */
+ 0, /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 3, /* GLint vertexSize; */
+ 3 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_V3F = {
+ 0, /* GLenum colorType; */
+ 0, /* GLint colorSize; */
+ 0, /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ 0, /* GLenum normalType; */
+ 0, /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 3, /* GLint vertexSize; */
+ 3 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_C3F_V3F = {
+ GL_FLOAT, /* GLenum colorType; */
+ 3, /* GLint colorSize; */
+ 3 * sizeof(GLfloat), /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ 0, /* GLenum normalType; */
+ 0, /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 3, /* GLint vertexSize; */
+ 3 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_C4F_V3F = {
+ GL_FLOAT, /* GLenum colorType; */
+ 4, /* GLint colorSize; */
+ 4 * sizeof(GLfloat), /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ 0, /* GLenum normalType; */
+ 0, /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 3, /* GLint vertexSize; */
+ 3 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_N3F_V3F = {
+ 0, /* GLenum colorType; */
+ 0, /* GLint colorSize; */
+ 0, /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ GL_FLOAT, /* GLenum normalType; */
+ 3 * sizeof(GLfloat), /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 3, /* GLint vertexSize; */
+ 3 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+const GPUarrays GPU_ARRAYS_C3F_N3F_V3F = {
+ GL_FLOAT, /* GLenum colorType; */
+ 3, /* GLint colorSize; */
+ 3 * sizeof(GLfloat), /* GLint colorStride; */
+ NULL, /* void* colorPointer; */
+
+ GL_FLOAT, /* GLenum normalType; */
+ 3 * sizeof(GLfloat), /* GLint normalStride; */
+ NULL, /* void* normalPointer; */
+
+ GL_FLOAT, /* GLenum vertexType; */
+ 3, /* GLint vertexSize; */
+ 3 * sizeof(GLfloat), /* GLint vertexStride; */
+ NULL, /* void* vertexPointer; */
+};
+
+
+
+void gpuAppendClientArrays(
+ const GPUarrays* arrays,
+ GLint first,
+ GLsizei count)
+{
+ gpu_append_client_arrays(arrays, first, count);
+}
+
+
+
+void gpuDrawClientArrays(
+ GLenum mode,
+ const GPUarrays *arrays,
+ GLint first,
+ GLsizei count)
+{
+ gpuBegin(mode);
+ gpu_append_client_arrays(arrays, first, count);
+ gpuEnd();
+}
+
+
+
+void gpuSingleClientArrays_V2F(
+ GLenum mode,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_V2F;
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 2*sizeof(GLfloat);
+
+ gpuImmediateFormat_V2();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientArrays_V3F(
+ GLenum mode,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_V3F;
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_V3();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientArrays_C3F_V3F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_C3F_V3F;
+
+ arrays.colorPointer = colorPointer;
+ arrays.colorStride = colorStride != 0 ? colorStride : 3*sizeof(GLfloat);
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_C4_V3();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientArrays_C4F_V3F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_C4F_V3F;
+
+ arrays.colorPointer = colorPointer;
+ arrays.colorStride = colorStride != 0 ? colorStride : 4*sizeof(GLfloat);
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_C4_V3();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientArrays_N3F_V3F(
+ GLenum mode,
+ const void *__restrict normalPointer,
+ GLint normalStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_N3F_V3F;
+
+ arrays.normalPointer = normalPointer;
+ arrays.normalStride = normalStride != 0 ? normalStride : 3*sizeof(GLfloat);
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_N3_V3();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientArrays_C3F_N3F_V3F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict normalPointer,
+ GLint normalStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_C3F_N3F_V3F;
+
+ arrays.colorPointer = colorPointer;
+ arrays.colorStride = colorStride != 0 ? colorStride : 3*sizeof(GLfloat);
+
+ arrays.normalPointer = normalPointer;
+ arrays.normalStride = normalStride != 0 ? normalStride : 3*sizeof(GLfloat);
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_C4_N3_V3();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientArrays_C4UB_V2F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_C4UB_V2F;
+
+ arrays.colorPointer = colorPointer;
+ arrays.colorStride = colorStride != 0 ? colorStride : 4;
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 2*sizeof(GLfloat);
+
+ gpuImmediateFormat_C4_V2();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+
+
+void gpuSingleClientArrays_C4UB_V3F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLint first,
+ GLsizei count)
+{
+ GPUarrays arrays = GPU_ARRAYS_C4UB_V3F;
+
+ arrays.colorPointer = colorPointer;
+ arrays.colorStride = colorStride != 0 ? colorStride : 4;
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_C4_V3();
+ gpuDrawClientArrays(mode, &arrays, first, count);
+ gpuImmediateUnformat();
+}
+
+
+
+void gpuImmediateIndexRange(GLuint indexMin, GLuint indexMax)
+{
+ GPU_IMMEDIATE->index->indexMin = indexMin;
+ GPU_IMMEDIATE->index->indexMax = indexMax;
+}
+
+
+
+#define FIND_RANGE(suffix, ctype) \
+ static void find_range_##suffix( \
+ GLuint *__restrict arrayFirst, \
+ GLuint *__restrict arrayLast, \
+ GLsizei count, \
+ const ctype *__restrict indexes) \
+{ \
+ int i; \
+ \
+ GPU_ASSERT(count > 0); \
+ \
+ *arrayFirst = indexes[0]; \
+ *arrayLast = indexes[0]; \
+ \
+ for (i = 1; i < count; i++) { \
+ if (indexes[i] < *arrayFirst) { \
+ *arrayFirst = indexes[i]; \
+ } \
+ else if (indexes[i] > *arrayLast) { \
+ *arrayLast = indexes[i]; \
+ } \
+ } \
+}
+
+FIND_RANGE(ub, GLubyte )
+FIND_RANGE(us, GLushort)
+FIND_RANGE(ui, GLuint )
+
+
+
+void gpuImmediateIndexComputeRange(void)
+{
+ GLuint indexMin, indexMax;
+
+ GPUindex* index = GPU_IMMEDIATE->index;
+
+ switch (index->type) {
+ case GL_UNSIGNED_BYTE:
+ find_range_ub(&indexMin, &indexMax, index->count, (GLubyte* )(index->mappedBuffer));
+ break;
+
+ case GL_UNSIGNED_SHORT:
+ find_range_us(&indexMin, &indexMax, index->count, (GLushort*)(index->mappedBuffer));
+ break;
+
+ case GL_UNSIGNED_INT:
+ find_range_ui(&indexMin, &indexMax, index->count, (GLuint* )(index->mappedBuffer));
+ break;
+
+ default:
+ GPU_ABORT();
+ return;
+ }
+
+ gpuImmediateIndexRange(indexMin, indexMax);
+}
+
+
+
+void gpuSingleClientElements_V3F(
+ GLenum mode,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GLuint indexMin, indexMax;
+
+ find_range_ui(&indexMin, &indexMax, count, indexes);
+
+ gpuSingleClientRangeElements_V3F(
+ mode,
+ vertexPointer,
+ vertexStride,
+ indexMin,
+ indexMax,
+ count,
+ indexes);
+}
+
+void gpuSingleClientElements_N3F_V3F(
+ GLenum mode,
+ const void *__restrict normalPointer,
+ GLint normalStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GLuint indexMin, indexMax;
+
+ find_range_ui(&indexMin, &indexMax, count, indexes);
+
+ gpuSingleClientRangeElements_N3F_V3F(
+ mode,
+ normalPointer,
+ normalStride,
+ vertexPointer,
+ vertexStride,
+ indexMin,
+ indexMax,
+ count,
+ indexes);
+}
+
+void gpuSingleClientElements_C4UB_V3F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GLuint indexMin, indexMax;
+
+ find_range_ui(&indexMin, &indexMax, count, indexes);
+
+ gpuSingleClientRangeElements_C4UB_V3F(
+ mode,
+ colorPointer,
+ colorStride,
+ vertexPointer,
+ vertexStride,
+ indexMin,
+ indexMax,
+ count,
+ indexes);
+}
+
+
+
+void gpuDrawClientRangeElements(
+ GLenum mode,
+ const GPUarrays *__restrict arrays,
+ GLuint indexMin,
+ GLuint indexMax,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GLuint indexRange = indexMax - indexMin + 1;
+
+ gpuBegin(GL_NOOP);
+ gpuAppendClientArrays(arrays, indexMin, indexRange);
+ gpuEnd();
+
+ gpuIndexBegin(GL_UNSIGNED_INT);
+ gpuIndexRelativeuiv(indexRange + indexMin, count, indexes);
+ gpuIndexEnd();
+
+ gpuImmediateIndexRange(indexMin, indexMax);
+
+ GPU_IMMEDIATE->mode = mode;
+ gpu_draw_range_elements_gl();
+}
+
+void gpuSingleClientRangeElements_V3F(
+ GLenum mode,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLuint indexMin,
+ GLuint indexMax,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GPUarrays arrays = GPU_ARRAYS_V3F;
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_V3();
+ gpuDrawClientRangeElements(mode, &arrays, indexMin, indexMax, count, indexes);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientRangeElements_N3F_V3F(
+ GLenum mode,
+ const void *__restrict normalPointer,
+ GLint normalStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLuint indexMin,
+ GLuint indexMax,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GPUarrays arrays = GPU_ARRAYS_N3F_V3F;
+
+ arrays.normalPointer = normalPointer;
+ arrays.normalStride = normalStride != 0 ? normalStride : 3*sizeof(GLfloat);
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_N3_V3();
+ gpuDrawClientRangeElements(mode, &arrays, indexMin, indexMax, count, indexes);
+ gpuImmediateUnformat();
+}
+
+void gpuSingleClientRangeElements_C4UB_V3F(
+ GLenum mode,
+ const void *__restrict colorPointer,
+ GLint colorStride,
+ const void *__restrict vertexPointer,
+ GLint vertexStride,
+ GLuint indexMin,
+ GLuint indexMax,
+ GLsizei count,
+ const GLuint *__restrict indexes)
+{
+ GPUarrays arrays = GPU_ARRAYS_C4UB_V3F;
+
+ arrays.normalPointer = colorPointer;
+ arrays.normalStride = colorStride != 0 ? colorStride : 4*sizeof(GLubyte);
+
+ arrays.vertexPointer = vertexPointer;
+ arrays.vertexStride = vertexStride != 0 ? vertexStride : 3*sizeof(GLfloat);
+
+ gpuImmediateFormat_C4_V3();
+ gpuDrawClientRangeElements(mode, &arrays, indexMin, indexMax, count, indexes);
+ gpuImmediateUnformat();
+}
+
+
+
+GPUindex* gpuNewIndex(void)
+{
+ return (GPUindex*)MEM_callocN(sizeof(GPUindex), "GPUindex");
+}
+
+
+
+void gpuDeleteIndex(GPUindex *__restrict index)
+{
+ if (index) {
+ GPUimmediate* immediate = index->immediate;
+
+ gpu_index_shutdown_buffer_gl(index);
+ immediate->index = NULL;
+
+ MEM_freeN(index);
+ }
+}
+
+
+
+void gpuImmediateIndex(GPUindex * index)
+{
+ //GPU_ASSERT(GPU_IMMEDIATE->index == NULL);
+
+ if (index)
+ index->immediate = GPU_IMMEDIATE;
+
+ GPU_IMMEDIATE->index = index;
+}
+
+
+
+GPUindex* gpuGetImmediateIndex()
+{
+ return GPU_IMMEDIATE->index;
+}
+
+
+
+void gpuImmediateMaxIndexCount(GLsizei maxIndexCount, GLenum type)
+{
+ GPU_ASSERT(GPU_IMMEDIATE);
+ GPU_ASSERT(GPU_IMMEDIATE->index);
+
+ GPU_IMMEDIATE->index->maxIndexCount = maxIndexCount;
+ GPU_IMMEDIATE->index->type = type;
+}
+
+
+
+void gpuIndexBegin(GLenum type)
+{
+ GPUindex* index;
+
+ GPU_ASSERT(ELEM3(type, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT));
+
+ index = GPU_IMMEDIATE->index;
+
+ index->count = 0;
+ index->indexMin = 0;
+ index->indexMax = 0;
+ index->type = type;
+
+ gpu_index_begin_buffer_gl();
+}
+
+
+
+#define INDEX_RELATIVE(suffix, ctype, glsymbol) \
+void gpuIndexRelative##suffix(GLint offset, GLsizei count, const ctype *__restrict indexes) \
+{ \
+ int i; \
+ int start; \
+ int indexStart; \
+ GPUindex* index; \
+ \
+ GPU_ASSERT(GPU_IMMEDIATE); \
+ GPU_ASSERT(GPU_IMMEDIATE->index); \
+ GPU_ASSERT(GPU_IMMEDIATE->index->type == glsymbol); \
+ \
+ { \
+ GLboolean indexCountOK; \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->index->count + count <= GPU_IMMEDIATE->index->maxIndexCount, indexCountOK,); \
+ } \
+ \
+ start = GPU_IMMEDIATE->count; \
+ index = GPU_IMMEDIATE->index; \
+ indexStart = index->count; \
+ \
+ for (i = 0; i < count; i++) { \
+ ((ctype*)(index->mappedBuffer))[indexStart+i] = start - offset + ((ctype*)indexes)[i]; \
+ } \
+ \
+ index->count += count; \
+ index->offset = count*sizeof(ctype); \
+}
+
+INDEX_RELATIVE(ubv, GLubyte, GL_UNSIGNED_BYTE )
+INDEX_RELATIVE(usv, GLushort, GL_UNSIGNED_SHORT)
+INDEX_RELATIVE(uiv, GLuint, GL_UNSIGNED_INT )
+
+
+
+#define INDEX(suffix, ctype, glsymbol) \
+void gpuIndex##suffix(ctype nextIndex) \
+{ \
+ GPUindex* index; \
+ \
+ GPU_ASSERT(GPU_IMMEDIATE); \
+ GPU_ASSERT(GPU_IMMEDIATE->index); \
+ GPU_ASSERT(GPU_IMMEDIATE->index->type == glsymbol); \
+ \
+ { \
+ GLboolean indexCountOK; \
+ GPU_SAFE_RETURN(GPU_IMMEDIATE->index->count < GPU_IMMEDIATE->index->maxIndexCount, indexCountOK,); \
+ } \
+ \
+ index = GPU_IMMEDIATE->index; \
+ ((ctype*)(index->mappedBuffer))[index->count] = nextIndex; \
+ index->count++; \
+ index->offset += sizeof(ctype); \
+}
+
+INDEX(ub, GLubyte, GL_UNSIGNED_BYTE )
+INDEX(us, GLushort, GL_UNSIGNED_SHORT)
+INDEX(ui, GLuint, GL_UNSIGNED_INT )
+
+
+
+void gpuIndexEnd(void)
+{
+ gpu_index_end_buffer_gl();
+
+ GPU_IMMEDIATE->index->mappedBuffer = NULL;
+}