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:
daniel@transgaming.com 2010-03-11 19:41:38 +00:00
Родитель 45d035808a
Коммит 0f7aaf530b
13 изменённых файлов: 1493 добавлений и 324 удалений

Просмотреть файл

@ -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, &currentValueOffset);
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_

327
libGLESv2/geometry/dx9.cpp Normal file
Просмотреть файл

@ -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;
}
}

81
libGLESv2/geometry/dx9.h Normal file
Просмотреть файл

@ -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"