taskGnash - The GNU Flash player - Tasks: task #7385, Implement a "stage...


You are not allowed to post comments on this tracker with your current authentification level.

task #7385: Implement a "stage matrix" instead of X/Y scales

Submitted by:  Udo Giacomozzi <udog>
Submitted on:  Mon Oct 15 13:27:04 2007  
Should Start On: Sun Oct 14 22:00:00 2007Should be Finished on: Sun Oct 14 22:00:00 2007
Category: todoPriority: 6
Status: NonePrivacy: Public
Percent Complete: 40%Assigned to: None
Open/Closed: OpenEffort: 0.00

(Jump to the original submission Jump to the original submission)

Thu May 29 14:25:20 2008, comment #9:

Udo, I guess we have a the "stage" matrix now, right ?
What we have to sort out next is the "renderer" vs. "gui" matrix
ie: what goes where, wheter they are serialized or not.
I mean:

core <---> gui <---> renderer


core <---> gui
core <---> renderer

We currently have:

core <---> gui and renderer using the same

Sandro Santilli <strk>
Project Member
Mon Oct 22 18:05:54 2007, comment #8:

Discussion in IRC was continued:

It's probably better to keep scaling in gui.cpp (like the current design). So gui.cpp would define the stage matrix and pass it over to the renderers.

Neither movie_root nor the GUI implementations (ie. GTK.cpp) would know about this stage matrix. Instead, gui.cpp acts like a coordinate gateway and converts between screen coordinates (GUI side) and ActionScript coordinates (movie_root side).

Concatenation of the stage matrix to the object matrix is done in-place by the renderers.

This is what happens when the user clicks in the middle of a 200% scaled window (native movie size 100x100 pixels):

1) GTK sends mouse move event at 200/200 (window center)

2) GTK GUI receives the event and calls Gui::notify_mouse_moved(200, 200)

3) gui.cpp reverse-applies the stage-matrix to these coordinates getting 100/100 as new coordinates

4) gui.cpp calls movie_root::notify_mouse_moved(100, 100)

5) an ActionScript handler onMouseDown is invoked with _xmouse=100

This works the same way with all scaleModes (only the stage matrix changes). Note neither movie_root nor the GTK GUI knows about the scale mode.

Similarly, when the renderer has to render a shape it goes this way:

1) Before rendering the frame it receives the current stage matrix from gui.cpp

2) The renderer function draw_shape_character() is called (with definition and instance reference, as usual)

3) The renderer calls get_world_matrix() of the instance

4) The stage matrix received in step 1 is concatenated

5) The shape is rendered using this final matrix, not needing any x/y scale or twips->pixel conversion

I hope this description is clear :)

Udo Giacomozzi <udog>
Project Member
Mon Oct 22 17:02:59 2007, comment #7:

I added some developers to the CC list because I can only speak for AGG and backends in general, resp. GTK and FB GUIs and may be missing something for the alternatives.

Udo Giacomozzi <udog>
Project Member
Mon Oct 22 16:54:51 2007, comment #6:

Ok, I try to summarize our IRC discussion:

Probably it's a good idea to keep get_world_matrix() the way it is now and add a get_render_matrix(). The latter would return get_world_matrix() with the stage matrix concatenated.

This way renderers would just have to use get_render_matrix() instead of get_world_matrix() and completely forget about scaling. Renderers should however have the ability to get just the stage matrix (maybe necessary for fill styles).

(Some?) mouse events are currently passed using PIXEL coordinates. But these are not the coordinates of the "physical" window as the GUIs reverse-scale the coordinates before passing it to movie_root.

Sandro would like to pass TWIPS instead of PIXEL coordinates (thus multiplying * 20) but I see no reason for that because this would not add any precision.

Anyway, mouse events should pass hardware pixel coordinates (ie. the physical pixel offset from the window origin) to movie_root which then simply uses it's stage matrix to convert the coordinates to the Flash coordinate system (which is a 1:1 conversion for a 100% scaled window!). This conversion could also be done in gui.cpp.

This change would mean reworking of all GUIs and all renderers (mainly dropping scaling) but would solve a bunch of problems, like different behavior of the GUIs and unsupported scaling modes. Also it would make life easier for renderer and GUI developers.

Udo Giacomozzi <udog>
Project Member
Tue Oct 16 08:28:41 2007, comment #5:

fine by me.
I'm not really into the gui/renderer interfaces to help more.

Sandro Santilli <strk>
Project Member
Mon Oct 15 23:25:12 2007, comment #4:

>The gui will notify resize to the core anyway, after appropriate management (like keeping aspect ratio), so the core could still set the stage matrix the way the gui chooses.

Ok, but what's the benefit from that? I ask because
1) the current design decides scaling in the GUI
2) it would still be the GUI that chooses the matrix and passes it to the core - why this additional step?

>Any shifting might still be computed in the GUI and communicated to the stage (movie_root) as a single set_matrix call.

Are you maybe talking about defining the matrix parameters in the GUI and just pass the result to the core? ...and just patch get_world_matrix() to concatenate that matrix? Ok, could be a solution, but be aware that get_world_matrix() had a different meaning (remain still in TWIPS coordinate space) and we have to check carefully what this means for fill styles (which are scaled too, but differently).

I still prefer to keep the core in it's own coordinate space (TWIPS) and let it up to the renderer to concatenate the final matrix.

Don't forget about mouse events, too.

>About pixels to twips conversions we should look case by case.

The standard divide-by-twenty define makes absolutely no sense once the player is resized.

Udo Giacomozzi <udog>
Project Member
Mon Oct 15 20:49:19 2007, comment #3:

The gui will notify resize to the core anyway, after appropriate management (like keeping aspect ratio), so the core could still set the stage matrix the way the gui chooses.
Note that we also already support the Stage ActionScript object (not deeply tested) which can be used by AS to disable resizes.

Any shifting might still be computed in the GUI and communicated to the stage (movie_root) as a single set_matrix call.

About pixels to twips conversions we should look case by case.

Sandro Santilli <strk>
Project Member
Mon Oct 15 15:49:50 2007, comment #2:

Yes, of course, because only the GUI knows the size of the output window and it's the GUI that in the current design chooses the scale (Gui::resize_view).

get_world_matrix() returns the final matrix in Flash coordinates (TWIPS). We need an additional step to get pixel coordinates.

When the Gnash player is sized in the movie's native size, then the global matrix would scale all coordinates by 0.05 (TWIPS->pixels).

If you scale the Gnash player to 2x size (-s 2) then the global matrix would scale by all coordinates by 0.1 (0.05*2).

So far it's the same what xscale/yscale does. Following situations require more:

If you just set the player window to use the double width but normal height, then the scale would still remain 0.05 but the movie would shift to the right to remain centered (at least that's what the proprietary player does).

A Flash designer can choose that a movie should not scale with the window. In this case the scaling would remain 0.05 but some shifting would be necessary.

Note such a global matrix would make any hardcoded TWIPS<->pixel conversion bogus (which it is anyway).

Udo Giacomozzi <udog>
Project Member
Mon Oct 15 15:26:25 2007, comment #1:

Do we really need any support from the GUI for this ?
IIRC the matrix we pass to the renderer comes from calls to get_world_matrix, and that function recurses till it reaches the root.

Currently, the root is the _levelX.
If the root was the stage itself, this should be automatic.
Maybe not very elegant (we'd need to check, since movie_root is NOT a character, so can't be set as the parent of _levelX).

Sandro Santilli <strk>
Project Member
Mon Oct 15 13:27:04 2007, original submission:

Most renderers currently use "xscale" and "yscale" factors to scale the root movie according to the window size. This has several disadvantages:

- it forces the movie to align to the upper left part of the window (normally Flash videos are always centered unless configured via ActionScript)

- it adds at least two floating point multiplications for each vector coordinate (plus two additions if you want to address the alignment problem).

The solution is simple and very effective: Use a "stage matrix", that is a master matrix that's concatenated to all other matrices during rendering. Since all graphic objects in Flash have a matrix anyway, this pratically eliminates the overhead for rescaling.

As a bonus, the movie can freely be shifted, scaled, sheared or rotated without adding any computational overhead. Rotation might be interesting for embedded devices (90° rotated display).

This also addresses the problem that each renderer has it's own way to deal with scaling while it's something that belongs to the core.

In the AGG renderer the matrix method is already implemented. It currently is not available to the "outside world" (see set_scale() implementation in render_handler_agg.cpp).

TODO / short term:

- eliminate set_scale in favor of a set_stage_matrix (or set_global_matrix if you prefer), eliminate X/Y factor variables

- implement matrix calculation in gui.cpp (or similar), based on current set_scale() implementation in render_handler_agg.cpp

- modify all non-AGG renderers to use the global matrix instead of factors. Again, see AGG renderer to see how the matrix should be concatenated. It's very easy. Maybe more tricky are the matrices for fill styles (in AGG they has to be inverse).

TODO / long term:

- implement ActionScript "Stage" class (if not yet available) and allow the root movie to be aligned to whatever is configured and, similarly, do scaling or not based on "Stage" settings.

Udo Giacomozzi <udog>
Project Member


No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -unavailable- added by udog (Inviting other GUI / renderer developers to the discussion...)
  • -unavailable- added by udog (Inviting other GUI / renderer developers to the discussion...)
  • -unavailable- added by udog (Inviting other GUI / renderer developers to the discussion...)
  • -unavailable- added by strk (Posted a comment)
  • -unavailable- added by udog (Submitted the item)

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.


    Please enter the title of George Orwell's famous dystopian book (it's a date):



    Follow 4 latest changes.

    Date Changed By Updated Field Previous Value => Replaced By
    Thu May 29 14:25:20 2008strkPercent Complete10%=>40%
    Mon Oct 22 17:00:23 2007udogCarbon-Copy-=>Added -unavailable-
      Carbon-Copy-=>Added -unavailable-
      Carbon-Copy-=>Added -unavailable-

    Back to the top

    Powered by Savane 3.1-cleanup