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