Revert "Move setupGeometry() from GrGLGpu to GrGLOpsRenderPass"
This reverts commit b67081f9cb
.
Reason for revert: Crash in glDeleteProgram on ES2
Original change's description:
> Move setupGeometry() from GrGLGpu to GrGLOpsRenderPass
>
> Change-Id: I8788b96e07216be738c0ce1babb810b05bf46694
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/273696
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
TBR=bsalomon@google.com,csmartdalton@google.com
Change-Id: Ibd1ae7c01ac8ac6ade94f6d542a6b711f53e7fb6
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/274021
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
parent
55f681faf3
commit
20e7a53cd2
@ -425,6 +425,7 @@ GrGLGpu::~GrGLGpu() {
|
||||
fCopyProgramArrayBuffer.reset();
|
||||
fMipmapProgramArrayBuffer.reset();
|
||||
|
||||
fHWProgram.reset();
|
||||
if (fHWProgramID) {
|
||||
// detach the current program so there is no confusion on OpenGL's part
|
||||
// that we want it to be deleted
|
||||
@ -500,6 +501,7 @@ void GrGLGpu::disconnect(DisconnectType type) {
|
||||
}
|
||||
}
|
||||
|
||||
fHWProgram.reset();
|
||||
fProgramCache.reset();
|
||||
|
||||
fHWProgramID = 0;
|
||||
@ -660,6 +662,7 @@ void GrGLGpu::onResetContext(uint32_t resetBits) {
|
||||
|
||||
if (resetBits & kProgram_GrGLBackendState) {
|
||||
fHWProgramID = 0;
|
||||
fHWProgram.reset();
|
||||
}
|
||||
++fResetTimestampForTextureParameters;
|
||||
}
|
||||
@ -1762,7 +1765,6 @@ void GrGLGpu::flushScissorTest(GrScissorTest scissorTest) {
|
||||
|
||||
void GrGLGpu::flushScissorRect(const SkIRect& scissor, int rtWidth, int rtHeight,
|
||||
GrSurfaceOrigin rtOrigin) {
|
||||
SkASSERT(TriState::kYes_TriState == fHWScissorSettings.fEnabled);
|
||||
auto nativeScissor = GrNativeRect::MakeRelativeTo(rtOrigin, rtHeight, scissor);
|
||||
if (fHWScissorSettings.fRect != nativeScissor) {
|
||||
GL_CALL(Scissor(nativeScissor.fX, nativeScissor.fY, nativeScissor.fWidth,
|
||||
@ -1811,27 +1813,26 @@ void GrGLGpu::disableWindowRectangles() {
|
||||
#endif
|
||||
}
|
||||
|
||||
sk_sp<GrGLProgram> GrGLGpu::flushGLState(GrRenderTarget* renderTarget,
|
||||
const GrProgramInfo& programInfo) {
|
||||
bool GrGLGpu::flushGLState(GrRenderTarget* renderTarget, const GrProgramInfo& programInfo) {
|
||||
this->handleDirtyContext();
|
||||
|
||||
sk_sp<GrGLProgram> program = fProgramCache->findOrCreateProgram(renderTarget, programInfo);
|
||||
if (!program) {
|
||||
GrCapsDebugf(this->caps(), "Failed to create program!\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
this->flushProgram(program->programID());
|
||||
|
||||
if (GrPrimitiveType::kPatches == programInfo.primitiveType()) {
|
||||
this->flushPatchVertexCount(programInfo.tessellationPatchVertexCount());
|
||||
}
|
||||
|
||||
sk_sp<GrGLProgram> program(fProgramCache->findOrCreateProgram(renderTarget, programInfo));
|
||||
if (!program) {
|
||||
GrCapsDebugf(this->caps(), "Failed to create program!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->flushProgram(std::move(program));
|
||||
|
||||
// Swizzle the blend to match what the shader will output.
|
||||
this->flushBlendAndColorWrite(programInfo.pipeline().getXferProcessor().getBlendInfo(),
|
||||
programInfo.pipeline().outputSwizzle());
|
||||
|
||||
program->updateUniforms(renderTarget, programInfo);
|
||||
fHWProgram->updateUniforms(renderTarget, programInfo);
|
||||
|
||||
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(renderTarget);
|
||||
GrStencilSettings stencil;
|
||||
@ -1853,18 +1854,85 @@ sk_sp<GrGLProgram> GrGLGpu::flushGLState(GrRenderTarget* renderTarget,
|
||||
// to be msaa-resolved (which will modify bound FBO state).
|
||||
this->flushRenderTarget(glRT);
|
||||
|
||||
return program;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLGpu::flushProgram(sk_sp<GrGLProgram> program) {
|
||||
if (!program) {
|
||||
fHWProgram.reset();
|
||||
fHWProgramID = 0;
|
||||
return;
|
||||
}
|
||||
SkASSERT((program == fHWProgram) == (fHWProgramID == program->programID()));
|
||||
if (program == fHWProgram) {
|
||||
return;
|
||||
}
|
||||
auto id = program->programID();
|
||||
SkASSERT(id);
|
||||
GL_CALL(UseProgram(id));
|
||||
fHWProgram = std::move(program);
|
||||
fHWProgramID = id;
|
||||
}
|
||||
|
||||
void GrGLGpu::flushProgram(GrGLuint id) {
|
||||
SkASSERT(id);
|
||||
if (fHWProgramID == id) {
|
||||
SkASSERT(!fHWProgram);
|
||||
return;
|
||||
}
|
||||
fHWProgram.reset();
|
||||
GL_CALL(UseProgram(id));
|
||||
fHWProgramID = id;
|
||||
}
|
||||
|
||||
void GrGLGpu::setupGeometry(const GrBuffer* indexBuffer,
|
||||
const GrBuffer* vertexBuffer,
|
||||
int baseVertex,
|
||||
const GrBuffer* instanceBuffer,
|
||||
int baseInstance,
|
||||
GrPrimitiveRestart enablePrimitiveRestart) {
|
||||
SkASSERT((enablePrimitiveRestart == GrPrimitiveRestart::kNo) || indexBuffer);
|
||||
|
||||
GrGLAttribArrayState* attribState;
|
||||
if (indexBuffer) {
|
||||
SkASSERT(indexBuffer->isCpuBuffer() ||
|
||||
!static_cast<const GrGpuBuffer*>(indexBuffer)->isMapped());
|
||||
attribState = fHWVertexArrayState.bindInternalVertexArray(this, indexBuffer);
|
||||
} else {
|
||||
attribState = fHWVertexArrayState.bindInternalVertexArray(this);
|
||||
}
|
||||
|
||||
int numAttribs = fHWProgram->numVertexAttributes() + fHWProgram->numInstanceAttributes();
|
||||
attribState->enableVertexArrays(this, numAttribs, enablePrimitiveRestart);
|
||||
|
||||
if (int vertexStride = fHWProgram->vertexStride()) {
|
||||
SkASSERT(vertexBuffer);
|
||||
SkASSERT(vertexBuffer->isCpuBuffer() ||
|
||||
!static_cast<const GrGpuBuffer*>(vertexBuffer)->isMapped());
|
||||
size_t bufferOffset = baseVertex * static_cast<size_t>(vertexStride);
|
||||
for (int i = 0; i < fHWProgram->numVertexAttributes(); ++i) {
|
||||
const auto& attrib = fHWProgram->vertexAttribute(i);
|
||||
static constexpr int kDivisor = 0;
|
||||
attribState->set(this, attrib.fLocation, vertexBuffer, attrib.fCPUType, attrib.fGPUType,
|
||||
vertexStride, bufferOffset + attrib.fOffset, kDivisor);
|
||||
}
|
||||
}
|
||||
if (int instanceStride = fHWProgram->instanceStride()) {
|
||||
SkASSERT(instanceBuffer);
|
||||
SkASSERT(instanceBuffer->isCpuBuffer() ||
|
||||
!static_cast<const GrGpuBuffer*>(instanceBuffer)->isMapped());
|
||||
size_t bufferOffset = baseInstance * static_cast<size_t>(instanceStride);
|
||||
int attribIdx = fHWProgram->numVertexAttributes();
|
||||
for (int i = 0; i < fHWProgram->numInstanceAttributes(); ++i, ++attribIdx) {
|
||||
const auto& attrib = fHWProgram->instanceAttribute(i);
|
||||
static constexpr int kDivisor = 1;
|
||||
attribState->set(this, attrib.fLocation, instanceBuffer, attrib.fCPUType,
|
||||
attrib.fGPUType, instanceStride, bufferOffset + attrib.fOffset,
|
||||
kDivisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GrGLenum GrGLGpu::bindBuffer(GrGpuBufferType type, const GrBuffer* buffer) {
|
||||
this->handleDirtyContext();
|
||||
|
||||
@ -2257,8 +2325,6 @@ void GrGLGpu::flushViewport(int width, int height) {
|
||||
}
|
||||
|
||||
GrGLenum GrGLGpu::prepareToDraw(GrPrimitiveType primitiveType) {
|
||||
fStats.incNumDraws();
|
||||
|
||||
if (this->glCaps().requiresCullFaceEnableDisableWhenDrawingLinesAfterNonLines() &&
|
||||
GrIsPrimTypeLines(primitiveType) && !GrIsPrimTypeLines(fLastPrimitiveType)) {
|
||||
GL_CALL(Enable(GR_GL_CULL_FACE));
|
||||
@ -2286,40 +2352,72 @@ GrGLenum GrGLGpu::prepareToDraw(GrPrimitiveType primitiveType) {
|
||||
SK_ABORT("invalid GrPrimitiveType");
|
||||
}
|
||||
|
||||
void GrGLGpu::drawArrays(GrPrimitiveType primitiveType, GrGLint baseVertex, GrGLsizei vertexCount) {
|
||||
SkASSERT(!this->glCaps().drawArraysBaseVertexIsBroken() || 0 == baseVertex);
|
||||
void GrGLGpu::draw(GrPrimitiveType primitiveType, const GrBuffer* vertexBuffer, int vertexCount,
|
||||
int baseVertex) {
|
||||
GrGLenum glPrimType = this->prepareToDraw(primitiveType);
|
||||
GL_CALL(DrawArrays(glPrimType, baseVertex, vertexCount));
|
||||
if (this->glCaps().drawArraysBaseVertexIsBroken()) {
|
||||
this->setupGeometry(nullptr, vertexBuffer, baseVertex, nullptr, 0, GrPrimitiveRestart::kNo);
|
||||
GL_CALL(DrawArrays(glPrimType, 0, vertexCount));
|
||||
} else {
|
||||
this->setupGeometry(nullptr, vertexBuffer, 0, nullptr, 0, GrPrimitiveRestart::kNo);
|
||||
GL_CALL(DrawArrays(glPrimType, baseVertex, vertexCount));
|
||||
}
|
||||
fStats.incNumDraws();
|
||||
}
|
||||
|
||||
void GrGLGpu::drawElements(GrPrimitiveType primitiveType, GrGLsizei indexCount, GrGLenum indexType,
|
||||
const void* indices) {
|
||||
GrGLenum glPrimType = this->prepareToDraw(primitiveType);
|
||||
GL_CALL(DrawElements(glPrimType, indexCount, indexType, indices));
|
||||
static const GrGLvoid* element_ptr(const GrBuffer* indexBuffer, int baseIndex) {
|
||||
size_t baseOffset = baseIndex * sizeof(uint16_t);
|
||||
if (indexBuffer->isCpuBuffer()) {
|
||||
return static_cast<const GrCpuBuffer*>(indexBuffer)->data() + baseOffset;
|
||||
} else {
|
||||
return reinterpret_cast<const GrGLvoid*>(baseOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::drawRangeElements(GrPrimitiveType primitiveType, GrGLuint minIndexValue,
|
||||
GrGLuint maxIndexValue, GrGLsizei indexCount, GrGLenum indexType,
|
||||
const void* indices) {
|
||||
SkASSERT(this->glCaps().drawRangeElementsSupport());
|
||||
void GrGLGpu::drawIndexed(GrPrimitiveType primitiveType, const GrBuffer* indexBuffer,
|
||||
int indexCount, int baseIndex, GrPrimitiveRestart primitiveRestart,
|
||||
uint16_t minIndexValue, uint16_t maxIndexValue,
|
||||
const GrBuffer* vertexBuffer, int baseVertex) {
|
||||
GrGLenum glPrimType = this->prepareToDraw(primitiveType);
|
||||
GL_CALL(DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount, indexType,
|
||||
indices));
|
||||
const GrGLvoid* elementPtr = element_ptr(indexBuffer, baseIndex);
|
||||
this->setupGeometry(indexBuffer, vertexBuffer, baseVertex, nullptr, 0, primitiveRestart);
|
||||
if (this->glCaps().drawRangeElementsSupport()) {
|
||||
GL_CALL(DrawRangeElements(glPrimType, minIndexValue, maxIndexValue, indexCount,
|
||||
GR_GL_UNSIGNED_SHORT, elementPtr));
|
||||
} else {
|
||||
GL_CALL(DrawElements(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT, elementPtr));
|
||||
}
|
||||
fStats.incNumDraws();
|
||||
}
|
||||
|
||||
void GrGLGpu::drawArraysInstanced(GrPrimitiveType primitiveType, GrGLint baseVertex,
|
||||
GrGLsizei vertexCount, GrGLsizei instanceCount) {
|
||||
SkASSERT(instanceCount <= this->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount));
|
||||
void GrGLGpu::drawInstanced(GrPrimitiveType primitiveType, const GrBuffer* instanceBuffer,
|
||||
int instanceCount, int baseInstance, const GrBuffer* vertexBuffer,
|
||||
int vertexCount, int baseVertex) {
|
||||
GrGLenum glPrimType = this->prepareToDraw(primitiveType);
|
||||
GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount, instanceCount));
|
||||
int maxInstances = this->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
|
||||
for (int i = 0; i < instanceCount; i += maxInstances) {
|
||||
this->setupGeometry(nullptr, vertexBuffer, 0, instanceBuffer, baseInstance + i,
|
||||
GrPrimitiveRestart::kNo);
|
||||
GL_CALL(DrawArraysInstanced(glPrimType, baseVertex, vertexCount,
|
||||
std::min(instanceCount - i, maxInstances)));
|
||||
fStats.incNumDraws();
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::drawElementsInstanced(GrPrimitiveType primitiveType, GrGLsizei indexCount,
|
||||
GrGLenum indexType, const void* indices,
|
||||
GrGLsizei instanceCount) {
|
||||
SkASSERT(instanceCount <= this->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount));
|
||||
void GrGLGpu::drawIndexedInstanced(
|
||||
GrPrimitiveType primitiveType, const GrBuffer* indexBuffer, int indexCount, int baseIndex,
|
||||
GrPrimitiveRestart primitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex) {
|
||||
GrGLenum glPrimType = this->prepareToDraw(primitiveType);
|
||||
GL_CALL(DrawElementsInstanced(glPrimType, indexCount, indexType, indices, instanceCount));
|
||||
const GrGLvoid* elementPtr = element_ptr(indexBuffer, baseIndex);
|
||||
int maxInstances = this->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
|
||||
for (int i = 0; i < instanceCount; i += maxInstances) {
|
||||
this->setupGeometry(indexBuffer, vertexBuffer, baseVertex,
|
||||
instanceBuffer, baseInstance + i, primitiveRestart);
|
||||
GL_CALL(DrawElementsInstanced(glPrimType, indexCount, GR_GL_UNSIGNED_SHORT, elementPtr,
|
||||
std::min(instanceCount - i, maxInstances)));
|
||||
fStats.incNumDraws();
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target, const SkIRect& resolveRect,
|
||||
@ -3824,7 +3922,6 @@ void GrGLGpu::testingOnly_flushGpuAndSync() {
|
||||
|
||||
GrGLAttribArrayState* GrGLGpu::HWVertexArrayState::bindInternalVertexArray(GrGLGpu* gpu,
|
||||
const GrBuffer* ibuf) {
|
||||
SkASSERT(!ibuf || ibuf->isCpuBuffer() || !static_cast<const GrGpuBuffer*>(ibuf)->isMapped());
|
||||
GrGLAttribArrayState* attribState;
|
||||
|
||||
if (gpu->glCaps().isCoreProfile()) {
|
||||
|
@ -73,42 +73,26 @@ public:
|
||||
// If the caller wishes to bind an index buffer to a specific VAO, it can call glBind directly.
|
||||
GrGLenum bindBuffer(GrGpuBufferType type, const GrBuffer*);
|
||||
|
||||
// Flushes state from GrProgramInfo to GL. Returns nullptr if the state couldn't be set.
|
||||
// The returned GrGLProgram can be used for binding textures and vertex attributes.
|
||||
//
|
||||
// The caller must keep the returned GrGLProgram alive until it is done issuing draws.
|
||||
sk_sp<GrGLProgram> flushGLState(GrRenderTarget*, const GrProgramInfo&) SK_WARN_UNUSED_RESULT;
|
||||
// Flushes state from GrProgramInfo to GL. Returns false if the state couldn't be set.
|
||||
bool flushGLState(GrRenderTarget*, const GrProgramInfo&);
|
||||
void flushScissorRect(const SkIRect&, int rtWidth, int rtHeight, GrSurfaceOrigin);
|
||||
|
||||
// Binds the vertex array that should be used for internal draws, enables 'numAttribs' vertex
|
||||
// arrays, and flushes the desired primitive restart settings. The returned GrGLAttribArrayState
|
||||
// should be used to set vertex attribute arrays.
|
||||
//
|
||||
// If an index buffer is provided, it will be bound to the vertex array. Otherwise the index
|
||||
// buffer binding will be left unchanged.
|
||||
//
|
||||
// NOTE: This binds the default VAO (ID=zero) unless we are on a core profile, in which case we
|
||||
// use a dummy array instead.
|
||||
GrGLAttribArrayState* bindInternalVertexArray(const GrBuffer* indexBuffer, int numAttribs,
|
||||
GrPrimitiveRestart primitiveRestart) {
|
||||
auto* attribState = fHWVertexArrayState.bindInternalVertexArray(this, indexBuffer);
|
||||
attribState->enableVertexArrays(this, numAttribs, primitiveRestart);
|
||||
return attribState;
|
||||
void bindTextures(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline,
|
||||
const GrSurfaceProxy* const primProcTextures[] = nullptr) {
|
||||
fHWProgram->bindTextures(primProc, pipeline, primProcTextures);
|
||||
}
|
||||
GrGLAttribArrayState* bindInternalVertexArray(const GrBuffer* indexBuffer, GrPrimitiveRestart);
|
||||
|
||||
// These methods invoke their GL namesakes, with added bookkeeping and assertions. The caller is
|
||||
// responsible to ensure the desired GL state is configured before calling (via flushGLState(),
|
||||
// flushScissor(), and bindInternalVertexArray()).
|
||||
void drawArrays(GrPrimitiveType, GrGLint baseVertex, GrGLsizei vertexCount);
|
||||
void drawElements(GrPrimitiveType, GrGLsizei indexCount, GrGLenum indexType,
|
||||
const void* indices);
|
||||
void drawRangeElements(GrPrimitiveType, GrGLuint minIndexValue, GrGLuint maxIndexValue,
|
||||
GrGLsizei indexCount, GrGLenum indexType, const void* indices);
|
||||
void drawArraysInstanced(GrPrimitiveType, GrGLint baseVertex, GrGLsizei vertexCount,
|
||||
GrGLsizei instanceCount);
|
||||
void drawElementsInstanced(GrPrimitiveType, GrGLsizei indexCount, GrGLenum indexType,
|
||||
const void* indices, GrGLsizei instanceCount);
|
||||
// These methods issue draws using the current GL state. The client must call flushGLState,
|
||||
// followed by flushScissorRect and/or bindTextures if applicable, before using these method.
|
||||
void draw(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount, int baseVertex);
|
||||
void drawIndexed(GrPrimitiveType, const GrBuffer* indexBuffer, int indexCount, int baseIndex,
|
||||
GrPrimitiveRestart, uint16_t minIndexValue, uint16_t maxIndexValue,
|
||||
const GrBuffer* vertexBuffer, int baseVertex);
|
||||
void drawInstanced(GrPrimitiveType, const GrBuffer* instanceBuffer, int instanceCount, int
|
||||
baseInstance, const GrBuffer* vertexBuffer, int vertexCount, int baseVertex);
|
||||
void drawIndexedInstanced(GrPrimitiveType, const GrBuffer* indexBuffer, int indexCount,
|
||||
int baseIndex, GrPrimitiveRestart, const GrBuffer* instanceBuffer,
|
||||
int instanceCount, int baseInstance, const GrBuffer* vertexBuffer,
|
||||
int baseVertex);
|
||||
|
||||
// The GrGLOpsRenderPass does not buffer up draws before submitting them to the gpu.
|
||||
// Thus this is the implementation of the clear call for the corresponding passthrough function
|
||||
@ -304,9 +288,19 @@ private:
|
||||
// binds texture unit in GL
|
||||
void setTextureUnit(int unitIdx);
|
||||
|
||||
void flushProgram(sk_sp<GrGLProgram>);
|
||||
|
||||
// Version for programs that aren't GrGLProgram.
|
||||
void flushProgram(GrGLuint);
|
||||
|
||||
// Sets up vertex/instance attribute pointers and strides.
|
||||
void setupGeometry(const GrBuffer* indexBuffer,
|
||||
const GrBuffer* vertexBuffer,
|
||||
int baseVertex,
|
||||
const GrBuffer* instanceBuffer,
|
||||
int baseInstance,
|
||||
GrPrimitiveRestart);
|
||||
|
||||
// Applies any necessary workarounds and returns the GL primitive type to use in draw calls.
|
||||
GrGLenum prepareToDraw(GrPrimitiveType primitiveType);
|
||||
|
||||
@ -469,6 +463,7 @@ private:
|
||||
int fHWActiveTextureUnitIdx;
|
||||
|
||||
GrGLuint fHWProgramID;
|
||||
sk_sp<GrGLProgram> fHWProgram;
|
||||
|
||||
enum TriState {
|
||||
kNo_TriState,
|
||||
@ -573,7 +568,7 @@ private:
|
||||
* state. This binds the default VAO (ID=zero) unless we are on a core profile, in which
|
||||
* case we use a dummy array instead.
|
||||
*
|
||||
* If an index buffer is provided, it will be bound to the vertex array. Otherwise the
|
||||
* If an index buffer is privided, it will be bound to the vertex array. Otherwise the
|
||||
* index buffer binding will be left unchanged.
|
||||
*
|
||||
* The returned GrGLAttribArrayState should be used to set vertex attribute arrays.
|
||||
|
@ -28,8 +28,7 @@ void GrGLOpsRenderPass::set(GrRenderTarget* rt, const SkIRect& contentBounds,
|
||||
bool GrGLOpsRenderPass::onBindPipeline(const GrProgramInfo& programInfo,
|
||||
const SkRect& drawBounds) {
|
||||
fPrimitiveType = programInfo.primitiveType();
|
||||
fGLProgram = fGpu->flushGLState(fRenderTarget, programInfo);
|
||||
return SkToBool(fGLProgram);
|
||||
return fGpu->flushGLState(fRenderTarget, programInfo);
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
|
||||
@ -39,104 +38,36 @@ void GrGLOpsRenderPass::onSetScissorRect(const SkIRect& scissor) {
|
||||
bool GrGLOpsRenderPass::onBindTextures(const GrPrimitiveProcessor& primProc,
|
||||
const GrPipeline& pipeline,
|
||||
const GrSurfaceProxy* const primProcTextures[]) {
|
||||
fGLProgram->bindTextures(primProc, pipeline, primProcTextures);
|
||||
fGpu->bindTextures(primProc, pipeline, primProcTextures);
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::setupGeometry(const GrBuffer* indexBuffer, const GrBuffer* vertexBuffer,
|
||||
int baseVertex, const GrBuffer* instanceBuffer,
|
||||
int baseInstance, GrPrimitiveRestart primitiveRestart) {
|
||||
SkASSERT((primitiveRestart == GrPrimitiveRestart::kNo) || indexBuffer);
|
||||
|
||||
int numAttribs = fGLProgram->numVertexAttributes() + fGLProgram->numInstanceAttributes();
|
||||
auto* attribState = fGpu->bindInternalVertexArray(indexBuffer, numAttribs, primitiveRestart);
|
||||
|
||||
if (int vertexStride = fGLProgram->vertexStride()) {
|
||||
SkASSERT(vertexBuffer);
|
||||
SkASSERT(vertexBuffer->isCpuBuffer() ||
|
||||
!static_cast<const GrGpuBuffer*>(vertexBuffer)->isMapped());
|
||||
size_t bufferOffset = baseVertex * static_cast<size_t>(vertexStride);
|
||||
for (int i = 0; i < fGLProgram->numVertexAttributes(); ++i) {
|
||||
const auto& attrib = fGLProgram->vertexAttribute(i);
|
||||
static constexpr int kDivisor = 0;
|
||||
attribState->set(fGpu, attrib.fLocation, vertexBuffer, attrib.fCPUType, attrib.fGPUType,
|
||||
vertexStride, bufferOffset + attrib.fOffset, kDivisor);
|
||||
}
|
||||
}
|
||||
if (int instanceStride = fGLProgram->instanceStride()) {
|
||||
SkASSERT(instanceBuffer);
|
||||
SkASSERT(instanceBuffer->isCpuBuffer() ||
|
||||
!static_cast<const GrGpuBuffer*>(instanceBuffer)->isMapped());
|
||||
size_t bufferOffset = baseInstance * static_cast<size_t>(instanceStride);
|
||||
int attribIdx = fGLProgram->numVertexAttributes();
|
||||
for (int i = 0; i < fGLProgram->numInstanceAttributes(); ++i, ++attribIdx) {
|
||||
const auto& attrib = fGLProgram->instanceAttribute(i);
|
||||
static constexpr int kDivisor = 1;
|
||||
attribState->set(fGpu, attrib.fLocation, instanceBuffer, attrib.fCPUType,
|
||||
attrib.fGPUType, instanceStride, bufferOffset + attrib.fOffset,
|
||||
kDivisor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const GrGLvoid* get_gl_index_ptr(const GrBuffer* indexBuffer, int baseIndex) {
|
||||
size_t baseOffset = baseIndex * sizeof(uint16_t);
|
||||
if (indexBuffer->isCpuBuffer()) {
|
||||
return static_cast<const GrCpuBuffer*>(indexBuffer)->data() + baseOffset;
|
||||
} else {
|
||||
return reinterpret_cast<const GrGLvoid*>(baseOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::onDraw(const GrBuffer* vertexBuffer, int vertexCount, int baseVertex) {
|
||||
if (fGpu->glCaps().drawArraysBaseVertexIsBroken()) {
|
||||
this->setupGeometry(nullptr, vertexBuffer, baseVertex, nullptr, 0, GrPrimitiveRestart::kNo);
|
||||
fGpu->drawArrays(fPrimitiveType, 0, vertexCount);
|
||||
return;
|
||||
}
|
||||
|
||||
this->setupGeometry(nullptr, vertexBuffer, 0, nullptr, 0, GrPrimitiveRestart::kNo);
|
||||
fGpu->drawArrays(fPrimitiveType, baseVertex, vertexCount);
|
||||
fGpu->draw(fPrimitiveType, vertexBuffer, vertexCount, baseVertex);
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::onDrawIndexed(const GrBuffer* indexBuffer, int indexCount, int baseIndex,
|
||||
GrPrimitiveRestart primitiveRestart, uint16_t minIndexValue,
|
||||
uint16_t maxIndexValue, const GrBuffer* vertexBuffer,
|
||||
int baseVertex) {
|
||||
const GrGLvoid* indexPtr = get_gl_index_ptr(indexBuffer, baseIndex);
|
||||
this->setupGeometry(indexBuffer, vertexBuffer, baseVertex, nullptr, 0, primitiveRestart);
|
||||
if (fGpu->glCaps().drawRangeElementsSupport()) {
|
||||
fGpu->drawRangeElements(fPrimitiveType, minIndexValue, maxIndexValue, indexCount,
|
||||
GR_GL_UNSIGNED_SHORT, indexPtr);
|
||||
} else {
|
||||
fGpu->drawElements(fPrimitiveType, indexCount, GR_GL_UNSIGNED_SHORT, indexPtr);
|
||||
}
|
||||
fGpu->drawIndexed(fPrimitiveType, indexBuffer, indexCount, baseIndex, primitiveRestart,
|
||||
minIndexValue, maxIndexValue, vertexBuffer, baseVertex);
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::onDrawInstanced(const GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, const GrBuffer* vertexBuffer,
|
||||
int vertexCount, int baseVertex) {
|
||||
int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
|
||||
for (int i = 0; i < instanceCount; i += maxInstances) {
|
||||
this->setupGeometry(nullptr, vertexBuffer, 0, instanceBuffer, baseInstance + i,
|
||||
GrPrimitiveRestart::kNo);
|
||||
fGpu->drawArraysInstanced(fPrimitiveType, baseVertex, vertexCount,
|
||||
std::min(instanceCount - i, maxInstances));
|
||||
}
|
||||
fGpu->drawInstanced(fPrimitiveType, instanceBuffer, instanceCount, baseInstance, vertexBuffer,
|
||||
vertexCount, baseVertex);
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::onDrawIndexedInstanced(
|
||||
const GrBuffer* indexBuffer, int indexCount, int baseIndex,
|
||||
GrPrimitiveRestart primitiveRestart, const GrBuffer* instanceBuffer, int instanceCount,
|
||||
int baseInstance, const GrBuffer* vertexBuffer, int baseVertex) {
|
||||
const GrGLvoid* indexPtr = get_gl_index_ptr(indexBuffer, baseIndex);
|
||||
int maxInstances = fGpu->glCaps().maxInstancesPerDrawWithoutCrashing(instanceCount);
|
||||
for (int i = 0; i < instanceCount; i += maxInstances) {
|
||||
this->setupGeometry(indexBuffer, vertexBuffer, baseVertex,
|
||||
instanceBuffer, baseInstance + i, primitiveRestart);
|
||||
fGpu->drawElementsInstanced(fPrimitiveType, indexCount, GR_GL_UNSIGNED_SHORT, indexPtr,
|
||||
std::min(instanceCount - i, maxInstances));
|
||||
}
|
||||
fGpu->drawIndexedInstanced(fPrimitiveType, indexBuffer, indexCount, baseIndex, primitiveRestart,
|
||||
instanceBuffer, instanceCount, baseInstance, vertexBuffer,
|
||||
baseVertex);
|
||||
}
|
||||
|
||||
void GrGLOpsRenderPass::onClear(const GrFixedClip& clip, const SkPMColor4f& color) {
|
||||
|
@ -49,10 +49,6 @@ public:
|
||||
private:
|
||||
GrGpu* gpu() override { return fGpu; }
|
||||
|
||||
void setupGeometry(const GrBuffer* indexBuffer, const GrBuffer* vertexBuffer, int baseVertex,
|
||||
const GrBuffer* instanceBuffer, int baseInstance,
|
||||
GrPrimitiveRestart enablePrimitiveRestart);
|
||||
|
||||
bool onBindPipeline(const GrProgramInfo& programInfo, const SkRect& drawBounds) override;
|
||||
void onSetScissorRect(const SkIRect& scissor) override;
|
||||
bool onBindTextures(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline,
|
||||
@ -76,7 +72,6 @@ private:
|
||||
StencilLoadAndStoreInfo fStencilLoadAndStoreInfo;
|
||||
|
||||
// Per-pipeline state.
|
||||
sk_sp<GrGLProgram> fGLProgram;
|
||||
GrPrimitiveType fPrimitiveType;
|
||||
|
||||
typedef GrOpsRenderPass INHERITED;
|
||||
|
@ -115,15 +115,14 @@ void GrGLPathRendering::onDrawPath(GrRenderTarget* renderTarget,
|
||||
const GrPath* path) {
|
||||
SkASSERT(!programInfo.hasDynamicScissors());
|
||||
SkASSERT(!programInfo.hasDynamicPrimProcTextures());
|
||||
sk_sp<GrGLProgram> program = this->gpu()->flushGLState(renderTarget, programInfo);
|
||||
if (!program) {
|
||||
if (!this->gpu()->flushGLState(renderTarget, programInfo)) {
|
||||
return;
|
||||
}
|
||||
if (programInfo.hasFixedScissor()) {
|
||||
this->gpu()->flushScissorRect(programInfo.fixedScissor(), renderTarget->width(),
|
||||
renderTarget->height(), programInfo.origin());
|
||||
}
|
||||
program->bindTextures(programInfo.primProc(), programInfo.pipeline(), nullptr);
|
||||
this->gpu()->bindTextures(programInfo.primProc(), programInfo.pipeline());
|
||||
|
||||
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user