Implement GL_OES_element_index_uint

TRAC #11951 Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch Author: Andrew Lewycky git-svn-id: https://angleproject.googlecode.com/svn/trunk@240 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 97bffae5
......@@ -239,6 +239,8 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
if (!mHasBeenCurrent)
{
initExtensionString();
mState.viewportX = 0;
mState.viewportY = 0;
mState.viewportWidth = surface->getWidth();
......@@ -1731,23 +1733,6 @@ void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
}
}
// The indices parameter to glDrawElements can have two interpretations:
// - as a pointer into client memory
// - as an offset into the current GL_ELEMENT_ARRAY_BUFFER buffer
// Handle these cases here and return a pointer to the index data.
const Index *Context::adjustIndexPointer(const void *indices)
{
if (mState.elementArrayBuffer)
{
Buffer *buffer = getBuffer(mState.elementArrayBuffer);
return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
}
else
{
return static_cast<const Index*>(indices);
}
}
void Context::applyVertexBuffer(GLint first, GLsizei count)
{
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
......@@ -1763,7 +1748,7 @@ void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
{
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
mVertexDataManager->preRenderValidate(indexInfo, translated);
mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
lookupAttributeMapping(translated);
......@@ -2256,7 +2241,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void*
if (!cullSkipsDraw(mode))
{
display->startScene();
device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/sizeof(Index), primitiveCount);
device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
}
}
......@@ -2575,6 +2560,25 @@ void Context::setVertexAttrib(GLuint index, const GLfloat *values)
mVertexDataManager->dirtyCurrentValues();
}
void Context::initExtensionString()
{
if (mBufferBackEnd->supportIntIndices())
{
mExtensionString += "GL_OES_element_index_uint ";
}
std::string::size_type end = mExtensionString.find_last_not_of(' ');
if (end != std::string::npos)
{
mExtensionString.resize(end+1);
}
}
const char *Context::getExtensionString() const
{
return mExtensionString.c_str();
}
}
extern "C"
......
......@@ -69,9 +69,6 @@ const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
const float ALIASED_POINT_SIZE_RANGE_MAX = 1.0f;
// Because indices are accessed internally, we convert them to a common format.
typedef unsigned short Index;
enum SamplerType
{
SAMPLER_2D,
......@@ -376,13 +373,14 @@ class Context
const char *getPixelShaderProfile();
const char *getVertexShaderProfile();
const char *getExtensionString() const;
Blit *getBlitter() { return mBlit; }
private:
DISALLOW_COPY_AND_ASSIGN(Context);
void lookupAttributeMapping(TranslatedAttribute *attributes);
const Index *adjustIndexPointer(const void *indices);
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
......@@ -423,6 +421,9 @@ class Context
typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap;
void initExtensionString();
std::string mExtensionString;
BufferBackEnd *mBufferBackEnd;
VertexDataManager *mVertexDataManager;
IndexDataManager *mIndexDataManager;
......
......@@ -16,30 +16,40 @@
namespace
{
enum { INITIAL_INDEX_BUFFER_SIZE = sizeof(gl::Index) * 8192 };
enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) };
}
namespace gl
{
IndexDataManager::IndexDataManager(Context *context, BufferBackEnd *backend)
: mContext(context), mBackend(backend)
: mContext(context), mBackend(backend), mIntIndicesSupported(backend->supportIntIndices())
{
mStreamBuffer = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE);
mStreamBufferShort = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
if (mIntIndicesSupported)
{
mStreamBufferInt = mBackend->createIndexBuffer(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
}
else
{
mStreamBufferInt = NULL;
}
}
IndexDataManager::~IndexDataManager()
{
delete mStreamBuffer;
delete mStreamBufferShort;
delete mStreamBufferInt;
}
namespace
{
template <class InputIndexType>
void copyIndices(const InputIndexType *in, GLsizei count, Index *out, GLuint *minIndex, GLuint *maxIndex)
template <class InputIndexType, class OutputIndexType>
void copyIndices(const InputIndexType *in, GLsizei count, OutputIndexType *out, GLuint *minIndex, GLuint *maxIndex)
{
Index first = *in;
InputIndexType first = *in;
GLuint minIndexSoFar = first;
GLuint maxIndexSoFar = first;
......@@ -62,7 +72,7 @@ void copyIndices(const InputIndexType *in, GLsizei count, Index *out, GLuint *mi
TranslatedIndexData IndexDataManager::preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices)
{
ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE);
ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT);
ASSERT(count > 0);
TranslatedIndexData translated;
......@@ -71,54 +81,100 @@ TranslatedIndexData IndexDataManager::preRenderValidate(GLenum mode, GLenum type
std::size_t requiredSpace = spaceRequired(type, count);
if (requiredSpace > mStreamBuffer->size())
{
std::size_t newSize = std::max(requiredSpace, 2 * mStreamBuffer->size());
TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize);
delete mStreamBuffer;
mStreamBuffer = newStreamBuffer;
}
mStreamBuffer->reserveSpace(requiredSpace);
TranslatedIndexBuffer *streamIb = prepareIndexBuffer(type, requiredSpace);
size_t offset;
void *output = mStreamBuffer->map(requiredSpace, &offset);
void *output = streamIb->map(requiredSpace, &offset);
translated.buffer = mStreamBuffer;
translated.buffer = streamIb;
translated.offset = offset;
translated.indexSize = indexSize(type);
translated.indices = static_cast<const Index*>(output);
translated.indices = output;
if (arrayElementBuffer != NULL)
{
indices = static_cast<const GLubyte*>(arrayElementBuffer->data()) + reinterpret_cast<GLsizei>(indices);
}
Index *out = static_cast<Index*>(output);
if (type == GL_UNSIGNED_SHORT)
if (type == GL_UNSIGNED_BYTE)
{
const GLushort *in = static_cast<const GLushort*>(indices);
const GLubyte *in = static_cast<const GLubyte*>(indices);
GLushort *out = static_cast<GLushort*>(output);
copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
}
else if (type == GL_UNSIGNED_INT)
{
const GLuint *in = static_cast<const GLuint*>(indices);
if (mIntIndicesSupported)
{
GLuint *out = static_cast<GLuint*>(output);
copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
}
else
{
// When 32-bit indices are unsupported, fake them by truncating to 16-bit.
GLushort *out = static_cast<GLushort*>(output);
copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
}
}
else
{
const GLubyte *in = static_cast<const GLubyte*>(indices);
const GLushort *in = static_cast<const GLushort*>(indices);
GLushort *out = static_cast<GLushort*>(output);
copyIndices(in, count, out, &translated.minIndex, &translated.maxIndex);
}
mStreamBuffer->unmap();
streamIb->unmap();
return translated;
}
std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count)
std::size_t IndexDataManager::indexSize(GLenum type) const
{
return (type == GL_UNSIGNED_INT && mIntIndicesSupported) ? sizeof(GLuint) : sizeof(GLushort);
}
std::size_t IndexDataManager::spaceRequired(GLenum type, GLsizei count) const
{
return (count + 1) * sizeof(Index); // +1 because we always leave an extra for line loops
return (count + 1) * indexSize(type); // +1 because we always leave an extra for line loops
}
TranslatedIndexBuffer *IndexDataManager::prepareIndexBuffer(GLenum type, std::size_t requiredSpace)
{
bool use32 = (type == GL_UNSIGNED_INT && mIntIndicesSupported);
TranslatedIndexBuffer *streamIb = use32 ? mStreamBufferInt : mStreamBufferShort;
if (requiredSpace > streamIb->size())
{
std::size_t newSize = std::max(requiredSpace, 2 * streamIb->size());
TranslatedIndexBuffer *newStreamBuffer = mBackend->createIndexBuffer(newSize, use32 ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT);
delete streamIb;
streamIb = newStreamBuffer;
if (use32)
{
mStreamBufferInt = streamIb;
}
else
{
mStreamBufferShort = streamIb;
}
}
streamIb->reserveSpace(requiredSpace);
return streamIb;
}
}
......@@ -31,8 +31,9 @@ struct TranslatedIndexData
GLuint minIndex;
GLuint maxIndex;
GLuint count;
GLuint indexSize;
const Index *indices;
const void *indices;
TranslatedIndexBuffer *buffer;
GLsizei offset;
......@@ -47,12 +48,17 @@ class IndexDataManager
TranslatedIndexData preRenderValidate(GLenum mode, GLenum type, GLsizei count, Buffer *arrayElementBuffer, const void *indices);
private:
std::size_t spaceRequired(GLenum type, GLsizei count);
std::size_t IndexDataManager::indexSize(GLenum type) const;
std::size_t spaceRequired(GLenum type, GLsizei count) const;
TranslatedIndexBuffer *prepareIndexBuffer(GLenum type, std::size_t requiredSpace);
Context *mContext;
BufferBackEnd *mBackend;
TranslatedIndexBuffer *mStreamBuffer;
bool mIntIndicesSupported;
TranslatedIndexBuffer *mStreamBufferShort;
TranslatedIndexBuffer *mStreamBufferInt;
};
}
......
......@@ -46,27 +46,7 @@ VertexDataManager::~VertexDataManager()
delete mCurrentValueBuffer;
}
VertexDataManager::ArrayTranslationHelper::ArrayTranslationHelper(GLint first, GLsizei count)
: mFirst(first), mCount(count)
{
}
void VertexDataManager::ArrayTranslationHelper::translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest)
{
converter.convertArray(source, stride, mCount, dest);
}
VertexDataManager::IndexedTranslationHelper::IndexedTranslationHelper(const Index *indices, Index minIndex, GLsizei count)
: mIndices(indices), mMinIndex(minIndex), mCount(count)
{
}
void VertexDataManager::IndexedTranslationHelper::translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest)
{
converter.convertIndexed(source, stride, mMinIndex, mCount, mIndices, dest);
}
std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::activeAttribs()
std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::getActiveAttribs() const
{
std::bitset<MAX_VERTEX_ATTRIBS> active;
......@@ -81,28 +61,11 @@ std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::activeAttribs()
}
GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
TranslatedAttribute *outAttribs)
{
ArrayTranslationHelper translationHelper(start, count);
return internalPreRenderValidate(mContext->getVertexAttribBlock(), activeAttribs(), start, start+count-1, &translationHelper, outAttribs);
}
GLenum VertexDataManager::preRenderValidate(const TranslatedIndexData &indexInfo,
TranslatedAttribute *outAttribs)
TranslatedAttribute *translated)
{
IndexedTranslationHelper translationHelper(indexInfo.indices, indexInfo.minIndex, indexInfo.count);
return internalPreRenderValidate(mContext->getVertexAttribBlock(), activeAttribs(), indexInfo.minIndex, indexInfo.maxIndex, &translationHelper, outAttribs);
}
const AttributeState *attribs = mContext->getVertexAttribBlock();
const std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs = getActiveAttribs();
GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attribs,
const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs,
Index minIndex,
Index maxIndex,
TranslationHelper *translator,
TranslatedAttribute *translated)
{
std::bitset<MAX_VERTEX_ATTRIBS> translateOrLift;
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
......@@ -127,7 +90,7 @@ GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attrib
if (attribs[i].mBoundBuffer != 0 && mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized).identity)
{
std::size_t stride = interpretGlStride(attribs[i]);
std::size_t offset = static_cast<std::size_t>(static_cast<const char*>(attribs[i].mPointer) - static_cast<const char*>(NULL)) + stride * minIndex;
std::size_t offset = static_cast<std::size_t>(static_cast<const char*>(attribs[i].mPointer) - static_cast<const char*>(NULL)) + stride * start;
if (mBackend->validateStream(attribs[i].mType, attribs[i].mSize, stride, offset))
{
......@@ -153,8 +116,6 @@ GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attrib
// Handle any attributes needing translation or lifting.
if (translateOrLift.any())
{
std::size_t count = maxIndex - minIndex + 1;
std::size_t requiredSpace = 0;
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
......@@ -204,9 +165,9 @@ GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attrib
size_t inputStride = interpretGlStride(attribs[i]);
input = static_cast<const char*>(input) + inputStride * minIndex;
input = static_cast<const char*>(input) + inputStride * start;
translator->translate(formatConverter, interpretGlStride(attribs[i]), input, output);
formatConverter.convertArray(input, inputStride, count, output);
mStreamBuffer->unmap();
}
......
......@@ -40,51 +40,8 @@ class VertexDataManager
GLsizei count,
TranslatedAttribute *outAttribs);
GLenum preRenderValidate(const TranslatedIndexData &indexInfo,
TranslatedAttribute* outAttribs);
private:
std::bitset<MAX_VERTEX_ATTRIBS> activeAttribs();
class TranslationHelper
{
public:
virtual ~TranslationHelper() { }
virtual void translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest) = 0;
};
class ArrayTranslationHelper : public TranslationHelper
{
public:
ArrayTranslationHelper(GLint first, GLsizei count);
void translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest);
private:
GLint mFirst;
GLsizei mCount;
};
class IndexedTranslationHelper : public TranslationHelper
{
public:
IndexedTranslationHelper(const Index *indices, Index minIndex, GLsizei count);
void translate(const FormatConverter &converter, GLint stride, const void *source, void *dest);
private:
const Index *mIndices;
Index mMinIndex;
GLsizei mCount;
};
GLenum internalPreRenderValidate(const AttributeState *attribs,
const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs,
Index minIndex,
Index maxIndex,
TranslationHelper *translator,
TranslatedAttribute *outAttribs);
std::bitset<MAX_VERTEX_ATTRIBS> getActiveAttribs() const;
void reloadCurrentValues(const AttributeState *attribs, std::size_t *offset);
......
......@@ -26,7 +26,6 @@ struct FormatConverter
{
bool identity;
std::size_t outputVertexSize;
void (*convertIndexed)(const void *in, std::size_t stride, Index minIndex, std::size_t n, const Index *indices, void *out);
void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
};
......@@ -53,9 +52,11 @@ class BufferBackEnd
public:
virtual ~BufferBackEnd() { }
virtual bool supportIntIndices() = 0;
virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size) = 0;
virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size) = 0;
virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size) = 0;
virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type) = 0;
virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize) = 0;
// For an identity-mappable stream, verify that the stride and offset are okay.
......
......@@ -32,7 +32,6 @@ class FormatConverterFactory
formatConverter.identity = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::identity;
formatConverter.outputVertexSize = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::finalSize;
formatConverter.convertIndexed = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::convertIndexed;
formatConverter.convertArray = gl::VertexDataConverter<InputType, WidenRule<IncomingWidth>, ElementConverter, DefaultValueRule>::convertArray;
return formatConverter;
......@@ -66,6 +65,14 @@ Dx9BackEnd::~Dx9BackEnd()
mDevice->Release();
}
bool Dx9BackEnd::supportIntIndices()
{
D3DCAPS9 caps;
mDevice->GetDeviceCaps(&caps);
return (caps.MaxVertexIndex >= (1 << 16));
}
TranslatedVertexBuffer *Dx9BackEnd::createVertexBuffer(std::size_t size)
{
return new Dx9VertexBuffer(mDevice, size);
......@@ -76,9 +83,9 @@ TranslatedVertexBuffer *Dx9BackEnd::createVertexBufferForStrideZero(std::size_t
return new Dx9VertexBufferZeroStrideWorkaround(mDevice, size);
}
TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size)
TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size, GLenum type)
{
return new Dx9IndexBuffer(mDevice, size);
return new Dx9IndexBuffer(mDevice, size, type);
}
// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
......@@ -325,10 +332,14 @@ void *Dx9BackEnd::Dx9VertexBufferZeroStrideWorkaround::streamingMap(std::size_t
return mapPtr;
}
Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size)
Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type)
: TranslatedIndexBuffer(size)
{
HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &mIndexBuffer, NULL);
ASSERT(type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT);
D3DFORMAT format = (type == GL_UNSIGNED_SHORT) ? D3DFMT_INDEX16 : D3DFMT_INDEX32;
HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, format, D3DPOOL_DEFAULT, &mIndexBuffer, NULL);
if (hr != S_OK)
{
ERR("Out of memory allocating an index buffer of size %lu.", size);
......
......@@ -23,9 +23,11 @@ class Dx9BackEnd : public BufferBackEnd
explicit Dx9BackEnd(IDirect3DDevice9 *d3ddevice);
~Dx9BackEnd();
virtual bool supportIntIndices();
virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size);
virtual TranslatedVertexBuffer *createVertexBufferForStrideZero(std::size_t size);
virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size);
virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size, GLenum type);
virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize);
virtual bool validateStream(GLenum type, std::size_t size, std::size_t stride, std::size_t offset) const;
......@@ -70,7 +72,7 @@ class Dx9BackEnd : public BufferBackEnd
class Dx9IndexBuffer : public TranslatedIndexBuffer
{
public:
Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size);
Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size, GLenum type);
virtual ~Dx9IndexBuffer();
IDirect3DIndexBuffer9 *getBuffer() const;
......
......@@ -149,7 +149,6 @@ struct NormalizedDefaultValues
// static const bool identity: true if this is an identity transform (with no widening)
// static const std::size_t finalSize: number of bytes per output vertex
// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided.
// static void convertIndexed(const void *in, std::size_t stride, std::size_t n, const Index *indices, void *out): convert an indexed array of vertices. Input may be strided, but output will be unstrided.
template <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
struct VertexDataConverter
......@@ -180,25 +179,6 @@ struct VertexDataConverter
return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
}
static void convertIndexed(const InputType *in, std::size_t stride, Index minIndex, std::size_t n, const Index *indices, OutputType *out)
{
for (std::size_t i = 0; i < n; i++)
{
const InputType *ein = pointerAddBytes(in, (indices[i] - minIndex) * stride);
OutputType *eout = pointerAddBytes(out, (indices[i] - minIndex) * finalSize);
copyComponent(eout, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(eout, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(eout, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(eout, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
}
}
static void convertIndexed(const void *in, std::size_t stride, Index minIndex, std::size_t n, const Index *indices, void *out)
{
convertIndexed(static_cast<const InputType*>(in), stride, minIndex, n, indices, static_cast<OutputType*>(out));
}
private:
// Advance the given pointer by a number of bytes (not pointed-to elements).
template <class T>
......
......@@ -1439,6 +1439,7 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv
{
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_SHORT:
case GL_UNSIGNED_INT:
break;
default:
return error(GL_INVALID_ENUM);
......@@ -2735,6 +2736,8 @@ const GLubyte* __stdcall glGetString(GLenum name)
try
{
gl::Context *context = gl::getContext();
switch (name)
{
case GL_VENDOR:
......@@ -2746,7 +2749,7 @@ const GLubyte* __stdcall glGetString(GLenum name)
case GL_SHADING_LANGUAGE_VERSION:
return (GLubyte*)"OpenGL ES GLSL ES 1.00 (git-devel "__DATE__ " " __TIME__")";
case GL_EXTENSIONS:
return (GLubyte*)"";
return (GLubyte*)((context != NULL) ? context->getExtensionString() : "");
default:
return error(GL_INVALID_ENUM, (GLubyte*)NULL);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment