OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 | 8 |
9 #include "GrGLGpu.h" | 9 #include "GrGLGpu.h" |
10 #include "GrGLGLSL.h" | 10 #include "GrGLGLSL.h" |
(...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1392 sbDesc, | 1392 sbDesc, |
1393 width, | 1393 width, |
1394 height, | 1394 height, |
1395 samples, | 1395 samples, |
1396 format); | 1396 format); |
1397 return stencil; | 1397 return stencil; |
1398 } | 1398 } |
1399 | 1399 |
1400 //////////////////////////////////////////////////////////////////////////////// | 1400 //////////////////////////////////////////////////////////////////////////////// |
1401 | 1401 |
| 1402 // GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a cli
ent's vertex buffer |
| 1403 // objects are implemented as client-side-arrays on tile-deferred architectures. |
| 1404 #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW |
| 1405 |
1402 GrVertexBuffer* GrGLGpu::onCreateVertexBuffer(size_t size, bool dynamic) { | 1406 GrVertexBuffer* GrGLGpu::onCreateVertexBuffer(size_t size, bool dynamic) { |
1403 GrGLVertexBuffer::Desc desc; | 1407 GrGLVertexBuffer::Desc desc; |
1404 desc.fDynamic = dynamic; | 1408 desc.fUsage = dynamic ? GrGLBufferImpl::kDynamicDraw_Usage : GrGLBufferImpl:
:kStaticDraw_Usage; |
1405 desc.fSizeInBytes = size; | 1409 desc.fSizeInBytes = size; |
1406 | 1410 |
1407 if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && desc.fDynamic) { | 1411 if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && dynamic) { |
1408 desc.fID = 0; | 1412 desc.fID = 0; |
1409 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); | 1413 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); |
1410 return vertexBuffer; | 1414 return vertexBuffer; |
1411 } else { | 1415 } else { |
1412 GL_CALL(GenBuffers(1, &desc.fID)); | 1416 GL_CALL(GenBuffers(1, &desc.fID)); |
1413 if (desc.fID) { | 1417 if (desc.fID) { |
1414 fHWGeometryState.setVertexBufferID(this, desc.fID); | 1418 fHWGeometryState.setVertexBufferID(this, desc.fID); |
1415 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1419 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
1416 // make sure driver can allocate memory for this buffer | 1420 // make sure driver can allocate memory for this buffer |
1417 GL_ALLOC_CALL(this->glInterface(), | 1421 GL_ALLOC_CALL(this->glInterface(), |
1418 BufferData(GR_GL_ARRAY_BUFFER, | 1422 BufferData(GR_GL_ARRAY_BUFFER, |
1419 (GrGLsizeiptr) desc.fSizeInBytes, | 1423 (GrGLsizeiptr) desc.fSizeInBytes, |
1420 nullptr, // data ptr | 1424 nullptr, // data ptr |
1421 desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_
STATIC_DRAW)); | 1425 dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATI
C_DRAW)); |
1422 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { | 1426 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { |
1423 GL_CALL(DeleteBuffers(1, &desc.fID)); | 1427 GL_CALL(DeleteBuffers(1, &desc.fID)); |
1424 this->notifyVertexBufferDelete(desc.fID); | 1428 this->notifyVertexBufferDelete(desc.fID); |
1425 return nullptr; | 1429 return nullptr; |
1426 } | 1430 } |
1427 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); | 1431 GrGLVertexBuffer* vertexBuffer = new GrGLVertexBuffer(this, desc); |
1428 return vertexBuffer; | 1432 return vertexBuffer; |
1429 } | 1433 } |
1430 return nullptr; | 1434 return nullptr; |
1431 } | 1435 } |
1432 } | 1436 } |
1433 | 1437 |
1434 GrIndexBuffer* GrGLGpu::onCreateIndexBuffer(size_t size, bool dynamic) { | 1438 GrIndexBuffer* GrGLGpu::onCreateIndexBuffer(size_t size, bool dynamic) { |
1435 GrGLIndexBuffer::Desc desc; | 1439 GrGLIndexBuffer::Desc desc; |
1436 desc.fDynamic = dynamic; | 1440 desc.fUsage = dynamic ? GrGLBufferImpl::kDynamicDraw_Usage : GrGLBufferImpl:
:kStaticDraw_Usage; |
1437 desc.fSizeInBytes = size; | 1441 desc.fSizeInBytes = size; |
1438 | 1442 |
1439 if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && desc.fDynamic) { | 1443 if (this->glCaps().useNonVBOVertexAndIndexDynamicData() && dynamic) { |
1440 desc.fID = 0; | 1444 desc.fID = 0; |
1441 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); | 1445 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); |
1442 return indexBuffer; | 1446 return indexBuffer; |
1443 } else { | 1447 } else { |
1444 GL_CALL(GenBuffers(1, &desc.fID)); | 1448 GL_CALL(GenBuffers(1, &desc.fID)); |
1445 if (desc.fID) { | 1449 if (desc.fID) { |
1446 fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, desc.fID
); | 1450 fHWGeometryState.setIndexBufferIDOnDefaultVertexArray(this, desc.fID
); |
1447 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); | 1451 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
1448 // make sure driver can allocate memory for this buffer | 1452 // make sure driver can allocate memory for this buffer |
1449 GL_ALLOC_CALL(this->glInterface(), | 1453 GL_ALLOC_CALL(this->glInterface(), |
1450 BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, | 1454 BufferData(GR_GL_ELEMENT_ARRAY_BUFFER, |
1451 (GrGLsizeiptr) desc.fSizeInBytes, | 1455 (GrGLsizeiptr) desc.fSizeInBytes, |
1452 nullptr, // data ptr | 1456 nullptr, // data ptr |
1453 desc.fDynamic ? GR_GL_DYNAMIC_DRAW : GR_GL_
STATIC_DRAW)); | 1457 dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATI
C_DRAW)); |
1454 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { | 1458 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { |
1455 GL_CALL(DeleteBuffers(1, &desc.fID)); | 1459 GL_CALL(DeleteBuffers(1, &desc.fID)); |
1456 this->notifyIndexBufferDelete(desc.fID); | 1460 this->notifyIndexBufferDelete(desc.fID); |
1457 return nullptr; | 1461 return nullptr; |
1458 } | 1462 } |
1459 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); | 1463 GrIndexBuffer* indexBuffer = new GrGLIndexBuffer(this, desc); |
1460 return indexBuffer; | 1464 return indexBuffer; |
1461 } | 1465 } |
1462 return nullptr; | 1466 return nullptr; |
1463 } | 1467 } |
1464 } | 1468 } |
1465 | 1469 |
| 1470 GrTransferBuffer* GrGLGpu::onCreateTransferBuffer(size_t size, TransferType type
) { |
| 1471 GrGLTransferBuffer::Desc desc; |
| 1472 bool toGpu = (kCpuToGpu_TransferType == type); |
| 1473 desc.fUsage = toGpu ? GrGLBufferImpl::kStreamDraw_Usage : GrGLBufferImpl::kS
treamRead_Usage; |
| 1474 |
| 1475 desc.fSizeInBytes = size; |
| 1476 |
| 1477 // TODO: check caps to see if we can create a PBO, and which kind |
| 1478 GL_CALL(GenBuffers(1, &desc.fID)); |
| 1479 if (desc.fID) { |
| 1480 CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
| 1481 // make sure driver can allocate memory for this buffer |
| 1482 GrGLenum type = toGpu ? GR_GL_PIXEL_UNPACK_BUFFER : GR_GL_PIXEL_PACK_BUF
FER; |
| 1483 GL_ALLOC_CALL(this->glInterface(), |
| 1484 BufferData(type, |
| 1485 (GrGLsizeiptr) desc.fSizeInBytes, |
| 1486 nullptr, // data ptr |
| 1487 (toGpu ? GR_GL_STREAM_DRAW : GR_GL_STREAM_READ)
)); |
| 1488 if (CHECK_ALLOC_ERROR(this->glInterface()) != GR_GL_NO_ERROR) { |
| 1489 GL_CALL(DeleteBuffers(1, &desc.fID)); |
| 1490 return nullptr; |
| 1491 } |
| 1492 GrTransferBuffer* transferBuffer = new GrGLTransferBuffer(this, desc, ty
pe); |
| 1493 return transferBuffer; |
| 1494 } |
| 1495 |
| 1496 return nullptr; |
| 1497 } |
| 1498 |
1466 void GrGLGpu::flushScissor(const GrScissorState& scissorState, | 1499 void GrGLGpu::flushScissor(const GrScissorState& scissorState, |
1467 const GrGLIRect& rtViewport, | 1500 const GrGLIRect& rtViewport, |
1468 GrSurfaceOrigin rtOrigin) { | 1501 GrSurfaceOrigin rtOrigin) { |
1469 if (scissorState.enabled()) { | 1502 if (scissorState.enabled()) { |
1470 GrGLIRect scissor; | 1503 GrGLIRect scissor; |
1471 scissor.setRelativeTo(rtViewport, | 1504 scissor.setRelativeTo(rtViewport, |
1472 scissorState.rect().fLeft, | 1505 scissorState.rect().fLeft, |
1473 scissorState.rect().fTop, | 1506 scissorState.rect().fTop, |
1474 scissorState.rect().width(), | 1507 scissorState.rect().width(), |
1475 scissorState.rect().height(), | 1508 scissorState.rect().height(), |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1596 const GrPipeline& pipeline) const { | 1629 const GrPipeline& pipeline) const { |
1597 if (!GrGLProgramDescBuilder::Build(desc, primProc, pipeline, this)) { | 1630 if (!GrGLProgramDescBuilder::Build(desc, primProc, pipeline, this)) { |
1598 SkDEBUGFAIL("Failed to generate GL program descriptor"); | 1631 SkDEBUGFAIL("Failed to generate GL program descriptor"); |
1599 } | 1632 } |
1600 } | 1633 } |
1601 | 1634 |
1602 void GrGLGpu::bindBuffer(GrGLuint id, GrGLenum type) { | 1635 void GrGLGpu::bindBuffer(GrGLuint id, GrGLenum type) { |
1603 this->handleDirtyContext(); | 1636 this->handleDirtyContext(); |
1604 if (GR_GL_ARRAY_BUFFER == type) { | 1637 if (GR_GL_ARRAY_BUFFER == type) { |
1605 this->bindVertexBuffer(id); | 1638 this->bindVertexBuffer(id); |
1606 } else { | 1639 } else if (GR_GL_ELEMENT_ARRAY_BUFFER == type) { |
1607 SkASSERT(GR_GL_ELEMENT_ARRAY_BUFFER == type); | |
1608 this->bindIndexBufferAndDefaultVertexArray(id); | 1640 this->bindIndexBufferAndDefaultVertexArray(id); |
1609 } | 1641 } |
1610 } | 1642 } |
1611 | 1643 |
1612 void GrGLGpu::releaseBuffer(GrGLuint id, GrGLenum type) { | 1644 void GrGLGpu::releaseBuffer(GrGLuint id, GrGLenum type) { |
1613 this->handleDirtyContext(); | 1645 this->handleDirtyContext(); |
1614 GL_CALL(DeleteBuffers(1, &id)); | 1646 GL_CALL(DeleteBuffers(1, &id)); |
1615 if (GR_GL_ARRAY_BUFFER == type) { | 1647 if (GR_GL_ARRAY_BUFFER == type) { |
1616 this->notifyVertexBufferDelete(id); | 1648 this->notifyVertexBufferDelete(id); |
1617 } else { | 1649 } else if (GR_GL_ELEMENT_ARRAY_BUFFER == type) { |
1618 SkASSERT(GR_GL_ELEMENT_ARRAY_BUFFER == type); | |
1619 this->notifyIndexBufferDelete(id); | 1650 this->notifyIndexBufferDelete(id); |
1620 } | 1651 } |
1621 } | 1652 } |
1622 | 1653 |
1623 // GL_STREAM_DRAW triggers an optimization in Chromium's GPU process where a cli
ent's vertex buffer | 1654 static GrGLenum get_gl_usage(GrGLBufferImpl::Usage usage) { |
1624 // objects are implemented as client-side-arrays on tile-deferred architectures. | 1655 static const GrGLenum grToGL[] = { |
1625 #define DYNAMIC_USAGE_PARAM GR_GL_STREAM_DRAW | 1656 GR_GL_STATIC_DRAW, // GrGLBufferImpl::kStaticDraw_Usage |
| 1657 DYNAMIC_USAGE_PARAM, // GrGLBufferImpl::kDynamicDraw_Usage |
| 1658 GR_GL_STREAM_DRAW, // GrGLBufferImpl::kStreamDraw_Usage |
| 1659 GR_GL_STREAM_READ, // GrGLBufferImpl::kStreamRead_Usage |
| 1660 }; |
| 1661 static_assert(SK_ARRAY_COUNT(grToGL) == GrGLBufferImpl::kUsageCount, "array_
size_mismatch"); |
1626 | 1662 |
1627 void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, bool dynamic, size_t curren
tSize, | 1663 return grToGL[usage]; |
1628 size_t requestedSize) { | 1664 } |
| 1665 |
| 1666 void* GrGLGpu::mapBuffer(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage
, |
| 1667 size_t currentSize, size_t requestedSize) { |
1629 void* mapPtr = nullptr; | 1668 void* mapPtr = nullptr; |
| 1669 GrGLenum glUsage = get_gl_usage(usage); |
1630 // Handling dirty context is done in the bindBuffer call | 1670 // Handling dirty context is done in the bindBuffer call |
1631 switch (this->glCaps().mapBufferType()) { | 1671 switch (this->glCaps().mapBufferType()) { |
1632 case GrGLCaps::kNone_MapBufferType: | 1672 case GrGLCaps::kNone_MapBufferType: |
1633 break; | 1673 break; |
1634 case GrGLCaps::kMapBuffer_MapBufferType: | 1674 case GrGLCaps::kMapBuffer_MapBufferType: |
1635 this->bindBuffer(id, type); | 1675 this->bindBuffer(id, type); |
1636 // Let driver know it can discard the old data | 1676 // Let driver know it can discard the old data |
1637 if (GR_GL_USE_BUFFER_DATA_NULL_HINT || currentSize != requestedSize)
{ | 1677 if (GR_GL_USE_BUFFER_DATA_NULL_HINT || currentSize != requestedSize)
{ |
1638 GL_CALL(BufferData(type, requestedSize, nullptr, | 1678 GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); |
1639 dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_
DRAW)); | |
1640 } | 1679 } |
1641 GL_CALL_RET(mapPtr, MapBuffer(type, GR_GL_WRITE_ONLY)); | 1680 GL_CALL_RET(mapPtr, MapBuffer(type, GR_GL_WRITE_ONLY)); |
1642 break; | 1681 break; |
1643 case GrGLCaps::kMapBufferRange_MapBufferType: { | 1682 case GrGLCaps::kMapBufferRange_MapBufferType: { |
1644 this->bindBuffer(id, type); | 1683 this->bindBuffer(id, type); |
1645 // Make sure the GL buffer size agrees with fDesc before mapping. | 1684 // Make sure the GL buffer size agrees with fDesc before mapping. |
1646 if (currentSize != requestedSize) { | 1685 if (currentSize != requestedSize) { |
1647 GL_CALL(BufferData(type, requestedSize, nullptr, | 1686 GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); |
1648 dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_
DRAW)); | |
1649 } | 1687 } |
1650 static const GrGLbitfield kAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT
| | 1688 static const GrGLbitfield kAccess = GR_GL_MAP_INVALIDATE_BUFFER_BIT
| |
1651 GR_GL_MAP_WRITE_BIT; | 1689 GR_GL_MAP_WRITE_BIT; |
1652 GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, kAccess))
; | 1690 GL_CALL_RET(mapPtr, MapBufferRange(type, 0, requestedSize, kAccess))
; |
1653 break; | 1691 break; |
1654 } | 1692 } |
1655 case GrGLCaps::kChromium_MapBufferType: | 1693 case GrGLCaps::kChromium_MapBufferType: |
1656 this->bindBuffer(id, type); | 1694 this->bindBuffer(id, type); |
1657 // Make sure the GL buffer size agrees with fDesc before mapping. | 1695 // Make sure the GL buffer size agrees with fDesc before mapping. |
1658 if (currentSize != requestedSize) { | 1696 if (currentSize != requestedSize) { |
1659 GL_CALL(BufferData(type, requestedSize, nullptr, | 1697 GL_CALL(BufferData(type, requestedSize, nullptr, glUsage)); |
1660 dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_
DRAW)); | |
1661 } | 1698 } |
1662 GL_CALL_RET(mapPtr, MapBufferSubData(type, 0, requestedSize, GR_GL_W
RITE_ONLY)); | 1699 GL_CALL_RET(mapPtr, MapBufferSubData(type, 0, requestedSize, GR_GL_W
RITE_ONLY)); |
1663 break; | 1700 break; |
1664 } | 1701 } |
1665 return mapPtr; | 1702 return mapPtr; |
1666 } | 1703 } |
1667 | 1704 |
1668 void GrGLGpu::bufferData(GrGLuint id, GrGLenum type, bool dynamic, size_t curren
tSize, | 1705 void GrGLGpu::bufferData(GrGLuint id, GrGLenum type, GrGLBufferImpl::Usage usage
, |
1669 const void* src, size_t srcSizeInBytes) { | 1706 size_t currentSize, const void* src, size_t srcSizeInBy
tes) { |
1670 SkASSERT(srcSizeInBytes <= currentSize); | 1707 SkASSERT(srcSizeInBytes <= currentSize); |
1671 // bindbuffer handles dirty context | 1708 // bindbuffer handles dirty context |
1672 this->bindBuffer(id, type); | 1709 this->bindBuffer(id, type); |
1673 GrGLenum usage = dynamic ? DYNAMIC_USAGE_PARAM : GR_GL_STATIC_DRAW; | 1710 GrGLenum glUsage = get_gl_usage(usage); |
1674 | 1711 |
1675 #if GR_GL_USE_BUFFER_DATA_NULL_HINT | 1712 #if GR_GL_USE_BUFFER_DATA_NULL_HINT |
1676 if (currentSize == srcSizeInBytes) { | 1713 if (currentSize == srcSizeInBytes) { |
1677 GL_CALL(BufferData(type, (GrGLsizeiptr) srcSizeInBytes, src, usage)); | 1714 GL_CALL(BufferData(type, (GrGLsizeiptr) srcSizeInBytes, src, glUsage)); |
1678 } else { | 1715 } else { |
1679 // Before we call glBufferSubData we give the driver a hint using | 1716 // Before we call glBufferSubData we give the driver a hint using |
1680 // glBufferData with nullptr. This makes the old buffer contents | 1717 // glBufferData with nullptr. This makes the old buffer contents |
1681 // inaccessible to future draws. The GPU may still be processing | 1718 // inaccessible to future draws. The GPU may still be processing |
1682 // draws that reference the old contents. With this hint it can | 1719 // draws that reference the old contents. With this hint it can |
1683 // assign a different allocation for the new contents to avoid | 1720 // assign a different allocation for the new contents to avoid |
1684 // flushing the gpu past draws consuming the old contents. | 1721 // flushing the gpu past draws consuming the old contents. |
1685 // TODO I think we actually want to try calling bufferData here | 1722 // TODO I think we actually want to try calling bufferData here |
1686 GL_CALL(BufferData(type, currentSize, nullptr, usage)); | 1723 GL_CALL(BufferData(type, currentSize, nullptr, glUsage)); |
1687 GL_CALL(BufferSubData(type, 0, (GrGLsizeiptr) srcSizeInBytes, src)); | 1724 GL_CALL(BufferSubData(type, 0, (GrGLsizeiptr) srcSizeInBytes, src)); |
1688 } | 1725 } |
1689 #else | 1726 #else |
1690 // Note that we're cheating on the size here. Currently no methods | 1727 // Note that we're cheating on the size here. Currently no methods |
1691 // allow a partial update that preserves contents of non-updated | 1728 // allow a partial update that preserves contents of non-updated |
1692 // portions of the buffer (map() does a glBufferData(..size, nullptr..)) | 1729 // portions of the buffer (map() does a glBufferData(..size, nullptr..)) |
1693 GL_CALL(BufferData(type, srcSizeInBytes, src, usage)); | 1730 GL_CALL(BufferData(type, srcSizeInBytes, src, glUsage)); |
1694 #endif | 1731 #endif |
1695 } | 1732 } |
1696 | 1733 |
1697 void GrGLGpu::unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr) { | 1734 void GrGLGpu::unmapBuffer(GrGLuint id, GrGLenum type, void* mapPtr) { |
1698 // bind buffer handles the dirty context | 1735 // bind buffer handles the dirty context |
1699 switch (this->glCaps().mapBufferType()) { | 1736 switch (this->glCaps().mapBufferType()) { |
1700 case GrGLCaps::kNone_MapBufferType: | 1737 case GrGLCaps::kNone_MapBufferType: |
1701 SkDEBUGFAIL("Shouldn't get here."); | 1738 SkDEBUGFAIL("Shouldn't get here."); |
1702 return; | 1739 return; |
1703 case GrGLCaps::kMapBuffer_MapBufferType: // fall through | 1740 case GrGLCaps::kMapBuffer_MapBufferType: // fall through |
(...skipping 1694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3398 this->setVertexArrayID(gpu, 0); | 3435 this->setVertexArrayID(gpu, 0); |
3399 } | 3436 } |
3400 int attrCount = gpu->glCaps().maxVertexAttributes(); | 3437 int attrCount = gpu->glCaps().maxVertexAttributes(); |
3401 if (fDefaultVertexArrayAttribState.count() != attrCount) { | 3438 if (fDefaultVertexArrayAttribState.count() != attrCount) { |
3402 fDefaultVertexArrayAttribState.resize(attrCount); | 3439 fDefaultVertexArrayAttribState.resize(attrCount); |
3403 } | 3440 } |
3404 attribState = &fDefaultVertexArrayAttribState; | 3441 attribState = &fDefaultVertexArrayAttribState; |
3405 } | 3442 } |
3406 return attribState; | 3443 return attribState; |
3407 } | 3444 } |
OLD | NEW |