-
Notifications
You must be signed in to change notification settings - Fork 5.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent app from accessing the GPU in the background in EncodeImage #28369
Prevent app from accessing the GPU in the background in EncodeImage #28369
Conversation
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat. If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about testing. One not great idea would be to pull ConvertToRasterUsingResourceContext into a header and making templated so you can pass in a mock SyncSwitch. You could go as high as ConvertImageToRaster. Since it's just a file local function it shouldn't change much. You might want to try @chinmaygarde for better ideas.
template<typename Switch>
sk_sp<SkImage> ConvertToRasterUsingResourceContext(
sk_sp<SkImage> image,
GrDirectContext* resource_context
const std::shared_ptr<Switch>& sync_switch) {
...
}
lib/ui/painting/image_encoding.cc
Outdated
@@ -132,19 +143,20 @@ void ConvertImageToRaster(sk_sp<SkImage> image, | |||
// to prevent concurrent usage of the image on both the IO and raster threads. | |||
raster_task_runner->PostTask([image, encode_task = std::move(encode_task), | |||
resource_context, snapshot_delegate, | |||
io_task_runner]() { | |||
io_task_runner, &gpu_disable_sync_switch]() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be capture a copy of the shared_ptr, not a reference to the shared_ptr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/ui/painting/image_encoding.cc
Outdated
sk_sp<SkImage> raster_image = | ||
snapshot_delegate->ConvertToRasterImage(image); | ||
|
||
io_task_runner->PostTask([image, encode_task = std::move(encode_task), | ||
raster_image = std::move(raster_image), | ||
resource_context]() mutable { | ||
resource_context, | ||
&gpu_disable_sync_switch]() mutable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, capture a copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
I briefly tried your suggestion, and I think the change is still a bit big.Since existing tests can ensure that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good now minus a naming nit. The existing tests don't assert that the new code is actually doing anything. A low level test that tests that the sync switch at least is being exercised is better than nothing. I wouldn't worry about how easy something is to revert.
I personally think the imperfect test is better than no test. If you strongly disagree we can defer the decision about no tests to someone else on the team.
(edit: To be clear, my request for changes has to do with the name change. The testing question I can defer to someone else on the team if you feel strongly against the tests)
lib/ui/painting/image_encoding.cc
Outdated
@@ -65,15 +65,24 @@ void InvokeDataCallback(std::unique_ptr<DartPersistentValue> callback, | |||
|
|||
sk_sp<SkImage> ConvertToRasterUsingResourceContext( | |||
sk_sp<SkImage> image, | |||
GrDirectContext* resource_context) { | |||
fml::WeakPtr<GrDirectContext> resource_context, | |||
const std::shared_ptr<const fml::SyncSwitch>& gpu_disable_sync_switch) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/gpu_disable_sync_switch/is_gpu_disabled_sync_switch
That way the "SetIfTrue" makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
I agree with @gaaclarke that this PR needs at least a simple unit test. Among other reasons, without a test, it can't be considered for a cherry-pick to the beta or stable branches if one is needed. The test @gaaclarke describes sounds adequate to me. |
Hi, @gaaclarke @zanderso (editing ColdPaleLight : I added the test: #28369 (comment) )
Anyway, I will add a test to this PR. Thanks |
Hi, @gaaclarke @zanderso
This Idea comes from : #25868 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't particularly like this test. I'm out-of-office but I'd like to spend some time trying to write a test for you when the holiday weekend is over. I probably won't approve something like this until you've decided this is the best you could come up with and one of us tries to come up with an alternative. If @zanderso, feels different that's fine with me.
Hi, @gaaclarke You are more experienced in this field than me, so I will follow the advice you provided before to tweak the test. Let me talk about my initial thoughts. I thought the advantages of this test are these two:
The disadvantage of this test is that these two: ( I guess this may be the reason you don’t like this test )
Then I saw that |
lib/ui/painting/image_encoding.h
Outdated
#include "flutter/lib/ui/ui_dart_state.h" | ||
#include "third_party/skia/include/core/SkCanvas.h" | ||
#include "third_party/skia/include/core/SkImage.h" | ||
#include "third_party/skia/include/core/SkSurface.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: This is where I am a little hesitant to use this approach. We have included more header files than before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pull ConvertToRasterUsingResourceContext
into its own header file and include it in image_encoding.cc
and image_encoding_unittests.cc
. Name it something like image_encoding_impl.h
. It doesn't need to be publicly visible from image_encoding.h
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Hi, @gaaclarke I revert the previous test and wrote a new test based on your suggestion:
Would you mind reviewing it again? Thanks |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! I like this approach much better, thanks. Sorry I didn't explain myself better last time. Your last approach relied on conditional compilation which is difficult to maintain. That's why this approach is preferred.
const std::shared_ptr<const MockSyncSwitch>& is_gpu_disabled_sync_switch = | ||
std::make_shared<MockSyncSwitch>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This variable shouldn't be a reference. You can just use auto here auto is_gpu_disabled_sync_switch = std::make_shared<MockSyncSwitch>();
since the type is in the right hand expression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/ui/painting/image_encoding.h
Outdated
#include "flutter/lib/ui/ui_dart_state.h" | ||
#include "third_party/skia/include/core/SkCanvas.h" | ||
#include "third_party/skia/include/core/SkImage.h" | ||
#include "third_party/skia/include/core/SkSurface.h" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just pull ConvertToRasterUsingResourceContext
into its own header file and include it in image_encoding.cc
and image_encoding_unittests.cc
. Name it something like image_encoding_impl.h
. It doesn't need to be publicly visible from image_encoding.h
CreateNewThread() // io | ||
); | ||
|
||
auto nativeEncodeImage = [&](Dart_NativeArguments args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/nativeEncodeImage/native_encode_image
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
lib/ui/painting/image_encoding.cc
Outdated
if (!raster_image) { | ||
// The rasterizer was unable to render the cross-context image | ||
// (presumably because it does not have a GrContext). In that case, | ||
// convert the image on the IO thread using the resource context. | ||
raster_image = | ||
ConvertToRasterUsingResourceContext(image, resource_context); | ||
raster_image = ConvertToRasterUsingResourceContext<fml::SyncSwitch>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove <fml::SyncSwitch>
, the type system will do that for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work @ColdPaleLight! Nice find, nice fix, and nice followup on your PR. Thanks =)
This PR was a bit weird because it was hard to test, I think this is a good approach though considering the circumstances.
.WillOnce([](const MockSyncSwitch::Handlers& handlers) { | ||
handlers.true_handler(); | ||
}); | ||
ConvertToRasterUsingResourceContext<MockSyncSwitch>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: remove <MockSyncSwitch>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Thank you, @gaaclarke , I have learned a lot from you in this process. : ) |
ab24644
to
52a9c03
Compare
(rebasing onto master to try to address the CI flakes) |
Is this fixing in flutter 2.8 ? It still have MTLGetWarningMode crash in flutter 2.8 |
This patch is in 2.8. I think the problem you encountered should be related to flutter/flutter#89171, you can pay attention to the 2.9 or higher version. |
fix issue: flutter/flutter#89182
about test:
(edit ColdPaleLight: I added the new test as #28369 (comment))
(edit ColdPaleLight: I added the test #28369 (comment))I tried to add a test like before, but this is a bit difficult, maybe I need some helpPre-launch Checklist
writing and running engine tests.
///
).