paulslocum
Posts: 69
Joined: Sun Apr 09, 2017 10:54 pm

How to achieve Dispmanx supersampling with sprites?

Sun Apr 22, 2018 10:12 am

I'm trying to move a sprite from a PNG around the screen with 2X supersampling. I need to be able to position a spite half-way between pixels for smoother movement.

It's pretty easy to achieve supersampling just by scaling down the destination rectangle of a Dispmanx double buffer, but then it's unclear how to blit a sprite into the Dispmanx resource/buffer? (the example code I'm using is linked below) If I use vc_dispmanx_resource_write_data() to copy the PNG data into the buffer, then it doesn't blit correctly unless the destination Dispmanx buffer is the same width as the image. And there's still no way I see to blit the image into the buffer at an X/Y offset.

Is there some better way to do this? I'm wondering if I should use the Dispmanx offscreen display and snapshot features to achieve this? Or maybe just write my own blit routine that allows for X and Y offsets?

This is the Dispmanx double-buffer example I've been using::
https://github.com/AndrewFromMelbourne/ ... ster/worms

User avatar
AndyD
Posts: 2321
Joined: Sat Jan 21, 2012 8:13 am
Location: Melbourne, Australia
Contact: Website

Re: How to achieve Dispmanx supersampling with sprites?

Sun Apr 29, 2018 12:41 am

I haven't tried to do this myself. When you specify the source rectangle for an element, the x and y offset and the width and height are specified as 16.16 fixed point 32 bit integers. You could try and add an element and change the source rectangle with fractional x and y offsets. Have a look at scrollingLayer.c to see how to dynamically change the source rectangle.

Hope that helps,

Andrew

paulslocum
Posts: 69
Joined: Sun Apr 09, 2017 10:54 pm

Re: How to achieve Dispmanx supersampling with sprites?

Sun Apr 29, 2018 2:33 pm

I'm a bit confused about where you're getting that the rectangle is a fixed point fractional integer. That does not seem to be the case from my use of the Dispmanx functions. VC_RECT_T is defined as:

Code: Select all

/* We have so many rectangle types; let's try to introduce a common one. */
typedef struct tag_VC_RECT_T {
   int32_t x;
   int32_t y;
   int32_t width;
   int32_t height;
} VC_RECT_T;
https://github.com/raspberrypi/userland ... ge_types.h

User avatar
Paeryn
Posts: 1897
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: How to achieve Dispmanx supersampling with sprites?

Sun Apr 29, 2018 3:16 pm

The source rectangle passed to vc_dispmanx_element_add() or vc_dispmanx_element_change_attributes() is definitely in 16.16 fixed point format. Taken from my function for computing the rectangles which allows an arbitrary rectangle of a surface to be mapped to a rectangle on the display, I use it to crop OpenVG surfaces so only part of the image is shown.

Code: Select all

	vc_dispmanx_rect_set(dst_rect, dx, dy, w, h);
	vc_dispmanx_rect_set(src_rect, sx << 16, sy << 16, w << 16, h << 16);
She who travels light — forgot something.

paulslocum
Posts: 69
Joined: Sun Apr 09, 2017 10:54 pm

Re: How to achieve Dispmanx supersampling with sprites?

Sun Apr 29, 2018 3:58 pm

Oh yeah, you're right, I didn't even catch that in the example code I started with. Yet the destination rect is not. Ultimately I gave up on using Dispmanx directly partly just because it doesn't have much documentation, and the capabilities are pretty limited.

I ended up using OpenVG to draw into a double-sized Dispmanx layer which was then scaled to half-size on screen. The only problem was that I couldn't find any example or library that would load transparent PNGs into OpenVG, so I'll share a rough code snippet in case it helps someone (it's missing cleanup, but should get you started. The resize isn't necessary.):

Code: Select all

   
  FIBITMAP *dibOriginal = FreeImage_Load(FIF_PNG, textName, PNG_DEFAULT);
  FIBITMAP *dib = FreeImage_Rescale( dibOriginal, FreeImage_GetWidth(dibOriginal)*1.6, FreeImage_GetHeight(dibOriginal)*1.6, FILTER_BICUBIC );
  VGImageFormat rgbaFormat = VG_sABGR_8888; //VG_sRGBA_8888;
  unsigned int width = FreeImage_GetWidth(dib);
  unsigned int height = FreeImage_GetHeight(dib);
  unsigned int stride = FreeImage_GetPitch(dib);
  VGImage img = vgCreateImage( rgbaFormat, width, height, VG_IMAGE_QUALITY_BETTER );
  VGubyte *data = FreeImage_GetBits(dib);
  vgImageSubData( img, data, stride, rgbaFormat, 0, 0, width, height );
  vgSetPixels( clockX, WINDOW_HEIGHT-clockY, img, 0, 0, width, height );

Return to “Graphics programming”

Who is online

Users browsing this forum: No registered users and 1 guest