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