Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@iskakaushik
Copy link
Contributor

@iskakaushik iskakaushik commented Aug 19, 2020

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_callback that 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

See EC-1 in flutter.dev/go/double-buffered-window-resize
@iskakaushik iskakaushik requested review from stuartmorgan-g and removed request for gw280 August 19, 2020 18:50
Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionality LGTM (although @chinmaygarde should definitely review as well), but some nits.

}

GLFrameInfo frame_info = {.width = static_cast<uint32_t>(size.width()),
.height = static_cast<uint32_t>(size.height())};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Labelled aggregate initialization is non-standard until C++20; please don't use it at this point. (Applies throughout the PR.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

return true;
}

GLFrameInfo frame_info = {.width = static_cast<uint32_t>(size.width()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please declare this closer to where it's used (per style guide).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


namespace flutter {

struct GLFrameInfo {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a declaration comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

FlutterOpenGLTexture* /* texture out */);
typedef void (*VsyncCallback)(void* /* user data */, intptr_t /* baton */);

typedef struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs a declaration comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

uint32_t height;
} FlutterFrameInfo;

typedef uint32_t (*FBOWithFrameInfoCallBack)(void* /* user data */,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

BoolCallback make_current;
BoolCallback clear_current;
BoolCallback present;
/// This is an optional callback. Exactly one of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"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.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

FlutterOpenGLTexture* /* texture out */);
typedef void (*VsyncCallback)(void* /* user data */, intptr_t /* baton */);

typedef struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This struct should start with a size in case we want to add more information to it in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


size_t GetSoftwareSurfacePresentCount() const;

std::vector<FlutterFrameInfo> GetGLFBOFrameInfos();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a declaration comment, since the implementation isn't inline to make it obvious what it does. (Or, alternately, comment the ivar.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few nits but a good foundation.

engine.reset();
}

TEST_F(EmbedderTest, FrameInfoContainsValidWidthAndHeight) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another test here to verify that engine initialization is aborted if both the old and new callbacks are specified by the embedder.

BoolCallback make_current;
BoolCallback clear_current;
BoolCallback present;
/// This is an optional callback. Exactly one of
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

uint32_t height;
} FlutterFrameInfo;

typedef uint32_t (*FBOWithFrameInfoCallBack)(void* /* user data */,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

uint32_t width;
/// The height of the surface that will be backed by the fbo.
uint32_t height;
} FlutterFrameInfo;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like something we can reuse later. How about FlutterUIntSize? There is already a FlutterSize but those are doubles.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

nullptr;
// only one of these callbacks must exist.
if (fbo_callback_exists == fbo_with_frame_info_callback_exists) {
LOG_EMBEDDER_ERROR(kInternalInconsistency,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another pass. Almost there.

} FlutterFrameInfo;

typedef uint32_t (*UIntFrameInfoCallback)(void* /* user data */,
FlutterFrameInfo* /* frame info */);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const FlutterFrameInfo* since this is not an in-out parameter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// 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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto about the zero initializing structs and ivar names elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy-pasta error.

@iskakaushik iskakaushik added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Aug 19, 2020
@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • This pull request has changes requested by @stuartmorgan. Please resolve those before re-applying the label.

@fluttergithubbot fluttergithubbot removed the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Aug 19, 2020
double x;
double y;
} FlutterPoint;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: maybe move FlutterRect, FlutterPoint, and FLutterRoundedRect up as well so these similar structs all remain together.

@iskakaushik iskakaushik added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Aug 19, 2020
@fluttergithubbot fluttergithubbot merged commit 26fe912 into flutter:master Aug 19, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Aug 20, 2020
frame_latch.Wait();

ASSERT_EQ(frames_expected, frames_seen);
ASSERT_EQ(context.GetGLFBOFrameInfos().size(), frames_seen);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is racy. context.GetGLFBOFrameInfos() can have 9 entries.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

cla: yes platform-android platform-ios waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants