ChatGPT解决这个技术问题 Extra ChatGPT

Understanding Canvas and Surface concepts

I'm struggling to understand the process of drawing to SurfaceView and therefore the whole Surface/Canvas/Bitmap system, which is used in Android.

I've read all articles and API documentation pages, which I was able to find on android-developers site, a few tutorials of android graphics, LunarLander source code and this question.

Please tell me, which of these statements are true, which are not, and why.

Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it. All View's of window share the same Surface and thus share the same Canvas. SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.

There is also one additional question:

Why is there a need for a Surface class, if there is already a Canvas for high-level operations with bitmap. Give an example of a situation where Canvas is non-suitable for doing work which Surface can do.


h
hackbod

Here are some definitions:

A Surface is an object holding pixels that are being composited to the screen. Every window you see on the screen (a dialog, your full-screen activity, the status bar) has its own surface that it draws in to, and Surface Flinger renders these to the final display in their correct Z-order. A surface typically has more than one buffer (usually two) to do double-buffered rendering: the application can be drawing its next UI state while the surface flinger is compositing the screen using the last buffer, without needing to wait for the application to finish drawing.

A window is basically like you think of a window on the desktop. It has a single Surface in which the contents of the window is rendered. An application interacts with the Window Manager to create windows; the Window Manager creates a Surface for each window and gives it to the application for drawing. The application can draw whatever it wants in the Surface; to the Window Manager it is just an opaque rectangle.

A View is an interactive UI element inside of a window. A window has a single view hierarchy attached to it, which provides all of the behavior of the window. Whenever the window needs to be redrawn (such as because a view has invalidated itself), this is done into the window's Surface. The Surface is locked, which returns a Canvas that can be used to draw into it. A draw traversal is done down the hierarchy, handing the Canvas down for each view to draw its part of the UI. Once done, the Surface is unlocked and posted so that the just drawn buffer is swapped to the foreground to then be composited to the screen by Surface Flinger.

A SurfaceView is a special implementation of View that also creates its own dedicated Surface for the application to directly draw into (outside of the normal view hierarchy, which otherwise must share the single Surface for the window). The way this works is simpler than you may expect -- all SurfaceView does is ask the window manager to create a new window, telling it to Z-order that window either immediately behind or in front of the SurfaceView's window, and positioning it to match where the SurfaceView appears in the containing window. If the surface is being placed behind the main window (in Z order), SurfaceView also fills its part of the main window with transparency so that the surface can be seen.

A Bitmap is just an interface to some pixel data. The pixels may be allocated by Bitmap itself when you are directly creating one, or it may be pointing to pixels it doesn't own such as what internally happens to hook a Canvas up to a Surface for drawing. (A Bitmap is created and pointed to the current drawing buffer of the Surface.)

Also please keep in mind that, as this implies, a SurfaceView is a pretty heavy-weight object. If you have multiple SurfaceViews in a particular UI, stop and think about whether this is really needed. If you have more than two, you almost certainly have too many.


Thank you very much! Answer made things clearer. Part about hooking Canvas up to Surface is unclear, though. Can't imagine where such operation is needed. Can next be example of that operation: drawing Bitmap on a Canvas, acquired from SurfaceHolder with lockCanvas() method?
That is how drawing happens Canvas is the 2d drawing API. If you are going to draw o to a surface, you need to make a Canvas that points to its buffer to use the Canvas 2d drawing API to draw in to it.
In addition to #hackbod's answer, SurfaceView can also be rendered from secondary thread which is not possible for View objects
A surface also has a lockHardwareCanvas function which binds to a canvas that is provided by the GPU and is not a software canvas. This GPU bound canvas has a limited number of 2D drawing functions but has a higher performance than a software-based canvas.
"If you have multiple SurfaceViews in a particular UI, stop and think about whether this is really needed. If you have more than two, you almost certainly have too many." - Not true at all. Virtually all video conferencing apps, including Zoom, use the SurfaceView to display a single video. It is totally normal to have many of these displayed simultaneously on the same screen to view multiple participants in a video meeting.
S
Sabeeh

https://i.stack.imgur.com/z1OpA.jpg

Here is a very basic and simple conceptual overview of how interaction happens among the Window, Surface, Canvas, and Bitmap. Sometimes, a visual representation helps a lot in understanding twisted concepts. I hope this graphic could help someone.


Visualy Images are better than text :D
a
akshay7692

A Bitmap is simply a wrapper for a collection of pixels. Think of it as an array of pixels with some other convenient functions.

The Canvas is simply the class that contains all the drawing methods. It is similar to the Graphics class in AWT/Swing if you are familiar with that. All the logic on how to draw a circle, or a box, etc is contained inside Canvas. A canvas draws on a Bitmap or an open GL container but there is no reason why in the future it could be extended to draw onto other types of rasters.

SurfaceView is a View that contains a Surface. A surface is similar to a bitmap (it has a pixel store). I do not know how it is implemented but I'd imagine it is a some kind of Bitmap wrapper with extra methods for things that are directly related to screen displays (That is the reason for a surface, a Bitmap is too generic). You can get a Canvas from your Surface which is really getting the Canvas associated with the underlying Bitmap.

Your questions.

1.Canvas has its own Bitmap attached to it. Surface has its own Canvas attached to it.

Yes, a canvas operates on a Bitmap (or an open GL panel). Surface gives you a Canvas that is operating on whatever Surface is using for its Bitmap style pixel store.

2.All View's of window share the same Surface and thus share the same Canvas.

No. You could have as many surface views as you want.

3.SurfaceView is subclass of View, which, unlike other View's subclasses and View itself, has its own Surface to draw in.

Yes. Just like ListView is a subclass of View that has its own List data structure. Each subclass of View does something different.


So, Bitmap and Surface are just different species of pixel store and Canvas can wrap either of them?
Basically yes. Except Canvas can't write to a surface, it operates on whatever Surface is using for as its own pixel store (without looking at the android source I can't say for certain what it is). It's probably some kind of Bitmap extension since Canvas only provides constructors for Bitmap and GL.
Great help, thank you! About answer 2. In my question I've meant standard views, not SurfaceViews. Suppose I have RelativeLayout with plenty of fields and buttons. In this case, is Surface attached to the whole window and shared by all Views in view hierarchy?
Remember Surface is just a collection of pixels. So each surface view has its own surface and each one can be rendered on a different part of the screen. They don't necessary fill the screen (although that is the common usage, to render graphics on a full screen game).
I really wouldn't think of Bitmap and Surface as equivalent. A Surface is an object that surface flinger, the window compositor, knows about. That is, it is something directly visible on the screen, has a Z-order on the screen, etc.

关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now