Home | History | Annotate | Download | only in graphics
      1 <html devsite>
      2   <head>
      3     <title>BufferQueue and gralloc</title>
      4     <meta name="project_path" value="/_project.yaml" />
      5     <meta name="book_path" value="/_book.yaml" />
      6   </head>
      7   <body>
      8   <!--
      9       Copyright 2017 The Android Open Source Project
     10 
     11       Licensed under the Apache License, Version 2.0 (the "License");
     12       you may not use this file except in compliance with the License.
     13       You may obtain a copy of the License at
     14 
     15           http://www.apache.org/licenses/LICENSE-2.0
     16 
     17       Unless required by applicable law or agreed to in writing, software
     18       distributed under the License is distributed on an "AS IS" BASIS,
     19       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20       See the License for the specific language governing permissions and
     21       limitations under the License.
     22   -->
     23 
     24 
     25 
     26 <p>Understanding the Android graphics system starts behind the scenes with
     27 BufferQueue and the gralloc HAL.</p>
     28 
     29 <p>The BufferQueue class is at the heart of everything graphical in Android. Its
     30 role is simple: Connect something that generates buffers of graphical data (the
     31 <em>producer</em>) to something that accepts the data for display or further
     32 processing (the <em>consumer</em>). Nearly everything that moves buffers of
     33 graphical data through the system relies on BufferQueue.</p>
     34 
     35 <p>The gralloc memory allocator performs buffer allocations and is
     36 implemented through a vendor-specific HAL interface (see
     37 <code>hardware/libhardware/include/hardware/gralloc.h</code>). The
     38 <code>alloc()</code> function takes expected arguments (width, height, pixel
     39 format) as well as a set of usage flags (detailed below).</p>
     40 
     41 <h2 id="BufferQueue">BufferQueue producers and consumers</h2>
     42 
     43 <p>Basic usage is straightforward: The producer requests a free buffer
     44 (<code>dequeueBuffer()</code>), specifying a set of characteristics including
     45 width, height, pixel format, and usage flags. The producer populates the buffer
     46 and returns it to the queue (<code>queueBuffer()</code>). Later, the consumer
     47 acquires the buffer (<code>acquireBuffer()</code>) and makes use of the buffer
     48 contents. When the consumer is done, it returns the buffer to the queue
     49 (<code>releaseBuffer()</code>).</p>
     50 
     51 <p>Recent Android devices support the <em>sync framework</em>, which enables the
     52 system to do nifty things when combined with hardware components that can
     53 manipulate graphics data asynchronously. For example, a producer can submit a
     54 series of OpenGL ES drawing commands and then enqueue the output buffer before
     55 rendering completes. The buffer is accompanied by a fence that signals when the
     56 contents are ready. A second fence accompanies the buffer when it is returned
     57 to the free list, so the consumer can release the buffer while the contents are
     58 still in use. This approach improves latency and throughput as the buffers
     59 move through the system.</p>
     60 
     61 <p>Some characteristics of the queue, such as the maximum number of buffers it
     62 can hold, are determined jointly by the producer and the consumer. However, the
     63 BufferQueue is responsible for allocating buffers as it needs them. Buffers are
     64 retained unless the characteristics change; for example, if the producer
     65 requests buffers with a different size, old buffers are freed and new buffers
     66 are allocated on demand.</p>
     67 
     68 <p>Producers and consumers can live in different processes. Currently, the
     69 consumer always creates and owns the data structure. In older versions of
     70 Android, only the producer side was binderized (i.e. producer could be in a
     71 remote process but consumer had to live in the process where the queue was
     72 created). Android 4.4 and later releases moved toward a more general
     73 implementation.</p>
     74 
     75 <p>Buffer contents are never copied by BufferQueue (moving that much data around
     76 would be very inefficient). Instead, buffers are always passed by handle.</p>
     77 
     78 <h2 id="gralloc_HAL">gralloc HAL usage flags</h2>
     79 
     80 <p>The gralloc allocator is not just another way to allocate memory on the
     81 native heap; in some situations, the allocated memory may not be cache-coherent
     82 or could be totally inaccessible from user space. The nature of the allocation
     83 is determined by the usage flags, which include attributes such as:</p>
     84 
     85 <ul>
     86 <li>How often the memory will be accessed from software (CPU)</li>
     87 <li>How often the memory will be accessed from hardware (GPU)</li>
     88 <li>Whether the memory will be used as an OpenGL ES (GLES) texture</li>
     89 <li>Whether the memory will be used by a video encoder</li>
     90 </ul>
     91 
     92 <p>For example, if your format specifies RGBA 8888 pixels, and you indicate the
     93 buffer will be accessed from software (meaning your application will touch
     94 pixels directly) then the allocator must create a buffer with 4 bytes per pixel
     95 in R-G-B-A order. If instead, you say the buffer will be only accessed from
     96 hardware and as a GLES texture, the allocator can do anything the GLES driver
     97 wants&mdash;BGRA ordering, non-linear swizzled layouts, alternative color
     98 formats, etc. Allowing the hardware to use its preferred format can improve
     99 performance.</p>
    100 
    101 <p>Some values cannot be combined on certain platforms. For example, the video
    102 encoder flag may require YUV pixels, so adding software access and specifying
    103 RGBA 8888 would fail.</p>
    104 
    105 <p>The handle returned by the gralloc allocator can be passed between processes
    106 through Binder.</p>
    107 
    108 <h2 id=tracking>Tracking BufferQueue with systrace</h2>
    109 
    110 <p>To really understand how graphics buffers move around, use systrace. The
    111 system-level graphics code is well instrumented, as is much of the relevant app
    112 framework code.</p>
    113 
    114 <p>A full description of how to use systrace effectively would fill a rather
    115 long document. Start by enabling the <code>gfx</code>, <code>view</code>, and
    116 <code>sched</code> tags. You'll also see BufferQueues in the trace. If you've
    117 used systrace before, you've probably seen them but maybe weren't sure what they
    118 were. As an example, if you grab a trace while
    119 <a href="https://github.com/google/grafika">Grafika's</a> "Play video
    120 (SurfaceView)" is running, the row labeled <em>SurfaceView</em> tells you how
    121 many buffers were queued up at any given time.</p>
    122 
    123 <p>The value increments while the app is active&mdash;triggering the rendering
    124 of frames by the MediaCodec decoder&mdash;and decrements while SurfaceFlinger is
    125 doing work, consuming buffers. When showing video at 30fps, the queue's value
    126 varies from 0 to 1 because the ~60fps display can easily keep up with the
    127 source. (Notice also that SurfaceFlinger only wakes when there's work to
    128 be done, not 60 times per second. The system tries very hard to avoid work and
    129 will disable VSYNC entirely if nothing is updating the screen.)</p>
    130 
    131 <p>If you switch to Grafika's "Play video (TextureView)" and grab a new trace,
    132 you'll see a row labeled
    133 com.android.grafika/com.android.grafika.PlayMovieActivity. This is the main UI
    134 layer, which is just another BufferQueue. Because TextureView renders into the
    135 UI layer (rather than a separate layer), you'll see all of the video-driven
    136 updates here.</p>
    137 
    138 <p>For more information about the systrace tool, refer to <a
    139 href="https://developer.android.com/studio/profile/systrace-commandline.html">Systrace
    140 documentation</a>.</p>
    141 
    142   </body>
    143 </html>
    144