зеркало из https://github.com/AvaloniaUI/angle.git
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
This commit is contained in:
Родитель
45d035808a
Коммит
0f7aaf530b
|
@ -29,6 +29,8 @@ class Config;
|
|||
|
||||
namespace gl
|
||||
{
|
||||
struct TranslatedAttribute;
|
||||
|
||||
class Buffer;
|
||||
class Shader;
|
||||
class Program;
|
||||
|
@ -40,6 +42,8 @@ class Renderbuffer;
|
|||
class Colorbuffer;
|
||||
class Depthbuffer;
|
||||
class Stencilbuffer;
|
||||
class VertexDataManager;
|
||||
class BufferBackEnd;
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -57,6 +61,9 @@ enum
|
|||
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
|
||||
{
|
||||
float red;
|
||||
|
@ -65,18 +72,31 @@ struct Color
|
|||
float alpha;
|
||||
};
|
||||
|
||||
// Helper structure describing a single vertex attribute array
|
||||
struct Array
|
||||
// Helper structure describing a single vertex attribute
|
||||
class AttributeState
|
||||
{
|
||||
Array();
|
||||
public:
|
||||
AttributeState()
|
||||
: mType(GL_FLOAT), mSize(0), mNormalized(false), mStride(0), mPointer(NULL), mBoundBuffer(0), mEnabled(false)
|
||||
{
|
||||
mCurrentValue[0] = 0;
|
||||
mCurrentValue[1] = 0;
|
||||
mCurrentValue[2] = 0;
|
||||
mCurrentValue[3] = 1;
|
||||
}
|
||||
|
||||
bool enabled;
|
||||
GLuint boundBuffer;
|
||||
GLint size;
|
||||
GLenum type;
|
||||
GLboolean normalized;
|
||||
GLsizei stride;
|
||||
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
|
||||
|
@ -149,7 +169,7 @@ struct State
|
|||
GLuint renderbuffer;
|
||||
GLuint currentProgram;
|
||||
|
||||
Array vertexAttribute[MAX_VERTEX_ATTRIBS];
|
||||
AttributeState vertexAttribute[MAX_VERTEX_ATTRIBS];
|
||||
GLuint samplerTexture[MAX_TEXTURE_IMAGE_UNITS];
|
||||
|
||||
unsigned int startIndex;
|
||||
|
@ -216,8 +236,9 @@ class Context : public State
|
|||
|
||||
bool applyRenderTarget(bool ignoreViewport);
|
||||
void applyState();
|
||||
void applyVertexBuffer(int count);
|
||||
void applyIndexBuffer(const void *indices, int length);
|
||||
void applyVertexBuffer(GLint first, GLsizei count);
|
||||
void applyVertexBuffer(GLsizei count, const void *indices, GLenum indexType);
|
||||
void applyIndexBuffer(const void *indices, GLsizei count);
|
||||
void applyShaders();
|
||||
void applyTextures();
|
||||
|
||||
|
@ -239,6 +260,9 @@ class Context : public State
|
|||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Context);
|
||||
|
||||
void lookupAttributeMapping(TranslatedAttribute *attributes);
|
||||
const Index *adjustIndexPointer(const void *indices);
|
||||
|
||||
void detachBuffer(GLuint buffer);
|
||||
void detachTexture(GLuint texture);
|
||||
void detachFramebuffer(GLuint framebuffer);
|
||||
|
@ -271,6 +295,9 @@ class Context : public State
|
|||
typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
|
||||
RenderbufferMap mRenderbufferMap;
|
||||
|
||||
BufferBackEnd *mBufferBackEnd;
|
||||
VertexDataManager *mVertexDataManager;
|
||||
|
||||
// Recorded errors
|
||||
bool mInvalidEnum;
|
||||
bool mInvalidValue;
|
||||
|
|
|
@ -10,111 +10,79 @@
|
|||
|
||||
#include "Buffer.h"
|
||||
|
||||
#include "main.h"
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "debug.h"
|
||||
#include "geometry/backend.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
Buffer::Buffer()
|
||||
{
|
||||
mSize = 0;
|
||||
mData = NULL;
|
||||
|
||||
mVertexBuffer = NULL;
|
||||
mIndexBuffer = NULL;
|
||||
Buffer::Buffer(BufferBackEnd *backEnd)
|
||||
: mBackEnd(backEnd), mIdentityTranslation(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
mData = new unsigned char[size];
|
||||
const data_t* newdata = static_cast<const data_t*>(data);
|
||||
|
||||
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);
|
||||
|
||||
TranslatedVertexBuffer *newIdentityTranslation = mBackEnd->createVertexBuffer(size);
|
||||
|
||||
// No exceptions allowed after this point.
|
||||
|
||||
mContents.swap(newContents);
|
||||
|
||||
delete mIdentityTranslation;
|
||||
mIdentityTranslation = newIdentityTranslation;
|
||||
}
|
||||
else
|
||||
{
|
||||
const data_t* newdata = static_cast<const data_t*>(data);
|
||||
mContents.assign(newdata, newdata + size);
|
||||
}
|
||||
|
||||
return copyToIdentityBuffer(0, size);
|
||||
}
|
||||
|
||||
IDirect3DVertexBuffer9 *Buffer::getVertexBuffer()
|
||||
GLenum Buffer::bufferSubData(const void* data, GLsizeiptr size, GLintptr offset)
|
||||
{
|
||||
if (!mVertexBuffer)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
if (size < 0 || offset < 0) return GL_INVALID_VALUE;
|
||||
if (std::numeric_limits<GLsizeiptr>::max() - offset < size) return GL_INVALID_VALUE;
|
||||
if (size + offset > static_cast<GLsizeiptr>(mContents.size())) return GL_INVALID_VALUE;
|
||||
|
||||
HRESULT result = device->CreateVertexBuffer(mSize, 0, 0, D3DPOOL_MANAGED, &mVertexBuffer, 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 error(GL_OUT_OF_MEMORY, (IDirect3DVertexBuffer9*)NULL);
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
if (mVertexBuffer && mData)
|
||||
{
|
||||
void *dataStore;
|
||||
mVertexBuffer->Lock(0, mSize, &dataStore, 0);
|
||||
memcpy(dataStore, mData, mSize);
|
||||
mVertexBuffer->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
return mVertexBuffer;
|
||||
return copyToIdentityBuffer(offset, size);
|
||||
}
|
||||
|
||||
IDirect3DIndexBuffer9 *Buffer::getIndexBuffer()
|
||||
GLenum Buffer::copyToIdentityBuffer(GLintptr offset, GLsizeiptr length)
|
||||
{
|
||||
if (!mIndexBuffer)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
ASSERT(offset >= 0 && length >= 0);
|
||||
|
||||
HRESULT result = device->CreateIndexBuffer(mSize, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &mIndexBuffer, NULL);
|
||||
// This is a stalling map. Not great for performance.
|
||||
data_t *p = static_cast<data_t*>(mIdentityTranslation->map());
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY, (IDirect3DIndexBuffer9*)NULL);
|
||||
}
|
||||
memcpy(p + offset, &mContents[0] + offset, length);
|
||||
mIdentityTranslation->unmap();
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
if (mIndexBuffer && mData)
|
||||
{
|
||||
void *dataStore;
|
||||
mIndexBuffer->Lock(0, mSize, &dataStore, 0);
|
||||
memcpy(dataStore, mData, mSize);
|
||||
mIndexBuffer->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
return mIndexBuffer;
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
void Buffer::erase()
|
||||
{
|
||||
mSize = 0;
|
||||
|
||||
if (mData)
|
||||
{
|
||||
delete[] mData;
|
||||
mData = NULL;
|
||||
}
|
||||
|
||||
if (mVertexBuffer)
|
||||
{
|
||||
mVertexBuffer->Release();
|
||||
mVertexBuffer = NULL;
|
||||
}
|
||||
|
||||
if (mIndexBuffer)
|
||||
{
|
||||
mIndexBuffer->Release();
|
||||
mIndexBuffer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,37 +11,47 @@
|
|||
#ifndef LIBGLESV2_BUFFER_H_
|
||||
#define LIBGLESV2_BUFFER_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
#define GL_APICALL
|
||||
#include <GLES2/gl2.h>
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "angleutils.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
class BufferBackEnd;
|
||||
class TranslatedVertexBuffer;
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
Buffer();
|
||||
|
||||
explicit Buffer(BufferBackEnd *backEnd);
|
||||
~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();
|
||||
IDirect3DIndexBuffer9 *getIndexBuffer();
|
||||
void *data() { return &mContents[0]; }
|
||||
GLsizeiptr size() const { return mContents.size(); }
|
||||
|
||||
TranslatedVertexBuffer *identityBuffer() { return mIdentityTranslation; }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Buffer);
|
||||
|
||||
void erase();
|
||||
typedef unsigned char data_t;
|
||||
|
||||
unsigned int mSize;
|
||||
void *mData;
|
||||
std::vector<data_t> mContents;
|
||||
|
||||
IDirect3DVertexBuffer9 *mVertexBuffer;
|
||||
IDirect3DIndexBuffer9 *mIndexBuffer;
|
||||
BufferBackEnd *mBackEnd;
|
||||
TranslatedVertexBuffer *mIdentityTranslation;
|
||||
|
||||
GLenum copyToIdentityBuffer(GLintptr offset, GLsizeiptr length);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LIBGLESV2_BUFFER_H_
|
||||
|
|
|
@ -21,21 +21,14 @@
|
|||
#include "RenderBuffer.h"
|
||||
#include "mathutil.h"
|
||||
#include "utilities.h"
|
||||
#include "geometry/backend.h"
|
||||
#include "geometry/VertexDataManager.h"
|
||||
#include "geometry/dx9.h"
|
||||
|
||||
namespace gl
|
||||
{
|
||||
Array::Array()
|
||||
{
|
||||
enabled = false;
|
||||
boundBuffer = 0;
|
||||
size = 4;
|
||||
type = GL_FLOAT;
|
||||
normalized = GL_FALSE;
|
||||
stride = 0;
|
||||
pointer = NULL;
|
||||
}
|
||||
|
||||
Context::Context(const egl::Config *config) : mConfig(config)
|
||||
Context::Context(const egl::Config *config)
|
||||
: mConfig(config)
|
||||
{
|
||||
setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
depthClearValue = 1.0f;
|
||||
|
@ -126,6 +119,9 @@ Context::Context(const egl::Config *config) : mConfig(config)
|
|||
|
||||
currentProgram = 0;
|
||||
|
||||
mBufferBackEnd = NULL;
|
||||
mVertexDataManager = NULL;
|
||||
|
||||
mInvalidEnum = false;
|
||||
mInvalidValue = false;
|
||||
mInvalidOperation = false;
|
||||
|
@ -144,6 +140,9 @@ Context::~Context()
|
|||
delete mDepthbufferZero;
|
||||
delete mStencilbufferZero;
|
||||
|
||||
delete mBufferBackEnd;
|
||||
delete mVertexDataManager;
|
||||
|
||||
while (!mBufferMap.empty())
|
||||
{
|
||||
deleteBuffer(mBufferMap.begin()->first);
|
||||
|
@ -179,6 +178,12 @@ void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
|
|||
{
|
||||
IDirect3DDevice9 *device = display->getDevice();
|
||||
|
||||
if (!mBufferBackEnd)
|
||||
{
|
||||
mBufferBackEnd = new Dx9BackEnd(device);
|
||||
mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
|
||||
}
|
||||
|
||||
// Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
|
||||
IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
|
||||
IDirect3DSurface9 *defaultDepthStencil = NULL;
|
||||
|
@ -418,7 +423,7 @@ void Context::bindArrayBuffer(unsigned int buffer)
|
|||
{
|
||||
if (buffer != 0 && !getBuffer(buffer))
|
||||
{
|
||||
mBufferMap[buffer] = new Buffer();
|
||||
mBufferMap[buffer] = new Buffer(mBufferBackEnd);
|
||||
}
|
||||
|
||||
arrayBuffer = buffer;
|
||||
|
@ -428,7 +433,7 @@ void Context::bindElementArrayBuffer(unsigned int buffer)
|
|||
{
|
||||
if (buffer != 0 && !getBuffer(buffer))
|
||||
{
|
||||
mBufferMap[buffer] = new Buffer();
|
||||
mBufferMap[buffer] = new Buffer(mBufferBackEnd);
|
||||
}
|
||||
|
||||
elementArrayBuffer = buffer;
|
||||
|
@ -915,161 +920,68 @@ void Context::applyState()
|
|||
device->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
// Applies the vertex attribute and array bindings to the Direct3D 9 device
|
||||
void Context::applyVertexBuffer(int count)
|
||||
// Fill in the programAttribute field of the array of TranslatedAttributes based on the active GLSL program.
|
||||
void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
Program *programObject = getCurrentProgram();
|
||||
IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
|
||||
|
||||
D3DVERTEXELEMENT9 vertexElements[MAX_VERTEX_ATTRIBS + 1];
|
||||
D3DVERTEXELEMENT9 *currentElement = &vertexElements[0];
|
||||
|
||||
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (vertexAttribute[attributeIndex].enabled && programObject->isActiveAttribute(attributeIndex))
|
||||
if (attributes[i].enabled)
|
||||
{
|
||||
GLuint boundBuffer = vertexAttribute[attributeIndex].boundBuffer;
|
||||
UINT stride = vertexAttribute[attributeIndex].stride;
|
||||
GLint size = vertexAttribute[attributeIndex].size;
|
||||
GLenum type = vertexAttribute[attributeIndex].type;
|
||||
|
||||
if (stride == 0)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GL_BYTE: stride = size * sizeof(GLbyte); break;
|
||||
case GL_UNSIGNED_BYTE: stride = size * sizeof(GLubyte); break;
|
||||
case GL_SHORT: stride = size * sizeof(GLshort); break;
|
||||
case GL_UNSIGNED_SHORT: stride = size * sizeof(GLushort); break;
|
||||
case GL_FIXED: stride = size * sizeof(GLfixed); break;
|
||||
case GL_FLOAT: stride = size * sizeof(GLfloat); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
currentElement->Stream = attributeIndex;
|
||||
|
||||
if (boundBuffer)
|
||||
{
|
||||
currentElement->Offset = (unsigned short)vertexAttribute[attributeIndex].pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentElement->Offset = 0;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GL_BYTE:
|
||||
if (vertexAttribute[attributeIndex].normalized)
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
break;
|
||||
case GL_UNSIGNED_BYTE:
|
||||
if (vertexAttribute[attributeIndex].normalized)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1: UNIMPLEMENTED(); // FIXME
|
||||
case 2: UNIMPLEMENTED(); // FIXME
|
||||
case 3: UNIMPLEMENTED(); // FIXME
|
||||
case 4: currentElement->Type = D3DDECLTYPE_UBYTE4N; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
break;
|
||||
case GL_SHORT:
|
||||
if (vertexAttribute[attributeIndex].normalized)
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
break;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
if (vertexAttribute[attributeIndex].normalized)
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
else
|
||||
{
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
break;
|
||||
case GL_FIXED:
|
||||
UNIMPLEMENTED(); // FIXME
|
||||
break;
|
||||
case GL_FLOAT:
|
||||
switch (size)
|
||||
{
|
||||
case 1: currentElement->Type = D3DDECLTYPE_FLOAT1; break;
|
||||
case 2: currentElement->Type = D3DDECLTYPE_FLOAT2; break;
|
||||
case 3: currentElement->Type = D3DDECLTYPE_FLOAT3; break;
|
||||
case 4: currentElement->Type = D3DDECLTYPE_FLOAT4; break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
|
||||
currentElement->Method = D3DDECLMETHOD_DEFAULT;
|
||||
currentElement->Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
currentElement->UsageIndex = programObject->getInputMapping(attributeIndex);
|
||||
|
||||
currentElement++;
|
||||
|
||||
if (boundBuffer)
|
||||
{
|
||||
Buffer *buffer = getBuffer(boundBuffer);
|
||||
IDirect3DVertexBuffer9 *streamData = buffer->getVertexBuffer();
|
||||
device->SetStreamSource(attributeIndex, streamData, 0, stride);
|
||||
}
|
||||
else if (vertexAttribute[attributeIndex].pointer)
|
||||
{
|
||||
IDirect3DVertexBuffer9 *vertexBuffer = NULL;
|
||||
void *data;
|
||||
|
||||
HRESULT result = device->CreateVertexBuffer(stride * count, 0, 0, D3DPOOL_MANAGED, &vertexBuffer, NULL);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
vertexBuffer->Lock(0, 0, &data, 0);
|
||||
memcpy(data, vertexAttribute[attributeIndex].pointer, stride *count);
|
||||
vertexBuffer->Unlock();
|
||||
|
||||
device->SetStreamSource(attributeIndex, vertexBuffer, 0, stride);
|
||||
vertexBuffer->Release();
|
||||
}
|
||||
else UNIMPLEMENTED(); // FIXME
|
||||
}
|
||||
else
|
||||
{
|
||||
device->SetStreamSource(attributeIndex, NULL, 0, 0);
|
||||
attributes[i].programAttribute = getCurrentProgram()->getInputMapping(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D3DVERTEXELEMENT9 end = D3DDECL_END();
|
||||
*currentElement = end;
|
||||
// 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 (elementArrayBuffer)
|
||||
{
|
||||
Buffer *buffer = getBuffer(elementArrayBuffer);
|
||||
return reinterpret_cast<const Index*>(static_cast<unsigned char*>(buffer->data()) + reinterpret_cast<GLsizei>(indices));
|
||||
}
|
||||
else
|
||||
{
|
||||
return static_cast<const Index*>(indices);
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DVertexDeclaration9 *vertexDeclaration = NULL;
|
||||
HRESULT result = device->CreateVertexDeclaration(vertexElements, &vertexDeclaration);
|
||||
void Context::applyVertexBuffer(GLint first, GLsizei count)
|
||||
{
|
||||
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
|
||||
|
||||
mVertexDataManager->preRenderValidate(first, count, translated);
|
||||
|
||||
lookupAttributeMapping(translated);
|
||||
|
||||
mBufferBackEnd->preDraw(translated);
|
||||
}
|
||||
|
||||
void Context::applyVertexBuffer(GLsizei count, const void *indices, GLenum indexType)
|
||||
{
|
||||
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
|
||||
|
||||
mVertexDataManager->preRenderValidate(adjustIndexPointer(indices), count, translated);
|
||||
|
||||
lookupAttributeMapping(translated);
|
||||
|
||||
mBufferBackEnd->preDraw(translated);
|
||||
}
|
||||
|
||||
// Applies the indices and element array bindings to the Direct3D 9 device
|
||||
void Context::applyIndexBuffer(const void *indices, GLsizei count)
|
||||
{
|
||||
GLsizei length = count * sizeof(Index);
|
||||
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
IDirect3DIndexBuffer9 *indexBuffer = NULL;
|
||||
void *data;
|
||||
|
||||
HRESULT result = device->CreateIndexBuffer(length, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
|
@ -1078,53 +990,17 @@ void Context::applyVertexBuffer(int count)
|
|||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
if (vertexDeclaration)
|
||||
if (indexBuffer)
|
||||
{
|
||||
device->SetVertexDeclaration(vertexDeclaration);
|
||||
vertexDeclaration->Release(); // Will only effectively be deleted when no longer in use
|
||||
}
|
||||
}
|
||||
|
||||
// Applies the indices and element array bindings to the Direct3D 9 device
|
||||
void Context::applyIndexBuffer(const void *indices, int length)
|
||||
{
|
||||
IDirect3DDevice9 *device = getDevice();
|
||||
|
||||
if (elementArrayBuffer)
|
||||
{
|
||||
Buffer *buffer = getBuffer(elementArrayBuffer);
|
||||
IDirect3DIndexBuffer9 *indexBuffer = buffer->getIndexBuffer();
|
||||
indexBuffer->Lock(0, length, &data, 0);
|
||||
memcpy(data, adjustIndexPointer(indices), length);
|
||||
indexBuffer->Unlock();
|
||||
|
||||
device->SetIndices(indexBuffer);
|
||||
startIndex = (unsigned int)(size_t)indices / 2; // FIXME: Assumes even value and 16-bit indices
|
||||
indexBuffer->Release(); // Will only effectively be deleted when no longer in use
|
||||
}
|
||||
else if (indices)
|
||||
{
|
||||
IDirect3DIndexBuffer9 *indexBuffer = NULL;
|
||||
void *data;
|
||||
|
||||
HRESULT result = device->CreateIndexBuffer(length, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &indexBuffer, NULL);
|
||||
|
||||
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
|
||||
{
|
||||
return error(GL_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
if (indexBuffer)
|
||||
{
|
||||
indexBuffer->Lock(0, length, &data, 0);
|
||||
memcpy(data, indices, length);
|
||||
indexBuffer->Unlock();
|
||||
|
||||
device->SetIndices(indexBuffer);
|
||||
indexBuffer->Release(); // Will only effectively be deleted when no longer in use
|
||||
}
|
||||
|
||||
startIndex = 0;
|
||||
}
|
||||
else UNREACHABLE();
|
||||
startIndex = 0;
|
||||
}
|
||||
|
||||
// Applies the shaders and shader constants to the Direct3D 9 device
|
||||
|
@ -1521,7 +1397,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
|
|||
}
|
||||
|
||||
applyState();
|
||||
applyVertexBuffer(count);
|
||||
applyVertexBuffer(first, count);
|
||||
applyShaders();
|
||||
applyTextures();
|
||||
|
||||
|
@ -1560,8 +1436,8 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void*
|
|||
}
|
||||
|
||||
applyState();
|
||||
applyVertexBuffer(count);
|
||||
applyIndexBuffer(indices, count * sizeof(unsigned short));
|
||||
applyVertexBuffer(count, indices, type);
|
||||
applyIndexBuffer(indices, count);
|
||||
applyShaders();
|
||||
applyTextures();
|
||||
|
||||
|
@ -1722,9 +1598,9 @@ void Context::detachBuffer(GLuint buffer)
|
|||
|
||||
for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
|
||||
{
|
||||
if (vertexAttribute[attribute].boundBuffer == buffer)
|
||||
if (vertexAttribute[attribute].mBoundBuffer == buffer)
|
||||
{
|
||||
vertexAttribute[attribute].boundBuffer = 0;
|
||||
vertexAttribute[attribute].mBoundBuffer = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,336 @@
|
|||
//
|
||||
// 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.
|
||||
|
||||
#include "geometry/VertexDataManager.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "Program.h"
|
||||
|
||||
#include "Buffer.h"
|
||||
#include "geometry/backend.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 };
|
||||
}
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
VertexDataManager::VertexDataManager(Context *context, BufferBackEnd *backend)
|
||||
: mContext(context), mBackend(backend), mDirtyCurrentValues(true)
|
||||
{
|
||||
mStreamBuffer = mBackend->createVertexBuffer(INITIAL_STREAM_BUFFER_SIZE);
|
||||
try
|
||||
{
|
||||
mCurrentValueBuffer = mBackend->createVertexBuffer(4*sizeof(float)*MAX_VERTEX_ATTRIBS);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
delete mStreamBuffer;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
VertexDataManager::~VertexDataManager()
|
||||
{
|
||||
delete mStreamBuffer;
|
||||
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, GLsizei count)
|
||||
: mIndices(indices), mCount(count)
|
||||
{
|
||||
}
|
||||
|
||||
void VertexDataManager::IndexedTranslationHelper::translate(const FormatConverter &converter, GLsizei stride, const void *source, void *dest)
|
||||
{
|
||||
converter.convertIndexed(source, stride, mCount, mIndices, dest);
|
||||
}
|
||||
|
||||
std::bitset<MAX_VERTEX_ATTRIBS> VertexDataManager::activeAttribs()
|
||||
{
|
||||
std::bitset<MAX_VERTEX_ATTRIBS> active;
|
||||
|
||||
Program *p = mContext->getCurrentProgram();
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (p->isActiveAttribute(i))
|
||||
active[i] = true;
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
GLenum VertexDataManager::preRenderValidate(GLint start, GLsizei count,
|
||||
TranslatedAttribute *outAttribs)
|
||||
|
||||
{
|
||||
ArrayTranslationHelper translationHelper(start, count);
|
||||
|
||||
return internalPreRenderValidate(mContext->vertexAttribute, activeAttribs(), start, start+count, &translationHelper, outAttribs);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void indexRange(const Index *indices, std::size_t count, Index *minOut, Index *maxOut)
|
||||
{
|
||||
ASSERT(count > 0);
|
||||
|
||||
Index minSoFar = indices[0];
|
||||
Index maxSoFar = indices[0];
|
||||
|
||||
for (std::size_t i = 1; i < count; i++)
|
||||
{
|
||||
if (indices[i] > maxSoFar) maxSoFar = indices[i];
|
||||
if (indices[i] < minSoFar) minSoFar = indices[i];
|
||||
}
|
||||
|
||||
*minOut = minSoFar;
|
||||
*maxOut = maxSoFar;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
GLenum VertexDataManager::preRenderValidate(const Index *indices, GLsizei count,
|
||||
TranslatedAttribute *outAttribs)
|
||||
|
||||
{
|
||||
Index minIndex;
|
||||
Index maxIndex;
|
||||
|
||||
indexRange(indices, count, &minIndex, &maxIndex);
|
||||
|
||||
IndexedTranslationHelper translationHelper(indices, count);
|
||||
|
||||
return internalPreRenderValidate(mContext->vertexAttribute, activeAttribs(), minIndex, maxIndex, &translationHelper, outAttribs);
|
||||
}
|
||||
|
||||
GLenum VertexDataManager::internalPreRenderValidate(const AttributeState *attribs,
|
||||
const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs,
|
||||
Index minIndex,
|
||||
Index maxIndex,
|
||||
TranslationHelper *translator,
|
||||
TranslatedAttribute *outAttribs)
|
||||
{
|
||||
std::bitset<MAX_VERTEX_ATTRIBS> translateOrLift;
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (!activeAttribs[i] && attribs[i].mEnabled && attribs[i].mBoundBuffer != 0 && !mContext->getBuffer(attribs[i].mBoundBuffer))
|
||||
return GL_INVALID_OPERATION;
|
||||
}
|
||||
|
||||
TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
translated[i].enabled = activeAttribs[i];
|
||||
}
|
||||
|
||||
processNonArrayAttributes(attribs, activeAttribs, translated);
|
||||
|
||||
// Handle the identity-mapped attributes.
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (activeAttribs[i] && attribs[i].mEnabled)
|
||||
{
|
||||
if (attribs[i].mBoundBuffer != 0 && mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized).identity)
|
||||
{
|
||||
translated[i].type = attribs[i].mType;
|
||||
translated[i].size = attribs[i].mSize;
|
||||
translated[i].normalized = attribs[i].mNormalized;
|
||||
translated[i].offset = static_cast<std::size_t>(static_cast<const char*>(attribs[i].mPointer) - static_cast<const char*>(NULL));
|
||||
translated[i].stride = interpretGlStride(attribs[i]);
|
||||
translated[i].buffer = mContext->getBuffer(attribs[i].mBoundBuffer)->identityBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
translateOrLift[i] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
if (translateOrLift[i])
|
||||
{
|
||||
requiredSpace += spaceRequired(attribs[i], count);
|
||||
}
|
||||
}
|
||||
|
||||
if (requiredSpace > mStreamBuffer->size())
|
||||
{
|
||||
std::size_t newSize = std::max(requiredSpace, 3 * mStreamBuffer->size() / 2); // 1.5 x mStreamBuffer->size() is arbitrary and should be checked to see we don't have too many reallocations.
|
||||
|
||||
TranslatedVertexBuffer *newStreamBuffer = mBackend->createVertexBuffer(newSize);
|
||||
|
||||
delete mStreamBuffer;
|
||||
mStreamBuffer = newStreamBuffer;
|
||||
}
|
||||
|
||||
mStreamBuffer->reserveSpace(requiredSpace);
|
||||
|
||||
for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (translateOrLift[i])
|
||||
{
|
||||
FormatConverter formatConverter = mBackend->getFormatConverter(attribs[i].mType, attribs[i].mSize, attribs[i].mNormalized);
|
||||
|
||||
translated[i].type = attribs[i].mType;
|
||||
translated[i].size = attribs[i].mSize;
|
||||
translated[i].normalized = attribs[i].mNormalized;
|
||||
translated[i].stride = formatConverter.outputVertexSize;
|
||||
translated[i].buffer = mStreamBuffer;
|
||||
|
||||
void *output = mStreamBuffer->map(spaceRequired(attribs[i], count), &translated[i].offset);
|
||||
|
||||
const void *input;
|
||||
if (attribs[i].mBoundBuffer)
|
||||
{
|
||||
input = mContext->getBuffer(attribs[i].mBoundBuffer)->data();
|
||||
input = static_cast<const char*>(input) + reinterpret_cast<size_t>(attribs[i].mPointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
input = attribs[i].mPointer;
|
||||
}
|
||||
|
||||
translator->translate(formatConverter, interpretGlStride(attribs[i]), input, output);
|
||||
|
||||
mStreamBuffer->unmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::copy(translated, translated + MAX_VERTEX_ATTRIBS, outAttribs);
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
void VertexDataManager::reloadCurrentValues(const AttributeState *attribs, std::size_t *offset)
|
||||
{
|
||||
if (mDirtyCurrentValues)
|
||||
{
|
||||
std::size_t totalSize = 4 * sizeof(float) * MAX_VERTEX_ATTRIBS;
|
||||
|
||||
mCurrentValueBuffer->reserveSpace(totalSize);
|
||||
|
||||
float* p = static_cast<float*>(mCurrentValueBuffer->map(totalSize, offset));
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
memcpy(&p[i*4], attribs[i].mCurrentValue, sizeof(attribs[i].mCurrentValue)); // FIXME: this should be doing a translation. This assumes that GL_FLOATx4 is supported.
|
||||
}
|
||||
|
||||
mCurrentValueBuffer->unmap();
|
||||
|
||||
mDirtyCurrentValues = false;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t VertexDataManager::typeSize(GLenum type) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GL_BYTE: case GL_UNSIGNED_BYTE: return sizeof(GLbyte);
|
||||
case GL_SHORT: case GL_UNSIGNED_SHORT: return sizeof(GLshort);
|
||||
case GL_FIXED: return sizeof(GLfixed);
|
||||
case GL_FLOAT: return sizeof(GLfloat);
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t VertexDataManager::interpretGlStride(const AttributeState &attrib) const
|
||||
{
|
||||
return attrib.mStride ? attrib.mStride : typeSize(attrib.mType) * attrib.mSize;
|
||||
}
|
||||
|
||||
// Round up x (>=0) to the next multiple of multiple (>0).
|
||||
// 0 rounds up to 0.
|
||||
std::size_t VertexDataManager::roundUp(std::size_t x, std::size_t multiple) const
|
||||
{
|
||||
ASSERT(x >= 0);
|
||||
ASSERT(multiple > 0);
|
||||
|
||||
std::size_t remainder = x % multiple;
|
||||
if (remainder != 0)
|
||||
{
|
||||
return x + multiple - remainder;
|
||||
}
|
||||
else
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t VertexDataManager::spaceRequired(const AttributeState &attrib, std::size_t maxVertex) const
|
||||
{
|
||||
std::size_t size = mBackend->getFormatConverter(attrib.mType, attrib.mSize, attrib.mNormalized).outputVertexSize;
|
||||
size *= maxVertex;
|
||||
|
||||
return roundUp(size, 4 * sizeof(GLfloat));
|
||||
}
|
||||
|
||||
void VertexDataManager::processNonArrayAttributes(const AttributeState *attribs, const std::bitset<MAX_VERTEX_ATTRIBS> &activeAttribs, TranslatedAttribute *translated)
|
||||
{
|
||||
bool usesCurrentValues = false;
|
||||
|
||||
for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (activeAttribs[i] && !attribs[i].mEnabled)
|
||||
{
|
||||
usesCurrentValues = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usesCurrentValues)
|
||||
{
|
||||
std::size_t currentValueOffset;
|
||||
|
||||
reloadCurrentValues(attribs, ¤tValueOffset);
|
||||
|
||||
for (std::size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (activeAttribs[i] && !attribs[i].mEnabled)
|
||||
{
|
||||
translated[i].buffer = mCurrentValueBuffer;
|
||||
|
||||
translated[i].type = GL_FLOAT;
|
||||
translated[i].size = 4;
|
||||
translated[i].normalized = false;
|
||||
translated[i].stride = 0;
|
||||
translated[i].offset = currentValueOffset + 4 * sizeof(float) * i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
//
|
||||
// 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_
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// 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_
|
|
@ -0,0 +1,327 @@
|
|||
//
|
||||
// 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.
|
||||
|
||||
#include "dx9.h"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#define GL_APICALL
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include "Context.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "geometry/vertexconversion.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
template <class InputType, template <std::size_t IncomingWidth> class WidenRule, class ElementConverter, class DefaultValueRule = gl::SimpleDefaultValues<InputType> >
|
||||
class FormatConverterFactory
|
||||
{
|
||||
private:
|
||||
template <std::size_t IncomingWidth>
|
||||
static gl::FormatConverter getFormatConverterForSize()
|
||||
{
|
||||
gl::FormatConverter formatConverter;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public:
|
||||
static gl::FormatConverter getFormatConverter(std::size_t size)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 1: return getFormatConverterForSize<1>();
|
||||
case 2: return getFormatConverterForSize<2>();
|
||||
case 3: return getFormatConverterForSize<3>();
|
||||
case 4: return getFormatConverterForSize<4>();
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace gl
|
||||
{
|
||||
|
||||
Dx9BackEnd::Dx9BackEnd(IDirect3DDevice9 *d3ddevice)
|
||||
: mDevice(d3ddevice)
|
||||
{
|
||||
mDevice->AddRef();
|
||||
}
|
||||
|
||||
Dx9BackEnd::~Dx9BackEnd()
|
||||
{
|
||||
mDevice->Release();
|
||||
}
|
||||
|
||||
TranslatedVertexBuffer *Dx9BackEnd::createVertexBuffer(std::size_t size)
|
||||
{
|
||||
return new Dx9VertexBuffer(mDevice, size);
|
||||
}
|
||||
|
||||
TranslatedIndexBuffer *Dx9BackEnd::createIndexBuffer(std::size_t size)
|
||||
{
|
||||
return new Dx9IndexBuffer(mDevice, size);
|
||||
}
|
||||
|
||||
// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
|
||||
//
|
||||
// BYTE Translate to SHORT, expand to x2,x4 as needed.
|
||||
// BYTE-norm Translate to FLOAT since it can't be exactly represented as SHORT-norm.
|
||||
// UNSIGNED_BYTE x4 only. x1,x2,x3=>x4
|
||||
// UNSIGNED_BYTE-norm x4 only, x1,x2,x3=>x4
|
||||
// SHORT x2,x4 supported. x1=>x2, x3=>x4
|
||||
// SHORT-norm x2,x4 supported. x1=>x2, x3=>x4
|
||||
// UNSIGNED_SHORT unsupported, translate to float
|
||||
// UNSIGNED_SHORT-norm x2,x4 supported. x1=>x2, x3=>x4
|
||||
// FIXED (not in WebGL) Translate to float.
|
||||
// FLOAT Fully supported.
|
||||
|
||||
FormatConverter Dx9BackEnd::getFormatConverter(GLenum type, std::size_t size, bool normalize)
|
||||
{
|
||||
// FIXME: This should be rewritten to use C99 exact-sized types.
|
||||
switch (type)
|
||||
{
|
||||
case GL_BYTE:
|
||||
if (normalize)
|
||||
{
|
||||
return FormatConverterFactory<char, NoWiden, Normalize<char> >::getFormatConverter(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatConverterFactory<char, WidenToEven, Cast<char, short> >::getFormatConverter(size);
|
||||
}
|
||||
|
||||
case GL_UNSIGNED_BYTE:
|
||||
if (normalize)
|
||||
{
|
||||
return FormatConverterFactory<unsigned char, WidenToFour, Identity<unsigned char>, NormalizedDefaultValues<unsigned char> >::getFormatConverter(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatConverterFactory<unsigned char, WidenToFour, Identity<unsigned char> >::getFormatConverter(size);
|
||||
}
|
||||
|
||||
case GL_SHORT:
|
||||
if (normalize)
|
||||
{
|
||||
return FormatConverterFactory<short, WidenToEven, Identity<short>, NormalizedDefaultValues<short> >::getFormatConverter(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatConverterFactory<short, WidenToEven, Identity<short> >::getFormatConverter(size);
|
||||
}
|
||||
|
||||
case GL_UNSIGNED_SHORT:
|
||||
if (normalize)
|
||||
{
|
||||
return FormatConverterFactory<unsigned short, WidenToEven, Identity<unsigned short>, NormalizedDefaultValues<unsigned short> >::getFormatConverter(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FormatConverterFactory<unsigned short, NoWiden, Cast<unsigned short, float> >::getFormatConverter(size);
|
||||
}
|
||||
|
||||
case GL_FIXED:
|
||||
return FormatConverterFactory<int, NoWiden, FixedToFloat<int, 16> >::getFormatConverter(size);
|
||||
|
||||
case GL_FLOAT:
|
||||
return FormatConverterFactory<float, NoWiden, Identity<float> >::getFormatConverter(size);
|
||||
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
D3DDECLTYPE Dx9BackEnd::mapAttributeType(GLenum type, std::size_t size, bool normalized) const
|
||||
{
|
||||
static const D3DDECLTYPE byteTypes[2][4] = { { D3DDECLTYPE_SHORT2, D3DDECLTYPE_SHORT2, D3DDECLTYPE_SHORT4, D3DDECLTYPE_SHORT4 }, { D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT4 } };
|
||||
static const D3DDECLTYPE shortTypes[2][4] = { { D3DDECLTYPE_SHORT2, D3DDECLTYPE_SHORT2, D3DDECLTYPE_SHORT4, D3DDECLTYPE_SHORT4 }, { D3DDECLTYPE_SHORT2N, D3DDECLTYPE_SHORT2N, D3DDECLTYPE_SHORT4N, D3DDECLTYPE_SHORT4N } };
|
||||
static const D3DDECLTYPE ushortTypes[2][4] = { { D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT4 }, { D3DDECLTYPE_USHORT2N, D3DDECLTYPE_USHORT2N, D3DDECLTYPE_USHORT4N, D3DDECLTYPE_USHORT4N } };
|
||||
|
||||
static const D3DDECLTYPE floatTypes[4] = { D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3, D3DDECLTYPE_FLOAT4 };
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GL_BYTE: return byteTypes[normalized][size-1];
|
||||
case GL_UNSIGNED_BYTE: return normalized ? D3DDECLTYPE_UBYTE4N : D3DDECLTYPE_UBYTE4;
|
||||
case GL_SHORT: return shortTypes[normalized][size-1];
|
||||
case GL_UNSIGNED_SHORT: return ushortTypes[normalized][size-1];
|
||||
|
||||
case GL_FIXED:
|
||||
case GL_FLOAT:
|
||||
return floatTypes[size-1];
|
||||
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DVertexBuffer9 *Dx9BackEnd::getDxBuffer(TranslatedVertexBuffer *vb) const
|
||||
{
|
||||
return vb ? static_cast<Dx9VertexBuffer*>(vb)->getBuffer() : NULL;
|
||||
}
|
||||
|
||||
IDirect3DIndexBuffer9 *Dx9BackEnd::getDxBuffer(TranslatedIndexBuffer *ib) const
|
||||
{
|
||||
return ib ? static_cast<Dx9IndexBuffer*>(ib)->getBuffer() : NULL;
|
||||
}
|
||||
|
||||
GLenum Dx9BackEnd::preDraw(const TranslatedAttribute *attributes)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS+1];
|
||||
|
||||
D3DVERTEXELEMENT9 *nextElement = &elements[0];
|
||||
|
||||
for (BYTE i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (attributes[i].enabled)
|
||||
{
|
||||
nextElement->Stream = i;
|
||||
nextElement->Offset = 0;
|
||||
nextElement->Type = static_cast<BYTE>(mapAttributeType(attributes[i].type, attributes[i].size, attributes[i].normalized));
|
||||
nextElement->Method = D3DDECLMETHOD_DEFAULT;
|
||||
nextElement->Usage = D3DDECLUSAGE_TEXCOORD;
|
||||
nextElement->UsageIndex = attributes[i].programAttribute;
|
||||
nextElement++;
|
||||
}
|
||||
}
|
||||
|
||||
static const D3DVERTEXELEMENT9 end = D3DDECL_END();
|
||||
*nextElement = end;
|
||||
|
||||
IDirect3DVertexDeclaration9* vertexDeclaration;
|
||||
hr = mDevice->CreateVertexDeclaration(elements, &vertexDeclaration);
|
||||
mDevice->SetVertexDeclaration(vertexDeclaration);
|
||||
vertexDeclaration->Release();
|
||||
|
||||
for (size_t i = 0; i < MAX_VERTEX_ATTRIBS; i++)
|
||||
{
|
||||
if (attributes[i].enabled)
|
||||
{
|
||||
mDevice->SetStreamSource(i, getDxBuffer(attributes[i].buffer), attributes[i].offset, attributes[i].stride);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDevice->SetStreamSource(i, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return GL_NO_ERROR;
|
||||
}
|
||||
|
||||
Dx9BackEnd::Dx9VertexBuffer::Dx9VertexBuffer(IDirect3DDevice9 *device, std::size_t size)
|
||||
: TranslatedVertexBuffer(size)
|
||||
{
|
||||
HRESULT hr = device->CreateVertexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mVertexBuffer, NULL);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
ERR("Out of memory allocating a vertex buffer of size %lu.", size);
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
Dx9BackEnd::Dx9VertexBuffer::~Dx9VertexBuffer()
|
||||
{
|
||||
mVertexBuffer->Release();
|
||||
}
|
||||
|
||||
IDirect3DVertexBuffer9 *Dx9BackEnd::Dx9VertexBuffer::getBuffer() const
|
||||
{
|
||||
return mVertexBuffer;
|
||||
}
|
||||
|
||||
void *Dx9BackEnd::Dx9VertexBuffer::map()
|
||||
{
|
||||
void *mapPtr;
|
||||
|
||||
mVertexBuffer->Lock(0, 0, &mapPtr, 0);
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
void Dx9BackEnd::Dx9VertexBuffer::unmap()
|
||||
{
|
||||
mVertexBuffer->Unlock();
|
||||
}
|
||||
|
||||
void Dx9BackEnd::Dx9VertexBuffer::recycle()
|
||||
{
|
||||
void *dummy;
|
||||
mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
|
||||
mVertexBuffer->Unlock();
|
||||
}
|
||||
|
||||
void *Dx9BackEnd::Dx9VertexBuffer::streamingMap(std::size_t offset, std::size_t size)
|
||||
{
|
||||
void *mapPtr;
|
||||
|
||||
mVertexBuffer->Lock(offset, size, &mapPtr, D3DLOCK_NOOVERWRITE);
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
Dx9BackEnd::Dx9IndexBuffer::Dx9IndexBuffer(IDirect3DDevice9 *device, std::size_t size)
|
||||
: TranslatedIndexBuffer(size)
|
||||
{
|
||||
HRESULT hr = device->CreateIndexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &mIndexBuffer, NULL);
|
||||
if (hr != S_OK)
|
||||
{
|
||||
ERR("Out of memory allocating an index buffer of size %lu.", size);
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
}
|
||||
|
||||
Dx9BackEnd::Dx9IndexBuffer::~Dx9IndexBuffer()
|
||||
{
|
||||
mIndexBuffer->Release();
|
||||
}
|
||||
|
||||
IDirect3DIndexBuffer9*Dx9BackEnd::Dx9IndexBuffer::getBuffer() const
|
||||
{
|
||||
return mIndexBuffer;
|
||||
}
|
||||
|
||||
void *Dx9BackEnd::Dx9IndexBuffer::map()
|
||||
{
|
||||
void *mapPtr;
|
||||
|
||||
mIndexBuffer->Lock(0, 0, &mapPtr, 0);
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
void Dx9BackEnd::Dx9IndexBuffer::unmap()
|
||||
{
|
||||
mIndexBuffer->Unlock();
|
||||
}
|
||||
|
||||
void Dx9BackEnd::Dx9IndexBuffer::recycle()
|
||||
{
|
||||
void *dummy;
|
||||
mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD);
|
||||
mIndexBuffer->Unlock();
|
||||
}
|
||||
|
||||
void *Dx9BackEnd::Dx9IndexBuffer::streamingMap(std::size_t offset, std::size_t size)
|
||||
{
|
||||
void *mapPtr;
|
||||
|
||||
mIndexBuffer->Lock(offset, size, &mapPtr, D3DLOCK_NOOVERWRITE);
|
||||
|
||||
return mapPtr;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// 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_
|
|
@ -0,0 +1,228 @@
|
|||
//
|
||||
// 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
|
|||
return error(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
buffer->storeData(size, data);
|
||||
buffer->bufferData(data, size, usage);
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
|
@ -474,7 +474,36 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
|
|||
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&)
|
||||
{
|
||||
|
@ -1100,7 +1129,7 @@ void __stdcall glDisableVertexAttribArray(GLuint index)
|
|||
|
||||
if (context)
|
||||
{
|
||||
context->vertexAttribute[index].enabled = false;
|
||||
context->vertexAttribute[index].mEnabled = false;
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
|
@ -1214,7 +1243,7 @@ void __stdcall glEnableVertexAttribArray(GLuint index)
|
|||
|
||||
if (context)
|
||||
{
|
||||
context->vertexAttribute[index].enabled = true;
|
||||
context->vertexAttribute[index].mEnabled = true;
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
|
@ -3777,12 +3806,12 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo
|
|||
|
||||
if (context)
|
||||
{
|
||||
context->vertexAttribute[index].boundBuffer = context->arrayBuffer;
|
||||
context->vertexAttribute[index].size = size;
|
||||
context->vertexAttribute[index].type = type;
|
||||
context->vertexAttribute[index].normalized = normalized;
|
||||
context->vertexAttribute[index].stride = stride;
|
||||
context->vertexAttribute[index].pointer = ptr;
|
||||
context->vertexAttribute[index].mBoundBuffer = context->arrayBuffer;
|
||||
context->vertexAttribute[index].mSize = size;
|
||||
context->vertexAttribute[index].mType = type;
|
||||
context->vertexAttribute[index].mNormalized = normalized;
|
||||
context->vertexAttribute[index].mStride = stride;
|
||||
context->vertexAttribute[index].mPointer = ptr;
|
||||
}
|
||||
}
|
||||
catch(std::bad_alloc&)
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../Include/; ../Compiler/"
|
||||
AdditionalIncludeDirectories="../Include/; ../Compiler/;."
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
|
@ -118,7 +118,7 @@
|
|||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="../Include/; ../Compiler/"
|
||||
AdditionalIncludeDirectories="../Include/; ../Compiler/;."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBGLESV2_EXPORTS;_CRT_SECURE_NO_DEPRECATE;NOMINMAX"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
|
@ -224,6 +224,22 @@
|
|||
RelativePath=".\utilities.cpp"
|
||||
>
|
||||
</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
|
||||
Name="Header Files"
|
||||
|
@ -302,6 +318,26 @@
|
|||
RelativePath=".\utilities.h"
|
||||
>
|
||||
</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
|
||||
Name="Resource Files"
|
||||
|
|
Загрузка…
Ссылка в новой задаче