add SkMatrixPriv for specialized helpers

BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2268443002

Review-Url: https://codereview.chromium.org/2268443002
This commit is contained in:
reed 2016-08-22 06:39:49 -07:00 committed by Commit bot
parent 0a8efd7355
commit a39667c848
5 changed files with 96 additions and 20 deletions

View File

@ -842,6 +842,7 @@ private:
static const MapPtsProc gMapPtsProcs[];
friend class SkPerspIter;
friend class SkMatrixPriv;
};
SK_END_REQUIRE_DENSE

View File

@ -1102,6 +1102,15 @@ void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
}
}
static Sk4f sort_as_rect(const Sk4f& ltrb) {
Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
Sk4f min = Sk4f::Min(ltrb, rblt);
Sk4f max = Sk4f::Max(ltrb, rblt);
// We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
// ARM this sequence generates the fastest (a single instruction).
return Sk4f(min[2], min[3], max[0], max[1]);
}
void SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {
SkASSERT(dst);
SkASSERT(this->isScaleTranslate());
@ -1112,20 +1121,19 @@ void SkMatrix::mapRectScaleTranslate(SkRect* dst, const SkRect& src) const {
SkScalar ty = fMat[kMTransY];
Sk4f scale(sx, sy, sx, sy);
Sk4f trans(tx, ty, tx, ty);
Sk4f ltrb = Sk4f::Load(&src.fLeft) * scale + trans;
// need to sort so we're not inverted
Sk4f rblt(ltrb[2], ltrb[3], ltrb[0], ltrb[1]);
Sk4f min = Sk4f::Min(ltrb, rblt);
Sk4f max = Sk4f::Max(ltrb, rblt);
// We can extract either pair [0,1] or [2,3] from min and max and be correct, but on
// ARM this sequence generates the fastest (a single instruction).
Sk4f(min[2], min[3], max[0], max[1]).store(&dst->fLeft);
sort_as_rect(Sk4f::Load(&src.fLeft) * scale + trans).store(&dst->fLeft);
}
bool SkMatrix::mapRect(SkRect* dst, const SkRect& src) const {
SkASSERT(dst);
if (this->getType() <= kTranslate_Mask) {
SkScalar tx = fMat[kMTransX];
SkScalar ty = fMat[kMTransY];
Sk4f trans(tx, ty, tx, ty);
sort_as_rect(Sk4f::Load(&src.fLeft) + trans).store(&dst->fLeft);
return true;
}
if (this->isScaleTranslate()) {
this->mapRectScaleTranslate(dst, src);
return true;

70
src/core/SkMatrixPriv.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright 2016 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkMatrixPriv_DEFINE
#define SkMatrixPriv_DEFINE
#include "SkMatrix.h"
#include "SkNx.h"
class SkMatrixPriv {
public:
/**
* Attempt to map the rect through the inverse of the matrix. If it is not invertible,
* then this returns false and dst is unchanged.
*/
static bool SK_WARN_UNUSED_RESULT InverseMapRect(const SkMatrix& mx,
SkRect* dst, const SkRect& src) {
if (mx.getType() <= SkMatrix::kTranslate_Mask) {
SkScalar tx = mx.getTranslateX();
SkScalar ty = mx.getTranslateY();
Sk4f trans(tx, ty, tx, ty);
(Sk4f::Load(&src.fLeft) - trans).store(&dst->fLeft);
return true;
}
// Insert other special-cases here (e.g. scale+translate)
// general case
SkMatrix inverse;
if (mx.invert(&inverse)) {
inverse.mapRect(dst, src);
return true;
}
return false;
}
static void MapPointsWithStride(const SkMatrix& mx, SkPoint pts[], size_t stride, int count) {
SkASSERT(stride >= sizeof(SkPoint));
SkASSERT(0 == stride % sizeof(SkScalar));
SkMatrix::TypeMask tm = mx.getType();
if (SkMatrix::kIdentity_Mask == tm) {
return;
}
if (SkMatrix::kTranslate_Mask == tm) {
const SkScalar tx = mx.getTranslateX();
const SkScalar ty = mx.getTranslateY();
Sk2s trans(tx, ty);
for (int i = 0; i < count; ++i) {
(Sk2s::Load(&pts->fX) + trans).store(&pts->fX);
pts = (SkPoint*)((intptr_t)pts + stride);
}
return;
}
// Insert other special-cases here (e.g. scale+translate)
// general case
SkMatrix::MapXYProc proc = mx.getMapXYProc();
for (int i = 0; i < count; ++i) {
proc(mx, pts->fX, pts->fY, pts);
pts = (SkPoint*)((intptr_t)pts + stride);
}
}
};
#endif

View File

@ -37,6 +37,7 @@
#include "../private/GrAuditTrail.h"
#include "SkLatticeIter.h"
#include "SkMatrixPriv.h"
#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == fDrawingManager->getContext())
#define ASSERT_SINGLE_OWNER \
@ -260,12 +261,10 @@ void GrDrawContext::drawPaint(const GrClip& clip,
// map the four corners and bound them with a new rect. This will not
// produce a correct result for some perspective matrices.
if (!isPerspective) {
SkMatrix inverse;
if (!viewMatrix.invert(&inverse)) {
if (!SkMatrixPriv::InverseMapRect(viewMatrix, &r, r)) {
SkDebugf("Could not invert matrix\n");
return;
}
inverse.mapRect(&r);
this->drawRect(clip, *paint, viewMatrix, r);
} else {
SkMatrix localMatrix;
@ -314,17 +313,13 @@ static bool crop_filled_rect(const GrRenderTarget* rt, const GrClip& clip,
return true;
}
SkMatrix inverseViewMatrix;
if (!viewMatrix.invert(&inverseViewMatrix)) {
return false;
}
SkIRect clipDevBounds;
SkRect clipBounds;
SkASSERT(inverseViewMatrix.rectStaysRect());
clip.getConservativeBounds(rt->width(), rt->height(), &clipDevBounds);
inverseViewMatrix.mapRect(&clipBounds, SkRect::Make(clipDevBounds));
if (!SkMatrixPriv::InverseMapRect(viewMatrix, &clipBounds, SkRect::Make(clipDevBounds))) {
return false;
}
if (localRect) {
if (!rect->intersects(clipBounds)) {

View File

@ -15,6 +15,8 @@
#include "GrQuad.h"
#include "GrVertexBatch.h"
#include "SkMatrixPriv.h"
static const int kVertsPerInstance = 4;
static const int kIndicesPerInstance = 6;
@ -47,7 +49,7 @@ static void tesselate(intptr_t vertices,
rect.fRight, rect.fBottom, vertexStride);
if (viewMatrix) {
viewMatrix->mapPointsWithStride(positions, vertexStride, kVertsPerInstance);
SkMatrixPriv::MapPointsWithStride(*viewMatrix, positions, vertexStride, kVertsPerInstance);
}
// Setup local coords