screen capture not working with etnaviv on Android

Martin Fuzzey martin.fuzzey at flowbird.group
Fri Jan 17 18:35:45 UTC 2020


Hi,

when using etnaviv (mesa 19.3.2) on Android 8.1 (on i.MX6DL GC880) the 
screencap program generates empty files.
The issue appears to be that the render resources are not being flushed.
I have made it work (see below) but am not confident enough of the 
solution to propose it as a patch.


The screencap program (command line utility) creates the buffer to be 
filled from gralloc and passes it to surfaceflinger.

Surfaceflinger imports the buffer by doing eglCreateImageKHR() which 
ends up doing
droid_create_image_from_prime_fds() then etna_resource_from_handle()

That is bound to as a framebuffer with
     glGenTextures()
     glBindTexture()
     glEGLImageTargetTexture2DOES()
     glGenFramebuffers()
     glBindFramebuffer()

The screen is then rendered by surface flinger to that framebuffer

Finally a eglCreateSyncKHR() is done, followed by a glFlush()

Optionally (in debugging mode only) glReadPixels() is called.

[See 
http://androidxref.com/8.1.0_r33/s?refs=captureScreenImplLocked&project=frameworks 
for the real code]

When the glReadPixels() is done the buffer is filled with all zeros.

The following patch fixes that:

--- a/src/gallium/drivers/etnaviv/etnaviv_transfer.c
+++ b/src/gallium/drivers/etnaviv/etnaviv_transfer.c
@@ -367,6 +367,10 @@ etna_transfer_map(struct pipe_context *pctx, struct 
pipe_resource *prsc,
     if (trans->rsc || !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
        uint32_t prep_flags = 0;

+
+      if (usage & PIPE_TRANSFER_READ)
+         pctx->flush_resource(pctx, prsc);
+

This is also enough, when the glReadPixels() is called in debug mode, 
for the transfer to the client process to work.
However, without the glReadPixels() the capture does not work even with 
the patch, which is logical since the buffer is not mapped in that case.

I can make the normal case work too by making glFlush() flush the 
resources with this:

--- a/src/mesa/state_tracker/st_cb_flush.c
+++ b/src/mesa/state_tracker/st_cb_flush.c
@@ -52,6 +52,8 @@ st_flush(struct st_context *st,
           struct pipe_fence_handle **fence,
           unsigned flags)
  {
+   struct gl_framebuffer *fb = st->ctx->DrawBuffer;
+
     st_flush_bitmap_cache(st);

     /* We want to call this function periodically.
@@ -59,6 +61,21 @@ st_flush(struct st_context *st,
      */
     st_context_free_zombie_objects(st);

+   /* Flush any texture resources. Needed on etnaviv for screenshots */
+   if (fb) {
+      GLuint i;
+
+      for (i = 0; i < BUFFER_COUNT; i++) {
+         struct gl_renderbuffer_attachment *att = fb->Attachment + i;
+         struct gl_renderbuffer *rb = att->Renderbuffer;
+         struct st_renderbuffer *strb = st_renderbuffer(rb);
+
+         if (strb && strb->texture) {
+            st->pipe->flush_resource(st->pipe, strb->texture);
+         }
+      }
+   }
+
     st->pipe->flush(st->pipe, fence, flags);
  }


However I'm not sure this is the right way to fix this, expecially for 
the the second patch which modifies core code.

Any ideas?

Regards,

Martin


More information about the etnaviv mailing list