blob: 821bdaac3014bcd10b93f2852fbf0ebbe96e9163 [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ops/GrClearOp.h"
#include "include/gpu/GrRecordingContext.h"
#include "src/gpu/GrMemoryPool.h"
#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrOpsRenderPass.h"
#include "src/gpu/GrProxyProvider.h"
#include "src/gpu/GrRecordingContextPriv.h"
static bool contains_scissor(const GrScissorState& a, const GrScissorState& b) {
return !a.enabled() || (b.enabled() && a.rect().contains(b.rect()));
}
std::unique_ptr<GrClearOp> GrClearOp::MakeColor(GrRecordingContext* context,
const GrScissorState& scissor,
const SkPMColor4f& color) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<GrClearOp>(Buffer::kColor, scissor, color, false);
}
std::unique_ptr<GrClearOp> GrClearOp::MakeStencilClip(GrRecordingContext* context,
const GrScissorState& scissor,
bool insideMask) {
GrOpMemoryPool* pool = context->priv().opMemoryPool();
return pool->allocate<GrClearOp>(Buffer::kStencilClip, scissor, SkPMColor4f(), insideMask);
}
GrClearOp::GrClearOp(Buffer buffer, const GrScissorState& scissor,
const SkPMColor4f& color, bool insideMask)
: INHERITED(ClassID())
, fScissor(scissor)
, fColor(color)
, fStencilInsideMask(insideMask)
, fBuffer(buffer) {
this->setBounds(SkRect::Make(scissor.rect()), HasAABloat::kNo, IsHairline::kNo);
}
GrOp::CombineResult GrClearOp::onCombineIfPossible(GrOp* t, GrRecordingContext::Arenas*,
const GrCaps& caps) {
GrClearOp* other = t->cast<GrClearOp>();
if (other->fBuffer == fBuffer) {
// This could be much more complicated. Currently we look at cases where the new clear
// contains the old clear, or when the new clear is a subset of the old clear and they clear
// to the same value (color or stencil mask depending on target).
if (contains_scissor(other->fScissor, fScissor)) {
fScissor = other->fScissor;
fColor = other->fColor;
fStencilInsideMask = other->fStencilInsideMask;
return CombineResult::kMerged;
} else if (other->fColor == fColor && other->fStencilInsideMask == fStencilInsideMask &&
contains_scissor(fScissor, other->fScissor)) {
return CombineResult::kMerged;
}
} else if (other->fScissor == fScissor) {
// When the scissors are the exact same but the buffers are different, we can combine and
// clear both stencil and clear together in onExecute().
if (other->fBuffer & Buffer::kColor) {
SkASSERT((fBuffer & Buffer::kStencilClip) && !(fBuffer & Buffer::kColor));
fColor = other->fColor;
}
if (other->fBuffer & Buffer::kStencilClip) {
SkASSERT(!(fBuffer & Buffer::kStencilClip) && (fBuffer & Buffer::kColor));
fStencilInsideMask = other->fStencilInsideMask;
}
fBuffer = Buffer::kBoth;
}
return CombineResult::kCannotCombine;
}
void GrClearOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
SkASSERT(state->opsRenderPass());
if (fBuffer & Buffer::kColor) {
state->opsRenderPass()->clear(fScissor, fColor);
}
if (fBuffer & Buffer::kStencilClip) {
state->opsRenderPass()->clearStencilClip(fScissor, fStencilInsideMask);
}
}