After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 669065 - ShellScreenGrabber: grab the screen using pixel buffers
ShellScreenGrabber: grab the screen using pixel buffers
Status: RESOLVED FIXED
Product: gnome-shell
Classification: Core
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: gnome-shell-maint
gnome-shell-maint
Depends on:
Blocks:
 
 
Reported: 2012-01-30 21:52 UTC by Owen Taylor
Modified: 2012-04-05 13:13 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
ShellScreenGrabber: grab the screen using pixel buffers (16.32 KB, patch)
2012-01-30 21:52 UTC, Owen Taylor
needs-work Details | Review
ShellScreenGrabber: grab the screen using pixel buffers (16.67 KB, patch)
2012-01-31 15:29 UTC, Owen Taylor
committed Details | Review
Test case for timing glReadPixels (1.67 KB, text/x-c)
2012-02-26 02:35 UTC, Neil Roberts
  Details

Description Owen Taylor 2012-01-30 21:52:03 UTC
This patch is obviously a workaround for the Intel Mesa code in that the
Intel Mesa code could do the same thing internally; still, I think we probably
should land it here since it makes a difference between the screen recorder
working at all and not working, and screenshotting being instantaneous or
having a noticable delay.
Comment 1 Owen Taylor 2012-01-30 21:52:05 UTC
Created attachment 206473 [details] [review]
ShellScreenGrabber: grab the screen using pixel buffers

For the Intel drivers, using glReadPixels() to read into client-memory
directly from the frame buffer is much slower than creating a pixel
buffer, copying into that, and then mapping that for reading. On other
drivers, the two approaches are likely to be similar in speed. Create
a ShellScreenGrabber abstraction that uses pixel buffers if available.
Use that for screenshots and screen recording.
Comment 2 drago01 2012-01-31 09:37:13 UTC
Review of attachment 206473 [details] [review]:

Looks good to me and provides a *significant* speed boost on my GM45 based laptop (when recording).
The usage of pack_invert without checking breaks NVIDIA (and possibly fglrx) though.

::: src/shell-screen-grabber.c
@@ +133,3 @@
+      glPixelStorei (GL_PACK_SKIP_ROWS, 0);
+      glPixelStorei (GL_PACK_ALIGNMENT, 1);
+      glPixelStorei (GL_PACK_ALIGNMENT, 1);

You are setting this one twice.

@@ +134,3 @@
+      glPixelStorei (GL_PACK_ALIGNMENT, 1);
+      glPixelStorei (GL_PACK_ALIGNMENT, 1);
+      glPixelStorei (GL_PACK_INVERT_MESA, FALSE);

Should be GL_FALSE (both have the same value but still).
What is more important though you should check whether the GL_MESA_pack_invert is supported at all.
NVIDIA does not support it resulting into tons of:
Cogl-WARNING **: ./cogl-buffer.c:358: GL error (1280): Invalid enumeration value
Comment 3 drago01 2012-01-31 11:29:58 UTC
(In reply to comment #2)
> Review of attachment 206473 [details] [review]:
> 
> Looks good to me and provides a *significant* speed boost on my GM45 based
> laptop (when recording).
> The usage of pack_invert without checking breaks NVIDIA (and possibly fglrx)
> though.

Well "breaks" it just floods warning but the recording actually works.
Comment 4 Owen Taylor 2012-01-31 15:29:55 UTC
Created attachment 206525 [details] [review]
ShellScreenGrabber: grab the screen using pixel buffers

With fixes - thanks for the review.
Comment 5 drago01 2012-01-31 15:44:32 UTC
Review of attachment 206525 [details] [review]:

Looks good.
Comment 6 Owen Taylor 2012-01-31 15:48:26 UTC
Attachment 206525 [details] pushed as 4e89a5e - ShellScreenGrabber: grab the screen using pixel buffers
Comment 7 Neil Roberts 2012-02-26 02:35:33 UTC
Created attachment 208430 [details]
Test case for timing glReadPixels

For what it's worth, I had a quick look at trying to get Mesa to have a faster read pixels and I filed this bug here:

https://bugs.freedesktop.org/show_bug.cgi?id=46631

It looks like the fallback code in Mesa already has a fast path for the case where the format of the framebuffer and the destination buffer are the same so it can just do a memcpy. However it's over cautious with the format checking so it effectively wouldn't hit it unless you are using a floating point format to read into. The non-fast path case converts every pixel to an array of four floats and then does some floating point arithmetic to convert it back so it's no wonder it's slow.

I'm attaching a little standalone test case for timing glReadPixels. Without the patch and just using glReadPixels directly into normal memory it takes 10.319 seconds. With the patch it takes 0.832 seconds. If I change it to use a PBO with a map and memcpy to normal memory then it takes 0.805.

It seems kind of suprising that the blit/map/memcpy case is slightly faster because it implies copying the memory twice (although presumably the blit can be done faster than a memcpy). However both cases are very much in the same ballpark so I don't think it would be worthwhile using PBOs if we can use the fast path patch instead. It would be nice to try and avoid any direct GL usage in Gnome Shell because it is a layering violation. The more apps that do this the more limited we become with how we can change Cogl.
Comment 8 Neil Roberts 2012-04-05 13:13:56 UTC
You're probably fed up of me going on about the screen recorder by now, but just to let you know anyway, I've added a patch to Cogl to do the same workaround by reading into a temporary PBO when it detects it's running with Mesa on an Intel GPU. If Gnome Shell ever starts requiring a recent enough version of Cogl it might be worth dropping this patch to just let Cogl do it.

http://lists.freedesktop.org/archives/cogl/2012-April/000091.html