Add support for Vertex Buffer Data Translation

TRAC #11024 Signed-off-by: Nicolas Capens Signed-off-by: Daniel Koch Author: Andrew Lewycky <andrew.lewycky@transgaming.com> git-svn-id: https://angleproject.googlecode.com/svn/trunk@15 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 45d03580
...@@ -29,6 +29,8 @@ class Config; ...@@ -29,6 +29,8 @@ class Config;
namespace gl namespace gl
{ {
struct TranslatedAttribute;
class Buffer; class Buffer;
class Shader; class Shader;
class Program; class Program;
...@@ -40,6 +42,8 @@ class Renderbuffer; ...@@ -40,6 +42,8 @@ class Renderbuffer;
class Colorbuffer; class Colorbuffer;
class Depthbuffer; class Depthbuffer;
class Stencilbuffer; class Stencilbuffer;
class VertexDataManager;
class BufferBackEnd;
enum enum
{ {
...@@ -57,6 +61,9 @@ enum ...@@ -57,6 +61,9 @@ enum
IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5 IMPLEMENTATION_COLOR_READ_TYPE = GL_UNSIGNED_SHORT_5_6_5
}; };
// Because indices are accessed internally, we convert them to a common format.
typedef unsigned short Index;
struct Color struct Color
{ {
float red; float red;
...@@ -65,18 +72,31 @@ struct Color ...@@ -65,18 +72,31 @@ struct Color
float alpha; float alpha;
}; };
// Helper structure describing a single vertex attribute array // Helper structure describing a single vertex attribute
struct Array class AttributeState
{ {
Array(); public:
AttributeState()
bool enabled; : mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mBoundBuffer(0), mEnabled(false)
GLuint boundBuffer; {
GLint size; mCurrentValue[0] = 0;
GLenum type; mCurrentValue[1] = 0;
GLboolean normalized; mCurrentValue[2] = 0;
GLsizei stride; mCurrentValue[3] = 1;
const void *pointer; }
// From VertexArrayPointer
GLenum mType;
GLint mSize;
bool mNormalized;
GLsizei mStride; // 0 means natural stride
const void *mPointer;
GLuint mBoundBuffer; // Captured when VertexArrayPointer is called.
bool mEnabled; // From Enable/DisableVertexAttribArray
float mCurrentValue[4]; // From VertexAttrib4f
}; };
// Helper structure to store all raw state // Helper structure to store all raw state
...@@ -149,7 +169,7 @@ struct State ...@@ -149,7 +169,7 @@ struct State
GLuint renderbuffer; GLuint renderbuffer;
GLuint currentProgram; GLuint currentProgram;
Array vertexAttribute[MAX_VERTEX_ATTRIBS]; AttributeState vertexAttribute[MAX_VERTEX_ATTRIBS];
GLuint samplerTexture[MAX_TEXTURE_IMAGE_UNITS]; GLuint samplerTexture[MAX_TEXTURE_IMAGE_UNITS];
unsigned int startIndex; unsigned int startIndex;
...@@ -216,8 +236,9 @@ class Context : public State ...@@ -216,8 +236,9 @@ class Context : public State
bool applyRenderTarget(bool ignoreViewport); bool applyRenderTarget(bool ignoreViewport);
void applyState(); void applyState();
void applyVertexBuffer(int count); void applyVertexBuffer(GLint first, GLsizei count);
void applyIndexBuffer(const void *indices, int length); void applyVertexBuffer(GLsizei count, const void *indices, GLenum indexType);
void applyIndexBuffer(const void *indices, GLsizei count);
void applyShaders(); void applyShaders();
void applyTextures(); void applyTextures();
...@@ -239,6 +260,9 @@ class Context : public State ...@@ -239,6 +260,9 @@ class Context : public State
private: private:
DISALLOW_COPY_AND_ASSIGN(Context); DISALLOW_COPY_AND_ASSIGN(Context);
void lookupAttributeMapping(TranslatedAttribute *attributes);
const Index *adjustIndexPointer(const void *indices);
void detachBuffer(GLuint buffer); void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture); void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer); void detachFramebuffer(GLuint framebuffer);
...@@ -271,6 +295,9 @@ class Context : public State ...@@ -271,6 +295,9 @@ class Context : public State
typedef std::map<GLuint, Renderbuffer*> RenderbufferMap; typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap; RenderbufferMap mRenderbufferMap;
BufferBackEnd *mBufferBackEnd;
VertexDataManager *mVertexDataManager;
// Recorded errors // Recorded errors
bool mInvalidEnum; bool mInvalidEnum;
bool mInvalidValue; bool mInvalidValue;
......
...@@ -10,111 +10,79 @@ ...@@ -10,111 +10,79 @@
#include "Buffer.h" #include "Buffer.h"
#include "main.h" #include <cstdlib>
#include <limits>
#include <utility>
#include "debug.h"
#include "geometry/backend.h"
namespace gl namespace gl
{ {
Buffer::Buffer()
{
mSize = 0;
mData = NULL;
mVertexBuffer = NULL; Buffer::Buffer(BufferBackEnd *backEnd)
mIndexBuffer = NULL; : mBackEnd(backEnd), mIdentityTranslation(NULL)
{
} }
Buffer::~Buffer() Buffer::~Buffer()
{ {
erase(); delete mIdentityTranslation;
} }
void Buffer::storeData(GLsizeiptr size, const void *data) GLenum Buffer::bufferData(const void* data, GLsizeiptr size, GLenum usage)
{ {
erase(); if (size < 0) return GL_INVALID_VALUE;
mSize = size; const data_t* newdata = static_cast<const data_t*>(data);
mData = new unsigned char[size];
if (data) if (size != mContents.size())
{ {
memcpy(mData, data, size); // vector::resize only provides the basic exception guarantee, so use temporaries & swap to get the strong exception guarantee.
} // We don't want to risk having mContents and mIdentityTranslation that have different contents or even different sizes.
} std::vector<data_t> newContents(newdata, newdata + size);
IDirect3DVertexBuffer9 *Buffer::getVertexBuffer() TranslatedVertexBuffer *newIdentityTranslation = mBackEnd->createVertexBuffer(size);
{
if (!mVertexBuffer)
{
IDirect3DDevice9 *device = getDevice();
HRESULT result = device->CreateVertexBuffer(mSize, 0, 0, D3DPOOL_MANAGED, &mVertexBuffer, NULL);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) // No exceptions allowed after this point.
{
return error(GL_OUT_OF_MEMORY, (IDirect3DVertexBuffer9*)NULL);
}
ASSERT(SUCCEEDED(result)); mContents.swap(newContents);
if (mVertexBuffer && mData) delete mIdentityTranslation;
{ mIdentityTranslation = newIdentityTranslation;
void *dataStore; }
mVertexBuffer->Lock(0, mSize, &dataStore, 0); else
memcpy(dataStore, mData, mSize); {
mVertexBuffer->Unlock(); const data_t* newdata = static_cast<const data_t*>(data);
} mContents.assign(newdata, newdata + size);
} }
return mVertexBuffer; return copyToIdentityBuffer(0, size);
} }
IDirect3DIndexBuffer9 *Buffer::getIndexBuffer() GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset)
{ {
if (!mIndexBuffer) if (size < 0 || offset < 0) return GL_INVALID_VALUE;
{ if (std::numeric_limits<GLsizeiptr>::max() - offset < size) return GL_INVALID_VALUE;
IDirect3DDevice9 *device = getDevice(); if (size + offset > static_cast<GLsizeiptr>(mContents.size())) return GL_INVALID_VALUE;
HRESULT result = device->CreateIndexBuffer(mSize, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &mIndexBuffer, NULL); const data_t *newdata = static_cast<const data_t*>(data);
copy(newdata, newdata + size, mContents.begin() + offset);
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) return copyToIdentityBuffer(offset, size);
{
return error(GL_OUT_OF_MEMORY, (IDirect3DIndexBuffer9*)NULL);
}
ASSERT(SUCCEEDED(result));
if (mIndexBuffer && mData)
{
void *dataStore;
mIndexBuffer->Lock(0, mSize, &dataStore, 0);
memcpy(dataStore, mData, mSize);
mIndexBuffer->Unlock();
}
}
return mIndexBuffer;
} }
void Buffer::erase() GLenum Buffer::copyToIdentityBuffer(GLintptr offset, GLsizeiptr length)
{ {
mSize = 0; ASSERT(offset >= 0 && length >= 0);
if (mData) // This is a stalling map. Not great for performance.
{ data_t *p = static_cast<data_t*>(mIdentityTranslation->map());
delete[] mData;
mData = NULL;
}
if (mVertexBuffer) memcpy(p + offset, &mContents[0] + offset, length);
{ mIdentityTranslation->unmap();
mVertexBuffer->Release();
mVertexBuffer = NULL;
}
if (mIndexBuffer) return GL_NO_ERROR;
{
mIndexBuffer->Release();
mIndexBuffer = NULL;
}
} }
} }
...@@ -11,37 +11,47 @@ ...@@ -11,37 +11,47 @@
#ifndef LIBGLESV2_BUFFER_H_ #ifndef LIBGLESV2_BUFFER_H_
#define LIBGLESV2_BUFFER_H_ #define LIBGLESV2_BUFFER_H_
#include <cstddef>
#include <vector>
#define GL_APICALL #define GL_APICALL
#include <GLES2/gl2.h> #include <GLES2/gl2.h>
#include <d3d9.h>
#include "angleutils.h" #include "angleutils.h"
namespace gl namespace gl
{ {
class BufferBackEnd;
class TranslatedVertexBuffer;
class Buffer class Buffer
{ {
public: public:
Buffer(); explicit Buffer(BufferBackEnd *backEnd);
~Buffer(); ~Buffer();
void storeData(GLsizeiptr size, const void *data); GLenum bufferData(const void *data, GLsizeiptr size, GLenum usage);
GLenum bufferSubData(const void *data, GLsizeiptr size, GLintptr offset);
IDirect3DVertexBuffer9 *getVertexBuffer(); void *data() { return &mContents[0]; }
IDirect3DIndexBuffer9 *getIndexBuffer(); GLsizeiptr size() const { return mContents.size(); }
TranslatedVertexBuffer *identityBuffer() { return mIdentityTranslation; }
private: private:
DISALLOW_COPY_AND_ASSIGN(Buffer); DISALLOW_COPY_AND_ASSIGN(Buffer);
void erase(); typedef unsigned char data_t;
std::vector<data_t> mContents;
unsigned int mSize; BufferBackEnd *mBackEnd;
void *mData; TranslatedVertexBuffer *mIdentityTranslation;
IDirect3DVertexBuffer9 *mVertexBuffer; GLenum copyToIdentityBuffer(GLintptr offset, GLsizeiptr length);
IDirect3DIndexBuffer9 *mIndexBuffer;
}; };
} }
#endif // LIBGLESV2_BUFFER_H_ #endif // LIBGLESV2_BUFFER_H_
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// geometry/VertexDataManager.h: Defines the VertexDataManager, a class that
// runs the Buffer translation process.
#ifndef LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_
#define LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_
#include <bitset>
#include <cstddef>
#define GL_APICALL
#include <GLES2/gl2.h>
#include "Context.h"
namespace gl
{
class Buffer;
class BufferBackEnd;
class TranslatedVertexBuffer;
struct TranslatedAttribute;
struct FormatConverter;
class VertexDataManager
{
public:
VertexDataManager(Context *context, BufferBackEnd *backend);
~VertexDataManager();
void dirtyCurrentValues() { mDirtyCurrentValues = true; }
GLenum preRenderValidate(GLint start,
GLsizei count,
TranslatedAttribute *outAttribs);
GLenum preRenderValidate(const Index *indices,
GLsizei count,
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, GLsizei count);
void translate(const FormatConverter &converter, GLint stride, const void *source, void *dest);
private:
const Index *mIndices;
GLsizei mCount;
};
GLenum internalPreRenderValidate(const AttributeState *attribs,
const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs,
Index minIndex,
Index maxIndex,
TranslationHelper *translator,
TranslatedAttribute *outAttribs);
void reloadCurrentValues(const AttributeState *attribs, std::size_t *offset);
void processNonArrayAttributes(const AttributeState *attribs, const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs, TranslatedAttribute *translated);
std::size_t typeSize(GLenum type) const;
std::size_t interpretGlStride(const AttributeState &attrib) const;
std::size_t roundUp(std::size_t x, std::size_t multiple) const;
std::size_t spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const;
Context *mContext;
BufferBackEnd *mBackend;
TranslatedVertexBuffer *mCurrentValueBuffer;
TranslatedVertexBuffer *mStreamBuffer;
bool mDirtyCurrentValues;
};
}
#endif // LIBGLESV2_GEOMETRY_VERTEXDATAMANAGER_H_
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// geometry/backend.h: Abstract classes BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer
// that must be implemented by any API-specific implementation of ANGLE.
#include "geometry/backend.h"
#include "debug.h"
namespace gl
{
void *TranslatedBuffer::map(std::size_t requiredSpace, std::size_t *offset)
{
ASSERT(requiredSpace < mBufferSize);
reserveSpace(requiredSpace);
*offset = mCurrentPoint;
mCurrentPoint += requiredSpace;
return streamingMap(*offset, requiredSpace);
}
void TranslatedBuffer::reserveSpace(std::size_t requiredSpace)
{
if (mCurrentPoint + requiredSpace > mBufferSize)
{
recycle();
mCurrentPoint = 0;
}
}
}
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// geometry/backend.h: Abstract classes BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer
// that must be implemented by any API-specific implementation of ANGLE.
#ifndef LIBGLESV2_GEOMETRY_BACKEND_H_
#define LIBGLESV2_GEOMETRY_BACKEND_H_
#include <cstddef>
#define GL_APICALL
#include <GLES2/gl2.h>
#include "Context.h"
namespace gl
{
class TranslatedVertexBuffer;
class TranslatedIndexBuffer;
struct FormatConverter
{
bool identity;
std::size_t outputVertexSize;
void (*convertIndexed)(const void *in, std::size_t stride, std::size_t n, const Index *indices, void *out);
void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out);
};
struct TranslatedAttribute
{
bool enabled;
// These are the original untranslated values. (Or just have some sort of BufferBackEnd::TranslatedTypeKey.)
GLenum type;
std::size_t size;
bool normalized;
std::size_t offset;
std::size_t stride; // 0 means not to advance the read pointer at all
std::size_t programAttribute;
TranslatedVertexBuffer *buffer;
};
class BufferBackEnd
{
public:
virtual ~BufferBackEnd() { }
virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size) = 0;
virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size) = 0;
virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize) = 0;
virtual GLenum preDraw(const TranslatedAttribute *attributes) = 0;
};
class TranslatedBuffer
{
public:
explicit TranslatedBuffer(std::size_t size) : mBufferSize(size), mCurrentPoint(0) { }
virtual ~TranslatedBuffer() { }
std::size_t size() const { return mBufferSize; }
virtual void *map() = 0;
virtual void unmap() = 0;
void reserveSpace(std::size_t requiredSpace);
void *map(std::size_t requiredSpace, std::size_t *offset);
protected:
virtual void recycle() = 0;
virtual void *streamingMap(std::size_t offset, std::size_t size) = 0;
private:
std::size_t mBufferSize;
std::size_t mCurrentPoint;
DISALLOW_COPY_AND_ASSIGN(TranslatedBuffer);
};
class TranslatedVertexBuffer : public TranslatedBuffer
{
public:
explicit TranslatedVertexBuffer(std::size_t size) : TranslatedBuffer(size) { }
};
class TranslatedIndexBuffer : public TranslatedBuffer
{
public:
explicit TranslatedIndexBuffer(std::size_t size) : TranslatedBuffer(size) { }
};
}
#endif // LIBGLESV2_GEOMETRY_BACKEND_H_
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// geometry/dx9.h: Direct3D 9-based implementation of BufferBackEnd, TranslatedVertexBuffer and TranslatedIndexBuffer.
#ifndef LIBGLESV2_GEOMETRY_DX9_H_
#define LIBGLESV2_GEOMETRY_DX9_H_
#include <d3d9.h>
#include "Buffer.h"
#include "geometry/backend.h"
namespace gl
{
class Dx9BackEnd : public BufferBackEnd
{
public:
explicit Dx9BackEnd(IDirect3DDevice9 *d3ddevice);
~Dx9BackEnd();
virtual TranslatedVertexBuffer *createVertexBuffer(std::size_t size);
virtual TranslatedIndexBuffer *createIndexBuffer(std::size_t size);
virtual FormatConverter getFormatConverter(GLenum type, std::size_t size, bool normalize);
virtual GLenum preDraw(const TranslatedAttribute *attributes);
private:
IDirect3DDevice9 *mDevice;
class Dx9VertexBuffer : public TranslatedVertexBuffer
{
public:
Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size);
virtual ~Dx9VertexBuffer();
IDirect3DVertexBuffer9 *getBuffer() const;
protected:
virtual void *map();
virtual void unmap();
virtual void recycle();
virtual void *streamingMap(std::size_t offset, std::size_t size);
private:
IDirect3DVertexBuffer9 *mVertexBuffer;
};
class Dx9IndexBuffer : public TranslatedIndexBuffer
{
public:
Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size);
virtual ~Dx9IndexBuffer();
IDirect3DIndexBuffer9 *getBuffer() const;
protected:
virtual void *map();
virtual void unmap();
virtual void recycle();
virtual void *streamingMap(std::size_t offset, std::size_t size);
private:
IDirect3DIndexBuffer9 *mIndexBuffer;
};
IDirect3DVertexBuffer9 *getDxBuffer(TranslatedVertexBuffer *vb) const;
IDirect3DIndexBuffer9 *getDxBuffer(TranslatedIndexBuffer *ib) const;
D3DDECLTYPE mapAttributeType(GLenum type, std::size_t size, bool normalized) const;
};
}
#endif // LIBGLESV2_GEOMETRY_DX9_H_
//
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// geometry/vertexconversion.h: A library of vertex conversion classes that can be used to build
// the FormatConverter objects used by the buffer conversion system.
#ifndef LIBGLESV2_GEOMETRY_VERTEXCONVERSION_H_
#define LIBGLESV2_GEOMETRY_VERTEXCONVERSION_H_
#include <cstddef>
#include <limits>
#include "Context.h" // Defines Index
namespace gl
{
// Conversion types:
// static const bool identity: true if this is an identity transform, false otherwise
// static U convert(T): convert a single element from the input type to the output type
// typedef ... OutputType: the type produced by this conversion
template <class T>
struct Identity
{
static const bool identity = true;
typedef T OutputType;
static T convert(T x)
{
return x;
}
};
template <class FromT, class ToT>
struct Cast
{
static const bool identity = false;
typedef ToT OutputType;
static ToT convert(FromT x)
{
return static_cast<ToT>(x);
}
};
template <class T>
struct Cast<T, T>
{
static const bool identity = true;
typedef T OutputType;
static T convert(T x)
{
return static_cast<T>(x);
}
};
template <class T>
struct Normalize
{
static const bool identity = false;
typedef float OutputType;
static float convert(T x)
{
typedef std::numeric_limits<T> NL;
float f = static_cast<float>(x);
if (NL::is_signed)
{
// const float => VC2008 computes it at compile time
// static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
return (2*f+1)*divisor;
}
else
{
return f/NL::max();
}
}
};
template <class FromType, std::size_t ScaleBits>
struct FixedToFloat
{
static const bool identity = false;
typedef float OutputType;
static float convert(FromType x)
{
const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
return static_cast<float>(x) * divisor;
}
};
// Widen types:
// static const unsigned int initialWidth: number of components before conversion
// static const unsigned int finalWidth: number of components after conversion
// Float is supported at any size.
template <std::size_t N>
struct NoWiden
{
static const std::size_t initialWidth = N;
static const std::size_t finalWidth = N;
};
// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
template <std::size_t N>
struct WidenToEven
{
static const std::size_t initialWidth = N;
static const std::size_t finalWidth = N+(N&1);
};
template <unsigned int N>
struct WidenToFour
{
static const std::size_t initialWidth = N;
static const std::size_t finalWidth = 4;
};
// Most types have 0 and 1 that are just that.
template <class T>
struct SimpleDefaultValues
{
static T zero() { return static_cast<T>(0); }
static T one() { return static_cast<T>(1); }
};
// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
template <class T>
struct NormalizedDefaultValues
{
static T zero() { return static_cast<T>(0); }
static T one() { return std::numeric_limits<T>::max(); }
};
// Converter:
// 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
{
typedef typename Converter::OutputType OutputType;
typedef InT InputType;
static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out)
{
for (std::size_t i = 0; i < n; i++)
{
const InputType *ein = pointerAddBytes(in, i * stride);
copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
out += WidenRule::finalWidth;
}
}
static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out)
{
return convertArray(static_cast<const InputType*>(in), stride, n, static_cast<OutputType*>(out));
}
static void convertIndexed(const InputType *in, std::size_t stride, 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] * stride);
OutputType *eout = pointerAddBytes(out, indices[i] * 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, std::size_t n, const Index *indices, void *out)
{
convertIndexed(static_cast<const InputType*>(in), stride, n, indices, static_cast<OutputType*>(out));
}
private:
// Advance the given pointer by a number of bytes (not pointed-to elements).
template <class T>
static T *pointerAddBytes(T *basePtr, std::size_t numBytes)
{
return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(basePtr) + numBytes);
}
static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
{
if (WidenRule::finalWidth > elementindex)
{
if (WidenRule::initialWidth > elementindex)
{
*out = Converter::convert(in[elementindex]);
}
else
{
*out = defaultvalue;
}
}
}
};
}
#endif // LIBGLESV2_GEOMETRY_VERTEXCONVERSION_H_
...@@ -454,7 +454,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const void* data, GL ...@@ -454,7 +454,7 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const void* data, GL
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
buffer->storeData(size, data); buffer->bufferData(data, size, usage);
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -474,7 +474,36 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, ...@@ -474,7 +474,36 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
UNIMPLEMENTED(); // FIXME gl::Context *context = gl::getContext();
if (context)
{
gl::Buffer *buffer;
switch (target)
{
case GL_ARRAY_BUFFER:
buffer = context->getArrayBuffer();
break;
case GL_ELEMENT_ARRAY_BUFFER:
buffer = context->getElementArrayBuffer();
break;
default:
return error(GL_INVALID_ENUM);
}
if (!buffer)
{
return error(GL_INVALID_OPERATION);
}
GLenum err = buffer->bufferSubData(data, size, offset);
if (err != GL_NO_ERROR)
{
return error(err);
}
}
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
{ {
...@@ -1100,7 +1129,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index) ...@@ -1100,7 +1129,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index)
if (context) if (context)
{ {
context->vertexAttribute[index].enabled = false; context->vertexAttribute[index].mEnabled = false;
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -1214,7 +1243,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index) ...@@ -1214,7 +1243,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index)
if (context) if (context)
{ {
context->vertexAttribute[index].enabled = true; context->vertexAttribute[index].mEnabled = true;
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
...@@ -3777,12 +3806,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo ...@@ -3777,12 +3806,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo
if (context) if (context)
{ {
context->vertexAttribute[index].boundBuffer = context->arrayBuffer; context->vertexAttribute[index].mBoundBuffer = context->arrayBuffer;
context->vertexAttribute[index].size = size; context->vertexAttribute[index].mSize = size;
context->vertexAttribute[index].type = type; context->vertexAttribute[index].mType = type;
context->vertexAttribute[index].normalized = normalized; context->vertexAttribute[index].mNormalized = normalized;
context->vertexAttribute[index].stride = stride; context->vertexAttribute[index].mStride = stride;
context->vertexAttribute[index].pointer = ptr; context->vertexAttribute[index].mPointer = ptr;
} }
} }
catch(std::bad_alloc&) catch(std::bad_alloc&)
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="../Include/; ../Compiler/" AdditionalIncludeDirectories="../Include/; ../Compiler/;."
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX" PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
/> />
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../Include/; ../Compiler/" AdditionalIncludeDirectories="../Include/; ../Compiler/;."
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX" PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
RuntimeLibrary="0" RuntimeLibrary="0"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
...@@ -224,6 +224,22 @@ ...@@ -224,6 +224,22 @@
RelativePath=".\utilities.cpp" RelativePath=".\utilities.cpp"
> >
</File> </File>
<Filter
Name="Geometry"
>
<File
RelativePath=".\geometry\backend.cpp"
>
</File>
<File
RelativePath=".\geometry\dx9.cpp"
>
</File>
<File
RelativePath=".\geometry\VertexDataManager.cpp"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
...@@ -302,6 +318,26 @@ ...@@ -302,6 +318,26 @@
RelativePath=".\utilities.h" RelativePath=".\utilities.h"
> >
</File> </File>
<Filter
Name="Geometry"
>
<File
RelativePath=".\geometry\backend.h"
>
</File>
<File
RelativePath=".\geometry\dx9.h"
>
</File>
<File
RelativePath=".\geometry\vertexconversion.h"
>
</File>
<File
RelativePath=".\geometry\VertexDataManager.h"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="Resource Files" Name="Resource Files"
......
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