12-13-2012, 11:01 PM
So, I almost hate to even bring this up, because I'm worried everyone will think it's a great idea and we'll have to do it, but it makes a lot of sense what I've been thinking about. Of course the devil is in the details and maybe it'll get a lot uglier than what I think it will, but here is the broad outline. This is mostly for the RIVA developers, but others may read and comment on it if they have the stomach for such things. Some of this is just me brain dumping to make sure it actually makes sense by having to type it out loud.
The big issue of course is that people want to have native type scrolling. Of course they also want it in the regular IV and this subject addresses that as well. If I add that sort of support to the IV, I REALLY don't want to have to special case it all away for RIVA clients. That will add a lot of extra complexity of it's own, and getting rid of that complexity offsets some of the complexity of trying to let the RIVA clients do it as well.
The problem with supporting native scrolling is that it requires that the RIVA clients have information they don't have. In order to do a scroll of, say, a track list, it's pretty much necessary to draw the (yet) offscreen content into a bitmap, and scroll that bitmap into the visible area of the widget. This is generally also required because the stuff being scrolled has to be composited onto the underlying content, because it's usually stuff that has a full or partially transparent background.
The way the RIVA system works currently, the RIVA clients cannot do that because they don't know anything about what is not currently visible. They can only be told to draw what is visible, and therefore is being drawn. Those drawing commands are passed to the RIVA clients and they draw them locally. They can't anticipate information to the left or right (or below/above) that might be scrolled to and be prepared to scroll it. Even if we tried some way to provide them with that info, it would never work to try to scroll by them sending scroll commands to the server and the server sending them all those drawing commands back to repeatedly redraw the content (as required to simulate one layer sliding over another.)
Part I - Layers
So, what I've been thinking about is that the RIVA clients be extended to support layers. They still don't know about individual widgets and they don't need to. But instead of just one flat drawing surface that the RIVA server sends them drawing commands for, they would be able to support multiple layers (the main template bgn being just one of them), and the server could send them commands to draw on any given layer. Each layer would have a unique id and the RIVA client would be told about them, and how large they should be.
Each widget that has to support scrolling (and only a small set of them do) would then maintain its own memory bitmap, bigger than the actual widget, and it would draw content into that bitmap any time it wanted to, even if it's not visible. The widget would maintain a 'viewport', which is graphics speak for what area of the bitmap is currently visible with the rectange of the widget. This is how the IV itself would implement scrollable stuff. More stuff would be there than is actually visible, so you would just be moving the widget viewport around within the larger memory image of the widget.
For the RIVA clients, information about each of these memory bitmaps would be passed to them, and they would just treat them as layers. They wouldn't care any more about what's in them (widget-wise) than they currently do about the single big image. As mentioned each one would have a unique id so that drawning commands could target output to a specific layer. That output could be outside of the visible area. The RIVA client would be kept up to date as to the viewport position on each layer. So any time any content is drawn into the layer that intersections the viewport, they would need to draw that visible bit that changed.
The layers would also be given a z-order, and the clients would be responsible for composting the layers. I.e. when it's time to draw info to the screen, because some drawing commands intersected a layer's viewport area, or because the user closed a dialog box or something like that and uncovered part of the template, the client would just build up the actual content of the affected area by blitting in (using alpha based blitting) any content of each layer in z-rorder that intersects that update area. Then it finally blits the resulting composited image to the screen.
The main template would be the lowest level layer and would always be be composited in. After that, only those layers whose viewport intersects the update area would be updated. Usually it's only one. It would be very unusual to have two scroll widgets overlaying each other.
Now, to get to the real meat of the situation, scrolling would then become a local operation. When the user scrolls, the client would just keep the server informed as to where the viewport for the layer is moving. The server doesn't need to do anything but update his information for the viewport location. That way the client is always in sync with the client as to where the view port lies on any given layer. But the client would be free to move around within the available layer content locally all he wants. The server would need to know the viewpoint origin in order to correctly translate mouse/finger clicks to know what part of the actual widget content was hit.
So, as an example, the layer for a toolbar would contain all of the text areas of the tool bar. They would be predrawn into the memory bitmap of the layer. The RIVA client doesn't know it's a toolbar. The RIVA server just sends him commands to draw all of the content of the tool bar, even that not visible. The RIVA client can then just move it around all he wants. And that's all the user cares about as well, to be able to move around within the available content. When the user clicks on the screen, the RIVA client sends that to the server. The server finds the visible widget with the highest z-order that intersects that point. It subtracts the widget origin from the click point to get the relative position within the widget. It then uses the viewport position to know where within the larger virtual content of the widget the user actually clicked.
Part II - Flies in the Ointment
The complex issue will be those widgets where the whole potentially visible content cannot be put into a memory based virtual layer all at once. For most of them that won't be a problem, but for some it will be. We can't use up 50MB of memory just to scroll through a list, at least not on smaller devices.
Basically the widgets that will need to support scrolling are:
1. ToolBar - Not a problem
2. Horz/Vert Lists - Mostly not a problem, but will have to dynamically decide if they can contain the whole contents or not. Generally they can, but some might have too many items to do that. This includes the generic list browsers, the media category browser and other widgets that derive from the basic h/v list browsers.
3. Cover Art Browser - Generally never could be assumed to be able to contain all content.
4. Media Item Brower - Though it would be nice to say that no one would ever load enough tracks to become a problem, clearly they will. So this guy would have to assume it can't load all content at once.
5. Dynamic and Static Text - These shouldn't be an issue. If someone decided to load some pathologically large amount of text into one, they could just toss the excess. In any realistic scenario about the max text they will ever display is a movie description, or maybe a page or two of text gotten from a web site or some such thing. I'd be tempted to just say don't make these be scrollable, but ultimately they would need to be.
Though there are other potential scenarios, such as overlays that contains more content than they make visible, these would not have to be done immediately. And, once the RIVA clients implemented support for the general concept more scrollable things can be introduced and they wouldn't know the difference or care. So it's not an all or nothing up front gamble.
But, anyway, for those that are a problem, it gets a lot more complicated. They will have to build up content off screen but not in the same sort of natural and easy way the others can. They will like have to support multiple virtual pages, not just a single layer. The server can send the clients content for any of the pages as required. The pages would likely just be numbered (so the unique layer id plus a page number) and sized to the visible area of the widget. As the client indicates its moving the view port around, the server would have to send it content for pages currently off screen in the direction of travel. That would also mean that the pages would have to be in a circular buffer, such that the one on the far end can be brought around to the far end of the other side. It's the old thing of picking up the track behind the train and running it forward to put it in front of the train.
The big issue of course is that people want to have native type scrolling. Of course they also want it in the regular IV and this subject addresses that as well. If I add that sort of support to the IV, I REALLY don't want to have to special case it all away for RIVA clients. That will add a lot of extra complexity of it's own, and getting rid of that complexity offsets some of the complexity of trying to let the RIVA clients do it as well.
The problem with supporting native scrolling is that it requires that the RIVA clients have information they don't have. In order to do a scroll of, say, a track list, it's pretty much necessary to draw the (yet) offscreen content into a bitmap, and scroll that bitmap into the visible area of the widget. This is generally also required because the stuff being scrolled has to be composited onto the underlying content, because it's usually stuff that has a full or partially transparent background.
The way the RIVA system works currently, the RIVA clients cannot do that because they don't know anything about what is not currently visible. They can only be told to draw what is visible, and therefore is being drawn. Those drawing commands are passed to the RIVA clients and they draw them locally. They can't anticipate information to the left or right (or below/above) that might be scrolled to and be prepared to scroll it. Even if we tried some way to provide them with that info, it would never work to try to scroll by them sending scroll commands to the server and the server sending them all those drawing commands back to repeatedly redraw the content (as required to simulate one layer sliding over another.)
Part I - Layers
So, what I've been thinking about is that the RIVA clients be extended to support layers. They still don't know about individual widgets and they don't need to. But instead of just one flat drawing surface that the RIVA server sends them drawing commands for, they would be able to support multiple layers (the main template bgn being just one of them), and the server could send them commands to draw on any given layer. Each layer would have a unique id and the RIVA client would be told about them, and how large they should be.
Each widget that has to support scrolling (and only a small set of them do) would then maintain its own memory bitmap, bigger than the actual widget, and it would draw content into that bitmap any time it wanted to, even if it's not visible. The widget would maintain a 'viewport', which is graphics speak for what area of the bitmap is currently visible with the rectange of the widget. This is how the IV itself would implement scrollable stuff. More stuff would be there than is actually visible, so you would just be moving the widget viewport around within the larger memory image of the widget.
For the RIVA clients, information about each of these memory bitmaps would be passed to them, and they would just treat them as layers. They wouldn't care any more about what's in them (widget-wise) than they currently do about the single big image. As mentioned each one would have a unique id so that drawning commands could target output to a specific layer. That output could be outside of the visible area. The RIVA client would be kept up to date as to the viewport position on each layer. So any time any content is drawn into the layer that intersections the viewport, they would need to draw that visible bit that changed.
The layers would also be given a z-order, and the clients would be responsible for composting the layers. I.e. when it's time to draw info to the screen, because some drawing commands intersected a layer's viewport area, or because the user closed a dialog box or something like that and uncovered part of the template, the client would just build up the actual content of the affected area by blitting in (using alpha based blitting) any content of each layer in z-rorder that intersects that update area. Then it finally blits the resulting composited image to the screen.
The main template would be the lowest level layer and would always be be composited in. After that, only those layers whose viewport intersects the update area would be updated. Usually it's only one. It would be very unusual to have two scroll widgets overlaying each other.
Now, to get to the real meat of the situation, scrolling would then become a local operation. When the user scrolls, the client would just keep the server informed as to where the viewport for the layer is moving. The server doesn't need to do anything but update his information for the viewport location. That way the client is always in sync with the client as to where the view port lies on any given layer. But the client would be free to move around within the available layer content locally all he wants. The server would need to know the viewpoint origin in order to correctly translate mouse/finger clicks to know what part of the actual widget content was hit.
So, as an example, the layer for a toolbar would contain all of the text areas of the tool bar. They would be predrawn into the memory bitmap of the layer. The RIVA client doesn't know it's a toolbar. The RIVA server just sends him commands to draw all of the content of the tool bar, even that not visible. The RIVA client can then just move it around all he wants. And that's all the user cares about as well, to be able to move around within the available content. When the user clicks on the screen, the RIVA client sends that to the server. The server finds the visible widget with the highest z-order that intersects that point. It subtracts the widget origin from the click point to get the relative position within the widget. It then uses the viewport position to know where within the larger virtual content of the widget the user actually clicked.
Part II - Flies in the Ointment
The complex issue will be those widgets where the whole potentially visible content cannot be put into a memory based virtual layer all at once. For most of them that won't be a problem, but for some it will be. We can't use up 50MB of memory just to scroll through a list, at least not on smaller devices.
Basically the widgets that will need to support scrolling are:
1. ToolBar - Not a problem
2. Horz/Vert Lists - Mostly not a problem, but will have to dynamically decide if they can contain the whole contents or not. Generally they can, but some might have too many items to do that. This includes the generic list browsers, the media category browser and other widgets that derive from the basic h/v list browsers.
3. Cover Art Browser - Generally never could be assumed to be able to contain all content.
4. Media Item Brower - Though it would be nice to say that no one would ever load enough tracks to become a problem, clearly they will. So this guy would have to assume it can't load all content at once.
5. Dynamic and Static Text - These shouldn't be an issue. If someone decided to load some pathologically large amount of text into one, they could just toss the excess. In any realistic scenario about the max text they will ever display is a movie description, or maybe a page or two of text gotten from a web site or some such thing. I'd be tempted to just say don't make these be scrollable, but ultimately they would need to be.
Though there are other potential scenarios, such as overlays that contains more content than they make visible, these would not have to be done immediately. And, once the RIVA clients implemented support for the general concept more scrollable things can be introduced and they wouldn't know the difference or care. So it's not an all or nothing up front gamble.
But, anyway, for those that are a problem, it gets a lot more complicated. They will have to build up content off screen but not in the same sort of natural and easy way the others can. They will like have to support multiple virtual pages, not just a single layer. The server can send the clients content for any of the pages as required. The pages would likely just be numbered (so the unique layer id plus a page number) and sized to the visible area of the widget. As the client indicates its moving the view port around, the server would have to send it content for pages currently off screen in the direction of travel. That would also mean that the pages would have to be in a circular buffer, such that the one on the far end can be brought around to the far end of the other side. It's the old thing of picking up the track behind the train and running it forward to put it in front of the train.
Dean Roddey
Explorans limites defectum
Explorans limites defectum