wined3d: Use VBOs for index buffers.
This commit is contained in:
parent
ecfd4cb0e4
commit
59ae2a56fb
|
@ -443,21 +443,67 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *ifac
|
|||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
|
||||
GLenum error, glUsage;
|
||||
TRACE("Creating VBO for Index Buffer %p\n", object);
|
||||
|
||||
ENTER_GL();
|
||||
while(glGetError());
|
||||
|
||||
GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
|
||||
error = glGetError();
|
||||
if(error != GL_NO_ERROR || object->vbo == 0) {
|
||||
ERR("Creating a vbo failed, continueing without vbo for this buffer\n");
|
||||
object->vbo = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
|
||||
error = glGetError();
|
||||
if(error != GL_NO_ERROR) {
|
||||
ERR("Failed to bind index buffer, continueing without vbo for this buffer\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
|
||||
* copy no readback will be needed
|
||||
*/
|
||||
glUsage = GL_STATIC_DRAW;
|
||||
GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
|
||||
error = glGetError();
|
||||
if(error != GL_NO_ERROR) {
|
||||
ERR("Failed to initialize the index buffer\n");
|
||||
goto out;
|
||||
}
|
||||
LEAVE_GL();
|
||||
TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
|
||||
return;
|
||||
|
||||
out:
|
||||
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
|
||||
GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
|
||||
LEAVE_GL();
|
||||
object->vbo = 0;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
|
||||
WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
|
||||
HANDLE *sharedHandle, IUnknown *parent) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
IWineD3DIndexBufferImpl *object;
|
||||
TRACE("(%p) Creating index buffer\n", This);
|
||||
|
||||
|
||||
/* Allocate the storage for the device */
|
||||
D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
|
||||
|
||||
/*TODO: use VBO's */
|
||||
if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
|
||||
|
||||
if (Pool == WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
|
||||
object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
|
||||
}
|
||||
|
||||
if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
|
||||
CreateIndexBufferVBO(This, object);
|
||||
}
|
||||
|
||||
TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
|
||||
debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
|
||||
*ppIndexBuffer = (IWineD3DIndexBuffer *) object;
|
||||
|
@ -2557,10 +2603,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWine
|
|||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
/* So far only the base vertex index is tracked */
|
||||
/* The base vertex index affects the stream sources, while
|
||||
* The index buffer is a seperate index buffer state
|
||||
*/
|
||||
if(BaseVertexIndex != oldBaseIndex) {
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
|
||||
}
|
||||
if(oldIdxs != pIndexData) {
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
|
||||
}
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
|
@ -4224,9 +4275,11 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *
|
|||
UINT idxStride = 2;
|
||||
IWineD3DIndexBuffer *pIB;
|
||||
WINED3DINDEXBUFFER_DESC IdxBufDsc;
|
||||
GLint vbo;
|
||||
|
||||
pIB = This->stateBlock->pIndexData;
|
||||
This->stateBlock->streamIsUP = FALSE;
|
||||
vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
|
||||
|
||||
TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
|
||||
PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
|
||||
|
@ -4245,7 +4298,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *
|
|||
}
|
||||
|
||||
drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
|
||||
idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
|
||||
idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
@ -4310,6 +4363,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *
|
|||
This->stateBlock->loadBaseVertexIndex = 0;
|
||||
/* Mark the state dirty until we have nicer tracking of the stream source pointers */
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
|
||||
|
||||
drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
|
||||
|
||||
|
@ -4332,8 +4386,10 @@ static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *i
|
|||
* that value.
|
||||
*/
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
|
||||
IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
|
||||
This->stateBlock->baseVertexIndex = 0;
|
||||
This->up_strided = DrawPrimStrideData;
|
||||
This->stateBlock->streamIsUP = TRUE;
|
||||
drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
|
||||
This->up_strided = NULL;
|
||||
return WINED3D_OK;
|
||||
|
|
|
@ -571,7 +571,7 @@ static void drawStridedFast(IWineD3DDevice *iface,UINT numberOfVertices, GLenum
|
|||
const void *idxData, short idxSize, ULONG minIndex, ULONG startIdx, ULONG startVertex) {
|
||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||
|
||||
if (idxData != NULL /* This crashes sometimes!*/) {
|
||||
if (idxSize != 0 /* This crashes sometimes!*/) {
|
||||
TRACE("(%p) : glElements(%x, %d, %d, ...)\n", This, glPrimitiveType, numberOfVertices, minIndex);
|
||||
idxData = idxData == (void *)-1 ? NULL : idxData;
|
||||
#if 1
|
||||
|
@ -629,7 +629,15 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
|
|||
TRACE("Using slow vertex array code\n");
|
||||
|
||||
/* Variable Initialization */
|
||||
if (idxData != NULL) {
|
||||
if (idxSize != 0) {
|
||||
/* Immediate mode drawing can't make use of indices in a vbo - get the data from the index buffer.
|
||||
* If the index buffer has no vbo(not supported or other reason), or with user pointer drawing
|
||||
* idxData will be != NULL
|
||||
*/
|
||||
if(idxData == NULL) {
|
||||
idxData = ((IWineD3DIndexBufferImpl *) This->stateBlock->pIndexData)->resource.allocatedMemory;
|
||||
}
|
||||
|
||||
if (idxSize == 2) pIdxBufS = (const short *) idxData;
|
||||
else pIdxBufL = (const long *) idxData;
|
||||
}
|
||||
|
@ -1165,7 +1173,7 @@ inline void drawStridedInstanced(IWineD3DDevice *iface, WineDirect3DVertexStride
|
|||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
|
||||
IWineD3DStateBlockImpl *stateblock = This->stateBlock;
|
||||
|
||||
if (idxData == NULL) {
|
||||
if (idxSize == 0) {
|
||||
/* This is a nasty thing. MSDN says no hardware supports that and apps have to use software vertex processing.
|
||||
* We don't support this for now
|
||||
*
|
||||
|
|
|
@ -58,6 +58,15 @@ static ULONG WINAPI IWineD3DIndexBufferImpl_Release(IWineD3DIndexBuffer *iface)
|
|||
ULONG ref = InterlockedDecrement(&This->resource.ref);
|
||||
TRACE("(%p) : Releasing from %d\n", This, ref + 1);
|
||||
if (ref == 0) {
|
||||
if(This->vbo) {
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
|
||||
checkGLcall("glBindBufferARB");
|
||||
GL_EXTCALL(glDeleteBuffersARB(1, &This->vbo));
|
||||
checkGLcall("glDeleteBuffersARB");
|
||||
LEAVE_GL();
|
||||
}
|
||||
|
||||
IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
|
||||
HeapFree(GetProcessHeap(), 0, This);
|
||||
}
|
||||
|
@ -108,13 +117,49 @@ static HRESULT WINAPI IWineD3DIndexBufferImpl_GetParent(IWineD3DIndexBuffer *ifa
|
|||
****************************************************** */
|
||||
static HRESULT WINAPI IWineD3DIndexBufferImpl_Lock(IWineD3DIndexBuffer *iface, UINT OffsetToLock, UINT SizeToLock, BYTE** ppbData, DWORD Flags) {
|
||||
IWineD3DIndexBufferImpl *This = (IWineD3DIndexBufferImpl *)iface;
|
||||
TRACE("(%p) : no real locking yet, offset %d, size %d, Flags=%x\n", This, OffsetToLock, SizeToLock, Flags);
|
||||
TRACE("(%p) : offset %d, size %d, Flags=%x\n", This, OffsetToLock, SizeToLock, Flags);
|
||||
|
||||
InterlockedIncrement(&This->lockcount);
|
||||
*ppbData = (BYTE *)This->resource.allocatedMemory + OffsetToLock;
|
||||
|
||||
if(Flags & (WINED3DLOCK_READONLY | WINED3DLOCK_NO_DIRTY_UPDATE) || This->vbo == 0) {
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
if(This->dirtystart != This->dirtyend) {
|
||||
if(This->dirtystart > OffsetToLock) This->dirtystart = OffsetToLock;
|
||||
if(SizeToLock) {
|
||||
if(This->dirtyend < OffsetToLock + SizeToLock) This->dirtyend = OffsetToLock + SizeToLock;
|
||||
} else {
|
||||
This->dirtyend = This->resource.size;
|
||||
}
|
||||
} else {
|
||||
This->dirtystart = OffsetToLock;
|
||||
if(SizeToLock)
|
||||
This->dirtyend = OffsetToLock + SizeToLock;
|
||||
else
|
||||
This->dirtyend = This->resource.size;
|
||||
}
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
static HRESULT WINAPI IWineD3DIndexBufferImpl_Unlock(IWineD3DIndexBuffer *iface) {
|
||||
IWineD3DIndexBufferImpl *This = (IWineD3DIndexBufferImpl *)iface;
|
||||
TRACE("(%p) : stub\n", This);
|
||||
unsigned long locks = InterlockedDecrement(&This->lockcount);
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
/* For now load in unlock */
|
||||
if(locks == 0 && This->vbo) {
|
||||
ENTER_GL();
|
||||
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, This->vbo));
|
||||
checkGLcall("glBindBufferARB");
|
||||
GL_EXTCALL(glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
|
||||
This->dirtystart, This->dirtyend - This->dirtystart, This->resource.allocatedMemory + This->dirtystart));
|
||||
checkGLcall("glBufferSubDataARB");
|
||||
LEAVE_GL();
|
||||
This->dirtystart = 0;
|
||||
This->dirtyend = 0;
|
||||
}
|
||||
return WINED3D_OK;
|
||||
}
|
||||
static HRESULT WINAPI IWineD3DIndexBufferImpl_GetDesc(IWineD3DIndexBuffer *iface, WINED3DINDEXBUFFER_DESC *pDesc) {
|
||||
|
|
|
@ -3062,6 +3062,17 @@ static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
|
|||
checkGLcall("glScissor");
|
||||
}
|
||||
|
||||
static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
|
||||
if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
|
||||
if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
|
||||
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
|
||||
} else {
|
||||
IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
|
||||
GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const struct StateEntry StateTable[] =
|
||||
{
|
||||
/* State name representative, apply function */
|
||||
|
@ -4077,6 +4088,7 @@ const struct StateEntry StateTable[] =
|
|||
{ /*511, WINED3DTS_WORLDMATRIX(255) */ STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)), transform_worldex },
|
||||
/* Various Vertex states follow */
|
||||
{ /* , STATE_STREAMSRC */ STATE_VDECL, vertexdeclaration },
|
||||
{ /* , STATE_INDEXBUFFER */ STATE_INDEXBUFFER, indexbuffer },
|
||||
{ /* , STATE_VDECL */ STATE_VDECL, vertexdeclaration },
|
||||
{ /* , STATE_VSHADER */ STATE_VDECL, vertexdeclaration },
|
||||
{ /* , STATE_VIEWPORT */ STATE_VIEWPORT, viewport },
|
||||
|
|
|
@ -426,8 +426,10 @@ typedef void (*APPLYSTATEFUNC)(DWORD state, IWineD3DStateBlockImpl *stateblock,
|
|||
|
||||
#define STATE_STREAMSRC (STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)) + 1)
|
||||
#define STATE_IS_STREAMSRC(a) ((a) == STATE_STREAMSRC)
|
||||
#define STATE_INDEXBUFFER (STATE_STREAMSRC + 1)
|
||||
#define STATE_IS_INDEXBUFFER(a) ((a) == STATE_INDEXBUFFER)
|
||||
|
||||
#define STATE_VDECL (STATE_STREAMSRC + 1)
|
||||
#define STATE_VDECL (STATE_INDEXBUFFER + 1)
|
||||
#define STATE_IS_VDECL(a) ((a) == STATE_VDECL)
|
||||
|
||||
#define STATE_VSHADER (STATE_VDECL + 1)
|
||||
|
@ -793,6 +795,10 @@ typedef struct IWineD3DIndexBufferImpl
|
|||
const IWineD3DIndexBufferVtbl *lpVtbl;
|
||||
IWineD3DResourceClass resource;
|
||||
|
||||
GLuint vbo;
|
||||
UINT dirtystart, dirtyend;
|
||||
LONG lockcount;
|
||||
|
||||
/* WineD3DVertexBuffer specifics */
|
||||
} IWineD3DIndexBufferImpl;
|
||||
|
||||
|
|
Loading…
Reference in New Issue