{"id":20970,"date":"2015-03-26T16:09:16","date_gmt":"2015-03-26T15:09:16","guid":{"rendered":"https:\/\/www.inovex.de\/\/?p=231"},"modified":"2015-03-26T16:09:16","modified_gmt":"2015-03-26T15:09:16","slug":"android-graphics-pipeline-from-button-to-framebuffer-part-1","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/","title":{"rendered":"Android Graphics Pipeline: From Button to Framebuffer (Part 1)"},"content":{"rendered":"<p>In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline. Google itself already released some insights and documentation on the subject such as the beautiful Google I\/O 2012 talk <em><a href=\"https:\/\/www.youtube.com\/watch?v=Q8m9sHdyXnE\">For Butter or Worse<\/a><\/em>\u00a0by Chet Haase and Romain Guy (go watch it if you haven\u2019t!) or the article <em><a href=\"http:\/\/source.android.com\/devices\/graphics\/architecture.html\">Graphics architecture<\/a><\/em>. While they certainly help to get the big picture involved in getting a simple view displayed on the screen, they are not that helpful when trying to understand the source code behind it. This series will give you a gentle jump start into the interesting world of the Android Graphics Pipeline.<!--more--><\/p>\n<p>Beware, a lot of source code and sequence diagrams will be involved in this mini-series! Its worth a read though, especially if you have even the slightest interest in the Android Graphics Pipeline, as you are going to learn a lot (or at least get to look at some pretty pictures). So get yourself a coffee and read on!<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_82_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Introduction\" >Introduction<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#The-Big-Picture-Pipeline-Overview\" >The Big Picture: Pipeline Overview<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Display-Lists\" >Display Lists<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Diving-into-code\" >Diving into code<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Root-View\" >Root View<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Creating-the-Display-Lists\" >Creating the Display Lists<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Read-on\" >Read on<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Download\" >Download<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#Get-in-touch\" >Get in touch<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Introduction\"><\/span>Introduction<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In order to fully understand the journey all views undertake on the way to the screen, we will use a small demo app and describe every major stage in the Android Graphics Pipeline, starting with the public Android Java API (SDK), going to native C++ code and finally looking at the raw OpenGL drawing operations.<\/p>\n<figure id=\"attachment_232\" aria-describedby=\"caption-attachment-232\" style=\"width: 300px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/one-button-layout-cropped.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-232 size-medium\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/one-button-layout-cropped-300x186.png\" alt=\"One Button\" width=\"300\" height=\"186\" data-wp-pid=\"232\" \/><\/a><figcaption id=\"caption-attachment-232\" class=\"wp-caption-text\">The demo app in all its glory. This little app is causing enough code-coverage in the Android Graphics internals, so that it&#8217;s actually a pretty good example.<\/figcaption><\/figure>\n<p>The activity consists of a simple<span class=\"lang:java decode:true crayon-inline\"> RelativeLayout<\/span>, an <span class=\"lang:java decode:true crayon-inline\">ActionBar<\/span>\u00a0with the application icon and title and a simple <span class=\"lang:java decode:true crayon-inline \">Button<\/span>\u00a0which reads <em>Hello world!<\/em>.<\/p>\n<figure id=\"attachment_233\" aria-describedby=\"caption-attachment-233\" style=\"width: 800px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/one-button-viewhierarchy.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-233 size-large\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/one-button-viewhierarchy-1024x396.png\" alt=\"The view hierarchy of our simple demo app is actually quite complex.\" width=\"800\" height=\"309\" data-wp-pid=\"233\" \/><\/a><figcaption id=\"caption-attachment-233\" class=\"wp-caption-text\">The view hierarchy of our simple demo app is actually quite complex.<\/figcaption><\/figure>\n<p>Inside the Android view hierarchy, the relative layout consists of a simple color-gradient background. More complex, the action bar is composed of the background, which is a gradient combined with a bitmap, the <em>One Button<\/em> text element and the application icon, which is also a bitmap. A 9-Patch is used as the background for the button, and the text element <em>Hello World!<\/em> is drawn on top of it. The navigation bar and status bar at the top and bottom of the screen are not part of the apps activity, they will be rendered by the\u00a0<span class=\"lang:java decode:true crayon-inline \">SystemUI<\/span>\u00a0\u00a0system service instead.<\/p>\n<h2 id=\"the-big-picture-pipeline-overview\"><span class=\"ez-toc-section\" id=\"The-Big-Picture-Pipeline-Overview\"><\/span>The Big Picture: Pipeline Overview<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Having watched the Google I\/O talk <em>For Butter or Worse<\/em>, you will certainly recognize the following slide, which shows the complete Android Graphics Pipeline.<\/p>\n<figure id=\"attachment_234\" aria-describedby=\"caption-attachment-234\" style=\"width: 800px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/pipeline.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-234 size-large\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/pipeline-1024x458.png\" alt=\"The complete Android Graphics Pipeline, as presented at Google I\/O 2012.\" width=\"800\" height=\"358\" data-wp-pid=\"234\" \/><\/a><figcaption id=\"caption-attachment-234\" class=\"wp-caption-text\">The complete Android Graphics Pipeline, as presented at Google I\/O 2012.<\/figcaption><\/figure>\n<p>The Surface Flinger is responsible for creating a graphics buffer and compositing it onto the main display and while certainly very important for the Android system, is not covered at this time.<\/p>\n<p>Instead, we will look at a fine selection of components which are doing most of the heavy lifting in bringing the view to the screen:<\/p>\n<figure id=\"attachment_235\" aria-describedby=\"caption-attachment-235\" style=\"width: 800px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/interesting_bits.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-235 size-large\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/interesting_bits-1024x302.png\" alt=\"The interesting bits (at least for these blog posts) of the pipeline.\" width=\"800\" height=\"236\" data-wp-pid=\"235\" \/><\/a><figcaption id=\"caption-attachment-235\" class=\"wp-caption-text\">The interesting bits (at least for these blog posts) of the pipeline.<\/figcaption><\/figure>\n<h2 id=\"display-lists\"><span class=\"ez-toc-section\" id=\"Display-Lists\"><\/span>Display Lists<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>As you may already know, Android uses a concept called <span class=\"lang:java decode:true crayon-inline\">DisplayList<\/span>s to render all its views. For those of you who don\u2019t know, a display list is a sequence of graphics commands needed to be executed to render a specific view. These display lists are an important element to achieve the high performance of the Android Graphics Pipeline.<\/p>\n<p><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/display-lists.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-236 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/display-lists.png\" alt=\"Display Lists\" width=\"1014\" height=\"344\" data-wp-pid=\"236\" \/><\/a><\/p>\n<p>Every view of the view hierarchy has a corrsponding display list, which is generated by the views <span class=\"lang:java decode:true crayon-inline \">onDraw()<\/span>\u00a0method, which every developer knows about. In order to draw the view hierarchy onto the screen, only the display lists need to be evaluated and executed. In case a single view gets invalidated (due to user input, animations or transitions), the affected display lists will be rebuilt and eventually redrawn. This is preventing Android from calling the quite expensive <span class=\"lang:java decode:true crayon-inline \">onDraw()<\/span>\u00a0methods every frame.<\/p>\n<p>&nbsp;<\/p>\n<p>Display lists can also be nested, meaning that a display list can issue a command to draw a childrens display list. This is important in order to be able to reproduce view hierarchies with display lists. After all, even our simple app has multiple nested views.<\/p>\n<p>These commands are a mixture of statements that can be directly mapped to OpenGL commands, such as translating and setting up clipping rectangles, and more complex commands such as <span class=\"lang:java decode:true crayon-inline \">DrawText<\/span>\u00a0and <span class=\"lang:java decode:true crayon-inline\">DrawPatch<\/span>. These need a more complex set of OpenGL commands.<\/p>\n<pre class=\"lang:sh decode:true \" title=\"An example of a display list for a button.\">Save 3\n\nDrawPatch\n\nSave 3\n\nClipRect 20.00, 4.00, 99.00, 44.00, 1\n\nTranslate 20.00, 12.00\n\nDrawText 9, 18, 9, 0.00, 19.00, 0x17e898\n\nRestore\n\nRestoreToCount 0<\/pre>\n<p>In the example above, you can clearly see what kind of operations are present in a display list for our simple button. The first operation is to save the current translation matrix to the stack, so that it can be later restored. It then proceeds to draw the buttons 9-Patch, followed by another save command. This is necessary because for the text to be drawn, a clipping rectangle is set up to only affect the region that where text will be drawn. Mobile GPUs can take this rectangle as an hint to further optimize the draw calls in later stages. The drawing origin is than translated to the text position and the text is drawn. At the end, the original translation matrix and state is restored from the stack, which also resets the clipping rectangle.<\/p>\n<p>The complete log of the display lists for our example application can be seen at the bottom of this post.<\/p>\n<h2 id=\"diving-into-code\"><span class=\"ez-toc-section\" id=\"Diving-into-code\"><\/span>Diving into code<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>With this newly accuired knowledge we are ready to dive into the code.<\/p>\n<h3 id=\"root-view\"><span class=\"ez-toc-section\" id=\"Root-View\"><\/span>Root View<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Every Android activity has an implicit root view at the top of the view hierarchy, containing exactly one child view. This child is the first real view of the application defined by the application developer. The root view is responsible for scheduling and executing multiple operations such as drawing and invalidating views, among other.<\/p>\n<p>Similarly, every view has a reference to its parent. The first view inside the view hierarchy, which the root view references, has this root view as a parent. While serving as a base class for every visible element and widget, the <span class=\"lang:java decode:true crayon-inline \">View<\/span>\u00a0class does not support any children. However, the derrived <span class=\"lang:java decode:true crayon-inline \">ViewGroup<\/span>\u00a0supports multiple children and serves as a container base class, which is used by the standard layouts (<span class=\"lang:java decode:true crayon-inline \">RelativeLayout<\/span>\u00a0etc.).<\/p>\n<p>If a view is (partially) invalidated, the view will call the root views <span class=\"lang:java decode:true crayon-inline\">invalidateChildInParent()<\/span>\u00a0method. The root view keeps track of all invalidated areas and schedules a new traversal at the choreographer, which is performed on the next VSync event.<\/p>\n<figure id=\"attachment_237\" aria-describedby=\"caption-attachment-237\" style=\"width: 909px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/view-invalidate.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-237 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/view-invalidate.png\" alt=\"ViewRoot: InvalidateChildInParent(\u2026)\" width=\"909\" height=\"630\" data-wp-pid=\"237\" \/><\/a><figcaption id=\"caption-attachment-237\" class=\"wp-caption-text\">ViewRoot: InvalidateChildInParent(\u2026)<\/figcaption><\/figure>\n<pre class=\"lang:java decode:true \">public ViewParent invalidateChildInParent(int[] location, Rect dirty) {\n\n    \/\/ Add the new dirty rect to the current one\n\n    mDirty.union(dirty.left, dirty.top,\n\n                 dirty.right, dirty.bottom);\n\n    \/\/ Already scheduled?\n\n    if (!mWillDrawSoon) {\n\n        scheduleTraversals();\n\n    }\n\n    return null;\n\n}<\/pre>\n<h3 id=\"creating-the-display-lists\"><span class=\"ez-toc-section\" id=\"Creating-the-Display-Lists\"><\/span>Creating the Display Lists<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>As previously mentioned, each view is responsible to generate its own display list. When a VSync event is fired and the choreographer called <span class=\"lang:java decode:true crayon-inline\">performTraversals<\/span>\u00a0on the root view, the\u00a0<span class=\"lang:java decode:true crayon-inline\">HardwareRenderer<\/span>\u00a0is asked to draw the view, which in turn will ask the view to generate its display list.<\/p>\n<p><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/perform-traversals1.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-238 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/perform-traversals1.png\" alt=\"Traversals 1\" width=\"923\" height=\"398\" data-wp-pid=\"238\" \/><\/a><\/p>\n<p>With currently almost 20.000 lines of code, the <span class=\"lang:java decode:true crayon-inline \">View<\/span>\u00a0\u00a0is one of the bigger classes inside the Android framework. This comes as no surprise, as it is the building block for every widget and application. It handles the keyboard, trackball and touch events, as well as scrolling, scrollbars, layouting and measuring, and much, much more.<\/p>\n<p><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/view-getdisplaylist.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-239 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/view-getdisplaylist.png\" alt=\"View Getdisplaylist\" width=\"834\" height=\"525\" data-wp-pid=\"239\" \/><\/a><\/p>\n<p>Called by the Hardware Renderer, the <span class=\"lang:java decode:true crayon-inline\">View.getDisplayList(\u2026)<\/span>\u00a0method will create a new internal display list, which will be used for rest of the views lifetime. The internal display list is then asked to supply a canvas big enough to accommodate the view. Supplying a\u00a0<span class=\"lang:java decode:true crayon-inline\">GLES20RecordingCanvas<\/span>, the view and all its children will use it to draw upon, and is therefore handed to the\u00a0<span class=\"lang:java decode:true crayon-inline\">draw(\u2026)<\/span>\u00a0method. The canvas is somewhat special, as it will not execute drawing commands but rather save them as commands inside the display list. This means that the widgets and every view can use the normal drawing API without even noticing that the commands are <em>rendered<\/em> to a display list.<\/p>\n<pre class=\"lang:java decode:true\" title=\"View: getDisplayList(\u2026)\">private DisplayList getDisplayList(DisplayList displayList,\n\n                                   boolean isLayer) {\n\n    HardwareCanvas canvas = displayList.start(width, height);\n\n    if (!isLayer &amp;&amp; layerType != LAYER_TYPE_NONE) {\n\n        \/\/ Layers don't get drawn via a display list\n\n    } else {\n\n        draw(canvas);\n\n    }\n\n    return displayList;\n\n}<\/pre>\n<p>Inside the <span class=\"lang:java decode:true crayon-inline \">draw(\u2026)<\/span>\u00a0method, the view will execute the <span class=\"lang:java decode:true crayon-inline \">onDraw()<\/span>\u00a0code, rendering itself onto the supplied canvas. If the view has any children, it will also call the <span class=\"lang:java decode:true crayon-inline \">draw()<\/span>\u00a0method of each of them. These children could be anything, from a normal button to another layout or view group, which itself includes another set of children, which will also get drawn.<\/p>\n<p><a href=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/view-draw.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-241 size-full\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/view-draw.png\" alt=\"View Draw\" width=\"620\" height=\"461\" data-wp-pid=\"241\" \/><\/a><\/p>\n<h2 id=\"stay-tuned\"><span class=\"ez-toc-section\" id=\"Read-on\"><\/span>Read on<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>With the generation of the display list this first part comes to an end. <a href=\"https:\/\/www.inovex.de\/\/android-graphics-pipeline-from-button-to-framebuffer-part-2\/\" target=\"_blank\" rel=\"noopener\">Jump to part 2<\/a> where\u00a0we will actually take a look at how these display lists get rendered to the screen!<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Download\"><\/span>Download<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The full Bachelor&#8217;s Thesis on which this article is based is <a href=\"http:\/\/mathias-garbe.de\/files\/introduction-android-graphics.pdf\" target=\"_blank\" rel=\"noopener\">available for download<\/a>.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Get-in-touch\"><\/span>Get in touch<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Interested in Android Development, Mobile and Embedded Systems? Have a look at our full portfolio on <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/mobile\/\" target=\"_blank\" rel=\"noopener\">our website<\/a>, drop us an <a href=\"mailto:list-blog@inovex.de\">email<\/a> or call <a href=\"tel:+497216190210\">+49 721 619 021-0<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline. Google itself already released some insights and documentation on the subject such as the beautiful Google I\/O 2012 talk For Butter or Worse\u00a0by Chet Haase and Romain Guy (go watch it if you haven\u2019t!) or [&hellip;]<\/p>\n","protected":false},"author":20,"featured_media":12015,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[510,74],"service":[],"coauthors":[{"id":20,"display_name":"Mathias Garbe","user_nicename":"mgarbe"}],"class_list":["post-20970","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-apps-2","tag-iot"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Android Graphics Pipeline: From Button to Framebuffer (Part 1)<\/title>\n<meta name=\"description\" content=\"In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Android Graphics Pipeline: From Button to Framebuffer (Part 1)\" \/>\n<meta property=\"og:description\" content=\"In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2015-03-26T15:09:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2300\" \/>\n\t<meta property=\"og:image:height\" content=\"876\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Mathias Garbe\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop-1024x390.jpg\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mathias Garbe\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"8\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Mathias Garbe\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/\"},\"author\":{\"name\":\"Mathias Garbe\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/20a077747bb387e2233213d27195b789\"},\"headline\":\"Android Graphics Pipeline: From Button to Framebuffer (Part 1)\",\"datePublished\":\"2015-03-26T15:09:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/\"},\"wordCount\":1474,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/titelbild-android-crop.jpg\",\"keywords\":[\"Apps\",\"IoT\"],\"articleSection\":[\"Applications\",\"English Content\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/\",\"name\":\"Android Graphics Pipeline: From Button to Framebuffer (Part 1)\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/titelbild-android-crop.jpg\",\"datePublished\":\"2015-03-26T15:09:16+00:00\",\"description\":\"In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/titelbild-android-crop.jpg\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2015\\\/03\\\/titelbild-android-crop.jpg\",\"width\":2300,\"height\":876,\"caption\":\"Eine Android Figur mit dem inovex Logo steht auf einem ge\u00f6ffneten Laptop\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/android-graphics-pipeline-from-button-to-framebuffer-part-1\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Android Graphics Pipeline: From Button to Framebuffer (Part 1)\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#website\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\\\/\\\/www.inovex.de\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/inovexde\",\"https:\\\/\\\/x.com\\\/inovexgmbh\",\"https:\\\/\\\/www.instagram.com\\\/inovexlife\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/company\\\/inovex\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/#\\\/schema\\\/person\\\/20a077747bb387e2233213d27195b789\",\"name\":\"Mathias Garbe\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/911e68f92a8e63ff7f30008aaec8b66a2eb0177f8c880b64028b865b63149b24?s=96&d=retro&r=g3c26b5c18718786d4395456db2dafb83\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/911e68f92a8e63ff7f30008aaec8b66a2eb0177f8c880b64028b865b63149b24?s=96&d=retro&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/911e68f92a8e63ff7f30008aaec8b66a2eb0177f8c880b64028b865b63149b24?s=96&d=retro&r=g\",\"caption\":\"Mathias Garbe\"},\"url\":\"https:\\\/\\\/www.inovex.de\\\/de\\\/blog\\\/author\\\/mgarbe\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Android Graphics Pipeline: From Button to Framebuffer (Part 1)","description":"In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/","og_locale":"de_DE","og_type":"article","og_title":"Android Graphics Pipeline: From Button to Framebuffer (Part 1)","og_description":"In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline.","og_url":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2015-03-26T15:09:16+00:00","og_image":[{"width":2300,"height":876,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop.jpg","type":"image\/jpeg"}],"author":"Mathias Garbe","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop-1024x390.jpg","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Mathias Garbe","Gesch\u00e4tzte Lesezeit":"8\u00a0Minuten","Written by":"Mathias Garbe"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/"},"author":{"name":"Mathias Garbe","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/20a077747bb387e2233213d27195b789"},"headline":"Android Graphics Pipeline: From Button to Framebuffer (Part 1)","datePublished":"2015-03-26T15:09:16+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/"},"wordCount":1474,"commentCount":2,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop.jpg","keywords":["Apps","IoT"],"articleSection":["Applications","English Content","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/","url":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/","name":"Android Graphics Pipeline: From Button to Framebuffer (Part 1)","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop.jpg","datePublished":"2015-03-26T15:09:16+00:00","description":"In this mini-series of blog articles we want to shed some light on the internals of the Android Graphics Pipeline.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop.jpg","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2015\/03\/titelbild-android-crop.jpg","width":2300,"height":876,"caption":"Eine Android Figur mit dem inovex Logo steht auf einem ge\u00f6ffneten Laptop"},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/android-graphics-pipeline-from-button-to-framebuffer-part-1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Android Graphics Pipeline: From Button to Framebuffer (Part 1)"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/20a077747bb387e2233213d27195b789","name":"Mathias Garbe","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/911e68f92a8e63ff7f30008aaec8b66a2eb0177f8c880b64028b865b63149b24?s=96&d=retro&r=g3c26b5c18718786d4395456db2dafb83","url":"https:\/\/secure.gravatar.com\/avatar\/911e68f92a8e63ff7f30008aaec8b66a2eb0177f8c880b64028b865b63149b24?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/911e68f92a8e63ff7f30008aaec8b66a2eb0177f8c880b64028b865b63149b24?s=96&d=retro&r=g","caption":"Mathias Garbe"},"url":"https:\/\/www.inovex.de\/de\/blog\/author\/mgarbe\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/20970","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/20"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=20970"}],"version-history":[{"count":0,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/20970\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/12015"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=20970"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=20970"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=20970"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=20970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}