[embedder] Add FBO callback that takes frame info#20617
[embedder] Add FBO callback that takes frame info#20617fluttergithubbot merged 3 commits intoflutter:masterfrom
Conversation
56b270b to
5ff79a7
Compare
See EC-1 in flutter.dev/go/double-buffered-window-resize
stuartmorgan-g
left a comment
There was a problem hiding this comment.
Functionality LGTM (although @chinmaygarde should definitely review as well), but some nits.
shell/gpu/gpu_surface_gl.cc
Outdated
| } | ||
|
|
||
| GLFrameInfo frame_info = {.width = static_cast<uint32_t>(size.width()), | ||
| .height = static_cast<uint32_t>(size.height())}; |
There was a problem hiding this comment.
Labelled aggregate initialization is non-standard until C++20; please don't use it at this point. (Applies throughout the PR.)
shell/gpu/gpu_surface_gl.cc
Outdated
| return true; | ||
| } | ||
|
|
||
| GLFrameInfo frame_info = {.width = static_cast<uint32_t>(size.width()), |
There was a problem hiding this comment.
Please declare this closer to where it's used (per style guide).
|
|
||
| namespace flutter { | ||
|
|
||
| struct GLFrameInfo { |
There was a problem hiding this comment.
Needs a declaration comment.
| FlutterOpenGLTexture* /* texture out */); | ||
| typedef void (*VsyncCallback)(void* /* user data */, intptr_t /* baton */); | ||
|
|
||
| typedef struct { |
There was a problem hiding this comment.
Needs a declaration comment.
shell/platform/embedder/embedder.h
Outdated
| uint32_t height; | ||
| } FlutterFrameInfo; | ||
|
|
||
| typedef uint32_t (*FBOWithFrameInfoCallBack)(void* /* user data */, |
shell/platform/embedder/embedder.h
Outdated
| BoolCallback make_current; | ||
| BoolCallback clear_current; | ||
| BoolCallback present; | ||
| /// This is an optional callback. Exactly one of |
There was a problem hiding this comment.
"Optional" seems somewhat misleading here; if someone skims quickly they might think this is the same as the other optional callbacks, where it truly is optional. I would just remove this first sentence and start with the "Exactly one of ..." part. (Same below.)
| FlutterOpenGLTexture* /* texture out */); | ||
| typedef void (*VsyncCallback)(void* /* user data */, intptr_t /* baton */); | ||
|
|
||
| typedef struct { |
There was a problem hiding this comment.
This struct should start with a size in case we want to add more information to it in the future.
|
|
||
| size_t GetSoftwareSurfacePresentCount() const; | ||
|
|
||
| std::vector<FlutterFrameInfo> GetGLFBOFrameInfos(); |
There was a problem hiding this comment.
Please add a declaration comment, since the implementation isn't inline to make it obvious what it does. (Or, alternately, comment the ivar.)
chinmaygarde
left a comment
There was a problem hiding this comment.
A few nits but a good foundation.
| engine.reset(); | ||
| } | ||
|
|
||
| TEST_F(EmbedderTest, FrameInfoContainsValidWidthAndHeight) { |
There was a problem hiding this comment.
Another test here to verify that engine initialization is aborted if both the old and new callbacks are specified by the embedder.
shell/platform/embedder/embedder.h
Outdated
| BoolCallback make_current; | ||
| BoolCallback clear_current; | ||
| BoolCallback present; | ||
| /// This is an optional callback. Exactly one of |
There was a problem hiding this comment.
Instead of saying this is optional, can we say "specifying one (and only one) of the fbo_callback or fbo_with_frame_info_callback is required. Specifying both is an error and engine intialization will be terminated.".
shell/platform/embedder/embedder.h
Outdated
| uint32_t height; | ||
| } FlutterFrameInfo; | ||
|
|
||
| typedef uint32_t (*FBOWithFrameInfoCallBack)(void* /* user data */, |
There was a problem hiding this comment.
I don't believe prepositions are used in in the embedder API. Also, the uint32_t needing to be an FBO is not really required. How about UIntFrameInfoCallback instead to keep this consistent with the UIntCallback you are upgrading?
| uint32_t width; | ||
| /// The height of the surface that will be backed by the fbo. | ||
| uint32_t height; | ||
| } FlutterFrameInfo; |
There was a problem hiding this comment.
This seems like something we can reuse later. How about FlutterUIntSize? There is already a FlutterSize but those are doubles.
There was a problem hiding this comment.
Do you foresee a case where this object will be need to expanded? If so, FBOWithFrameInfoCallBack will need to take a pointer to this. It will also need to have a struct size member.
shell/platform/embedder/embedder.cc
Outdated
| nullptr; | ||
| // only one of these callbacks must exist. | ||
| if (fbo_callback_exists == fbo_with_frame_info_callback_exists) { | ||
| LOG_EMBEDDER_ERROR(kInternalInconsistency, |
There was a problem hiding this comment.
LOG_EMBEDDER_ERROR is only used right before returning control to the caller. kInternalInconsistency isn't actually going to be returned to the caller here. Just get rid of this line as the result of IsRendererValid is used to generate the error later.
chinmaygarde
left a comment
There was a problem hiding this comment.
Another pass. Almost there.
shell/platform/embedder/embedder.h
Outdated
| } FlutterFrameInfo; | ||
|
|
||
| typedef uint32_t (*UIntFrameInfoCallback)(void* /* user data */, | ||
| FlutterFrameInfo* /* frame info */); |
There was a problem hiding this comment.
const FlutterFrameInfo* since this is not an in-out parameter.
| // SetOpenGLRendererConfig must be called before this. | ||
| FML_CHECK(renderer_config_.type == FlutterRendererType::kOpenGL); | ||
| renderer_config_.open_gl.fbo_callback = [](void* context) -> uint32_t { | ||
| FlutterFrameInfo tmp; |
There was a problem hiding this comment.
Zero initialize structs for good measure. That makes it resilient to updates to the struct. So, FlutterFrameInfo frame_info = {}; I'd also avoid vars with terse names like tmp.
There was a problem hiding this comment.
Ditto about the zero initializing structs and ivar names elsewhere.
There was a problem hiding this comment.
Renamed to frame_info, and zero initialized it.
| return reinterpret_cast<EmbedderTestContext*>(context)->GLGetFramebuffer(); | ||
| opengl_renderer_config_.fbo_with_frame_info_callback = | ||
| [](void* context, FlutterFrameInfo* frame_info) -> uint32_t { | ||
| FlutterFrameInfo tmp; |
There was a problem hiding this comment.
Unclear why you prefer this form of copying of the struct instead of just return reinterpret_cast<EmbedderTestContext*>(context)->GLGetFramebuffer(*frame_info). That is more resilient to updates to the frame info struct.
There was a problem hiding this comment.
copy-pasta error.
|
This pull request is not suitable for automatic merging in its current state.
|
| @@ -502,11 +544,6 @@ typedef struct { | |||
| double y; | |||
| } FlutterPoint; | |||
|
|
|||
There was a problem hiding this comment.
Nit: maybe move FlutterRect, FlutterPoint, and FLutterRoundedRect up as well so these similar structs all remain together.
| frame_latch.Wait(); | ||
|
|
||
| ASSERT_EQ(frames_expected, frames_seen); | ||
| ASSERT_EQ(context.GetGLFBOFrameInfos().size(), frames_seen); |
There was a problem hiding this comment.
This is racy. context.GetGLFBOFrameInfos() can have 9 entries.
Flutter conflates the size of the frame that is rendered by the framework and the size of the render surface itself. While these are usually the same, this breaks down in cases where the render surface size is being updated constantly.
To this effect, we will be adding a variant of
fbo_callbackthat takes a FrameInfo struct.fbo_callback_with_frame_info. FrameInfo will contain the size of the layer tree that Flutter plans on rendering to the FBO. This lets us create and return an FBO of the requested size along with any additional bookkeeping.See EC-1 in flutter.dev/go/double-buffered-window-resize and flutter/flutter#44136