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 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();
    }
}
bool GeoSplitVertexArrayPumpGroup::masterAttribGeoSetupPump(
          DrawEnv                     *pEnv,
    const GeoIntegralProperty         *lengths,
    const GeoIntegralProperty         *types,
    const Geometry::MFPropertiesType  *prop,
    const Geometry::MFPropIndicesType *propIdx,
          bool                         withFallback)
{
#ifdef DEBUG_WHICH_PUMP
    static bool bPrinted = false;

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

    // Setup: get all the data
    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;
    }

    // we need positions
    if(pumpData.attribPtr[0]              == NULL ||
       pumpData.attribPtr[0]->getUseVBO() == false)
    {
#ifdef DEBUG_WHICH_PUMP
        static bool bPrinted1 = false;

        if(bPrinted1 == false)
        {
#endif
        if(withFallback == false)
        {
            SWARNING << "GeoSplitVertexArrayPumpGroup::masterAttribGeoPump: "
                     << "No positions." << endLog;
        }
#ifdef DEBUG_WHICH_PUMP
            bPrinted1 = true;
        }
#endif
        return false;
    }

    for(Int16 i = nattrib - 1; i >= 0; --i)
    {
        if(pumpData.attribPtr[i]         != NULL &&
           pumpData.attribPtr[i]->size() != 1     )
        {
            pumpData.attribPtr[i]->activate(pEnv, i + 16); // XXX HACK
        }
    }

    return true;
}
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 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;
                }
            }
        }
    }
}
void GeoImmediatePumpGroup::masterClassicGeoPump(DrawEnv  *pEnv,
                                                 Geometry *geo)
{
    Window *win = pEnv->getWindow();
    
    // Setup: get all the data

    pumpInternalSetup( Type, GeoPTypes *, getTypes, true );
    pumpInternalSetup( Length, GeoPLengths *, getLengths, false );

    pumpGLSetup        ( Position,   Geometry::PositionsIndex      );
    pumpGLSetup        ( Color,      Geometry::ColorsIndex         );
    pumpGLSetup        ( Normal,     Geometry::NormalsIndex        );
    pumpGLSetup        ( TexCoords,  Geometry::TexCoordsIndex      );
    pumpGLExtSetup     ( SecColor,   Geometry::SecondaryColorsIndex);
    pumpMultiGLExtSetup( TexCoords1, Geometry::TexCoords1Index     );
    pumpMultiGLExtSetup( TexCoords2, Geometry::TexCoords2Index     );
    pumpMultiGLExtSetup( TexCoords3, Geometry::TexCoords3Index     );
    pumpMultiGLExtSetup( TexCoords4, Geometry::TexCoords4Index     );
    pumpMultiGLExtSetup( TexCoords5, Geometry::TexCoords5Index     );
    pumpMultiGLExtSetup( TexCoords6, Geometry::TexCoords6Index     );
    pumpMultiGLExtSetup( TexCoords7, Geometry::TexCoords7Index     );
    
    // check if the node is empty
    if(TypePtr == NULL || TypePtr->getSize() == 0)
        return;

    // if it's not empty we need positions
    if(! PositionData)
    {
        SWARNING << "masterPump: Geometry " << geo << " has no positions!?!"
                 << endLog;
        OSG_GV_ASSERT(false);                                              
        return;
    }

    // overall attributes?
    if(ColorData && ColorPtr->getSize() == 1)   
    {
        ColorFunc(ColorData);
        ColorData = NULL;
    }
    if(NormalData && NormalPtr->getSize() == 1) 
    {
        NormalFunc(NormalData);
        NormalData = NULL;
    }
    if(win->hasExtension(_extSecondaryColor) && SecColorData && 
       SecColorPtr->getSize() == 1)   
    {
        SecColorFunc(SecColorData);
        SecColorData = NULL;
    }
    if(TexCoordsData && TexCoordsPtr->getSize() == 1) 
    {
        TexCoordsFunc(TexCoordsData);
        TexCoordsData = NULL;
    }
    if(win->hasExtension(_extMultitexture))
    {
        if(TexCoords1Data && TexCoords1Ptr->getSize() == 1) 
        {
            TexCoords1Func(GL_TEXTURE1_ARB, TexCoords1Data);
            TexCoords1Data = NULL;
        }
        if(TexCoords2Data && TexCoords2Ptr->getSize() == 1) 
        {
            TexCoords2Func(GL_TEXTURE2_ARB, TexCoords2Data);
            TexCoords2Data = NULL;
        }
        if(TexCoords3Data && TexCoords3Ptr->getSize() == 1) 
        {
            TexCoords3Func(GL_TEXTURE3_ARB, TexCoords3Data);
            TexCoords3Data = NULL;
        }
        if(TexCoords4Data && TexCoords4Ptr->getSize() == 1) 
        {
            TexCoords4Func(GL_TEXTURE4_ARB, TexCoords4Data);
            TexCoords4Data = NULL;
        }
        if(TexCoords2Data && TexCoords2Ptr->getSize() == 1) 
        {
            TexCoords2Func(GL_TEXTURE2_ARB, TexCoords2Data);
            TexCoords2Data = NULL;
        }
        if(TexCoords5Data && TexCoords2Ptr->getSize() == 1) 
        {
            TexCoords2Func(GL_TEXTURE2_ARB, TexCoords2Data);
            TexCoords2Data = NULL;
        }
        if(TexCoords6Data && TexCoords6Ptr->getSize() == 1) 
        {
            TexCoords6Func(GL_TEXTURE6_ARB, TexCoords6Data);
            TexCoords6Data = NULL;
        }
        if(TexCoords7Data && TexCoords7Ptr->getSize() == 1) 
        {
            TexCoords7Func(GL_TEXTURE7_ARB, TexCoords7Data);
            TexCoords7Data = NULL;
        }
    }
 
    // Length handling. Special case: no length given

    UInt32 curlen;
    UInt32 nprims;

    // no lengths? use all available data for the first type
    if(LengthPtr == NULL)
    {
        if(TypePtr->getSize() != 1)
        {
            SWARNING << "masterPump: Geometry " << geo 
                     << " has no length but more than one type!?!"
                     << endLog;
            return;
        }
        
        nprims = 1;
        if (PositionIndex != NULL)
        {
            curlen = PositionIndex->getSize();
        }
        else
        {
            curlen = PositionPtr->getSize();
        }
    }
    else
    {
        nprims = TypePtr->getSize();
        LengthPtr->getValue(curlen, 0);
    }
    
    UInt32 vertindex = 0;

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

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

        for(; curlen > 0; --curlen, ++vertindex)
        {
            if(ColorData)
            {
                if (ColorIndex != NULL)
                {
                    ColorFunc(ColorData + ColorStride * 
                              ColorIndex->getValue<UInt32>(vertindex));
                }
                else
                {
                    ColorFunc(ColorData + ColorStride * vertindex);
                }
            }
            
            if(NormalData)
            {
                if (NormalIndex != NULL)
                {
                    NormalFunc(NormalData + NormalStride * 
                               NormalIndex->getValue<UInt32>(vertindex));
                }
                else
                {
                    NormalFunc(NormalData + NormalStride * vertindex);
                }
            }
            
            if(win->hasExtension(_extSecondaryColor) && SecColorData)
            {
                if (SecColorIndex != NULL)
                {
                    SecColorFunc(SecColorData + SecColorStride * 
                               SecColorIndex->getValue<UInt32>(vertindex));
                }
                else
                {
                    SecColorFunc(SecColorData + SecColorStride * vertindex);
                }
            }
            
            if(TexCoordsData)
            {
                if (TexCoordsIndex != NULL)
                {
                    TexCoordsFunc(TexCoordsData + TexCoordsStride * 
                                 TexCoordsIndex->getValue<UInt32>(vertindex));
                }
                else
                {
                    TexCoordsFunc(TexCoordsData + TexCoordsStride * vertindex);
                }
            }
            
            if(win->hasExtension(_extMultitexture))
            {
                if(TexCoords1Data)
                {
                    if (TexCoords1Index != NULL)
                    {
                        TexCoords1Func(GL_TEXTURE1_ARB, 
                                  TexCoords1Data + TexCoords1Stride * 
                                  TexCoords1Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords1Func(GL_TEXTURE1_ARB, 
                                  TexCoords1Data + TexCoords1Stride * vertindex);
                    }
                }

                if(TexCoords2Data)
                {
                    if (TexCoords2Index != NULL)
                    {
                        TexCoords2Func(GL_TEXTURE2_ARB, 
                                  TexCoords2Data + TexCoords2Stride * 
                                  TexCoords2Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords2Func(GL_TEXTURE2_ARB, 
                                  TexCoords2Data + TexCoords2Stride * vertindex);
                    }
                }

                if(TexCoords3Data)
                {
                    if (TexCoords3Index != NULL)
                    {
                        TexCoords3Func(GL_TEXTURE3_ARB, 
                                  TexCoords3Data + TexCoords3Stride * 
                                  TexCoords3Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords3Func(GL_TEXTURE3_ARB, 
                                  TexCoords3Data + TexCoords3Stride * vertindex);
                    }
                }

                if(TexCoords4Data)
                {
                    if (TexCoords4Index != NULL)
                    {
                        TexCoords4Func(GL_TEXTURE4_ARB, 
                                  TexCoords4Data + TexCoords4Stride * 
                                  TexCoords4Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords4Func(GL_TEXTURE4_ARB, 
                                  TexCoords4Data + TexCoords4Stride * vertindex);
                    }
                }

                if(TexCoords5Data)
                {
                    if (TexCoords5Index != NULL)
                    {
                        TexCoords5Func(GL_TEXTURE5_ARB, 
                                  TexCoords5Data + TexCoords5Stride * 
                                  TexCoords5Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords5Func(GL_TEXTURE5_ARB, 
                                  TexCoords5Data + TexCoords5Stride * vertindex);
                    }
                }

                if(TexCoords6Data)
                {
                    if (TexCoords6Index != NULL)
                    {
                        TexCoords6Func(GL_TEXTURE6_ARB, 
                                  TexCoords6Data + TexCoords6Stride * 
                                  TexCoords6Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords6Func(GL_TEXTURE6_ARB, 
                                  TexCoords6Data + TexCoords6Stride * vertindex);
                    }
                }

                if(TexCoords7Data)
                {
                    if (TexCoords7Index != NULL)
                    {
                        TexCoords7Func(GL_TEXTURE7_ARB, 
                                  TexCoords7Data + TexCoords7Stride * 
                                  TexCoords7Index->getValue<UInt32>(vertindex));
                    }
                    else
                    {
                        TexCoords7Func(GL_TEXTURE7_ARB, 
                                  TexCoords7Data + TexCoords7Stride * vertindex);
                    }
                }
                }
            
            if (PositionIndex != NULL)
            {
                PositionFunc(PositionData + PositionStride * 
                             PositionIndex->getValue<UInt32>(vertindex));
            }
            else
            {
                PositionFunc(PositionData + PositionStride * vertindex);
            }

        }

        glEnd();
    }
}