/* GL locking is done by the caller */ static void drawStridedSlowVs(IWineD3DDevice *iface, const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, UINT idxSize, UINT startIdx) { IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; const struct wined3d_gl_info *gl_info = &This->adapter->gl_info; LONG SkipnStrides = startIdx + This->stateBlock->loadBaseVertexIndex; const WORD *pIdxBufS = NULL; const DWORD *pIdxBufL = NULL; UINT vx_index; int i; IWineD3DStateBlockImpl *stateblock = This->stateBlock; const BYTE *ptr; if (idxSize) { /* 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 non-NULL. */ if (!idxData) idxData = buffer_get_sysmem((struct wined3d_buffer *)This->stateBlock->pIndexData, gl_info); if (idxSize == 2) pIdxBufS = idxData; else pIdxBufL = idxData; } else if (idxData) { ERR("non-NULL idxData with 0 idxSize, this should never happen\n"); return; } /* Start drawing in GL */ glBegin(glPrimitiveType); for (vx_index = 0; vx_index < numberOfVertices; ++vx_index) { if (idxData != NULL) { /* Indexed so work out the number of strides to skip */ if (idxSize == 2) SkipnStrides = pIdxBufS[startIdx + vx_index] + stateblock->loadBaseVertexIndex; else SkipnStrides = pIdxBufL[startIdx + vx_index] + stateblock->loadBaseVertexIndex; } for (i = MAX_ATTRIBS - 1; i >= 0; i--) { if (!(si->use_map & (1 << i))) continue; ptr = si->elements[i].data + si->elements[i].stride * SkipnStrides + stateblock->streamOffset[si->elements[i].stream_idx]; send_attribute(This, si->elements[i].format_desc->format, i, ptr); } SkipnStrides++; } glEnd(); }
void GenericRenderer::set_auto_attributes_on_shader(Renderable &buffer) { /* * Binding attributes generically is hard. So we have some template magic in the send_attribute * function above that takes the VertexData member functions we need to provide the attribute * and just makes the whole thing generic. Before this was 100s of lines of boilerplate. Thank god * for templates! */ send_attribute(SP_ATTR_VERTEX_POSITION, buffer.vertex_data(), &VertexData::has_positions, &VertexData::position_offset); send_attribute(SP_ATTR_VERTEX_TEXCOORD0, buffer.vertex_data(), &VertexData::has_texcoord0, &VertexData::texcoord0_offset); send_attribute(SP_ATTR_VERTEX_TEXCOORD1, buffer.vertex_data(), &VertexData::has_texcoord1, &VertexData::texcoord1_offset); send_attribute(SP_ATTR_VERTEX_TEXCOORD2, buffer.vertex_data(), &VertexData::has_texcoord2, &VertexData::texcoord2_offset); send_attribute(SP_ATTR_VERTEX_TEXCOORD3, buffer.vertex_data(), &VertexData::has_texcoord3, &VertexData::texcoord3_offset); send_attribute(SP_ATTR_VERTEX_DIFFUSE, buffer.vertex_data(), &VertexData::has_diffuse, &VertexData::diffuse_offset); send_attribute(SP_ATTR_VERTEX_NORMAL, buffer.vertex_data(), &VertexData::has_normals, &VertexData::normal_offset); }
/* GL locking is done by the caller */ static inline void drawStridedInstanced(IWineD3DDevice *iface, const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, UINT idxSize, UINT startIdx) { UINT numInstances = 0, i; int numInstancedAttribs = 0, j; UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */]; IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface; IWineD3DStateBlockImpl *stateblock = This->stateBlock; 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 * * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements. * But the StreamSourceFreq value has a different meaning in that situation. */ FIXME("Non-indexed instanced drawing is not supported\n"); return; } TRACE("(%p) : glElements(%x, %d, ...)\n", This, glPrimitiveType, numberOfVertices); /* First, figure out how many instances we have to draw */ for(i = 0; i < MAX_STREAMS; i++) { /* Look at the streams and take the first one which matches */ if(((stateblock->streamFlags[i] & WINED3DSTREAMSOURCE_INSTANCEDATA) || (stateblock->streamFlags[i] & WINED3DSTREAMSOURCE_INDEXEDDATA)) && stateblock->streamSource[i]) { /* D3D9 could set streamFreq 0 with (INSTANCEDATA or INDEXEDDATA) and then it is handled as 1. See d3d9/tests/visual.c-> stream_test() */ if(stateblock->streamFreq[i] == 0){ numInstances = 1; } else { numInstances = stateblock->streamFreq[i]; /* use the specified number of instances from the first matched stream. See d3d9/tests/visual.c-> stream_test() */ } break; /* break, because only the first suitable value is interesting */ } } for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i) { if (!(si->use_map & (1 << i))) continue; if (stateblock->streamFlags[si->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA) { instancedData[numInstancedAttribs] = i; numInstancedAttribs++; } } /* now draw numInstances instances :-) */ for(i = 0; i < numInstances; i++) { /* Specify the instanced attributes using immediate mode calls */ for(j = 0; j < numInstancedAttribs; j++) { const BYTE *ptr = si->elements[instancedData[j]].data + si->elements[instancedData[j]].stride * i + stateblock->streamOffset[si->elements[instancedData[j]].stream_idx]; if (si->elements[instancedData[j]].buffer_object) { struct wined3d_buffer *vb = (struct wined3d_buffer *)stateblock->streamSource[si->elements[instancedData[j]].stream_idx]; ptr += (long) buffer_get_sysmem(vb); } send_attribute(This, si->elements[instancedData[j]].format_desc->format, instancedData[j], ptr); } glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (const char *)idxData+(idxSize * startIdx)); checkGLcall("glDrawElements"); } }
/* GL locking is done by the caller */ static void drawStridedInstanced(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state, const struct wined3d_stream_info *si, UINT numberOfVertices, GLenum glPrimitiveType, const void *idxData, UINT idxSize, UINT startIdx) { UINT numInstances = 0, i; int numInstancedAttribs = 0, j; UINT instancedData[sizeof(si->elements) / sizeof(*si->elements) /* 16 */]; if (!idxSize) { /* 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 * * Shouldn't be too hard to support with opengl, in theory just call glDrawArrays instead of drawElements. * But the StreamSourceFreq value has a different meaning in that situation. */ FIXME("Non-indexed instanced drawing is not supported\n"); return; } /* First, figure out how many instances we have to draw */ for (i = 0; i < MAX_STREAMS; ++i) { /* Look at the streams and take the first one which matches */ if (state->streams[i].buffer && ((state->streams[i].flags & WINED3DSTREAMSOURCE_INSTANCEDATA) || (state->streams[i].flags & WINED3DSTREAMSOURCE_INDEXEDDATA))) { /* Use the specified number of instances from the first matched * stream. A streamFreq of 0 (with INSTANCEDATA or INDEXEDDATA) * is handled as 1. See d3d9/tests/visual.c-> stream_test(). */ numInstances = state->streams[i].frequency ? state->streams[i].frequency : 1; break; } } for (i = 0; i < sizeof(si->elements) / sizeof(*si->elements); ++i) { if (!(si->use_map & (1 << i))) continue; if (state->streams[si->elements[i].stream_idx].flags & WINED3DSTREAMSOURCE_INSTANCEDATA) { instancedData[numInstancedAttribs] = i; numInstancedAttribs++; } } /* now draw numInstances instances :-) */ for(i = 0; i < numInstances; i++) { /* Specify the instanced attributes using immediate mode calls */ for(j = 0; j < numInstancedAttribs; j++) { const BYTE *ptr = si->elements[instancedData[j]].data + si->elements[instancedData[j]].stride * i + state->streams[si->elements[instancedData[j]].stream_idx].offset; if (si->elements[instancedData[j]].buffer_object) { struct wined3d_buffer *vb = state->streams[si->elements[instancedData[j]].stream_idx].buffer; ptr += (ULONG_PTR)buffer_get_sysmem(vb, gl_info); } send_attribute(gl_info, si->elements[instancedData[j]].format->id, instancedData[j], ptr); } glDrawElements(glPrimitiveType, numberOfVertices, idxSize == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (const char *)idxData+(idxSize * startIdx)); checkGLcall("glDrawElements"); } }