Transcription

AN13075i.MX RT1170 Heterogeneous Graphics PipelineRev. 0 — 12/20201 IntroductionThe i.MX RT1170 crossover MCU features several options to generate,compose, and blend graphics content before sending it to a display: 2D Vector Graphics GPU: This engine can render scalable vectorgraphics and compose and manipulate bitmaps.Application NoteContents12345Introduction.12D vector graphics GPU.1PXP 2D accelerator.23LCDIFV2 display controller.25Sample application implementations. 29 PXP Graphics Accelerator: This 2D engine can manipulate and blend bitmaps, its main features are scaling, fixed-anglerotation and color space conversion. LCDIF: The display controller allows you to create up to eight display layers, offering on-the-fly blending capabilities withmulti-format support.This application note gives a brief overview of each one of the engines, how to initialize them, use them independently, and finally,it introduces a use case on how to use them in unison to get a performance and resource boost. Each stage has an associatedsoftware project to make things easier.2 2D vector graphics GPUThe GPU on the i.MX RT1170 is an instance of the GC355 GPU from Verisilicon. This is the only accelerator on the platformcapable of procedurally generating graphics based on input geometry.The user interfaces with this engine using a graphics API. This application note focuses on the VGLite API. OpenVG will beavailable at a later date.2.1 VGLiteVGLite is a lightweight 2D graphics API, designed to have a small memory footprint and low CPU overhead.The two main drawing functions on VGLite are vg lite draw, which renders vector graphics primitives, and vg lite blit, whichrenders bitmaps, also known as raster images.2.1.1 VGLite vector rendering pipelineTo render vector graphics, you need the following six pieces of information:1. Target: This is the target buffer that will hold the resulting rendered image.2. Path data: Consists of a set of coordinates and path segments that define the shape of the geometry that will berendered.3. Fill rule: Specifies the scheme selected to fill the geometric shapes with a solid color.4. Transformation: An affine transformation is provided via a 3x3 matrix.5. Color: The path color is defined using a 32bpp value (alpha, red, green, and blue, each using eight bits). Each pixelcovered by the path will have this color.6. Blend rules: The path will be blended to the extended buffer content based on these rules.

NXP Semiconductors2D vector graphics GPUOpen the NXPLogo project from the associated software: This is an incremental example explaining how to use the informationpieces, in this sample we will render the NXP logo using vector graphics. The code is divided into seven steps controlled by theTEST STEP macro. The first step (INITIAL LOGO) renders the NXP logo as follows:Figure 1. First step expected render result: the NXP Logo using vector graphics2.1.1.1 Path dataThe path data is the most important piece of information. It defines the shape of what you want to render. The path data is providedas a pair of structured data pieces:1. Opcode: defines the operation2. Arguments: 2D coordinate data consumed by the operation.The N letter can be defined using 10 opcodes as follows:Figure 2. N Letter path data: commands1. Move To: Initial point for the N letter.2. Eight Line To opcodes defining the shape of the N letter.3. Close Path opcode, instructing that the open paths must be closed.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note2 / 36

NXP Semiconductors2D vector graphics GPUEach one of the opcodes above consumes the following coordinate data:Figure 3. N Letter path data: commands and coordinates1. Move To: consumes two coordinates (x and y).2. Line To: consumes each two coordinates and it will define a line from the previous point to the newly specified point.3. The Close Path does not consume any additional data.The information for this path is stored in the nPathData array in the code.The X letter is defined similarly to the N letter. The Move to opcode is followed by a series of Line To opcodes and finally the ClosePath opcode:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note3 / 36

NXP Semiconductors2D vector graphics GPUFigure 4. X Letter path data: commands and coordinatesInformation for this path is stored in the xPathData array in the code.The P letter is more interesting. It contains curves and an inner path that will allow us to showcase the fill rule later.Let’s initially define it as two outlines defined within a single path, an outer figure, and an inner figure. The outer figure is definedby the following six opcodes:1. Move To: (514.92, 0)2. Line To: (648.62, 0)3. Cubic Curve To: (648.62, 191.07). A cubic curve has two control points: c1 (740.62, 0) and c2 (740.62, 191.07).4. Line To: (514.92, 191.07)5. Line To: (514.92, 244.57)6. Line To: (440.06, 121.88)7. Line To: (514.92, 0)The inner figure will be defined within the same path structure:8. Move To: (514.92, 61.14)9. Line To: (613.96, 61.14)10. Cubic Curve To: (613.96. 130.44) with control points on (639.4, 61.14) and (639.4, 130.44)11. Line To: (514.92, 130.44)i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note4 / 36

NXP Semiconductors2D vector graphics GPU12. Line To: (514.92, 61.14)Finally, you close the path:13. Close PathFigure 5. P Letter path data: commands and coordinatesThe information for this path is stored in the pPathData array in the code.With the information for each path ready, the next step is to initialize the vg lite path t structures:vg lite init path(&nPath, VG LITE FP32, VG LITE HIGH, sizeof(nPathData), nPathData, 0, 0, 720, 1280);vg lite init path(&xPath, VG LITE FP32, VG LITE HIGH, sizeof(xPathData), xPathData, 0, 0, 720, 1280);vg lite init path(&pPath, VG LITE FP32, VG LITE HIGH, sizeof(pPathData), pPathData, 0, 0, 720, 1280);The code to render the three letters to the display is as follows:vg lite identity(&matrix);vg lite draw(rt, &nPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF000000);vg lite draw(rt, &xPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF000000);vg lite draw(rt, &pPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF000000);i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note5 / 36

NXP Semiconductors2D vector graphics GPUNotice how we call vg lite draw three times (one time per letter). This is because our paths are separated. We could render it witha single draw call, but as we plan to change path colors, we separated it into several draw calls from the beginning.The following figure is a direct copy of the render result from the i.MXRT 1170:Figure 6. Actual render result2.1.1.2 Fill ruleWe will use the P letter to showcase how the fill rule affects how the inner shapes within a path are interpreted. Change theTEST STEP macro to FILL RULE.The fill rule allows you to cut holes into paths and that allows the P letter to have the space in the center.We change the fill rule for the P letter from VG LITE FILL EVEN ODD to VG LITE FILL NON ZERO as follows:vg lite draw(rt, &pPath, VG LITE FILL NON ZERO, &matrix, VG LITE BLEND NONE, 0xFF000000);The inner hole in the path will not be considered:Figure 7. Fill rule VG LITE FILL NON ZERO causes the P path to be completely filled2.1.1.3 TransformationTransformation is a powerful feature of the GPU. It allows you to define a 3x3 matrix for 2D affine transformations (an affinetransformation is a linear transformation followed by a translation). It also enables us to describe projective transformations.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note6 / 36

NXP Semiconductors2D vector graphics GPUThere are matrix objects and functions on VGLite, but let’s start by not using them to gain an intuition of how matrices are defined.Change the TEST STEP macro to TRANSFORM INTUITION.The matrices fed to VGLite consist of 9 floating-point values, arranged in a 3x3 array.Figure 8. VGLite matrixThe matrix is arranged in a row major order, which means that your matrix in the memory would look like this:Figure 9. Matrix in the memoryThis is the same as creating a single array with nine positions:float userMatrix[9] {1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0};The VGLite vectors are column vectors. Consider this when building your transformation matrices. Let’s build a rotation matrix.Let’s say that we want to rotate by 28 degrees around the origin. Remember that for the VGLite’s coordinate system, where theX axis points to the right and the Y axis points down, the positive angles rotate clockwise.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note7 / 36

NXP Semiconductors2D vector graphics GPUFigure 10. Expected transformation of the basis vectorsNow, to build the matrix, we place: The transformed coordinates of the X axis to the first column. The transformed coordinates of the Y axis to the second column. As we do not have translation, we will leave the third column as (0,0,1).Figure 11. Rotation Matrixi.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note8 / 36

NXP Semiconductors2D vector graphics GPUWith this, we can now store the values in the array positions:userMatrix[0] cosf(angleInRadians);userMatrix[1] -sinf(angleInRadians);userMatrix[3] sinf(angleInRadians);userMatrix[4] cosf(angleInRadians);vg lite draw(rt, &nPath, VG LITE FILL EVEN ODD, (vg lite matrix t *)&userMatrix,VG LITE BLEND NONE, 0xFF000000);vg lite draw(rt, &xPath, VG LITE FILL EVEN ODD, (vg lite matrix t *)&userMatrix,VG LITE BLEND NONE, 0xFF000000);vg lite draw(rt, &pPath, VG LITE FILL EVEN ODD, (vg lite matrix t *)&userMatrix,VG LITE BLEND NONE, 0xFF000000);The rendering result with this transformation is as follows:Figure 12. Transformation rendering resultIt matches exactly what we expected.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note9 / 36

NXP Semiconductors2D vector graphics GPUFigure 13. Render result matches the basis vectors transformationNow that you have an idea of what is happening under the hood, use the vg lite matrix t structure and the vg lite rotate functionto achieve the same thing. Change the TEST STEP macro to TRANSFORM VG LITE.The code to achieve the same transformation from the previous step is simplified as follows:vg lite rotate(28.0f, &matrix);vg lite draw(rt, &nPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF000000);vg lite draw(rt, &xPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF000000);vg lite draw(rt, &pPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF000000);2.1.1.4 ColorWhen drawing, you can specify a color for each path. To match the NXP logo with its true colors, change the TEST STEP macroto COLOR. Specify a different color for each letter:vg lite draw(rt, &nPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF10B4E8);vg lite draw(rt, &xPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFFD9AE8B);vg lite draw(rt, &pPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND NONE, 0xFF21D1C9);The render result of such color configuration is as follows:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note10 / 36

NXP Semiconductors2D vector graphics GPUFigure 14. Color rendering result2.1.1.5 BlendBoth the alpha field within the color parameter and the blend function define the effect that the alpha will have on both the pathand the destination buffer. Change the TEST STEP macro to BLEND.The most common blend function configuration is VG LITE BLEND SRC OVR, which, for each pixel, implements the followingequation to define the final color value of the pixel:S (1 - Sa) * D“S” is the path color, “D” is the color stored in the target buffer, and “Sa” is the alpha value of the path.In the following code, the target buffer is set to a solid red color and the path is rendered with an alpha value of 0x7F, which isroughly an opacity of 0.5:vg lite clear(rt, NULL, 0xFF0000FF);vg lite draw(rt, &nPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND SRC OVER, 0x7F10B4E8);vg lite draw(rt, &xPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND SRC OVER, 0x7FD9AE8B);vg lite draw(rt, &pPath, VG LITE FILL EVEN ODD, &matrix, VG LITE BLEND SRC OVER, 0x7F21D1C9);The result for each letter’s color would be:N: Base color: red: 0xE8 232, green: 0x B4 180, blue: 0x10 16 Resulting colors— Red 232 (255 - 127) * 255 255 0xFF— Green 180 (255 - 127) * 0 184 0xB4— Blue 16 (255 - 127) * 0 16 0x10 Resulting color in ABGR 0xFF10B4FFX: Base color: red: 0x8B 139, green: 0xAE 174, blue: 0xD9 217 Resulting colors— Red 139 (255 - 127) * 255 255 0xFF— Green 174 (255 - 127) * 0 174 0xAE— Blue 217 (255 - 127) * 0 217 0xD9i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note11 / 36

NXP Semiconductors2D vector graphics GPU Resulting color in ABGR 0xFFD9AEFFP: Base color: red: 0xC9 201, green: 0xD1 209, blue: 0x21 33 Resulting colors— Red 201 (255 - 127) * 255 255 0xFF— Green 209 (255 - 127) * 0 209 0xD1— Blue 33 (255 - 127) * 0 33 0x21 Resulting color in ABGR 0xFF21D1FFLet’s compare those colors against a dump of our render target:Figure 15. Color comparedThe rectangles above each letter were set using the colors that we calculated, and the letters are the actual result from our buffer.As you can see they are nearly the same, but you will notice a slight difference. This is because our target buffer is configured asRGB565 and some color information is lost during the color conversion process.2.1.1.6 Linear gradientsYou can define linear gradients for the colors in each path. To do this, use an additional structure called vg lite linear gradient tand a draw function variant vg lite draw gradient. Change the TEST STEP macro to LINEAR GRADIENTS.When you create a gradient, it will generate a 256x1 image that will be then applied to the path automatically. You can control thesize and orientation of the gradient using a matrix. Each gradient has its own 3x3 matrix.For each gradient, define the colors and stops. Stops are offsets on the 256x1 image. Colors are assigned to those stops and thecolors between the stops will be interpolated.We will use the three gradients below to define the color of the NXP letters. Each gradient has its own stop and color information:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note12 / 36

NXP Semiconductors2D vector graphics GPUFigure 16. Color gradientsThis can be translated to the following code:uint32 t nStopColors[] {0xFFE8B410, 0xFF000000};uint32 t nStops[] {0, 255};uint32 t xStopColors[] {0xFF000000, 0xFF8BAED9, 0xFF000000};uint32 t xStops[] {0, 128, 255};uint32 t pStopColors[] {0xFF000000, 0xFFC9D121};uint32 t pStops[] {0, 255};To initialize the gradient structures with this information, use the following procedures:vg lite init grad(&nGradient);gradientMatrix vg lite get grad matrix(&nGradient);vg lite identity(gradientMatrix);vg lite set grad(&nGradient, 2, nStopColors, nStops);vg lite update grad(&nGradient);When the gradients are initialized, they must be transformed to be located where they must be.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note13 / 36

NXP Semiconductors2D vector graphics GPUFigure 17. Gradient transformationFor starters, each gradient must be translated horizontally to the start of each letter.The translation is not sufficient, because each letter is bigger than 256. We have to scale the gradient as well. This is where thegradient matrix comes in handy:The N letter has a width of 274.81, so we need to scale our gradient by 1.073 on the horizontal axis.The X letter has a width of 277.140 and the scale must be 1.0825. We also have to translate it to 218.86 on the horizontal axis.The P letter has a width of 277.380 so the scale must be 1.0835 and translated to 440 on the horizontal axis.The gradient transform is important. Without it, you get the following rendering result:Figure 18. Rendering result without gradient transformation2.1.2 VGLite raster pipelineVGLite also supports drawing images via the vg lite blit* functions. The base blit function requires the following piecesof information: Target: The target buffer that will hold the result of the blit function. Source: The buffer that will be composed into the target buffer. Transformation: Provided as a 3x3 matrix, it allows you to transform the source before composing it into the target. Withthis, you can achieve transformations like translation, scaling, rotating, shearing, and perspective. Blend Rule: Specify how alpha is used to compose the source into the target. Color: You can multiply your source buffer by a color before rendering it into the target. This is useful for rendering coloredfonts using an A8 or A4 source format. In this document, we will not use this parameter.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note14 / 36

NXP Semiconductors2D vector graphics GPU Filter: If the hardware allows, you can enable bilinear filtering for the bitmaps. In this document, we will not use any kind offiltering.2.1.2.1 Simple blitOpen the project VGLiteBlit from the associated software. We will look at these pieces of information one by one using theassociated software. Set the TEST STEP macro to SIMPLE BLIT.The objective of the first three steps will be to render this bitmap to the screen:Figure 19. Bitmap renderThe target buffer for this application will be provided by the VGLITE GetRenderTarget function. This function is not part of the coreVGLite API. Its goal is to give you a vg lite buffer t that is wrapped around the framebuffer that will be sent to the display.The source buffer for this step is a vg lite buffer t with a VG LITE RGBA4444 format and 720 pixels of width and height.To render it to the screen, use the vg lite blit function:vg lite identity(&matrix);vg lite blit(rt, &dial, &matrix, VG LITE BLEND NONE, 0, VG LITE FILTER POINT);The render target returned by VGLITE GetRenderTarget is rt and dial is the bitmap we plan to blit.A useful feature of the vg lite blit function is that it automatically performs color space conversion from the source format to thetarget format. In this case, it will convert from RGBA4444 to RGB565.When you render to your screen, you will see this:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note15 / 36

NXP Semiconductors2D vector graphics GPUFigure 20. Render result of a blit of a RGBA4444 buffer to RGB565 buffer, heavy color banding presentThat does not look like we expected it to look (the gradient is not smooth). This visual artifact is called color banding.This is because we are rendering a RGBA4444 buffer to a RGB565 buffer. None of those buffers have enough color informationto describe a smooth color gradient.Change the TEST STEP macro to NO BANDING. Under this configuration, we will render a RGBA8888 buffer to aRGB565 buffer.The result of this change looks better:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note16 / 36

NXP Semiconductors2D vector graphics GPUFigure 21. Render result of a blit of a RGBA8888 buffer to RGB565 buffer, slight color banding presentIt is still not perfect because our RGB565 target buffer still does not have enough information to completely remove the banding.To completely remove it, configure your render target as kVIDEO PixelFormatXRGB8888. To do this, open the display support.hfile and change the following macros from the following:#define DEMO BUFFER PIXEL FORMAT kVIDEO PixelFormatRGB565#define DEMO BUFFER BYTE PER PIXEL 2To this:#define DEMO BUFFER PIXEL FORMAT kVIDEO PixelFormatXRGB8888#define DEMO BUFFER BYTE PER PIXEL 4Render it again and finally, the result is what we expected:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note17 / 36

NXP Semiconductors2D vector graphics GPUFigure 22. Render result of a blit of a RGBA8888 buffer to a RGBA8888, no color bandingThis comes at a cost. From the first step to this one, our memory usage has risen substantially:Our initial step used 1 RGBA4444 buffer for the dial (720*720*2 bytes, or around 1 MB) and 2 RGB565 target buffers, each witha size of 720*1280*2 bytes. This equals to a sum of approximately 4.5 MB.When we took all the steps to remove the banding, we ended up with 1 RGBA8888 buffer for the dial (720*720*4 bytes or closeto 2 MB) and 2 XRGB8888 target buffers, each with a size of 720*1280*4 bytes. This equals to a sum of 9 MB.This will also impact the system bandwidth usage, as more memory must be moved each frame.In the LCDIF chapter, you will learn how to remove banding artifacts without having to pay this memory usage and bandwidth cost.2.1.2.2 BlendingThe dial that we are rendering is not blended with the background. Change the TEST STEP macro to BLENDING.In the redraw function, before calling the render function, we are clearing the target buffer with a gray color: vg lite clear(rt,NULL, 0xFF404040). However, when the dial was rendered, the whole background of the 720x720 image was interpreted asblack. This is because we had blending disabled. By changing the blend rule to VG LITE BLEND SRC OVER, you will get thefollowing output:i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note18 / 36

NXP Semiconductors2D vector graphics GPUFigure 23. Blending2.1.2.3 TransformationThe procedure to transform bitmaps is the same than the one to transform paths. Use a 3x3 matrix to describe the affinetransformation that you want to effectuate on the bitmap. The matrix objects and functions to do so are the same. Change theTEST STEP macro to SIMPLE TRANSFORMATION.In this step, we rotate a buffer by 45 degrees:Figure 24. Buffer rotationHowever, by having a 3x3 matrix, we can achieve even more complex transformations, like projections.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note19 / 36

NXP Semiconductors2D vector graphics GPUChange the TEST STEP macro to PERSPECTIVE 2 5 D. In this step, we build a projective transformation that maps thefollowing points: (sx0, sy0) to (dx0, dy0) (sx1, sy1) to (dx1, dy1) (sx2, sy2) to (dx2, dy2) (sx3, sy3) to (dx3, dy3)Figure 25. Projective transformationThe image below is a direct snapshot of the result of the transformation.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note20 / 36

NXP Semiconductors2D vector graphics GPUFigure 26. Transformation result snapshotTo achieve this, we ported the vguComputeWarpQuadToQuad from OpenVG’s utility libraries.2.1.2.4 Raster and vector operationsBecause vg lite draw also uses vg lite buffer t structures as targets, it allows you to mix the calls of these rendering functionsto achieve interesting effects. Change the TEST STEP macro to VECTOR AND RASTER.In this step, we create a vg lite buffer t where we will render a vector-based landscape:Figure 27. Vector-based landscapei.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note21 / 36

NXP Semiconductors2D vector graphics GPUOn top of that same buffer, we render an alpha mask with the VG LITE BLEND DST IN blend configuration. This enables us todiscard all pixels that are not covered by the white pixels on the mask.Figure 28. Alpha maskThe result in your target will look like this:Figure 29. Target resulti.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note22 / 36

NXP SemiconductorsPXP 2D accelerator3 PXP 2D acceleratorPixel Processing Pipeline (PXP) is a powerful 2D accelerator capable of composing graphics assets before sending them tothe display controller. Its most important functions are blitting, alpha blending, color space conversion, fixed angle rotation,and scaling.This chapter is brief, because the PXP is already well documented and there are multiple samples already included in the SDK.We will limit our use of PXP to blending its Alpha Surface (AS) with the Processed Surface (PS). Keep in mind that this modulehas far more capabilities than the ones we use here.Open the “LCDIF PXP” project from the application note software file.For this sample, we will use PXP to populate the buffers that will be sent to the display controller. In total, there will be three buffers:two for layer 0 (which will be constantly redrawn) and one for layer 1 (which will be initially populated).Layer 0 is configured with a size of 720x640 and an ARGB8888 color format. We will allocate two buffers, so the PXP only rendersto a buffer that is not currently being shown.Layer 1 is configured with a size of 144x394 and an ARGB8888 color format.The picture below color codes the layers as we want to display them:Figure 30. Layer color codesLayer 0 composition is divided into three PXP blit operations:The first blit configures the PS to point to a background image. The AS will point to a label and the output buffer will point to thebackbuffer for layer 0 (backbuffer is the buffer not currently shown).This will blend the AS and the PS in the output buffer.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note23 / 36

NXP SemiconductorsPXP 2D acceleratorFigure 31. Blending AS and PSWhen that blit ends, a second blit is prepared. In this case, the PS and the output buffer will both point to the layer0 backbuffer andthe AS will point to the label number 2. This effectively takes our previous render result and composes the new label on top of it.Figure 32. Same PS and output buffersFor the final layer 0 composition step, we do the same, but we use a third label.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note24 / 36

NXP SemiconductorsLCDIFV2 display controllerFigure 33. Third blit to layer 0For layer 1, we execute a single blit to populate its buffer, and we never touch it again.The result of both layers being shown and populated is as follows:Figure 34. Result with both layers shown4 LCDIFV2 display controllerThe LCDIF module fetches memory buffers and sends them to the display controller. i.MXRT1170’s LCDIFv2 module supportsup to eight layers that can be blended on the fly, without any other accelerator intervention.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note25 / 36

NXP SemiconductorsLCDIFV2 display controllerEach layer can be configured using different color formats, sizes, and positions and it can fetch buffers from any location in yourmemory map.Among the supported formats, there is a particularly useful one (Index8BPP). This allows you to define a 32-bit-per-pixel imageusing a color look-up table and an index array. Using this approach, you can get the advantages of defining an ARGB8888 bufferwithout having to spend the memory doing it.See the dial of section 2.1.2.1 and the color-banding artifacts we encountered. Let’s revisit it again.Instead of saving our image as an array of 720x1280 uint32 t, where each element of the array represents the color of each pixel inour image, we will save the image using two arrays. Our first array will be a 256 uint32 t array, where we will store as many colorsas we can for our image. The second array will contain 720x1280 uint8 t values, where each value is an index to the first array.Figure 35. The pallete to the right of the dial is the color look-up tableAny recent image manipulation software allows you to create a color-lookup table. In the above figure, to the right of the dial, youcan see the color table created from the image.The LCDIFV2 module will fetch the appropriate color based on the indices from the uint8 t array. If your image does not have morethan 256 colors (or it does not exceed this number by much), then the visual result will be equal or close to your original image.i.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note26 / 36

NXP SemiconductorsLCDIFV2 display controllerFigure 36. Render result of a Indexed color formatThe “LCDIF VGLite” project included in the software accompanying this application note shows you how to use the Index8Bppcolor format on one layer and VGLite on another layer.For layer 0, we will have a single 720x720 Index8BPP buffer. For layer 1, we will create two 416x416 ARGB8888 framebuffers.Figure 37. LCDIF VGLite project layer configurationi.MX RT1170 Heterogeneous Graphics Pipeline, Rev. 0, 12/2020Application Note27 / 36

NXP SemiconductorsLCDIFV2 display controllerThe InitLCDIFV2 function will configure the layers as shown in the image above. One important consideration here is that weadded a blend configuration so that layer 1 can be blended with layer 0 in the final step.const lcdifv2 blend config t blendConfig0 {.globalAlpha 255,.alphaMode kLCDIFV2 AlphaEmbedded,};const lcdifv2 blend config t blendConfig1 {.globalAlpha 255,.alphaMode kLCDIFV2 AlphaEmbedded,};The kLCDIFV2 AlphaEmbedded mode uses the alpha on the image to blend the images.The color lookup table is copied to the layer 0 configuration using the following function:LCDIFV2 SetLut(LCDIFV2, 0, Dial720Indexed8bpp CLUT, 255, false);Layer 1 buffers are wrapped by vg lite buffer t structures. In this way, we will be able to render to those buffers.renderTarget[0].width APP LAYER1 WIDTH;renderTarget[0].height APP LAYER1 HEIGHT;renderTarget[0].stride APP LAYER1 WIDTH*4;renderTarget[0].format VG LITE BGRA8888;renderTarget[0].memory (void *)vgLiteFrameBuffers[0];renderTarget[0].address (uint32 t)vgLiteFrameBuffers[0];renderTarget[1].width APP LAYER1 WIDTH;renderTarget[1].height APP LAYER1 HEIGHT;renderTarget[1].stride

vg_lite_draw(rt, &pPath, VG_LITE_FILL_NON_ZERO, &matrix, VG_LITE_BLEND_NONE, 0xFF000000); The inner hole in the path will not be considered: Figure 7. Fill rule VG_LITE_FILL_NON_ZERO causes the P path to be completely filled. 2.1.1.3 Transformation. Transformation is a powerful feature of the GPU. It allows you to define a 3x3 matrix for 2D .