#include <string.h>
+#include <assert.h>
+
+#include <algorithm>
#include "os.hpp"
#include "glimports.hpp"
}
static inline size_t
-_glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei maxIndex)
+_glArrayPointer_size(GLint size, GLenum type, GLsizei stride, GLsizei count)
{
+ if (!count) {
+ return 0;
+ }
+
+ if (size == GL_BGRA) {
+ size = 4;
+ }
+
+ if (size > 4) {
+ os::log("apitrace: warning: %s: unexpected size 0x%04X\n", __FUNCTION__, size);
+ }
+
size_t elementSize = size*_gl_type_size(type);
if (!stride) {
stride = (GLsizei)elementSize;
}
- return stride*maxIndex + elementSize;
+
+ return stride*(count - 1) + elementSize;
}
-#define _glVertexPointer_size(size, type, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
-#define _glNormalPointer_size(type, stride, maxIndex) _glArrayPointer_size(3, type, stride, maxIndex)
-#define _glColorPointer_size(size, type, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
-#define _glIndexPointer_size(type, stride, maxIndex) _glArrayPointer_size(1, type, stride, maxIndex)
-#define _glTexCoordPointer_size(size, type, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
-#define _glEdgeFlagPointer_size(stride, maxIndex) _glArrayPointer_size(1, GL_BOOL, stride, maxIndex)
-#define _glFogCoordPointer_size(type, stride, maxIndex) _glArrayPointer_size(1, type, stride, maxIndex)
-#define _glSecondaryColorPointer_size(size, type, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
-#define _glVertexAttribPointer_size(size, type, normalized, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
-#define _glVertexAttribPointerARB_size(size, type, normalized, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
-#define _glVertexAttribPointerNV_size(size, type, stride, maxIndex) _glArrayPointer_size(size, type, stride, maxIndex)
+#define _glVertexPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
+#define _glNormalPointer_size(type, stride, count) _glArrayPointer_size(3, type, stride, count)
+#define _glColorPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
+#define _glIndexPointer_size(type, stride, count) _glArrayPointer_size(1, type, stride, count)
+#define _glTexCoordPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
+#define _glEdgeFlagPointer_size(stride, count) _glArrayPointer_size(1, GL_BOOL, stride, count)
+#define _glFogCoordPointer_size(type, stride, count) _glArrayPointer_size(1, type, stride, count)
+#define _glSecondaryColorPointer_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
+#define _glVertexAttribPointer_size(size, type, normalized, stride, count) _glArrayPointer_size(size, type, stride, count)
+#define _glVertexAttribPointerARB_size(size, type, normalized, stride, count) _glArrayPointer_size(size, type, stride, count)
+#define _glVertexAttribPointerNV_size(size, type, stride, count) _glArrayPointer_size(size, type, stride, count)
+
+/**
+ * Same as glGetIntegerv, but passing the result in the return value.
+ */
+static inline GLint
+_glGetInteger(GLenum pname) {
+ GLint param = 0;
+ _glGetIntegerv(pname, ¶m);
+ return param;
+}
+
+static inline GLint
+_element_array_buffer_binding(void) {
+ return _glGetInteger(GL_ELEMENT_ARRAY_BUFFER_BINDING);
+}
static inline GLuint
-_glDrawArrays_maxindex(GLint first, GLsizei count)
+_glDrawArrays_count(GLint first, GLsizei count)
{
if (!count) {
return 0;
}
- return first + count - 1;
+ return first + count;
}
-#define _glDrawArraysEXT_maxindex _glDrawArrays_maxindex
+#define _glDrawArraysEXT_count _glDrawArrays_count
+
+/* Forward declaration for definition in gltrace.py */
+void
+_shadow_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
+ GLvoid *data);
static inline GLuint
-_glDrawElementsBaseVertex_maxindex(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex)
+_glDrawElementsBaseVertex_count(GLsizei count, GLenum type, const GLvoid *indices, GLint basevertex)
{
GLvoid *temp = 0;
- GLint element_array_buffer = 0;
if (!count) {
return 0;
}
- _glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &element_array_buffer);
+ GLint element_array_buffer = _element_array_buffer_binding();
if (element_array_buffer) {
// Read indices from index buffer object
GLintptr offset = (GLintptr)indices;
return 0;
}
memset(temp, 0, size);
- _glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp);
+ _shadow_glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, offset, size, temp);
indices = temp;
} else {
if (!indices) {
maxindex += basevertex;
- return maxindex;
+ return maxindex + 1;
}
-#define _glDrawRangeElementsBaseVertex_maxindex(start, end, count, type, indices, basevertex) _glDrawElementsBaseVertex_maxindex(count, type, indices, basevertex)
+#define _glDrawRangeElementsBaseVertex_count(start, end, count, type, indices, basevertex) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
-#define _glDrawElements_maxindex(count, type, indices) _glDrawElementsBaseVertex_maxindex(count, type, indices, 0);
-#define _glDrawRangeElements_maxindex(start, end, count, type, indices) _glDrawElements_maxindex(count, type, indices)
-#define _glDrawRangeElementsEXT_maxindex _glDrawRangeElements_maxindex
+#define _glDrawElements_count(count, type, indices) _glDrawElementsBaseVertex_count(count, type, indices, 0);
+#define _glDrawRangeElements_count(start, end, count, type, indices) _glDrawElements_count(count, type, indices)
+#define _glDrawRangeElementsEXT_count _glDrawRangeElements_count
/* FIXME take in consideration instancing */
-#define _glDrawArraysInstanced_maxindex(first, count, primcount) _glDrawArrays_maxindex(first, count)
-#define _glDrawElementsInstanced_maxindex(count, type, indices, primcount) _glDrawElements_maxindex(count, type, indices)
-#define _glDrawElementsInstancedBaseVertex_maxindex(count, type, indices, primcount, basevertex) _glDrawElementsBaseVertex_maxindex(count, type, indices, basevertex)
-#define _glDrawRangeElementsInstanced_maxindex(start, end, count, type, indices, primcount) _glDrawRangeElements_maxindex(start, end, count, type, indices)
-#define _glDrawRangeElementsInstancedBaseVertex_maxindex(start, end, count, type, indices, primcount, basevertex) _glDrawRangeElementsBaseVertex_maxindex(start, end, count, type, indices, basevertex)
+#define _glDrawArraysInstanced_count(first, count, primcount) _glDrawArrays_count(first, count)
+#define _glDrawElementsInstanced_count(count, type, indices, primcount) _glDrawElements_count(count, type, indices)
+#define _glDrawElementsInstancedBaseVertex_count(count, type, indices, primcount, basevertex) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
+#define _glDrawRangeElementsInstanced_count(start, end, count, type, indices, primcount) _glDrawRangeElements_count(start, end, count, type, indices)
+#define _glDrawRangeElementsInstancedBaseVertex_count(start, end, count, type, indices, primcount, basevertex) _glDrawRangeElementsBaseVertex_count(start, end, count, type, indices, basevertex)
+
+#define _glDrawArraysInstancedBaseInstance_count(first, count, primcount, baseinstance) _glDrawArrays_count(first, count)
+#define _glDrawElementsInstancedBaseInstance_count(count, type, indices, primcount, baseinstance) _glDrawElements_count(count, type, indices)
+#define _glDrawElementsInstancedBaseVertexBaseInstance_count(count, type, indices, primcount, basevertex, baseinstance) _glDrawElementsBaseVertex_count(count, type, indices, basevertex)
+
+#define _glDrawArraysInstancedARB_count _glDrawArraysInstanced_count
+#define _glDrawElementsInstancedARB_count _glDrawElementsInstanced_count
+#define _glDrawArraysInstancedEXT_count _glDrawArraysInstanced_count
+#define _glDrawElementsInstancedEXT_count _glDrawElementsInstanced_count
+
+typedef struct {
+ GLuint count;
+ GLuint primCount;
+ GLuint first;
+ GLuint baseInstance;
+} DrawArraysIndirectCommand;
+
+static inline GLuint
+_glMultiDrawArraysIndirect_count(const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
+ const DrawArraysIndirectCommand *cmd;
+ GLvoid *temp = 0;
-#define _glDrawArraysInstancedBaseInstance_maxindex(first, count, primcount, baseinstance) _glDrawArrays_maxindex(first, count)
-#define _glDrawElementsInstancedBaseInstance_maxindex(count, type, indices, primcount, baseinstance) _glDrawElements_maxindex(count, type, indices)
-#define _glDrawElementsInstancedBaseVertexBaseInstance_maxindex(count, type, indices, primcount, basevertex, baseinstance) _glDrawElementsBaseVertex_maxindex(count, type, indices, basevertex)
+ if (drawcount <= 0) {
+ return 0;
+ }
+
+ if (stride == 0) {
+ stride = sizeof *cmd;
+ }
+
+ GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
+ if (draw_indirect_buffer) {
+ // Read commands from indirect buffer object
+ GLintptr offset = (GLintptr)indirect;
+ GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
+ GLvoid *temp = malloc(size);
+ if (!temp) {
+ return 0;
+ }
+ memset(temp, 0, size);
+ _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
+ indirect = temp;
+ } else {
+ if (!indirect) {
+ return 0;
+ }
+ }
-#define _glDrawArraysInstancedARB_maxindex _glDrawArraysInstanced_maxindex
-#define _glDrawElementsInstancedARB_maxindex _glDrawElementsInstanced_maxindex
-#define _glDrawArraysInstancedEXT_maxindex _glDrawArraysInstanced_maxindex
-#define _glDrawElementsInstancedEXT_maxindex _glDrawElementsInstanced_maxindex
+ GLuint count = 0;
+ for (GLsizei i = 0; i < drawcount; ++i) {
+ cmd = (const DrawArraysIndirectCommand *)((const GLbyte *)indirect + i * stride);
+
+ GLuint count_i = _glDrawArraysInstancedBaseInstance_count(
+ cmd->first,
+ cmd->count,
+ cmd->primCount,
+ cmd->baseInstance
+ );
+
+ count = std::max(count, count_i);
+ }
+
+ if (draw_indirect_buffer) {
+ free(temp);
+ }
+
+ return count;
+}
static inline GLuint
-_glDrawArraysIndirect_maxindex(const GLvoid *indirect) {
- os::log("apitrace: warning: %s: unsupported\n", __FUNCTION__);
- return 0;
+_glDrawArraysIndirect_count(const GLvoid *indirect) {
+ return _glMultiDrawArraysIndirect_count(indirect, 1, 0);
}
+typedef struct {
+ GLuint count;
+ GLuint primCount;
+ GLuint firstIndex;
+ GLuint baseVertex;
+ GLuint baseInstance;
+} DrawElementsIndirectCommand;
+
static inline GLuint
-_glDrawElementsIndirect_maxindex(GLenum type, const GLvoid *indirect) {
- os::log("apitrace: warning: %s: unsupported\n", __FUNCTION__);
- return 0;
+_glMultiDrawElementsIndirect_count(GLenum type, const GLvoid *indirect, GLsizei drawcount, GLsizei stride) {
+ const DrawElementsIndirectCommand *cmd;
+ GLvoid *temp = 0;
+
+ if (drawcount <= 0) {
+ return 0;
+ }
+
+ if (stride == 0) {
+ stride = sizeof *cmd;
+ }
+
+ GLint draw_indirect_buffer = _glGetInteger(GL_DRAW_INDIRECT_BUFFER_BINDING);
+ if (draw_indirect_buffer) {
+ // Read commands from indirect buffer object
+ GLintptr offset = (GLintptr)indirect;
+ GLsizeiptr size = sizeof *cmd + (drawcount - 1) * stride;
+ GLvoid *temp = malloc(size);
+ if (!temp) {
+ return 0;
+ }
+ memset(temp, 0, size);
+ _glGetBufferSubData(GL_DRAW_INDIRECT_BUFFER, offset, size, temp);
+ indirect = temp;
+ } else {
+ if (!indirect) {
+ return 0;
+ }
+ }
+
+ cmd = (const DrawElementsIndirectCommand *)indirect;
+
+ GLuint count = 0;
+ for (GLsizei i = 0; i < drawcount; ++i) {
+ cmd = (const DrawElementsIndirectCommand *)((const GLbyte *)indirect + i * stride);
+
+ GLuint count_i = _glDrawElementsInstancedBaseVertexBaseInstance_count(
+ cmd->count,
+ type,
+ (GLvoid *)(uintptr_t)(cmd->firstIndex * _gl_type_size(type)),
+ cmd->primCount,
+ cmd->baseVertex,
+ cmd->baseInstance
+ );
+
+ count = std::max(count, count_i);
+ }
+
+ if (draw_indirect_buffer) {
+ free(temp);
+ }
+
+ return count;
}
static inline GLuint
-_glMultiDrawArrays_maxindex(const GLint *first, const GLsizei *count, GLsizei primcount) {
- GLuint maxindex = 0;
- for (GLsizei prim = 0; prim < primcount; ++prim) {
- GLuint maxindex_prim = _glDrawArrays_maxindex(first[prim], count[prim]);
- maxindex = std::max(maxindex, maxindex_prim);
+_glDrawElementsIndirect_count(GLenum type, const GLvoid *indirect) {
+ return _glMultiDrawElementsIndirect_count(type, indirect, 1, 0);
+}
+
+#define _glMultiDrawArraysIndirectAMD_count _glMultiDrawArraysIndirect_count
+#define _glMultiDrawElementsIndirectAMD_count _glMultiDrawElementsIndirect_count
+
+static inline GLuint
+_glMultiDrawArrays_count(const GLint *first, const GLsizei *count, GLsizei drawcount) {
+ GLuint _count = 0;
+ for (GLsizei draw = 0; draw < drawcount; ++draw) {
+ GLuint _count_draw = _glDrawArrays_count(first[draw], count[draw]);
+ _count = std::max(_count, _count_draw);
}
- return maxindex;
+ return _count;
}
static inline GLuint
-_glMultiDrawElements_maxindex(const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount) {
- GLuint maxindex = 0;
- for (GLsizei prim = 0; prim < primcount; ++prim) {
- GLuint maxindex_prim = _glDrawElements_maxindex(count[prim], type, indices[prim]);
- maxindex = std::max(maxindex, maxindex_prim);
+_glMultiDrawElements_count(const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount) {
+ GLuint _count = 0;
+ for (GLsizei draw = 0; draw < drawcount; ++draw) {
+ GLuint _count_draw = _glDrawElements_count(count[draw], type, indices[draw]);
+ _count = std::max(_count, _count_draw);
}
- return maxindex;
+ return _count;
}
static inline GLuint
-_glMultiDrawElementsBaseVertex_maxindex(const GLsizei *count, GLenum type, const GLvoid* *indices, GLsizei primcount, const GLint * basevertex) {
- GLuint maxindex = 0;
- for (GLsizei prim = 0; prim < primcount; ++prim) {
- GLuint maxindex_prim = _glDrawElementsBaseVertex_maxindex(count[prim], type, indices[prim], basevertex[prim]);
- maxindex = std::max(maxindex, maxindex_prim);
+_glMultiDrawElementsBaseVertex_count(const GLsizei *count, GLenum type, const GLvoid* const *indices, GLsizei drawcount, const GLint * basevertex) {
+ GLuint _count = 0;
+ for (GLsizei draw = 0; draw < drawcount; ++draw) {
+ GLuint _count_draw = _glDrawElementsBaseVertex_count(count[draw], type, indices[draw], basevertex[draw]);
+ _count = std::max(_count, _count_draw);
}
- return maxindex;
+ return _count;
}
-#define _glMultiDrawArraysEXT_maxindex _glMultiDrawArrays_maxindex
-#define _glMultiDrawElementsEXT_maxindex _glMultiDrawElements_maxindex
+#define _glMultiDrawArraysEXT_count _glMultiDrawArrays_count
+#define _glMultiDrawElementsEXT_count _glMultiDrawElements_count
-#define _glMultiModeDrawArraysIBM_maxindex(first, count, primcount, modestride) _glMultiDrawArrays_maxindex(first, count, primcount)
-#define _glMultiModeDrawElementsIBM_maxindex(count, type, indices, primcount, modestride) _glMultiDrawElements_maxindex(count, type, (const GLvoid **)indices, primcount)
+#define _glMultiModeDrawArraysIBM_count(first, count, drawcount, modestride) _glMultiDrawArrays_count(first, count, drawcount)
+#define _glMultiModeDrawElementsIBM_count(count, type, indices, drawcount, modestride) _glMultiDrawElements_count(count, type, (const GLvoid **)indices, drawcount)
static inline size_t
#define _glMap2f_size _glMap2d_size
+/**
+ * Number of channels in this format.
+ *
+ * That is, the number of elements per pixel when this format is passed with a
+ * to DrawPixels, ReadPixels, TexImage*, TexSubImage*, GetTexImage, etc.
+ */
static inline unsigned
_gl_format_channels(GLenum format) {
switch (format) {
case GL_COLOR_INDEX:
case GL_RED:
+ case GL_RED_INTEGER:
case GL_GREEN:
+ case GL_GREEN_INTEGER:
case GL_BLUE:
+ case GL_BLUE_INTEGER:
case GL_ALPHA:
+ case GL_ALPHA_INTEGER:
case GL_INTENSITY:
case GL_LUMINANCE:
+ case GL_LUMINANCE_INTEGER_EXT:
case GL_DEPTH_COMPONENT:
case GL_STENCIL_INDEX:
return 1;
case GL_DEPTH_STENCIL:
case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA_INTEGER_EXT:
case GL_RG:
- case GL_HILO_NV:
- case GL_DSDT_NV:
+ case GL_RG_INTEGER:
+ case GL_422_EXT: // (luminance, chrominance)
+ case GL_422_REV_EXT: // (luminance, chrominance)
+ case GL_422_AVERAGE_EXT: // (luminance, chrominance)
+ case GL_422_REV_AVERAGE_EXT: // (luminance, chrominance)
+ case GL_HILO_NV: // (hi, lo)
+ case GL_DSDT_NV: // (ds, dt)
+ case GL_YCBCR_422_APPLE: // (luminance, chroma)
+ case GL_RGB_422_APPLE: // (G, B) on even pixels, (G, R) on odd pixels
+ case GL_YCRCB_422_SGIX: // (Y, [Cb,Cr])
return 2;
case GL_RGB:
+ case GL_RGB_INTEGER:
case GL_BGR:
- case GL_DSDT_MAG_NV:
+ case GL_BGR_INTEGER:
+ case GL_DSDT_MAG_NV: // (ds, dt, magnitude)
+ case GL_YCRCB_444_SGIX: // (Cb, Y, Cr)
return 3;
case GL_RGBA:
+ case GL_RGBA_INTEGER:
case GL_BGRA:
+ case GL_BGRA_INTEGER:
case GL_ABGR_EXT:
case GL_CMYK_EXT:
- case GL_DSDT_MAG_VIB_NV:
+ case GL_DSDT_MAG_VIB_NV: // (ds, dt, magnitude, vibrance)
return 4;
case GL_CMYKA_EXT:
return 5;
+ case GL_FORMAT_SUBSAMPLE_24_24_OML:
+ case GL_FORMAT_SUBSAMPLE_244_244_OML:
+ // requires UNSIGNED_INT_10_10_10_2, so this value will be ignored
+ return 0;
default:
os::log("apitrace: warning: %s: unexpected format GLenum 0x%04X\n", __FUNCTION__, format);
return 0;
return (x + (y - 1)) & ~(y - 1);
}
-static inline size_t
-_gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) {
+static inline void
+_gl_format_size(GLenum format, GLenum type,
+ unsigned & bits_per_element, unsigned & bits_per_pixel)
+{
unsigned num_channels = _gl_format_channels(format);
- unsigned bits_per_pixel;
switch (type) {
case GL_BITMAP:
- bits_per_pixel = 1;
+ bits_per_pixel = bits_per_element = 1;
break;
case GL_BYTE:
case GL_UNSIGNED_BYTE:
- bits_per_pixel = 8 * num_channels;
+ bits_per_element = 8;
+ bits_per_pixel = bits_per_element * num_channels;
break;
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_HALF_FLOAT:
- bits_per_pixel = 16 * num_channels;
+ bits_per_element = 16;
+ bits_per_pixel = bits_per_element * num_channels;
break;
case GL_INT:
case GL_UNSIGNED_INT:
case GL_FLOAT:
- bits_per_pixel = 32 * num_channels;
+ bits_per_element = 32;
+ bits_per_pixel = bits_per_element * num_channels;
break;
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_BYTE_2_3_3_REV:
- bits_per_pixel = 8;
+ bits_per_pixel = bits_per_element = 8;
break;
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_UNSIGNED_SHORT_8_8_MESA:
case GL_UNSIGNED_SHORT_8_8_REV_MESA:
- bits_per_pixel = 16;
+ bits_per_pixel = bits_per_element = 16;
break;
case GL_UNSIGNED_INT_8_8_8_8:
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_INT_5_9_9_9_REV:
case GL_UNSIGNED_INT_S8_S8_8_8_NV:
case GL_UNSIGNED_INT_8_8_S8_S8_REV_NV:
- bits_per_pixel = 32;
+ bits_per_pixel = bits_per_element = 32;
break;
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
- bits_per_pixel = 64;
+ bits_per_pixel = bits_per_element = 64;
break;
default:
os::log("apitrace: warning: %s: unexpected type GLenum 0x%04X\n", __FUNCTION__, type);
- bits_per_pixel = 0;
+ bits_per_pixel = bits_per_element = 0;
break;
}
+}
+
+static inline size_t
+_glClearBufferData_size(GLenum format, GLenum type) {
+ unsigned bits_per_element;
+ unsigned bits_per_pixel;
+ _gl_format_size(format, type, bits_per_element, bits_per_pixel);
+ return (bits_per_pixel + 7)/8;
+}
+
+static inline size_t
+_gl_image_size(GLenum format, GLenum type, GLsizei width, GLsizei height, GLsizei depth, GLboolean has_unpack_subimage) {
+
+ unsigned bits_per_element;
+ unsigned bits_per_pixel;
+ _gl_format_size(format, type, bits_per_element, bits_per_pixel);
GLint alignment = 4;
GLint row_length = 0;
size_t row_stride = (row_length*bits_per_pixel + 7)/8;
- if ((GLint)bits_per_pixel < alignment*8 &&
- (bits_per_pixel & 7) == 0 &&
- _is_pot(bits_per_pixel)) {
+ if ((bits_per_element == 1*8 ||
+ bits_per_element == 2*8 ||
+ bits_per_element == 4*8 ||
+ bits_per_element == 8*8) &&
+ (GLint)bits_per_element < alignment*8) {
row_stride = _align(row_stride, alignment);
}
}
}
-/*
- * attribute list, terminated by the given terminator.
- */
-template<class T>
static inline size_t
-_AttribList_size(const T *pAttribList, const T terminator = static_cast<T>(0))
+_glPath_coords_size(GLsizei numCoords, GLenum coordType)
{
- size_t size = 0;
+ switch (coordType) {
+ case GL_BYTE:
+ return numCoords * sizeof(GLbyte);
+ case GL_UNSIGNED_BYTE:
+ return numCoords * sizeof(GLubyte);
+ case GL_SHORT:
+ return numCoords * sizeof(GLshort);
+ case GL_UNSIGNED_SHORT:
+ return numCoords * sizeof(GLushort);
+ case GL_FLOAT:
+ return numCoords * sizeof(GLfloat);
+ default:
+ return 0;
+ }
+}
- if (pAttribList) {
- do {
- ++size;
- } while (*pAttribList++ != terminator);
+static inline size_t
+_glPath_fontName_size(GLenum fontTarget, const void *fontName)
+{
+ switch (fontTarget) {
+ case GL_STANDARD_FONT_NAME_NV:
+ case GL_SYSTEM_FONT_NAME_NV:
+ case GL_FILE_NAME_NV:
+ {
+ // Include +1 to copy nul terminator.
+ GLsizei size = GLsizei(strlen(reinterpret_cast<const char*>(fontName))+1);
+ return size;
+ }
+ default:
+ return 0;
}
+}
- return size;
+static inline size_t
+_glPath_chardcodes_size(GLsizei numGlyphs, GLenum type)
+{
+ GLsizei bytes_per_glyph;
+ switch (type) {
+ case GL_FLOAT:
+ case GL_INT:
+ bytes_per_glyph = 4;
+ break;
+ case GL_BYTE:
+ bytes_per_glyph = 1;
+ break;
+ case GL_SHORT:
+ bytes_per_glyph = 2;
+ break;
+ default:
+ return 0;
+ }
+ return bytes_per_glyph*numGlyphs;
+}
+
+static GLsizei floatPerTransformList(GLenum transformType)
+{
+ switch (transformType) {
+ case GL_NONE:
+ return 0;
+ case GL_TRANSLATE_X_NV:
+ case GL_TRANSLATE_Y_NV:
+ return 1;
+ case GL_TRANSLATE_2D_NV:
+ return 2;
+ case GL_TRANSLATE_3D_NV:
+ return 3;
+ case GL_AFFINE_2D_NV:
+ case GL_TRANSPOSE_AFFINE_2D_NV:
+ return 6;
+ case GL_PROJECTIVE_2D_NV:
+ case GL_TRANSPOSE_PROJECTIVE_2D_NV:
+ return 9;
+ case GL_AFFINE_3D_NV:
+ case GL_TRANSPOSE_AFFINE_3D_NV:
+ return 12;
+ case GL_PROJECTIVE_3D_NV:
+ case GL_TRANSPOSE_PROJECTIVE_3D_NV:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+static inline size_t
+_gl_transformType_size(GLenum transformType)
+{
+ return floatPerTransformList(transformType)*sizeof(GLfloat);
+}
+
+static inline size_t
+_gl_transformType_size(GLsizei numPaths, GLenum transformType)
+{
+ return numPaths*floatPerTransformList(transformType)*sizeof(GLfloat);
+}
+
+static size_t valuesPerPathParameter(GLenum pname)
+{
+ switch (pname) {
+ case GL_PATH_FILL_MODE_NV:
+ case GL_PATH_FILL_MASK_NV:
+ case GL_PATH_FILL_COVER_MODE_NV:
+ case GL_PATH_STROKE_WIDTH_NV:
+ case GL_PATH_INITIAL_END_CAP_NV:
+ case GL_PATH_TERMINAL_END_CAP_NV:
+ case GL_PATH_JOIN_STYLE_NV:
+ case GL_PATH_MITER_LIMIT_NV:
+ case GL_PATH_INITIAL_DASH_CAP_NV:
+ case GL_PATH_TERMINAL_DASH_CAP_NV:
+ case GL_PATH_DASH_OFFSET_NV:
+ case GL_PATH_DASH_OFFSET_RESET_NV:
+ case GL_PATH_CLIENT_LENGTH_NV:
+ case GL_PATH_STROKE_COVER_MODE_NV:
+ case GL_PATH_STROKE_MASK_NV:
+ case GL_PATH_STROKE_OVERSAMPLE_COUNT_NV:
+ case GL_PATH_SAMPLE_QUALITY_NV:
+ case GL_PATH_END_CAPS_NV: // not valid for glGetPathParameter
+ case GL_PATH_DASH_CAPS_NV: // not valid for glGetPathParameter
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline size_t
+_gl_PathParameter_size(GLenum pname)
+{
+ return valuesPerPathParameter(pname);
+}
+
+// See RFC-3629 "UTF-8, a transformation format of ISO 10646"
+// http://www.rfc-editor.org/rfc/rfc3629.txt
+// http://rfc-ref.org/RFC-TEXTS/3629/index.html
+static bool
+__glPathGetCodePointUTF8(const void *&utf_string,
+ GLuint &code_point)
+{
+ const GLubyte *p = reinterpret_cast<const GLubyte*>(utf_string);
+ GLubyte c0 = p[0];
+ if ((c0 & 0x80) == 0x00) {
+ // Zero continuation (0 to 127)
+ code_point = c0;
+ assert(code_point <= 127);
+ p += 1;
+ } else {
+ GLubyte c1 = p[1];
+ if ((c1 & 0xC0) != 0x80) {
+ // Stop processing the UTF byte sequence early.
+ return false;
+ }
+ if ((c0 & 0xE0) == 0xC0) {
+ // One contination (128 to 2047)
+ code_point = ((c0 & 0x1F) << 6) | (c1 & 0x3F);
+ if (code_point < 128) {
+ return false;
+ }
+ assert(code_point >= 128 && code_point <= 2047);
+ p += 2;
+ } else {
+ GLubyte c2 = p[2];
+ if ((c2 & 0xC0) != 0x80) {
+ // Stop processing the UTF byte sequence early.
+ return false;
+ }
+ if ((c0 & 0xF0) == 0xE0) {
+ // Two continuation (2048 to 55295 and 57344 to 65535)
+ code_point = ((c0 & 0x0F) << 12) |
+ ((c1 & 0x3F) << 6) |
+ (c2 & 0x3F);
+ // "The definition of UTF-8 prohibits encoding character numbers between
+ // U+D800 and U+DFFF, which are reserved for use with the UTF-16
+ // encoding form (as surrogate pairs) and do not directly represent
+ // characters."
+ // 0xD800 = 55,296
+ // 0xDFFF = 57,343
+ if ((code_point >= 55296) && (code_point <= 57343)) {
+ // Stop processing the UTF byte sequence early.
+ return false;
+ }
+ if (code_point < 2048) {
+ return false;
+ }
+ assert(code_point >= 2048 && code_point <= 65535);
+ assert(code_point < 55296 || code_point > 57343);
+ p += 3;
+ } else {
+ GLubyte c3 = p[3];
+ if ((c3 & 0xC0) != 0x80) {
+ // Stop processing the UTF byte sequence early.
+ return false;
+ }
+ if ((c0 & 0xF8) == 0xF0) {
+ // Three continuation (65536 to 1114111)
+ code_point = ((c0 & 0x07) << 18) |
+ ((c1 & 0x3F) << 12) |
+ ((c2 & 0x3F) << 6) |
+ (c3 & 0x3F);
+ if (code_point < 65536 && code_point > 1114111) {
+ return false;
+ }
+ assert(code_point >= 65536 && code_point <= 1114111);
+ p += 4;
+ } else {
+ // Skip invalid or restricted encodings.
+ // Stop processing the UTF byte sequence early.
+ return false;
+ }
+ }
+ }
+ }
+ utf_string = p;
+ return true;
+}
+
+// See RFC-2781 "UTF-16, a transformation format of ISO 10646"
+// http://rfc-ref.org/RFC-TEXTS/2781/index.html
+// http://www.rfc-editor.org/rfc/rfc2781.txt
+static bool
+__glPathGetCodePointUTF16(const void *&utf_string,
+ GLuint &code_point)
+{
+ // Section 2.2 (Decoding UTF-16) of http://www.rfc-editor.org/rfc/rfc2781.txt
+ // "Decoding of a single character from UTF-16 to an ISO 10646 character
+ // value proceeds as follows."
+ const GLushort *p = reinterpret_cast<const GLushort*>(utf_string);
+
+ // "Let W1 be the next 16-bit integer in the
+ // sequence of integers representing the text."
+ GLushort W1 = p[0];
+ // "1) If W1 < 0xD800 or W1 > 0xDFFF, the character value U is the value
+ // of W1. Terminate."
+ if ((W1 < 0xDB00) || (W1 > 0xDFFF)) {
+ code_point = W1;
+ p += 1;
+ } else {
+ // "2) Determine if W1 is between 0xD800 and 0xDBFF."
+ bool between1 = (W1 >= 0xDB00) && (W1 <= 0xDBFF);
+ if (!between1) {
+ // "If not, the sequence
+ // is in error and no valid character can be obtained using W1.
+ // Terminate."
+ return false;
+ }
+ // "Let W2 be the (eventual) next integer following W1."
+ GLushort W2 = p[1];
+ // DOES NOT APPLY because API provides character (not byte) count.
+ // "3) If there is no W2 (that is, the sequence ends with W1), [Terminate]"
+
+ // "... or if W2 is not between 0xDC00 and 0xDFFF, the sequence
+ // is in error. Terminate."
+ bool between2 = (W2 >= 0xDC00) && (W2 <= 0xDFFF);
+ if (!between2) {
+ return false;
+ }
+ // "4) Construct a 20-bit unsigned integer U', taking the 10 low-order
+ // bits of W1 as its 10 high-order bits and the 10 low-order bits of
+ // W2 as its 10 low-order bits."
+ code_point = ((W1 & 0x3FF) << 10) |
+ (W2 & 0x3FF);
+ // "5) Add 0x10000 to U' to obtain the character value U. Terminate."
+ code_point += 0x10000;
+ p += 2;
+ }
+ utf_string = p;
+ return true;
}
+static size_t bytesOfSequence(GLsizei count, GLenum type, const GLvoid *sequence)
+{
+ GLsizei bytes_per_element;
+ switch (type) {
+ case GL_BYTE:
+ bytes_per_element = sizeof(GLbyte);
+ break;
+ case GL_UNSIGNED_BYTE:
+ bytes_per_element = sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ bytes_per_element = sizeof(GLshort);
+ break;
+ case GL_UNSIGNED_SHORT:
+ bytes_per_element = sizeof(GLushort);
+ break;
+ case GL_INT:
+ bytes_per_element = sizeof(GLint);
+ break;
+ case GL_UNSIGNED_INT:
+ bytes_per_element = sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ bytes_per_element = sizeof(GLfloat);
+ break;
+ case GL_2_BYTES:
+ bytes_per_element = 2*sizeof(GLubyte);
+ break;
+ case GL_3_BYTES:
+ bytes_per_element = 3*sizeof(GLubyte);
+ break;
+ case GL_4_BYTES:
+ bytes_per_element = 4*sizeof(GLubyte);
+ break;
+ case GL_UTF8_NV:
+ {
+ const void *utf_string = sequence;
+ for (GLsizei i=0; i<count; i++) {
+ GLuint code_point; // ignored
+ bool ok = __glPathGetCodePointUTF8(utf_string, code_point);
+ if (!ok) {
+ break;
+ }
+ }
+ const char *start = reinterpret_cast<const char*>(sequence);
+ const char *end = reinterpret_cast<const char*>(utf_string);
+ return end - start;
+ }
+ case GL_UTF16_NV:
+ {
+ const void *utf_string = sequence;
+ for (GLsizei i=0; i<count; i++) {
+ GLuint code_point; // ignored
+ bool ok = __glPathGetCodePointUTF16(utf_string, code_point);
+ if (!ok) {
+ break;
+ }
+ }
+ const char *start = reinterpret_cast<const char*>(sequence);
+ const char *end = reinterpret_cast<const char*>(utf_string);
+ return end - start;
+ }
+ default: // generate INVALID_ENUM
+ return 0;
+ }
+ if (count > 0) {
+ return count * bytes_per_element;
+ } else {
+ return 0;
+ }
+}
+
+static inline size_t
+_gl_Paths_size(GLsizei numPaths, GLenum pathNameType, const GLvoid *paths)
+{
+ return bytesOfSequence(numPaths, pathNameType, paths);
+}
+
+static inline size_t
+_gl_PathColorGen_size(GLenum genMode, GLenum colorFormat)
+{
+ GLsizei coeffsPerComponent;
+ switch (genMode) {
+ case GL_NONE:
+ coeffsPerComponent = 0;
+ break;
+ case GL_OBJECT_LINEAR:
+ case GL_PATH_OBJECT_BOUNDING_BOX_NV:
+ coeffsPerComponent = 3;
+ break;
+ case GL_EYE_LINEAR:
+ coeffsPerComponent = 4;
+ break;
+ default:
+ return 0;
+ }
+
+ GLsizei components;
+ switch (colorFormat) {
+ case GL_LUMINANCE:
+ case GL_ALPHA:
+ case GL_INTENSITY:
+ components = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ components = 2;
+ break;
+ case GL_RGB:
+ components = 3;
+ break;
+ case GL_RGBA:
+ components = 4;
+ break;
+ default:
+ return 0;
+ }
+
+ GLsizei numCoeffs = components * coeffsPerComponent;
+ return numCoeffs*sizeof(GLfloat);
+}
+
+static inline size_t
+_gl_PathTexGen_size(GLenum genMode, GLsizei components)
+{
+ GLsizei coeffsPerComponent;
+ switch (genMode) {
+ case GL_NONE:
+ return 0;
+ case GL_OBJECT_LINEAR:
+ case GL_PATH_OBJECT_BOUNDING_BOX_NV:
+ coeffsPerComponent = 3;
+ break;
+ case GL_EYE_LINEAR:
+ coeffsPerComponent = 4;
+ break;
+ default:
+ return 0;
+ }
+
+ if (components < 1 || components > 4) {
+ return 0;
+ }
+
+ GLsizei numCoeffs = components * coeffsPerComponent;
+ return numCoeffs*sizeof(GLfloat);
+}
+
+static size_t valuesPerGetPathParameter(GLenum pname)
+{
+ switch (pname) {
+ case GL_PATH_FILL_MODE_NV:
+ case GL_PATH_FILL_MASK_NV:
+ case GL_PATH_FILL_COVER_MODE_NV:
+ case GL_PATH_STROKE_WIDTH_NV:
+ case GL_PATH_INITIAL_END_CAP_NV:
+ case GL_PATH_TERMINAL_END_CAP_NV:
+ case GL_PATH_JOIN_STYLE_NV:
+ case GL_PATH_MITER_LIMIT_NV:
+ case GL_PATH_INITIAL_DASH_CAP_NV:
+ case GL_PATH_TERMINAL_DASH_CAP_NV:
+ case GL_PATH_DASH_OFFSET_NV:
+ case GL_PATH_DASH_OFFSET_RESET_NV:
+ case GL_PATH_CLIENT_LENGTH_NV:
+ case GL_PATH_STROKE_COVER_MODE_NV:
+ case GL_PATH_STROKE_MASK_NV:
+ case GL_PATH_STROKE_OVERSAMPLE_COUNT_NV:
+ case GL_PATH_SAMPLE_QUALITY_NV:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static inline size_t
+_gl_GetPathParameter_size(GLenum pname)
+{
+ return valuesPerGetPathParameter(pname);
+}
+
+static inline size_t
+_gl_GetPathSpacing(GLsizei numPaths, GLenum transformType)
+{
+ switch (transformType) {
+ case GL_TRANSLATE_X_NV:
+ return (numPaths-1)*1;
+ case GL_TRANSLATE_2D_NV:
+ return (numPaths-1)*2;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Helper function for determining the string lengths for glShaderSource and
+ * glShaderSourceARB, which is a tad too complex to inline in the specs.
+ */
+template<class Char>
+static inline size_t
+_glShaderSource_length(const Char * const * string, const GLint *length, GLsizei index)
+{
+ if (length != NULL && length[index] >= 0) {
+ return (size_t)length[index];
+ } else {
+ return strlen(string[index]);
+ }
+}
+
+/**
+ * Helper function for determining the string lengths for glGetDebugMessageLog*.
+ */
+template<class Char>
+static inline size_t
+_glGetDebugMessageLog_length(const Char * string, const GLsizei *lengths, GLuint count)
+{
+ size_t size = 0;
+ GLuint index;
+ if (lengths) {
+ for (index = 0; index < count; ++index) {
+ size += lengths[index];
+ }
+ } else {
+ for (index = 0; index < count; ++index) {
+ size += strlen(&string[size]) + 1;
+ }
+ }
+ if (size) {
+ // Remove the last null terminator
+ --size;
+ }
+ return size;
+}
/*
* (key, value) attribute list, terminated by the given terminator.