=== modified file 'src/composite-canvas-xrender.cc'
@@ -30,8 +30,6 @@
#include "options.h"
#include "log.h"
-#include <sys/shm.h>
-
CompositeCanvasXRender::~CompositeCanvasXRender()
{
release_resources();
@@ -56,14 +54,92 @@
}
bool
+CompositeCanvasXRender::have_xdbe()
+{
+ int major, minor;
+ bool have_xdbe = false;
+
+ /* Check for the Xdbe extension */
+ if (XdbeQueryExtension(xdpy_, &major, &minor)) {
+ Log::debug("Xdbe extension version %d.%d\n", major, minor);
+ have_xdbe = true;
+ }
+ else {
+ Log::info("** Xdbe extension not supported. You may experience flickering.\n");
+ }
+
+ return have_xdbe;
+}
+
+bool
+CompositeCanvasXRender::ensure_xdbe_back_buffer()
+{
+ XdbeScreenVisualInfo *xdbe_screen_vis_info;
+ XWindowAttributes canvas_attr;
+ int num_screens = 1;
+ bool dbe_visual_found = false;
+
+ if (xdbe_back_buffer_)
+ return true;
+
+ if (!have_xdbe())
+ return false;
+
+ /* Check if the canvas visual supports double-buffering */
+ if (!XGetWindowAttributes(xdpy_, canvas_, &canvas_attr)) {
+ Log::error("XGetWindowAttributes failed!\n");
+ return false;
+ }
+
+ xdbe_screen_vis_info = XdbeGetVisualInfo(xdpy_, &canvas_, &num_screens);
+ if (!xdbe_screen_vis_info || num_screens == 0) {
+ Log::error("XdbeGetVisualInfo failed!\n");
+ return false;
+ }
+
+ for (int i = 0; i < xdbe_screen_vis_info[0].count; i++) {
+ XdbeVisualInfo *vis_info = &xdbe_screen_vis_info[0].visinfo[i];
+ if (vis_info->visual == XVisualIDFromVisual(canvas_attr.visual)) {
+ dbe_visual_found = true;
+ break;
+ }
+ }
+
+ XdbeFreeVisualInfo(xdbe_screen_vis_info);
+
+ if (!dbe_visual_found) {
+ Log::info("** The window visual does not support double buffering."
+ " You may experience flickering!\n");
+ return false;
+ }
+
+ /* Allocate the back buffer */
+ xdbe_back_buffer_ = XdbeAllocateBackBufferName(xdpy_, canvas_,
+ XdbeBackground);
+ if (!xdbe_back_buffer_) {
+ Log::error("XdbeAllocateBufferName failed!\n");
+ return false;
+ }
+
+ return true;
+}
+
+bool
CompositeCanvasXRender::ensure_xrender_picture()
{
+ Drawable drawable;
+
if (xrender_picture_)
return true;
if (!have_xrender())
return false;
+ if (!ensure_xdbe_back_buffer())
+ drawable = canvas_;
+ else
+ drawable = xdbe_back_buffer_;
+
XWindowAttributes canvas_attr;
if (!XGetWindowAttributes(xdpy_, canvas_, &canvas_attr)) {
@@ -81,7 +157,7 @@
return false;
}
- xrender_picture_ = XRenderCreatePicture(xdpy_, canvas_, pict_format,
+ xrender_picture_ = XRenderCreatePicture(xdpy_, drawable, pict_format,
0, NULL);
if (!xrender_picture_) {
Log::error("XRenderCreatePicture failed!\n");
@@ -132,7 +208,11 @@
if (xrender_picture_)
XRenderFreePicture(xdpy_, xrender_picture_);
+ if (xdbe_back_buffer_)
+ XdbeDeallocateBackBufferName(xdpy_, xdbe_back_buffer_);
+
xrender_picture_ = 0;
+ xdbe_back_buffer_ = 0;
}
CompositeWindow *
@@ -144,6 +224,10 @@
void
CompositeCanvasXRender::update_screen()
{
+ if (xdbe_back_buffer_) {
+ XdbeSwapInfo swap_info = {canvas_, XdbeBackground};
+ XdbeSwapBuffers(xdpy_, &swap_info, 1);
+ }
}
std::string
=== modified file 'src/composite-canvas-xrender.h'
@@ -29,12 +29,14 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/Xrender.h>
+#include <X11/extensions/Xdbe.h>
class CompositeCanvasXRender: public CompositeCanvas
{
public:
CompositeCanvasXRender() :
- CompositeCanvas("xrender"), xrender_picture_(0) {}
+ CompositeCanvas("xrender"), xrender_picture_(0), xdbe_back_buffer_(0)
+ {}
virtual ~CompositeCanvasXRender();
@@ -50,10 +52,13 @@
void reshape(int width, int height);
private:
+ bool have_xdbe();
+ bool have_xrender();
+ bool ensure_xdbe_back_buffer();
bool ensure_xrender_picture();
- bool have_xrender();
Picture xrender_picture_;
+ XdbeBackBuffer xdbe_back_buffer_;
};
#endif /* COMPOSITE_CANVAS_XRENDER_H_ */