bool
OsdGLDrawContext::allocate(FarMesh<OsdVertex> *farMesh,
                           GLuint vbo,
                           int numElements,
                           bool requirePtexCoordinates,
                           bool requireFVarData)
{
    FarPatchTables const * patchTables = farMesh->GetPatchTables();

    if (not patchTables) {
        // uniform patches
        isAdaptive = false;

        // XXX: farmesh should have FarDensePatchTable for dense mesh indices.
        //      instead of GetFaceVertices().
        const FarSubdivisionTables<OsdVertex> *tables = farMesh->GetSubdivisionTables();
        int level = tables->GetMaxLevel();
        const std::vector<int> &indices = farMesh->GetFaceVertices(level-1);

        // XXX: farmesh or FarSubdivisionTables should have a virtual method
        // to determine loop or not
        bool loop =
            dynamic_cast<const FarLoopSubdivisionTables<OsdVertex>*>(tables) != NULL;

        int numIndices = (int)indices.size();

        // Allocate and fill index buffer.
        glGenBuffers(1, &patchIndexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     numIndices * sizeof(unsigned int), &(indices[0]), GL_STATIC_DRAW);

#if defined(GL_ES_VERSION_2_0)
        // OpenGLES 2 supports only triangle topologies for filled
        // primitives i.e. not QUADS or PATCHES or LINES_ADJACENCY
        // For the convenience of clients build build a triangles
        // index buffer by splitting quads.
        int numQuads = indices.size() / 4;
        int numTrisIndices = numQuads * 6;

        std::vector<short> trisIndices;
        trisIndices.reserve(numTrisIndices);
        for (int i=0; i<numQuads; ++i) {
            const int * quad = &indices[i*4];
            trisIndices.push_back(short(quad[0]));
            trisIndices.push_back(short(quad[1]));
            trisIndices.push_back(short(quad[2]));

            trisIndices.push_back(short(quad[2]));
            trisIndices.push_back(short(quad[3]));
            trisIndices.push_back(short(quad[0]));
        }

        // Allocate and fill triangles index buffer.
        glGenBuffers(1, &patchTrianglesIndexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchTrianglesIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     numTrisIndices * sizeof(short), &(trisIndices[0]), GL_STATIC_DRAW);
#endif

        OsdPatchArray array;
        array.desc.type = kNonPatch;
        array.patchSize = loop ? 3 : 4;
        array.firstIndex = 0;
        array.numIndices = numIndices;

        patchArrays.push_back(array);

        // Allocate ptex coordinate buffer if requested (for non-adaptive)
        if (requirePtexCoordinates) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
            GLuint ptexCoordinateBuffer = 0;
            glGenTextures(1, &ptexCoordinateTextureBuffer);
            glGenBuffers(1, &ptexCoordinateBuffer);
            glBindBuffer(GL_TEXTURE_BUFFER, ptexCoordinateBuffer);

            const std::vector<int> &ptexCoordinates =
                farMesh->GetPtexCoordinates(level-1);
            int size = (int)ptexCoordinates.size() * sizeof(GLint);

            glBufferData(GL_TEXTURE_BUFFER, size, &(ptexCoordinates[0]), GL_STATIC_DRAW);

            glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
            glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
            glDeleteBuffers(1, &ptexCoordinateBuffer);
            glBindTexture(GL_TEXTURE_BUFFER, 0);
#endif
        }

        // Allocate fvar data buffer if requested (for non-adaptive)
        if (requireFVarData) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
            GLuint fvarDataBuffer = 0;
            glGenTextures(1, &fvarDataTextureBuffer);
            glGenBuffers(1, &fvarDataBuffer);
            glBindBuffer(GL_TEXTURE_BUFFER, fvarDataBuffer);

            const std::vector<float> &fvarData = farMesh->GetFVarData(level-1);
            int size = (int)fvarData.size() * sizeof(float);

            glBufferData(GL_TEXTURE_BUFFER, size, &(fvarData[0]), GL_STATIC_DRAW);

            glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
            glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
            glDeleteBuffers(1, &fvarDataBuffer);
            glBindTexture(GL_TEXTURE_BUFFER, 0);
#endif
        }

        return true;
    }

    // adaptive patches
    isAdaptive = true;

    // Determine buffer sizes
    int totalPatchIndices = 
        patchTables->GetFullRegularPatches().GetSize() +
        patchTables->GetFullBoundaryPatches().GetSize() +
        patchTables->GetFullCornerPatches().GetSize() +
        patchTables->GetFullGregoryPatches().GetSize() +
        patchTables->GetFullBoundaryGregoryPatches().GetSize();

    int totalPatchLevels = 
        patchTables->GetFullRegularPatches().GetSize()/patchTables->GetRegularPatchRingsize() +
        patchTables->GetFullBoundaryPatches().GetSize()/patchTables->GetBoundaryPatchRingsize() +
        patchTables->GetFullCornerPatches().GetSize()/patchTables->GetCornerPatchRingsize() +
        patchTables->GetFullGregoryPatches().GetSize()/patchTables->GetGregoryPatchRingsize() +
        patchTables->GetFullBoundaryGregoryPatches().GetSize()/patchTables->GetGregoryPatchRingsize();

    for (int p=0; p<5; ++p) {
        totalPatchIndices +=
            patchTables->GetTransitionRegularPatches(p).GetSize();

        totalPatchLevels +=
            patchTables->GetTransitionRegularPatches(p).GetSize()/patchTables->GetRegularPatchRingsize();

        for (int r=0; r<4; ++r) {
            totalPatchIndices +=
                patchTables->GetTransitionBoundaryPatches(p, r).GetSize() +
                patchTables->GetTransitionCornerPatches(p, r).GetSize();

            totalPatchLevels +=
                patchTables->GetTransitionBoundaryPatches(p, r).GetSize()/patchTables->GetBoundaryPatchRingsize() +
                patchTables->GetTransitionCornerPatches(p, r).GetSize()/patchTables->GetCornerPatchRingsize();
        }
    }

    // Allocate and fill index buffer.
    glGenBuffers(1, &patchIndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
        totalPatchIndices * sizeof(unsigned int), NULL, GL_STATIC_DRAW);

#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
    GLuint patchLevelBuffer = 0;
    glGenBuffers(1, &patchLevelBuffer);
    glBindBuffer(GL_TEXTURE_BUFFER, patchLevelBuffer);
    glBufferData(GL_TEXTURE_BUFFER,
        totalPatchLevels * sizeof(unsigned char), NULL, GL_STATIC_DRAW);
#endif

    // Allocate ptex coordinate buffer if requested
    GLuint ptexCoordinateBuffer = 0;
    if (requirePtexCoordinates) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
        glGenTextures(1, &ptexCoordinateTextureBuffer);
        glGenBuffers(1, &ptexCoordinateBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, ptexCoordinateBuffer);
        glBufferData(GL_ARRAY_BUFFER,
            totalPatchLevels * sizeof(int) * 2, NULL, GL_STATIC_DRAW);
#endif
    }

    // Allocate fvar data buffer if requested
    GLuint fvarDataBuffer = 0;
    if (requireFVarData) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
        glGenTextures(1, &fvarDataTextureBuffer);
        glGenBuffers(1, &fvarDataBuffer);
        glBindBuffer(GL_UNIFORM_BUFFER, fvarDataBuffer);
        glBufferData(GL_UNIFORM_BUFFER,
            totalPatchLevels * sizeof(float) * farMesh->GetTotalFVarWidth()*4, NULL, GL_STATIC_DRAW);
#endif
    }

    int indexBase = 0;
    int levelBase = 0;
    int maxValence = patchTables->GetMaxValence();

    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullRegularPatches(),
                        patchTables->GetRegularPatchRingsize(),
                        patchTables->GetFullRegularPtexCoordinates(),
                        patchTables->GetFullRegularFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kRegular, 0, 0, 0, 0), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullBoundaryPatches(),
                        patchTables->GetBoundaryPatchRingsize(),
                        patchTables->GetFullBoundaryPtexCoordinates(),
                        patchTables->GetFullBoundaryFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kBoundary, 0, 0, 0, 0), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullCornerPatches(),
                        patchTables->GetCornerPatchRingsize(),
                        patchTables->GetFullCornerPtexCoordinates(),
                        patchTables->GetFullCornerFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kCorner, 0, 0, 0, 0), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullGregoryPatches(),
                        patchTables->GetGregoryPatchRingsize(),
                        patchTables->GetFullGregoryPtexCoordinates(),
                        patchTables->GetFullGregoryFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kGregory, 0, 0,
                                           maxValence, numElements), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullBoundaryGregoryPatches(),
                        patchTables->GetGregoryPatchRingsize(),
                        patchTables->GetFullBoundaryGregoryPtexCoordinates(),
                        patchTables->GetFullBoundaryGregoryFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kBoundaryGregory, 0, 0,
                                           maxValence, numElements),
                        (int)patchTables->GetFullGregoryPatches().GetSize());

    for (int p=0; p<5; ++p) {
        _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetTransitionRegularPatches(p),
                        patchTables->GetRegularPatchRingsize(),
                        patchTables->GetTransitionRegularPtexCoordinates(p),
                        patchTables->GetTransitionRegularFVarData(p),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kTransitionRegular, p, 0, 0, 0), 0);
        for (int r=0; r<4; ++r) {
            _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetTransitionBoundaryPatches(p, r),
                        patchTables->GetBoundaryPatchRingsize(),
                        patchTables->GetTransitionBoundaryPtexCoordinates(p, r),
                        patchTables->GetTransitionBoundaryFVarData(p, r),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kTransitionBoundary, p, r, 0, 0), 0);
            _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetTransitionCornerPatches(p, r),
                        patchTables->GetCornerPatchRingsize(),
                        patchTables->GetTransitionCornerPtexCoordinates(p, r),
                        patchTables->GetTransitionCornerFVarData(p, r),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kTransitionCorner, p, r, 0, 0), 0);
        }
    }

#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
    // finalize level texture buffer
    glGenTextures(1, &patchLevelTextureBuffer);
    glBindTexture(GL_TEXTURE_BUFFER, patchLevelTextureBuffer);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R8I, patchLevelBuffer);
    glDeleteBuffers(1, &patchLevelBuffer);

    // finalize ptex coordinate texture buffer
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    if (requirePtexCoordinates) {
        glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
        glDeleteBuffers(1, &ptexCoordinateBuffer);
    }
    // finalize fvar data texture buffer
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
    if (requireFVarData) {
        glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
        glDeleteBuffers(1, &fvarDataBuffer);
    }
#endif

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
    glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif

    // allocate and initialize additional buffer data
    FarPatchTables::VertexValenceTable const &
        valenceTable = patchTables->GetVertexValenceTable();

    if (not valenceTable.empty()) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
        GLuint buffer = 0;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_TEXTURE_BUFFER, buffer);
        glBufferData(GL_TEXTURE_BUFFER,
                valenceTable.size() * sizeof(unsigned int),
                &valenceTable[0], GL_STATIC_DRAW);

        glGenTextures(1, &vertexValenceTextureBuffer);
        glBindTexture(GL_TEXTURE_BUFFER, vertexValenceTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
        glDeleteBuffers(1, &buffer);

        glGenTextures(1, &vertexTextureBuffer);
        glBindTexture(GL_TEXTURE_BUFFER, vertexTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, vbo);

        glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif
    }

    FarPatchTables::QuadOffsetTable const &
        quadOffsetTable = patchTables->GetQuadOffsetTable();

    if (not quadOffsetTable.empty()) {
#if defined(GL_ARB_texture_buffer_object) || defined(GL_VERSION_3_1)
        GLuint buffer = 0;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_TEXTURE_BUFFER, buffer);
        glBufferData(GL_TEXTURE_BUFFER,
                quadOffsetTable.size() * sizeof(unsigned int),
                &quadOffsetTable[0], GL_STATIC_DRAW);

        glGenTextures(1, &quadOffsetTextureBuffer);
        glBindTexture(GL_TEXTURE_BUFFER, quadOffsetTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
        glDeleteBuffers(1, &buffer);

        glBindBuffer(GL_TEXTURE_BUFFER, 0);
#endif
    }

    return true;
}
bool
OsdD3D11DrawContext::allocate(FarMesh<OsdVertex> *farMesh,
                              ID3D11Buffer *vertexBuffer,
                              int numElements,
                              ID3D11DeviceContext *pd3d11DeviceContext,
                              bool requirePtexCoordinates,
                              bool requireFVarData)
{
    ID3D11Device *pd3d11Device = NULL;
    pd3d11DeviceContext->GetDevice(&pd3d11Device);
    assert(pd3d11Device);

    FarPatchTables const * patchTables = farMesh->GetPatchTables();

    if (not patchTables) {
        // uniform patches
        isAdaptive = false;

        // XXX: farmesh should have FarDensePatchTable for dense mesh indices.
        //      instead of GetFaceVertices().
        const FarSubdivisionTables<OsdVertex> *tables = farMesh->GetSubdivisionTables();
        int level = tables->GetMaxLevel();
        const std::vector<int> &indices = farMesh->GetFaceVertices(level-1);

        // XXX: farmesh or FarSubdivisionTables should have a virtual method
        // to determine loop or not
        bool loop =
            dynamic_cast<const FarLoopSubdivisionTables<OsdVertex>*>(tables) != NULL;

        int numIndices = (int)indices.size();

        // Allocate and fill index buffer.
        D3D11_BUFFER_DESC bd;
        bd.ByteWidth = numIndices * sizeof(int);
        bd.Usage = D3D11_USAGE_DEFAULT;
        bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
        bd.CPUAccessFlags = 0;
        bd.MiscFlags = 0;
        bd.StructureByteStride = sizeof(int);
        D3D11_SUBRESOURCE_DATA initData;
        initData.pSysMem = &indices[0];
        HRESULT hr = pd3d11Device->CreateBuffer(&bd, &initData, &patchIndexBuffer);
        if (FAILED(hr)) {
            return false;
        }

        OsdPatchArray array;
        array.desc.type = kNonPatch;
        array.patchSize = loop ? 3 : 4;
        array.firstIndex = 0;
        array.numIndices = numIndices;

        patchArrays.push_back(array);
        return true;
    }

    // adaptive patches
    isAdaptive = true;

    // Determine buffer sizes
    int totalPatchIndices =
        patchTables->GetFullRegularPatches().GetSize() +
        patchTables->GetFullBoundaryPatches().GetSize() +
        patchTables->GetFullCornerPatches().GetSize() +
        patchTables->GetFullGregoryPatches().GetSize() +
        patchTables->GetFullBoundaryGregoryPatches().GetSize();

    int totalPatchLevels =
        patchTables->GetFullRegularPatches().GetSize()/patchTables->GetRegularPatchRingsize() +
        patchTables->GetFullBoundaryPatches().GetSize()/patchTables->GetBoundaryPatchRingsize() +
        patchTables->GetFullCornerPatches().GetSize()/patchTables->GetCornerPatchRingsize() +
        patchTables->GetFullGregoryPatches().GetSize()/patchTables->GetGregoryPatchRingsize() +
        patchTables->GetFullBoundaryGregoryPatches().GetSize()/patchTables->GetGregoryPatchRingsize();

    for (int p=0; p<5; ++p) {
        totalPatchIndices +=
            patchTables->GetTransitionRegularPatches(p).GetSize();

        totalPatchLevels +=
            patchTables->GetTransitionRegularPatches(p).GetSize()/patchTables->GetRegularPatchRingsize();

        for (int r=0; r<4; ++r) {
            totalPatchIndices +=
                patchTables->GetTransitionBoundaryPatches(p, r).GetSize() +
                patchTables->GetTransitionCornerPatches(p, r).GetSize();

            totalPatchLevels +=
                patchTables->GetTransitionBoundaryPatches(p, r).GetSize()/patchTables->GetBoundaryPatchRingsize() +
                patchTables->GetTransitionCornerPatches(p, r).GetSize()/patchTables->GetCornerPatchRingsize();
        }
    }

    // Allocate and fill index buffer.
    D3D11_BUFFER_DESC bd;
    bd.ByteWidth = totalPatchIndices * sizeof(int);
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    bd.MiscFlags = 0;
    bd.StructureByteStride = sizeof(int);
    HRESULT hr = pd3d11Device->CreateBuffer(&bd, NULL, &patchIndexBuffer);
    if (FAILED(hr)) {
        return false;
    }

    D3D11_MAPPED_SUBRESOURCE mappedResource;
    hr = pd3d11DeviceContext->Map(patchIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(hr)) {
        return false;
    }
    unsigned int * indexBuffer = (unsigned int *) mappedResource.pData;

    bd.ByteWidth = totalPatchLevels * sizeof(unsigned int);
    bd.Usage = D3D11_USAGE_DYNAMIC;
    bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
    bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    bd.MiscFlags = 0;
    bd.StructureByteStride = sizeof(unsigned int);
    hr = pd3d11Device->CreateBuffer(&bd, NULL, &patchLevelBuffer);
    if (FAILED(hr)) {
        return false;
    }

    D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
    ZeroMemory(&srvd, sizeof(srvd));
    srvd.Format = DXGI_FORMAT_R32_UINT;
    srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
    srvd.Buffer.FirstElement = 0;
    srvd.Buffer.NumElements = totalPatchLevels;
    hr = pd3d11Device->CreateShaderResourceView(patchLevelBuffer, &srvd, &patchLevelBufferSRV);
    if (FAILED(hr)) {
        return false;
    }

    hr = pd3d11DeviceContext->Map(patchLevelBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    if (FAILED(hr)) {
        return false;
    }
    unsigned int * levelBuffer = (unsigned int *) mappedResource.pData;

    int indexBase = 0;
    int levelBase = 0;
    int maxValence = patchTables->GetMaxValence();

    _AppendPatchArray(indexBuffer, &indexBase,
                      levelBuffer, &levelBase,
                      patchTables->GetFullRegularPatches(),
                      patchTables->GetRegularPatchRingsize(),
                      patchTables->GetFullRegularPtexCoordinates(),
                      patchTables->GetFullRegularFVarData(),
                      farMesh->GetTotalFVarWidth(),
                      OsdPatchDescriptor(kRegular, 0, 0, 0, 0), 0);
    _AppendPatchArray(indexBuffer, &indexBase,
                      levelBuffer, &levelBase,
                      patchTables->GetFullBoundaryPatches(),
                      patchTables->GetBoundaryPatchRingsize(),
                      patchTables->GetFullBoundaryPtexCoordinates(),
                      patchTables->GetFullBoundaryFVarData(),
                      farMesh->GetTotalFVarWidth(),
                      OsdPatchDescriptor(kBoundary, 0, 0, 0, 0), 0);
    _AppendPatchArray(indexBuffer, &indexBase,
                      levelBuffer, &levelBase,
                      patchTables->GetFullCornerPatches(),
                      patchTables->GetCornerPatchRingsize(),
                      patchTables->GetFullCornerPtexCoordinates(),
                      patchTables->GetFullCornerFVarData(),
                      farMesh->GetTotalFVarWidth(),
                      OsdPatchDescriptor(kCorner, 0, 0, 0, 0), 0);
    _AppendPatchArray(indexBuffer, &indexBase,
                      levelBuffer, &levelBase,
                      patchTables->GetFullGregoryPatches(),
                      patchTables->GetGregoryPatchRingsize(),
                      patchTables->GetFullGregoryPtexCoordinates(),
                      patchTables->GetFullGregoryFVarData(),
                      farMesh->GetTotalFVarWidth(),
                      OsdPatchDescriptor(kGregory, 0, 0,
                                         maxValence, numElements), 0);
    _AppendPatchArray(indexBuffer, &indexBase,
                      levelBuffer, &levelBase,
                      patchTables->GetFullBoundaryGregoryPatches(),
                      patchTables->GetGregoryPatchRingsize(),
                      patchTables->GetFullBoundaryGregoryPtexCoordinates(),
                      patchTables->GetFullBoundaryGregoryFVarData(),
                      farMesh->GetTotalFVarWidth(),
                      OsdPatchDescriptor(kBoundaryGregory, 0, 0,
                                         maxValence, numElements),
                      (int)patchTables->GetFullGregoryPatches().GetSize());

    for (int p=0; p<5; ++p) {
        _AppendPatchArray(indexBuffer, &indexBase,
                          levelBuffer, &levelBase,
                          patchTables->GetTransitionRegularPatches(p),
                          patchTables->GetRegularPatchRingsize(),
                          patchTables->GetTransitionRegularPtexCoordinates(p),
                          patchTables->GetTransitionRegularFVarData(p),
                          farMesh->GetTotalFVarWidth(),
                          OsdPatchDescriptor(kTransitionRegular, p, 0, 0, 0), 0);
        for (int r=0; r<4; ++r) {
            _AppendPatchArray(indexBuffer, &indexBase,
                              levelBuffer, &levelBase,
                              patchTables->GetTransitionBoundaryPatches(p, r),
                              patchTables->GetBoundaryPatchRingsize(),
                              patchTables->GetTransitionBoundaryPtexCoordinates(p, r),
                              patchTables->GetTransitionBoundaryFVarData(p, r),
                              farMesh->GetTotalFVarWidth(),
                              OsdPatchDescriptor(kTransitionBoundary, p, r, 0, 0), 0);
            _AppendPatchArray(indexBuffer, &indexBase,
                              levelBuffer, &levelBase,
                              patchTables->GetTransitionCornerPatches(p, r),
                              patchTables->GetCornerPatchRingsize(),
                              patchTables->GetTransitionCornerPtexCoordinates(p, r),
                              patchTables->GetTransitionCornerFVarData(p, r),
                              farMesh->GetTotalFVarWidth(),
                              OsdPatchDescriptor(kTransitionCorner, p, r, 0, 0), 0);
        }
    }

    pd3d11DeviceContext->Unmap(patchIndexBuffer, 0);
    pd3d11DeviceContext->Unmap(patchLevelBuffer, 0);

    // allocate and initialize additional buffer data
    FarPatchTables::VertexValenceTable const &
    valenceTable = patchTables->GetVertexValenceTable();

    if (not valenceTable.empty()) {
        D3D11_BUFFER_DESC bd;
        bd.ByteWidth = UINT(valenceTable.size() * sizeof(unsigned int));
        bd.Usage = D3D11_USAGE_DEFAULT;
        bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
        bd.CPUAccessFlags = 0;
        bd.MiscFlags = 0;
        bd.StructureByteStride = sizeof(unsigned int);
        D3D11_SUBRESOURCE_DATA initData;
        initData.pSysMem = &valenceTable[0];
        HRESULT hr = pd3d11Device->CreateBuffer(&bd, &initData, &vertexValenceBuffer);
        if (FAILED(hr)) {
            return false;
        }

        D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
        ZeroMemory(&srvd, sizeof(srvd));
        srvd.Format = DXGI_FORMAT_R32_UINT;
        srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
        srvd.Buffer.FirstElement = 0;
        srvd.Buffer.NumElements = UINT(valenceTable.size());
        hr = pd3d11Device->CreateShaderResourceView(vertexValenceBuffer, &srvd, &vertexValenceBufferSRV);
        if (FAILED(hr)) {
            return false;
        }

        ZeroMemory(&srvd, sizeof(srvd));
        srvd.Format = DXGI_FORMAT_R32_FLOAT;
        srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
        srvd.Buffer.FirstElement = 0;
        srvd.Buffer.NumElements = 6 * farMesh->GetNumVertices(); // XXX: dyu
        hr = pd3d11Device->CreateShaderResourceView(vertexBuffer, &srvd, &vertexBufferSRV);
        if (FAILED(hr)) {
            return false;
        }
    }

    FarPatchTables::QuadOffsetTable const &
    quadOffsetTable = patchTables->GetQuadOffsetTable();

    if (not quadOffsetTable.empty()) {
        D3D11_BUFFER_DESC bd;
        bd.ByteWidth = UINT(quadOffsetTable.size() * sizeof(unsigned int));
        bd.Usage = D3D11_USAGE_DEFAULT;
        bd.BindFlags = D3D11_BIND_SHADER_RESOURCE;
        bd.CPUAccessFlags = 0;
        bd.MiscFlags = 0;
        bd.StructureByteStride = sizeof(unsigned int);
        D3D11_SUBRESOURCE_DATA initData;
        initData.pSysMem = &quadOffsetTable[0];
        HRESULT hr = pd3d11Device->CreateBuffer(&bd, &initData, &quadOffsetBuffer);
        if (FAILED(hr)) {
            return false;
        }

        D3D11_SHADER_RESOURCE_VIEW_DESC srvd;
        ZeroMemory(&srvd, sizeof(srvd));
        srvd.Format = DXGI_FORMAT_R32_UINT;
        srvd.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
        srvd.Buffer.FirstElement = 0;
        srvd.Buffer.NumElements = UINT(quadOffsetTable.size());
        hr = pd3d11Device->CreateShaderResourceView(quadOffsetBuffer, &srvd, &quadOffsetBufferSRV);
        if (FAILED(hr)) {
            return false;
        }
    }

    return true;
}
Exemple #3
0
bool
OsdGLDrawContext::allocate(FarMesh<OsdVertex> *farMesh,
                           GLuint vbo,
                           int numElements,
                           bool requirePtexCoordinates,
                           bool requireFVarData)
{
    FarPatchTables const * patchTables = farMesh->GetPatchTables();

    if (not patchTables) {
        // uniform patches
        isAdaptive = false;

        // XXX: farmesh should have FarDensePatchTable for dense mesh indices.
        //      instead of GetFaceVertices().
        const FarSubdivisionTables<OsdVertex> *tables = farMesh->GetSubdivisionTables();
        int level = tables->GetMaxLevel();
        const std::vector<int> &indices = farMesh->GetFaceVertices(level-1);

        // XXX: farmesh or FarSubdivisionTables should have a virtual method
        // to determine loop or not
        bool loop =
            dynamic_cast<const FarLoopSubdivisionTables<OsdVertex>*>(tables) != NULL;

        int numIndices = (int)indices.size();

        // Allocate and fill index buffer.
        glGenBuffers(1, &patchIndexBuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                     numIndices * sizeof(unsigned int), &(indices[0]), GL_STATIC_DRAW);

        OsdPatchArray array;
        array.desc.type = kNonPatch;
        array.patchSize = loop ? 3 : 4;
        array.firstIndex = 0;
        array.numIndices = numIndices;

        patchArrays.push_back(array);

        // Allocate ptex coordinate buffer if requested (for non-adaptive)
        if (requirePtexCoordinates) {
            GLuint ptexCoordinateBuffer = 0;
            glGenTextures(1, &ptexCoordinateTextureBuffer);
            glGenBuffers(1, &ptexCoordinateBuffer);
            glBindBuffer(GL_TEXTURE_BUFFER, ptexCoordinateBuffer);

            const std::vector<int> &ptexCoordinates =
                farMesh->GetPtexCoordinates(level-1);
            int size = (int)ptexCoordinates.size() * sizeof(GLint);

            glBufferData(GL_TEXTURE_BUFFER, size, &(ptexCoordinates[0]), GL_STATIC_DRAW);

            glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
            glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
            glDeleteBuffers(1, &ptexCoordinateBuffer);
            glBindTexture(GL_TEXTURE_BUFFER, 0);
        }

        // Allocate fvar data buffer if requested (for non-adaptive)
        if (requireFVarData) {
            GLuint fvarDataBuffer = 0;
            glGenTextures(1, &fvarDataTextureBuffer);
            glGenBuffers(1, &fvarDataBuffer);
            glBindBuffer(GL_TEXTURE_BUFFER, fvarDataBuffer);

            const std::vector<float> &fvarData = farMesh->GetFVarData(level-1);
            int size = (int)fvarData.size() * sizeof(float);

            glBufferData(GL_TEXTURE_BUFFER, size, &(fvarData[0]), GL_STATIC_DRAW);

            glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
            glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
            glDeleteBuffers(1, &fvarDataBuffer);
            glBindTexture(GL_TEXTURE_BUFFER, 0);
        }

        return true;
    }

    // adaptive patches
    isAdaptive = true;

    // Determine buffer sizes
    int totalPatchIndices = 
        patchTables->GetFullRegularPatches().GetSize() +
        patchTables->GetFullBoundaryPatches().GetSize() +
        patchTables->GetFullCornerPatches().GetSize() +
        patchTables->GetFullGregoryPatches().GetSize() +
        patchTables->GetFullBoundaryGregoryPatches().GetSize();

    int totalPatchLevels = 
        patchTables->GetFullRegularPatches().GetSize()/patchTables->GetRegularPatchRingsize() +
        patchTables->GetFullBoundaryPatches().GetSize()/patchTables->GetBoundaryPatchRingsize() +
        patchTables->GetFullCornerPatches().GetSize()/patchTables->GetCornerPatchRingsize() +
        patchTables->GetFullGregoryPatches().GetSize()/patchTables->GetGregoryPatchRingsize() +
        patchTables->GetFullBoundaryGregoryPatches().GetSize()/patchTables->GetGregoryPatchRingsize();

    for (int p=0; p<5; ++p) {
        totalPatchIndices +=
            patchTables->GetTransitionRegularPatches(p).GetSize();

        totalPatchLevels +=
            patchTables->GetTransitionRegularPatches(p).GetSize()/patchTables->GetRegularPatchRingsize();

        for (int r=0; r<4; ++r) {
            totalPatchIndices +=
                patchTables->GetTransitionBoundaryPatches(p, r).GetSize() +
                patchTables->GetTransitionCornerPatches(p, r).GetSize();

            totalPatchLevels +=
                patchTables->GetTransitionBoundaryPatches(p, r).GetSize()/patchTables->GetBoundaryPatchRingsize() +
                patchTables->GetTransitionCornerPatches(p, r).GetSize()/patchTables->GetCornerPatchRingsize();
        }
    }

    // Allocate and fill index buffer.
    glGenBuffers(1, &patchIndexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, patchIndexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
        totalPatchIndices * sizeof(unsigned int), NULL, GL_STATIC_DRAW);

    GLuint patchLevelBuffer = 0;
    glGenBuffers(1, &patchLevelBuffer);
    glBindBuffer(GL_TEXTURE_BUFFER, patchLevelBuffer);
    glBufferData(GL_TEXTURE_BUFFER,
        totalPatchLevels * sizeof(unsigned char), NULL, GL_STATIC_DRAW);

    // Allocate ptex coordinate buffer if requested
    GLuint ptexCoordinateBuffer = 0;
    if (requirePtexCoordinates) {
        glGenTextures(1, &ptexCoordinateTextureBuffer);
        glGenBuffers(1, &ptexCoordinateBuffer);
        glBindBuffer(GL_ARRAY_BUFFER, ptexCoordinateBuffer);
        glBufferData(GL_ARRAY_BUFFER,
            totalPatchLevels * sizeof(int) * 2, NULL, GL_STATIC_DRAW);
    }

    // Allocate fvar data buffer if requested
    GLuint fvarDataBuffer = 0;
    if (requireFVarData) {
        glGenTextures(1, &fvarDataTextureBuffer);
        glGenBuffers(1, &fvarDataBuffer);
        glBindBuffer(GL_UNIFORM_BUFFER, fvarDataBuffer);
        glBufferData(GL_UNIFORM_BUFFER,
            totalPatchLevels * sizeof(float) * farMesh->GetTotalFVarWidth()*4, NULL, GL_STATIC_DRAW);
    }

    int indexBase = 0;
    int levelBase = 0;
    int maxValence = patchTables->GetMaxValence();

    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullRegularPatches(),
                        patchTables->GetRegularPatchRingsize(),
                        patchTables->GetFullRegularPtexCoordinates(),
                        patchTables->GetFullRegularFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kRegular, 0, 0, 0, 0), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullBoundaryPatches(),
                        patchTables->GetBoundaryPatchRingsize(),
                        patchTables->GetFullBoundaryPtexCoordinates(),
                        patchTables->GetFullBoundaryFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kBoundary, 0, 0, 0, 0), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullCornerPatches(),
                        patchTables->GetCornerPatchRingsize(),
                        patchTables->GetFullCornerPtexCoordinates(),
                        patchTables->GetFullCornerFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kCorner, 0, 0, 0, 0), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullGregoryPatches(),
                        patchTables->GetGregoryPatchRingsize(),
                        patchTables->GetFullGregoryPtexCoordinates(),
                        patchTables->GetFullGregoryFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kGregory, 0, 0,
                                           maxValence, numElements), 0);
    _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetFullBoundaryGregoryPatches(),
                        patchTables->GetGregoryPatchRingsize(),
                        patchTables->GetFullBoundaryGregoryPtexCoordinates(),
                        patchTables->GetFullBoundaryGregoryFVarData(),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kBoundaryGregory, 0, 0,
                                           maxValence, numElements),
                        (int)patchTables->GetFullGregoryPatches().GetSize());

    for (int p=0; p<5; ++p) {
        _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetTransitionRegularPatches(p),
                        patchTables->GetRegularPatchRingsize(),
                        patchTables->GetTransitionRegularPtexCoordinates(p),
                        patchTables->GetTransitionRegularFVarData(p),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kTransitionRegular, p, 0, 0, 0), 0);
        for (int r=0; r<4; ++r) {
            _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetTransitionBoundaryPatches(p, r),
                        patchTables->GetBoundaryPatchRingsize(),
                        patchTables->GetTransitionBoundaryPtexCoordinates(p, r),
                        patchTables->GetTransitionBoundaryFVarData(p, r),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kTransitionBoundary, p, r, 0, 0), 0);
            _AppendPatchArray(&indexBase, &levelBase,
                        patchTables->GetTransitionCornerPatches(p, r),
                        patchTables->GetCornerPatchRingsize(),
                        patchTables->GetTransitionCornerPtexCoordinates(p, r),
                        patchTables->GetTransitionCornerFVarData(p, r),
                        farMesh->GetTotalFVarWidth(),
                        OsdPatchDescriptor(kTransitionCorner, p, r, 0, 0), 0);
        }
    }

    // finalize level texture buffer
    glGenTextures(1, &patchLevelTextureBuffer);
    glBindTexture(GL_TEXTURE_BUFFER, patchLevelTextureBuffer);
    glTexBuffer(GL_TEXTURE_BUFFER, GL_R8I, patchLevelBuffer);
    glDeleteBuffers(1, &patchLevelBuffer);

    // finalize ptex coordinate texture buffer
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    if (requirePtexCoordinates) {
        glBindTexture(GL_TEXTURE_BUFFER, ptexCoordinateTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_RG32I, ptexCoordinateBuffer);
        glDeleteBuffers(1, &ptexCoordinateBuffer);
    }
    // finalize fvar data texture buffer
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
    if (requireFVarData) {
        glBindTexture(GL_TEXTURE_BUFFER, fvarDataTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, fvarDataBuffer);
        glDeleteBuffers(1, &fvarDataBuffer);
    }

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    glBindBuffer(GL_TEXTURE_BUFFER, 0);

    // allocate and initialize additional buffer data
    FarPatchTables::VertexValenceTable const &
        valenceTable = patchTables->GetVertexValenceTable();

    if (not valenceTable.empty()) {
        GLuint buffer = 0;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_TEXTURE_BUFFER, buffer);
        glBufferData(GL_TEXTURE_BUFFER,
                valenceTable.size() * sizeof(unsigned int),
                &valenceTable[0], GL_STATIC_DRAW);

        glGenTextures(1, &vertexValenceTextureBuffer);
        glBindTexture(GL_TEXTURE_BUFFER, vertexValenceTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
        glDeleteBuffers(1, &buffer);

        glGenTextures(1, &vertexTextureBuffer);
        glBindTexture(GL_TEXTURE_BUFFER, vertexTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32F, vbo);

        glBindBuffer(GL_TEXTURE_BUFFER, 0);
    }

    FarPatchTables::QuadOffsetTable const &
        quadOffsetTable = patchTables->GetQuadOffsetTable();

    if (not quadOffsetTable.empty()) {
        GLuint buffer = 0;
        glGenBuffers(1, &buffer);
        glBindBuffer(GL_TEXTURE_BUFFER, buffer);
        glBufferData(GL_TEXTURE_BUFFER,
                quadOffsetTable.size() * sizeof(unsigned int),
                &quadOffsetTable[0], GL_STATIC_DRAW);

        glGenTextures(1, &quadOffsetTextureBuffer);
        glBindTexture(GL_TEXTURE_BUFFER, quadOffsetTextureBuffer);
        glTexBuffer(GL_TEXTURE_BUFFER, GL_R32I, buffer);
        glDeleteBuffers(1, &buffer);

        glBindBuffer(GL_TEXTURE_BUFFER, 0);
    }

    return true;
}