Android: segfault rendering mouse cursor

Martin Fuzzey martin.fuzzey at flowbird.group
Mon Jul 23 14:42:40 UTC 2018


Hi,

on Android 8.1, etnaviv, gbm-gralloc, i.MX6 I get a segfault in input 
flinger when using a mouse.

This is because input flinger uses software rendering to draw the mouse 
pointer like this [frameworks/base/libs/input/SpriteController.cpp]

                 sp<Surface> surface = 
update.state.surfaceControl->getSurface();
                 ANativeWindow_Buffer outBuffer;
                 status_t status = surface->lock(&outBuffer, NULL);

                 SkBitmap surfaceBitmap;
                 ssize_t bpr = outBuffer.stride * 
bytesPerPixel(outBuffer.format);
#if 0
                 int hacked_stride = 32;
                 ALOGI("@MF@ hacking stride %d=>%d", outBuffer.stride, 
hacked_stride);
                 bpr = hacked_stride * bytesPerPixel(outBuffer.format);
#endif

surfaceBitmap.installPixels(SkImageInfo::MakeN32Premul(outBuffer.width, 
outBuffer.height),
                                             outBuffer.bits, bpr);
                 SkCanvas surfaceCanvas(surfaceBitmap);

                 ... (drawing code omitted)

                 status = surface->unlockAndPost();


Where surface is 29x37 pixels

The problem is that etnaviv allocates a tiled buffer with a stride of 
256 bytes (64 pixels).

This stride is obtained from gralloc.


However when the buffer is mapped for software rendering a linear mapped 
transfer buffer of a stride of 128 bytes (32 pixels) is allocated and 
mapped.

So, when the software renderer uses the stride obtained from gralloc to 
write into the locked buffer an overflow occurs, usually resulting in a 
segfault.


Activating the hack in #ifdef above (which changes the stride from 64 to 
32 pixels) makes it work but is obviously not the right solution.


The fundemental problem here seems to be that Android requires the 
stride to be returned during the buffer *allocation* whereas, when the 
internal and transfer buffers can have different geometries as for 
etnaviv, we really want to get the stride from the lock / map operation. 
Unfortunately we can't change the Android API here...


I also tried modifying gralloc to "lie" about the stride (just for 
buffers the size of the mouse pointer as a test).

But that causes "BO stride 128 is too small for RS engine width padding 
(256, format PIPE_FORMAT_R8G8B8A8_UNORM)"


The only way I can think of fixing this would be to artificially 
increase the stride of the transfer buffer to match that of the tiled 
buffer.

Of course that would waste some memory.


Regards,

Martin




More information about the etnaviv mailing list