Example #1
0
/* 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();
}
Example #2
0
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);
}
Example #3
0
/* 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");
    }
}
Example #4
0
/* 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");
    }
}