Commit Graph

18 Commits

Author SHA1 Message Date
Yotam Hacohen
4d5eaf95ec Remove 'invert' call from 'SetDeviceCoordinateSystem'
Instead of inverting 'deviceToGlobal', we pass the invert to the
function. 0.1% of all cpu time (M1 Mac) for Motionmark1.2 is spent
doing this inversion.

We can remove a matrix inversion in setDeviceCoordinateSystem by
taking advantage of the fact that we can easily compute the
inverted matrix from values available on hand. The code previously
computed:
  fGlobalToDevice = (priorDeviceToGlobal * newLayerMappingLayerToDevice)'
We have access to the following values:
  newLayerMappingLayerToDevice' = newLayerMappingDeviceToLayer
  priorDeviceToGlobal' = priorGlobalToDevice
With the matrix property (A * B)' = B' * A', we can calculate:
  fGlobalToDevice = newLayerMappingDeviceToLayer * priorGlobalToDevice

Change-Id: I39656f244fa5f907536d09d69f585f09f156f133
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/527505
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2022-04-20 16:27:02 +00:00
Michael Ludwig
66470f8b7d Pre-construct device-to-layer matrix for skif::Mappings
SkCanvas and SkDevice were using SkM44 and its definition of invert(),
but it was slightly more generous than SkMatrix::invert() so the fuzzer
caught a case where the layer's SkDevice had a valid transform but then
converting it to a SkMatrix in skif::Mapping was no longer invertible.

This modifies it so that skif::Mapping no longer tries to invert the
matrices. In almost all cases, the inverse of the layer-to-device
matrix can be constructed directly from a matrix multiply (that's what
device->getRelativeTransform() does). When the matrices are
ill-conditioned the constructed inverse may be inaccurate (hence why
SkMatrix::invert reports false), but in practice this happens for
ridiculously large transforms and the error isn't significant compared
to the precision range of the matrices anyways.

Other cases explicitly want to use the identity matrix for the layer
to device matrix, so I added a helper in the few places that would have
had to pass SkMatrix::I() twice instead.

The last case is drawImage() that creates its own skif::Mapping, now it
just calculates the inverse that skif::Mapping() would have done and if
it fails it drops the draw since it means the canvas matrix is bad.

Bug: chromium:1276525
Change-Id: Ib516bb2fac19d5e7397bd27d80f8e3932b25b2e2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/509396
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2022-02-16 16:26:40 +00:00
Michael Ludwig
3c0c185e0e Don't assume DecomposeCTM and setDeviceCoordSystem always succeed
Very originally, skif::Mapping::DecomposeCTM() and
SkBaseDevice::setDeviceCoordinateSystem assumed that if the canvas
matrix was invertible, then any scale decomposition would produce a
valid device coordinate system. This proved not to be true and fuzzers
quickly caught it, but I had attempted to address it by forcing
SkCanvas to do extra work so that the above two functions remained
unchanged.

However, it's become apparent that even making the assumption that the
product of two invertible matrices remains invertible does not always
hold true in the wonderful world of floating point math.

Instead, this rewrites DecomposeCTM and setDeviceCoordinateSystem to
return bools, allowing them to fail. This cleans up some of the earlier
checks that SkCanvas makes while computing the skif::Mapping, and it
also ensures that once we fold in the prior device's transform, the
net layer->global transform remains valid. If any of this fails, it
just gets rid of the new device and sets the clip to empty, basically
preventing drawing until the invalid layer has been restored.


Bug: chromium:1239968, chromium:1240685
Change-Id: Ib9ce8f95859e726a9eacf1154f6eef8dd3995500
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/442017
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2021-08-26 14:21:45 +00:00
Michael Ludwig
d6bf999365 Factor perspective scale into filter matrix decomposition
I experimented with passing in a rectangle and computing a geometric
mean of the scale factors for the 4 corners and center. The downside
to that approach is that callers either know the parameter-space bounds
or the device-space bounds. In the latter case, we have to map by the
inverse CTM, which opens up a can of worms. In practice it seemed using
just the center point worked out just as well.

This also updates the sample to draw the axes in the layer space instead
of parameter space. I found this helps display the scale effects of the
parameter-to-layer matrix better.

Bug: skia:9074
Change-Id: I855c85cdbe1072c451aa3a0601571f2e137e5203
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/327624
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
2020-10-16 18:49:51 +00:00
John Stiles
f4bda743ff Rename SkTArray::reserve to reserve_back.
The semantics of `vector::reserve` and `SkTArray::reserve` were not the
same. SkTArray::reserve takes a delta over the current array size,
whereas vector takes a total array size. This could lead to subtle
errors with over- or under-reservation, hurting performance.

This CL renames `SkTArray::reserve` to `SkTArray::reserve_back` to give
the SkTArray behavior a distinct (hopefully easily understandable) name,
leaving its functionality as-is.

Change-Id: Icbd3114bb317fd5f307f393c02ae6fb6f83764e9
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326956
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
2020-10-14 21:42:11 +00:00
Michael Ludwig
6aaecfb7f7 Update image filter debug samples to use new APIs
For clarity, this renames skif::Mapping::Make to skif::Mapping::DecomposeCTM
to really emphasize when it should be used over just a constructor.

Renames SampleBackdropBounds to SampleFilterBounds since the operations and
coordinate spaces that it visualizes are the same for regular or backdrop
filtering (we just swap the notion of src and dst devices, really).
Technically, this is not quite true yet since regular filtering modifies the
DAG with a matrix transform right now, but that's going away soon (tm).

The "new" SampleFilterBounds example is updated to use the new bounds APIs
that use the coord-space safe types in the skif namespace. It also visualizes
a filter, and simplifies some of the bounds being drawn and reported to
only those most interesting.

The SampleImageFilterDAG has been updated to match the soon-to-be state
of how SkCanvas processes regular image filters for a saveLayer. All
implicit matrix-transform node code is removed. The bounds calculation
code is similarly updated to use the new 'skif' types and functions. To
simplify the visualization of each node, the 'isolated' versions of the
bounds were dropped.

Bug: skia:9282, skia:9283
Change-Id: If2ad2c302e5165ae009bba93cea52bf0566a543a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/326718
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Auto-Submit: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
2020-10-14 20:45:41 +00:00
John Stiles
7571f9e490 Replace 'typedef xxxxx INHERITED' with 'using INHERITED = xxxx;'.
Mechanically updated via Xcode "Replace Regular Expression":

  typedef (.*) INHERITED;
    -->
  using INHERITED = $1;

The ClangTidy approach generated an even larger CL which would have
required a significant amount of hand-tweaking to be usable.

Change-Id: I671dc9d9efdf6d60151325c8d4d13fad7e10a15b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314999
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
2020-09-03 03:41:26 +00:00
Brian Osman
116b33e8ab Remove SkMaxScalar and SkMinScalar
Use std::max and std::min instead

Change-Id: Icf3796609e5cb511687fb50bd31229ae4b6b9b39
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/268841
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
2020-02-06 15:43:22 +00:00
Brian Salomon
9241a6d394 Reland "Reland "SkSurface asynchronous read APIs allow client to extend pixel lifetime""
This is a reland of 6fc04f88a8

Original change's description:
> Reland "SkSurface asynchronous read APIs allow client to extend pixel lifetime"
> 
> This is a reland of ce240cc6fd
> 
> Original change's description:
> > SkSurface asynchronous read APIs allow client to extend pixel lifetime
> > 
> > Previously the pixel data passed to the client was only valid during
> > the client's callback. This meant if the client wanted to defer
> > processing of the data a copy was necessary.
> > 
> > Now we pass an object to the callback and the pixel lifetime is tied
> > to the lifetime of that object.
> > 
> > The object may be holding a GPU transfer buffer mapped. We don't assume
> > that the object will be released on the direct GrContext thread. So
> > when the object is destroyed it posts a message to a new type,
> > GrClientMappedBufferManager, hanging off the direct context. The direct
> > context will periodically check for messages and unmap and then unref
> > buffers so that they can be reused. Currently this is done in
> > GrContext::performDeferredCleanup() and GrDrawingManager::flush().
> > 
> > The old API is kept around for backwards compatibility but it is
> > reimplemented as a bridge on top of the new mechanism.
> > 
> > Also a utility function to SkImageInfo is added to directly make a new
> > info with a specified dimensions rather than passing the width and
> > height separately to makeWH().
> > 
> > Bug: chromium:973403
> > Bug: skia:8962
> > 
> > Change-Id: Id5cf04235376170142a48e90d3ecd13fd021a2a6
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245457
> > Reviewed-by: Brian Osman <brianosman@google.com>
> > Commit-Queue: Brian Salomon <bsalomon@google.com>
> 
> Bug: chromium:973403, skia:8962
> Change-Id: I5cecd36276c8b6dc942cf549c7095db2df88530c
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245678
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

Bug: chromium:973403, skia:8962
Change-Id: Ie584c1c3ef8021c976f71b708e53871c693cc450
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/246057
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
2019-10-03 19:14:22 +00:00
Ravi Mistry
cb55010652 Revert "Reland "SkSurface asynchronous read APIs allow client to extend pixel lifetime""
This reverts commit 6fc04f88a8.

Reason for revert: Chrome roll failure suspect because of:
* https://chromium-review.googlesource.com/c/chromium/src/+/1837131 (22 commits)
* https://chromium-review.googlesource.com/c/chromium/src/+/1837214 (24 commits)

Original change's description:
> Reland "SkSurface asynchronous read APIs allow client to extend pixel lifetime"
>
> This is a reland of ce240cc6fd
>
> Original change's description:
> > SkSurface asynchronous read APIs allow client to extend pixel lifetime
> >
> > Previously the pixel data passed to the client was only valid during
> > the client's callback. This meant if the client wanted to defer
> > processing of the data a copy was necessary.
> >
> > Now we pass an object to the callback and the pixel lifetime is tied
> > to the lifetime of that object.
> >
> > The object may be holding a GPU transfer buffer mapped. We don't assume
> > that the object will be released on the direct GrContext thread. So
> > when the object is destroyed it posts a message to a new type,
> > GrClientMappedBufferManager, hanging off the direct context. The direct
> > context will periodically check for messages and unmap and then unref
> > buffers so that they can be reused. Currently this is done in
> > GrContext::performDeferredCleanup() and GrDrawingManager::flush().
> >
> > The old API is kept around for backwards compatibility but it is
> > reimplemented as a bridge on top of the new mechanism.
> >
> > Also a utility function to SkImageInfo is added to directly make a new
> > info with a specified dimensions rather than passing the width and
> > height separately to makeWH().
> >
> > Bug: chromium:973403
> > Bug: skia:8962
> >
> > Change-Id: Id5cf04235376170142a48e90d3ecd13fd021a2a6
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245457
> > Reviewed-by: Brian Osman <brianosman@google.com>
> > Commit-Queue: Brian Salomon <bsalomon@google.com>
>
> Bug: chromium:973403, skia:8962
> Change-Id: I5cecd36276c8b6dc942cf549c7095db2df88530c
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245678
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,brianosman@google.com

Change-Id: I9e01d1b82fb399b94292441d91da51176bb161d9
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:973403, skia:8962
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245956
Reviewed-by: Ravi Mistry <rmistry@google.com>
Commit-Queue: Ravi Mistry <rmistry@google.com>
2019-10-03 09:19:24 +00:00
Brian Salomon
6fc04f88a8 Reland "SkSurface asynchronous read APIs allow client to extend pixel lifetime"
This is a reland of ce240cc6fd

Original change's description:
> SkSurface asynchronous read APIs allow client to extend pixel lifetime
> 
> Previously the pixel data passed to the client was only valid during
> the client's callback. This meant if the client wanted to defer
> processing of the data a copy was necessary.
> 
> Now we pass an object to the callback and the pixel lifetime is tied
> to the lifetime of that object.
> 
> The object may be holding a GPU transfer buffer mapped. We don't assume
> that the object will be released on the direct GrContext thread. So
> when the object is destroyed it posts a message to a new type,
> GrClientMappedBufferManager, hanging off the direct context. The direct
> context will periodically check for messages and unmap and then unref
> buffers so that they can be reused. Currently this is done in
> GrContext::performDeferredCleanup() and GrDrawingManager::flush().
> 
> The old API is kept around for backwards compatibility but it is
> reimplemented as a bridge on top of the new mechanism.
> 
> Also a utility function to SkImageInfo is added to directly make a new
> info with a specified dimensions rather than passing the width and
> height separately to makeWH().
> 
> Bug: chromium:973403
> Bug: skia:8962
> 
> Change-Id: Id5cf04235376170142a48e90d3ecd13fd021a2a6
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245457
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

Bug: chromium:973403, skia:8962
Change-Id: I5cecd36276c8b6dc942cf549c7095db2df88530c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245678
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
2019-10-03 01:41:35 +00:00
Brian Salomon
9c219785a8 Revert "SkSurface asynchronous read APIs allow client to extend pixel lifetime"
This reverts commit ce240cc6fd.

Reason for revert: crashing in chrome unit test, abandoned context related?

Original change's description:
> SkSurface asynchronous read APIs allow client to extend pixel lifetime
> 
> Previously the pixel data passed to the client was only valid during
> the client's callback. This meant if the client wanted to defer
> processing of the data a copy was necessary.
> 
> Now we pass an object to the callback and the pixel lifetime is tied
> to the lifetime of that object.
> 
> The object may be holding a GPU transfer buffer mapped. We don't assume
> that the object will be released on the direct GrContext thread. So
> when the object is destroyed it posts a message to a new type,
> GrClientMappedBufferManager, hanging off the direct context. The direct
> context will periodically check for messages and unmap and then unref
> buffers so that they can be reused. Currently this is done in
> GrContext::performDeferredCleanup() and GrDrawingManager::flush().
> 
> The old API is kept around for backwards compatibility but it is
> reimplemented as a bridge on top of the new mechanism.
> 
> Also a utility function to SkImageInfo is added to directly make a new
> info with a specified dimensions rather than passing the width and
> height separately to makeWH().
> 
> Bug: chromium:973403
> Bug: skia:8962
> 
> Change-Id: Id5cf04235376170142a48e90d3ecd13fd021a2a6
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245457
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,brianosman@google.com

Change-Id: Ic14cf07a7629b167c9f34a651aa87a0326e74207
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:973403, skia:8962
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245721
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
2019-10-02 22:51:15 +00:00
Brian Salomon
ce240cc6fd SkSurface asynchronous read APIs allow client to extend pixel lifetime
Previously the pixel data passed to the client was only valid during
the client's callback. This meant if the client wanted to defer
processing of the data a copy was necessary.

Now we pass an object to the callback and the pixel lifetime is tied
to the lifetime of that object.

The object may be holding a GPU transfer buffer mapped. We don't assume
that the object will be released on the direct GrContext thread. So
when the object is destroyed it posts a message to a new type,
GrClientMappedBufferManager, hanging off the direct context. The direct
context will periodically check for messages and unmap and then unref
buffers so that they can be reused. Currently this is done in
GrContext::performDeferredCleanup() and GrDrawingManager::flush().

The old API is kept around for backwards compatibility but it is
reimplemented as a bridge on top of the new mechanism.

Also a utility function to SkImageInfo is added to directly make a new
info with a specified dimensions rather than passing the width and
height separately to makeWH().

Bug: chromium:973403
Bug: skia:8962

Change-Id: Id5cf04235376170142a48e90d3ecd13fd021a2a6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/245457
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
2019-10-02 19:20:08 +00:00
Michael Ludwig
8ee6cf3691 Move SkImageFilter functionality into private SkImageFilter_Base
Bug: skia:9281
Change-Id: I189dbf652580805641f8c4b9a6587cf15a9049dd
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/231256
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
2019-08-02 18:56:39 +00:00
Michael Ludwig
a861106e49 Update docs and samplecode to use new image filter factories
Bug: skia:9280
Change-Id: I03ba9bf1cc952dec77664721fdb3a311f47f7e89
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230884
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Hal Canary <halcanary@google.com>
2019-08-02 14:47:35 +00:00
Michael Ludwig
aa861a1907 Change SkMatrix::decomposeScale to use preScale
While most callers of decomposeScale only depend on the scale factors
that are returned, image filter decomposition depends on the remaining
matrix as well. Hence, the following necessary updates to work with
the new behavior of decomposeScale:

* Update imagefilter DAG sample to reflect prescaling
* Correct embedded matrix in SkApplyCTMToFilter
* Add comment to clipRectBounds() clarifying coordinate spaces and image filters

But, we want to have decomposeScale using preScale() because it then
produces a remainder matrix that can be used as the transform for the
image filter draw, instead of wrapping the image filter in an
SkMatrixImageFilter as currently done by SkApplyCTMToFilter.

Bug: skia:7211
Change-Id: If14570afb4189cebc75f3815e8ccdde05cb074e1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228438
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
2019-07-19 15:41:11 +00:00
Michael Ludwig
4a412aca07 Improve image-filter sample layout/rendering
This tweaks the colors of the filterBounds boxes that are drawn.
It switches DAG layout to be left-to-right instead of top-down.
Visualizes node results/bounds in the local filter space instead of
transforming into the final space.
Improves the source content so that the different branches of the filter
DAG have more meaningful differences.

Change-Id: Icca586dcbcc3156e13f9689ee19af9c03a0ed1eb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228059
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
2019-07-17 21:55:59 +00:00
Michael Ludwig
43c6da2a15 First pass at ImageFilter DAG visualizer sample
Change-Id: I04493af0a6ce1425c4acf68365135722dd3c218b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/227857
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
2019-07-17 20:59:37 +00:00