void GeoImmediatePumpGroup::masterClassicGeoPump(
          DrawEnv                     *pEnv,
    const GeoIntegralProperty         *lengths,
    const GeoIntegralProperty         *types,
    const Geometry::MFPropertiesType  *prop,
    const Geometry::MFPropIndicesType *propIdx)
{
    Window *win = pEnv->getWindow();

    // Setup: get all the data

    // check for empty geometry
    if(types == NULL || types->getSize() == 0)
        return;

    if(!pumpInternalSetup(types,   true))
        return;
    if(!pumpInternalSetup(lengths, false))
        return;

    PumpClassicInfo pumpInfo;
    pumpInfo.lengths = lengths;
    pumpInfo.types   = types;
    pumpInfo.prop    = prop;
    pumpInfo.propIdx = propIdx;

    // setup standard properties
    pumpGLSetup(pumpInfo, Geometry::PositionsIndex, PositionsPumpSlot);
    pumpGLSetup(pumpInfo, Geometry::ColorsIndex,    ColorsPumpSlot);
    pumpGLSetup(pumpInfo, Geometry::NormalsIndex,   NormalsPumpSlot);
    pumpGLSetup(pumpInfo, Geometry::TexCoordsIndex, TexCoordsPumpSlot);

    // setup extension properties
    if(win->hasExtension(_extSecondaryColor) == true)
    {
        pumpGLExtSetup(pumpInfo, Geometry::SecondaryColorsIndex,
                       SecColorsPumpSlot, win);
    }

    // setup extension multi properties
    if(win->hasExtension(_extMultitexture) == true)
    {
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords1Index,
                            TexCoords1PumpSlot, win);
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords2Index,
                            TexCoords2PumpSlot, win);
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords3Index,
                            TexCoords3PumpSlot, win);
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords4Index,
                            TexCoords4PumpSlot, win);
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords5Index,
                            TexCoords5PumpSlot, win);
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords6Index,
                            TexCoords6PumpSlot, win);
        pumpGLExtMultiSetup(pumpInfo, Geometry::TexCoords7Index,
                            TexCoords7PumpSlot, win);
    }

    // we need positions
    if(pumpInfo.attribPtr[Geometry::PositionsIndex] == NULL)
    {
        if(pumpInfo.attribPtr[Geometry::PositionsIndex]              == NULL ||
           pumpInfo.attribPtr[Geometry::PositionsIndex]->getUseVBO() == false)
        {
            SWARNING << "GeoImmediatePumpGroup::masterClassicGeoPump: "
                     << "No positions." << endLog;
            return;
        }
    }

    // global attribs?
    globalAttrib(pumpInfo, Geometry::NormalsIndex,   NormalsPumpSlot);
    globalAttrib(pumpInfo, Geometry::ColorsIndex,    ColorsPumpSlot);
    globalAttrib(pumpInfo, Geometry::TexCoordsIndex, TexCoordsPumpSlot);

    if(win->hasExtension(_extSecondaryColor) == true)
    {
        globalExtAttrib(pumpInfo,          Geometry::SecondaryColorsIndex,
                        SecColorsPumpSlot, win                            );
    }

    if(win->hasExtension(_extMultitexture) == true)
    {
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords1PumpSlot, GL_TEXTURE1_ARB, win);
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords2PumpSlot, GL_TEXTURE2_ARB, win);
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords3PumpSlot, GL_TEXTURE3_ARB, win);
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords4PumpSlot, GL_TEXTURE4_ARB, win);
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords5PumpSlot, GL_TEXTURE5_ARB, win);
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords6PumpSlot, GL_TEXTURE6_ARB, win);
        globalExtMultiAttrib(pumpInfo,           Geometry::TexCoords1Index,
                             TexCoords7PumpSlot, GL_TEXTURE7_ARB, win);
    }

    // Length handling. Special case: no length given

    UInt32 curlen;
    UInt32 nprims;

    // no lengths? use all available data for the first type
    if(lengths == NULL)
    {
        if(types->getSize() != 1)
        {
            SWARNING << "GeoImmediatePumpGroup::masterClassicGeoPump: "
                     << "No lengths, but more than one type?!"
                     << endLog;
            return;
        }

        nprims = 1;
        if(pumpInfo.attribIndex[Geometry::PositionsIndex] != NULL)
        {
            curlen = pumpInfo.attribIndex[Geometry::PositionsIndex]->getSize();
        }
        else
        {
            curlen = pumpInfo.attribPtr[Geometry::PositionsIndex]->getSize();
        }
    }
    else
    {
        nprims = types->getSize();
        lengths->getValue(curlen, 0);
    }

    UInt32 vertindex = 0;

    for(UInt32 primindex = 0; primindex < nprims; ++primindex)
    {
        glBegin(types->getValue<UInt16>(primindex));

        if(primindex < lengths->getSize())
            curlen = lengths->getValue<UInt32>(primindex);

        for(; curlen > 0; --curlen, ++vertindex)
        {
            pumpAttrib(pumpInfo, Geometry::NormalsIndex,   vertindex);
            pumpAttrib(pumpInfo, Geometry::ColorsIndex,    vertindex);
            pumpAttrib(pumpInfo, Geometry::TexCoordsIndex, vertindex);

            if(win->hasExtension(_extSecondaryColor) == true)
            {
                pumpAttrib(pumpInfo, Geometry::SecondaryColorsIndex, vertindex);
            }

            if(win->hasExtension(_extMultitexture))
            {
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords1Index,
                                GL_TEXTURE1_ARB, vertindex);
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords2Index,
                                GL_TEXTURE2_ARB, vertindex);
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords3Index,
                                GL_TEXTURE3_ARB, vertindex);
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords4Index,
                                GL_TEXTURE4_ARB, vertindex);
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords5Index,
                                GL_TEXTURE5_ARB, vertindex);
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords6Index,
                                GL_TEXTURE6_ARB, vertindex);
                pumpMultiAttrib(pumpInfo, Geometry::TexCoords7Index,
                                GL_TEXTURE7_ARB, vertindex);
            }

            pumpAttrib(pumpInfo, Geometry::PositionsIndex, vertindex);
        }

        glEnd();
    }
}
void GeoSplitVertexArrayPumpGroup::masterClassicGeoJustDrawPump(
          DrawEnv                     *pEnv,
    const GeoIntegralProperty         *lengths,
    const GeoIntegralProperty         *types,
    const Geometry::MFPropertiesType  *prop,
    const Geometry::MFPropIndicesType *propIdx,
          UInt32                       uiNumInstances)
{
#ifdef DEBUG_WHICH_PUMP
    static bool bPrinted = false;

    if(bPrinted == false)
    {
        fprintf(stderr, 
                "GeoSplitVertexArrayPumpGroup::masterClassicGeoJustDrawPump\n");
        bPrinted = true;
    }
#endif

    Window *win = pEnv->getWindow();

    // check for empty geometry
    if(types == NULL || types->size() == 0)
        return;

    if(!pumpInternalSetup(types,   true))
        return;
    if(!pumpInternalSetup(lengths, false))
        return;

    PumpData       pumpData;

    pumpData.lengths = lengths;
    pumpData.types   = types;
    pumpData.prop    = prop;
    pumpData.propIdx = propIdx;

    UInt16 nattrib = prop->size32();

    for(UInt16 i = 0; i < nattrib; ++i)
    {
        if(pumpGLSetup(pumpData, i) == false)
            continue;
    }

    // Length handling. Special case: no length given

    UInt32 curlen;
    UInt32 nprims;

    // no lengths? use all available data for the first type
    if(lengths == NULL)
    {
        if(types->size() != 1)
        {
            SWARNING << "GeoVertexArrayPumpGroup::masterAttribGeoPump: "
                     << "No lengths, but more than one type?!"
                     << endLog;
            return;
        }

        nprims = 1;

        if(propIdx->size() != 0 && (*propIdx)[0] != NULL)
        {
            curlen = (*propIdx)[0]->size32();
        }
        else
        {
            curlen = (*prop)[0]->size32();
        }
    }
    else
    {
        nprims = types->size32();
        lengths->getValue(curlen, 0);
    }

    // global attribs?
    globalAttrib(pumpData, Geometry::NormalsIndex,   NormalsPumpSlot);
    globalAttrib(pumpData, Geometry::ColorsIndex,    ColorsPumpSlot);
    globalAttrib(pumpData, Geometry::TexCoordsIndex, TexCoordsPumpSlot);

    if(win->hasExtOrVersion(_extSecondaryColor, 0x0104) == true)
    {
        globalExtAttrib(pumpData,          Geometry::SecondaryColorsIndex,
                        SecColorsPumpSlot, win                            );
    }

    if(win->hasExtOrVersion(_extMultitexture, 0x0103, 0x0200) == true)
    {
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords1PumpSlot, GL_TEXTURE1_ARB, win);
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords2PumpSlot, GL_TEXTURE2_ARB, win);
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords3PumpSlot, GL_TEXTURE3_ARB, win);
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords4PumpSlot, GL_TEXTURE4_ARB, win);
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords5PumpSlot, GL_TEXTURE5_ARB, win);
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords6PumpSlot, GL_TEXTURE6_ARB, win);
        globalExtMultiAttrib(pumpData,           Geometry::TexCoords1Index,
                             TexCoords7PumpSlot, GL_TEXTURE7_ARB, win);
    }

    UInt32 vertindex = 0;

    if(propIdx->size() != 0 && (*propIdx)[0] != NULL)
    {
        // Single Indexed

        GeoIntegralProperty *index       = (*propIdx)[0];
        const UInt8         *indexData   = index->getData();
        GLenum               indexFormat = index->getFormat();
        UInt32               indexStride =
            index->getStride() ? index->getStride() : index->getFormatSize() *
            index->getDimension();

#if 0
        index->activate(pEnv, 0);

        if(index->isInVBO(pEnv))
        {
#endif
            indexData = NULL;
#if 0
        }
#endif

        if(uiNumInstances > 1)
        {        
            OSGGETGLFUNCBYID_GL3_ES(glDrawElementsInstanced,
                                    osgGlDrawElementsInstanced,
                                    Geometry::getFuncIdDrawElementsInstanced(),
                                    win);

            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    osgGlDrawElementsInstanced(
                        types->getValue<UInt16>(primindex),
                        curlen,
                        indexFormat,
                        indexData + vertindex * indexStride,
                        uiNumInstances                     );

                    vertindex += curlen;
                }
            }
        }
        else
        {
            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    glDrawElements(types->getValue<UInt16>(primindex),
                                   curlen,
                                   indexFormat,
                                   indexData + vertindex * indexStride);

                    vertindex += curlen;
                }
            }
        }

#if 0
        index->deactivate(pEnv, 0);
#endif
    }
    else
    {
        if(uiNumInstances > 1)
        {
            OSGGETGLFUNCBYID_GL3_ES(glDrawArraysInstanced,
                                    osgGlDrawArraysInstanced,
                                    Geometry::getFuncIdDrawArraysInstanced(),
                                    win);
            // Non-indexed
            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    osgGlDrawArraysInstanced(
                        types->getValue<UInt16>(primindex), 
                        vertindex,
                        curlen,
                        uiNumInstances);

                    vertindex += curlen;
                }
            }
        }
        else
        {
            // Non-indexed
            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    glDrawArrays(types->getValue<UInt16>(primindex), vertindex,
                                 curlen);
                    vertindex += curlen;
                }
            }
        }
    }
}
void GeoImmediatePumpGroup::masterAttribGeoPump(
          DrawEnv                     *pEnv,
    const GeoIntegralProperty         *lengths,
    const GeoIntegralProperty         *types,
    const Geometry::MFPropertiesType  *prop,
    const Geometry::MFPropIndicesType *propIdx)
{
    Window *win = pEnv->getWindow();

    // Setup: get all the data

    // check for empty geometry
    if(types == NULL || types->getSize() == 0)
        return;

    if(!pumpInternalSetup(types,   true))
        return;
    if(!pumpInternalSetup(lengths, false))
        return;

    PumpAttribInfo pumpInfo;
    pumpInfo.lengths = lengths;
    pumpInfo.types   = types;
    pumpInfo.prop    = prop;
    pumpInfo.propIdx = propIdx;

    UInt16 nattrib = prop->size();

    for(UInt16 i = 0; i < nattrib; ++i)
    {
        if(pumpGLSetup(pumpInfo, i) == false)
            continue;

        UInt16 formatIdx = pumpInfo.attribPtr[i]->getFormat   () - formatBase;
        UInt16 dimIdx    = pumpInfo.attribPtr[i]->getDimension() - 1;
        UInt32 funcId    = Window::invalidFunctionID;

        if(pumpInfo.attribPtr[i]->getNormalize() == true)
        {
            funcId = normAttribPumpFuncIDs[formatIdx][dimIdx];

            if(funcId == Window::invalidFunctionID)
            {
                SWARNING << "GeoImmediatePumpGroup::masterAttribGeoPump: "
                         << "Invalid pump function for property " << i
                         << " type " << pumpInfo.attribPtr[i]->getDimension()
                         << "D " << formatNames[formatIdx] << " (normalizing)."
                         << endLog;

                pumpInfo.attribData[i] = NULL;
                pumpInfo.attribPtr [i] = NULL;
                continue;
            }
        }
        else
        {
            funcId = attribPumpFuncIDs[formatIdx][dimIdx];

            if(funcId == Window::invalidFunctionID)
            {
                SWARNING << "GeoImmediatePumpGroup::masterAttribGeoPump: "
                         << "Invalid pump function for property " << i
                         << " type " << pumpInfo.attribPtr[i]->getDimension()
                         << "D " << formatNames[formatIdx]
                         << endLog;

                pumpInfo.attribData[i] = NULL;
                pumpInfo.attribPtr [i] = NULL;
                continue;
            }
        }

        pumpInfo.attribPump[i] = reinterpret_cast<attribPumpFunc>(
            win->getFunction(funcId));

        if(pumpInfo.attribPump[i] == NULL)
        {
            SWARNING << "GeoImmediatePumpGroup::masterAttribGeoPump: "
                     << "Extension function for property " << i
                     << " type " << pumpInfo.attribPtr[i]->getDimension()
                     << "D " << formatNames[formatIdx]
                     << " not supported by Window " << win
                     << endLog;

            pumpInfo.attribData[i] = NULL;
            pumpInfo.attribPtr [i] = NULL;
            continue;
        }
    }

    // we need positions
    if(pumpInfo.attribPtr[0] == NULL)
    {
        if(pumpInfo.attribPtr[0]              == NULL ||
           pumpInfo.attribPtr[0]->getUseVBO() == false)
        {
            SWARNING << "GeoImmediatePumpGroup::masterAttribGeoPump: "
                     << "No positions." << endLog;
            return;
        }
    }

    // global attribs?
    for(Int16 i = 0; i < nattrib; ++i)
    {
        if(pumpInfo.attribData[i]            != NULL &&
           pumpInfo.attribPtr [i]->getSize() == 1      )
        {
            pumpInfo.attribPump[i](i, pumpInfo.attribData[i]);
            pumpInfo.attribData[i] = NULL;
        }
    }

    // Length handling. Special case: no length given

    UInt32 curlen;
    UInt32 nprims;

    // no lengths? use all available data for the first type
    if(lengths == NULL)
    {
        if(types->getSize() != 1)
        {
            SWARNING << "GeoImmediatePumpGroup::masterAttribGeoPump: "
                     << "No lengths, but more than one type?!"
                     << endLog;
            return;
        }

        nprims = 1;
        if(pumpInfo.attribIndex[0] != NULL)
        {
            curlen = pumpInfo.attribIndex[0]->getSize();
        }
        else
        {
            curlen = pumpInfo.attribPtr[0]->getSize();
        }
    }
    else
    {
        nprims = types->getSize();
        lengths->getValue(curlen, 0);
    }

    UInt32 vertindex = 0;

    for(UInt32 primindex = 0; primindex < nprims; ++primindex)
    {
        glBegin(types->getValue<UInt16>(primindex));

        if(primindex < lengths->getSize())
            curlen = lengths->getValue<UInt32>(primindex);

        for(; curlen > 0; --curlen, ++vertindex)
        {
            for(Int16 i = nattrib - 1; i >= 0; --i)
            {
                if(pumpInfo.attribData[i])
                {
                    if(pumpInfo.attribIndex[i] != NULL)
                    {
                        pumpInfo.attribPump[i](
                            i, pumpInfo.attribData  [i] +
                               pumpInfo.attribStride[i] *
                               pumpInfo.attribIndex [i]->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        pumpInfo.attribPump[i](
                            i, pumpInfo.attribData  [i] +
                               pumpInfo.attribStride[i] * vertindex);
                    }
                }
            }
        }

        glEnd();
    }
}
void GeoSplitVertexArrayPumpGroup::masterAttribGeoJustDrawPump(
    DrawEnv                     *pEnv,
    const GeoIntegralProperty         *lengths,
    const GeoIntegralProperty         *types,
    const Geometry::MFPropertiesType  *prop,
    const Geometry::MFPropIndicesType *propIdx,
          UInt32                       uiNumInstances)
{
#ifdef DEBUG_WHICH_PUMP
    static bool bPrinted = false;

    if(bPrinted == false)
    {
        fprintf(stderr, 
                "GeoSplitVertexArrayPumpGroup::masterAttribGeoJustDrawPump\n");
        bPrinted = true;
    }
#endif

    Window *win = pEnv->getWindow();

    // check for empty geometry
    if(types == NULL || types->size() == 0)
        return;

    if(!pumpInternalSetup(types,   true))
        return;
    if(!pumpInternalSetup(lengths, false))
        return;

    attribPumpFunc attribFunc[Geometry::MaxAttribs];
    PumpData       pumpData;

    pumpData.lengths = lengths;
    pumpData.types   = types;
    pumpData.prop    = prop;
    pumpData.propIdx = propIdx;

    UInt16 nattrib = prop->size32();

    for(UInt16 i = 0; i < nattrib; ++i)
    {
        if(pumpGLSetup(pumpData, i) == false)
            continue;

        UInt16 formatIdx = pumpData.attribPtr[i]->getFormat   () - formatBase;
        UInt16 dimIdx    = pumpData.attribPtr[i]->getDimension() - 1;

#if !defined(OSG_USE_OGLES_PROTOS) && !defined(OSG_USE_OGL3_PROTOS) && \
    !defined(OSG_USE_OGL4_PROTOS)
        UInt32 funcId    = Window::invalidFunctionID;

        if(pumpData.attribPtr[i]->getNormalize() == true)
        {
            funcId = normAttribPumpFuncIDs[formatIdx][dimIdx];

            if(funcId == Window::invalidFunctionID)
            {
                SWARNING << "GeoVertexArrayPumpGroup::masterAttribGeoPump: "
                         << "Invalid pump function for property " << i
                         << " type " << pumpData.attribPtr[i]->getDimension()
                         << "D " << formatNames[formatIdx] << " (normalizing)."
                         << endLog;

                pumpData.attribData[i] = NULL;
                pumpData.attribPtr [i] = NULL;
                continue;
            }
        }
        else
        {
            funcId = attribPumpFuncIDs[formatIdx][dimIdx];

            if(funcId == Window::invalidFunctionID)
            {
                SWARNING << "GeoVertexArrayPumpGroup::masterAttribGeoPump: "
                         << "Invalid pump function for property " << i
                         << " type " << pumpData.attribPtr[i]->getDimension()
                         << "D " << formatNames[formatIdx]
                         << endLog;

                pumpData.attribData[i] = NULL;
                pumpData.attribPtr [i] = NULL;
                continue;
            }
        }

        attribFunc[i] = reinterpret_cast<attribPumpFunc>(
            win->getFunction(funcId));

#else
        if(pumpData.attribPtr[i]->getNormalize() == true)
        {
            attribFunc[i] = attribNormPumpFuncs[formatIdx][dimIdx];
        }
        else
        {
            attribFunc[i] = attribPumpFuncs[formatIdx][dimIdx];
        }
#endif

        if(attribFunc[i] == NULL)
        {
            SWARNING << "GeoVertexArrayPumpGroup::masterAttribGeoPump: "
                     << "Extension function for property " << i
                     << " type " << pumpData.attribPtr[i]->getDimension()
                     << "D " << formatNames[formatIdx]
                     << " not supported by Window " << win
                     << endLog;

            pumpData.attribData[i] = NULL;
            pumpData.attribPtr [i] = NULL;
            continue;
        }
    }

    // Length handling. Special case: no length given

    UInt32 curlen;
    UInt32 nprims;

    // no lengths? use all available data for the first type
    if(lengths == NULL)
    {
        if(types->size() != 1)
        {
            SWARNING << "GeoVertexArrayPumpGroup::masterAttribGeoPump: "
                     << "No lengths, but more than one type?!"
                     << endLog;
            return;
        }

        nprims = 1;

        if(propIdx->size() != 0 && (*propIdx)[0] != NULL)
        {
            curlen = (*propIdx)[0]->size32();
        }
        else
        {
            curlen = (*prop)[0]->size32();
        }
    }
    else
    {
        nprims = types->size32();
        lengths->getValue(curlen, 0);
    }

    // global attribs?
    for(Int16 i = 0; i < nattrib; ++i)
    {
        if(pumpData.attribData[i]         != NULL &&
           pumpData.attribPtr [i]->size() == 1      )
        {
            attribFunc[i](i, pumpData.attribData[i]);
            pumpData.attribData[i] = NULL;
        }
    }

    UInt32 vertindex = 0;

    if(propIdx->size() != 0 && (*propIdx)[0] != NULL)
    {
        // Single Indexed

        GeoIntegralProperty *index       = (*propIdx)[0];
        const UInt8         *indexData   = index->getData();
        GLenum               indexFormat = index->getFormat();
        UInt32               indexStride =
            index->getStride() ? index->getStride() : index->getFormatSize() *
                                                      index->getDimension();

#if 0
        index->activate(pEnv, 0);

        if(index->isInVBO(pEnv))
        {
#endif
            indexData = NULL;
#if 0
        }
#endif

        if(uiNumInstances > 1)
        {
            OSGGETGLFUNCBYID_GL3_ES(glDrawElementsInstanced,
                                    osgGlDrawElementsInstanced,
                                    Geometry::getFuncIdDrawElementsInstanced(),
                                    win);

            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    osgGlDrawElementsInstanced(
                        types->getValue<UInt16>(primindex),
                        curlen,
                        indexFormat,
                        indexData + vertindex * indexStride,
                        uiNumInstances                     );

                    vertindex += curlen;
                }
            }
        }
        else
        {
            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    glDrawElements(types->getValue<UInt16>(primindex),
                               curlen,
                               indexFormat,
                               indexData + vertindex * indexStride);

                    vertindex += curlen;
                }
            }
        }

#if 0
        index->deactivate(pEnv, 0);
#endif
    }
    else
    {
        if(uiNumInstances > 1)
        {
            OSGGETGLFUNCBYID_GL3_ES(glDrawArraysInstanced,
                                    osgGlDrawArraysInstanced,
                                    Geometry::getFuncIdDrawArraysInstanced(),
                                    win);

            // Non-indexed
            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    osgGlDrawArraysInstanced(
                        types->getValue<UInt16>(primindex), 
                        vertindex,
                        curlen,
                        uiNumInstances                    );

                    vertindex += curlen;
                }
            }
        }
        else
        {
            // Non-indexed
            for(UInt32 primindex = 0; primindex < nprims; ++primindex)
            {
                if(primindex < lengths->size())
                    curlen = lengths->getValue<UInt32>(primindex);

                if(curlen > 0)
                {
                    glDrawArrays(types->getValue<UInt16>(primindex), vertindex,
                                 curlen);
                    vertindex += curlen;
                }
            }
        }
    }
}