Direct framebuffer access

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Direct framebuffer access

      Hi,

      I already posted a similar question to the stemwin forum but so far without result.
      I have a board with an external controller connected via an 8bit bus to my cpu, and my pixels are 16bit 565 format.
      Relevant calls setting this up:
      GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565 , 0, 0);
      GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66709 , GUIDRV_FLEXCOLOR_M16C0B8 )

      I am looking for a way to write raw image data (565 format) directly into the emwin framebuffer (which i assume is raw 565 too, when created with (?) ).

      Looking at the documentation and other forum posts i can only find indirect ways to get my data in there (untested):
      - I can create a memory device, get its data area (GUI_MEMDEV_GetDataPtr), write directly in there and then write the memory device to the frame buffer (GUI_MEMDEV_CopyToLCDAt) (probably this will work in chunks smaller than the full display).

      - I can use a GUI_BITMAP with pMethods = GUI_DRAW_BMP565 and fill its associated pData buffer (chunk or entire screen) with my data, then use GUI_DrawBitmap to transfer the buffer to the frame buffer. (note sure that GUI_DRAW_BMP565 is really raw565 or requires some bmp file formatting)

      Both ways are conceptually similar but require using an intermediate buffer and extra copy operation.
      I would like to skip this step and write directly into the framebuffer.

      But I can't find a way to query where that buffer is located exactly (am equivalent of GUI_MEMDEV_GetDataPtr)...
      What am I missing ?

      According to the reply to Direct LCD frame buffer access when using STemWin? direct framebuffer access should be possible somehow ?

      Regards
      Bram
    • Hi Bram,

      You are using a driver for an external LCD controller. Please note that there is no Framebuffer on emWin side. Using such a driver writes the data directly to the LCD controller.

      You could use a cache which is like a mirror of the RAM on the LCD controller by using the following as last paramter when calling GUIDRV_FlexColor_SetFunc():
      GUIDRV_FLEXCOLOR_M16C1B8

      With a cache emWin allocates a memory block to hold the complete screen data (xSize * ySize * Bytes per pixel). Unfortunately, it is not possible to access this memory directly.

      If you were using the GUIDRV_Lin driver it would be possible to acces the framebuffer directly because it is located on the MCU and gets not allocated by emWin.

      Regards,
      Sven
    • Hi Sven,

      Ok that is super interesting to know :), thank you.

      So that means Emwin is not 'aware' of what is currently visible on the screen ?
      And if i write eg some text on the screen, it will *only* transfer the pixels of the text ?
      I would have expected that it would overlay the text on the current background in a buffer, and then send the result to the LCD controller, or maybe a 'dirty' partial rectangular area or something .

      Anyway, that also means i can write my raw image directly to the LCD controller bypassing Emwin, and then put some text over it using Emwin functions and the result will be my raw image pixels with some pixels replaced by the text pixels ?

      Thanks,
      Bram
    • Hi,


      BramPeeters wrote:

      So that means Emwin is not 'aware' of what is currently visible on the screen ?
      emWin can read the data from LCD controller via the interface (e.g. SPI). Read functions have to be set when using no cache. If you are using a cache emWin has a copy of the LCD controllers RAM and doesn't need to read through the interface.


      BramPeeters wrote:

      And if i write eg some text on the screen, it will *only* transfer the pixels of the text ?
      emWin will transfer a rectangular area defined by the top left and bottom right pixel of a changed area. When pixel (10|10) and pixel (100|15) changing, emWin will send the complete rectangle defined by those pixels.


      BramPeeters wrote:

      I would have expected that it would overlay the text on the current background in a buffer, and then send the result to the LCD controller, or maybe a 'dirty' partial rectangular area or something .
      Thats how it's done. Either the data are read through the interface or taken from the cache.

      BramPeeters wrote:

      Anyway, that also means i can write my raw image directly to the LCD controller bypassing Emwin, and then put some text over it using Emwin functions and the result will be my raw image pixels with some pixels replaced by the text pixels ?
      This should work as long as you don't use a cache. If you bypass emWin and write directly to the RAM of the LCD controller emWin will read the data from the RAM when it comes to a drawing and will "know" about the bypassed data.

      If you use a cache emWin doesn't expect the bypassed data in the LCD controller RAM (it expects the RAM data are the same as those in the cache) and might overwrite it with data from the cache.

      Regards,
      Sven
    • Hi,

      Ok, thanks for the super clear & spot on explanation.
      It even answers one of the questions i had not asked yet, what is the advantage of using the cache :).

      My ideal scenario would be then to have a cache I can write into but sadly that is not option then :/.
      I will evaluate the speed of the other options then (cache + GUI_MEMDEV/cache + GUI_BITMAP/ no cache and readbacks) and pick what works best for me.

      Have a nice weekend !
      Bram
    • And thinking around the box about my getting to my 'ideal' scenario a bit more: does emwin 'leak' the cache location towards the lower level functions ?
      Eg if i would trigger a write of the entire screen by filling it with a color will he pass a buffer with the start address of the cache to the low level drivers ?
      And is the location of that cache constant or does it get relocated under certain circumstances.
      (I understand that this is totally dirty & bad and Segger is not responsible if a black hole opens and swallows earth as a result, but the device wont be used at Cern (I think) :P)
    • New

      And another realisation: If emwin does now work with a framebuffer, does this mean then when working with a memdev and caching not enabled, a GUI_MEMDEV_CopyToLCD command will do a direct write from the memdev memory area to the display (so no intermediate copy).
      Because that would be the perfect solution then (I think) ?
    • New

      Hi,


      BramPeeters wrote:

      It even answers one of the questions i had not asked yet, what is the advantage of using the cache :).
      You can avoid flickering effects and suppress a visual build up of the screen. By calling LCD_ControlCache(LCD_CC_LOCK) any drawing operations will be performed into the cache. When the last drawing is performed LCD_ControlCache(LCD_CC_UNLOCK) unlocks and flushes the cache. A flush causes the cache (actually only the dirty rect) to be send at once to the LCD controller. When using the Window Manager the lock/unlock gets done automatically.


      A cache might also increase the performance because it reduces the overhead when writing to the LCD controller. For example, drawing a row pixel by pixel with GUI_DrawPixel() will cause emWin to send a bunch of commands and data for every pixel (drawing a line pixel by pixel is never a good idea, but its just an example). If you do a lock before and unlock after, emWin will send commands for setting a rect on LCD controller only once and send all the data at once.



      BramPeeters wrote:

      Eg if i would trigger a write of the entire screen by filling it with a color will he pass a buffer with the start address of the cache to the low level drivers ?
      Unfortunately, not. the hardware routines called by emWin only receive the pure data.

      But the location should be constant as long as you do not call GUI_Exit() or delete the driver device.


      BramPeeters wrote:

      And another realisation: If emwin does now work with a framebuffer, does this mean then when working with a memdev and caching not enabled, a GUI_MEMDEV_CopyToLCD command will do a direct write from the memdev memory area to the display (so no intermediate copy).

      If you draw into a memory device (not using a cache) and draw the memory to the screen it gets send to the LCD controller at once. If you like you could use a memory device as some sort of framebuffer.

      If I get you right you want to write the raw pixel data of a bitmap directly to the LCD.
      Which format has the image?

      You could also generate a emWin bitmap in the RAM and draw this just as a bitmap with GUI_DrawBitmap(), just like this:

      C Source Code

      1. void MainTask(void) {
      2. GUI_BITMAP Bitmap;
      3. GUI_Init();
      4. Bitmap.BitsPerPixel = 16;
      5. Bitmap.XSize = 50;
      6. Bitmap.YSize = 50;
      7. Bitmap.BytesPerLine = Bitmap.XSize * Bitmap.BitsPerPixel / 8;
      8. Bitmap.pMethods = GUI_DRAW_BMPM565; // This 16bpp RGB, could also be GUI_DRAW_BMP565 which is 16bpp BGR or use any other format
      9. Bitmap.pPal = NULL; // No palette
      10. Bitmap.pData = (unsigned char *)pPointerToImageData; // A pointer to your raw image data
      11. GUI_DrawBitmap(&Bitmap, 0, 0); // Simply draw the image
      12. while (1) {
      13. GUI_Delay(100);
      14. }
      15. }
      Display All
      Regards,

      Sven
    • New

      Hi,


      Unfortunately, not. the hardware routines called by emWin only receive the pure data.
      Yes, but as far as I understand emwin transfers that data to the LCD controller using the GUI_PORT_API.pfWriteM8_A1 function.
      This function takes a pointer and a number of elements as arguments.
      And I would expect that this pointer argument points directly inside the cache region ? So if I write (or simulate to write) the entire screen, the lowest address given to me via this callback function will be the start of the cache region....


      But based on your feedback I think the memdev approach will be the best way of working for my scenario.

      I have raw (meaning already in a 565 format that corresponds the data that needs to be send to the LCD) 'template' images sitting in an external flash ( currently, but could be from other sources eg network) that I would like to immediately read out in the right location (= the "framebuffer", not yet the LCD controller ).
      Then some modifications need to happen on top of the template (eg add some text), and then the result needs to be transmitted to the lcd.

      The memdev approach will allow this with only 1 buffer (i am memory constrained but i have budget-ed in 1 such buffer), no extra copy operations, and no 'readbacks' from the LCD. (It's nice to know that If i ever need the extra memory it is possible to drop the display buffer at the cost of the readbacks)

      The Bitmap approach seems very similar but I don't think i can 'draw' on the bitmap using emwin functions to modify the image ?

      Edit: one thing missing with the memdev approach is that you don't have any control over the alignment of the buffer afaik (needed for certain memory operations)

      Thanks,
      Bram

      The post was edited 1 time, last by BramPeeters ().

    • New

      Hi,


      BramPeeters wrote:

      And I would expect that this pointer argument points directly inside the cache region ?
      Indeed, you are right. It should work if you store the address of the pointer passed to the function for writing multiple data bytes (e.g. the member pfWriteM16_A1 of GUI_PORT_API structure).

      You could also do the following, although I don't recommend it. I can't guarantee that it doesn't cause any bad behavior.

      C Source Code

      1. #include "GUIDRV_FlexColor_Private.h"
      2. void MainTask(void {
      3. U16 * pFrameBuffer;
      4. DRIVER_CONTEXT * pContext;
      5. GUI_DEVICE * pDevice;
      6. GUI_Init();
      7. Index = 0;
      8. pDevice = GUI_DEVICE__GetpDriver(0);
      9. pFrameBuffer = ((DRIVER_CONTEXT *)pDevice->u.pContext)->pVRAM;
      10. ...
      11. }
      Display All



      BramPeeters wrote:

      The Bitmap approach seems very similar but I don't think i can 'draw' on the bitmap using emwin functions to modify the image ?
      No, you can't write into any memory with emWin. Only into memory devices or any other device (e.g. through a driver device into the framebuffer or directly to the LCD controller memory).


      BramPeeters wrote:

      one thing missing with the memdev approach is that you don't have any control over the alignment of the buffer afaik (needed for certain memory operations)
      You don't have influence on the memory alignment through emWin.

      Regards,
      Sven