summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/cursor_channel.cpp8
-rw-r--r--client/gui/gui.cpp2
-rw-r--r--client/red_cairo_canvas.cpp2
-rw-r--r--client/red_pixmap_cairo.h2
-rw-r--r--client/screen.cpp2
-rw-r--r--client/windows/red_pixmap_cairo.cpp2
-rw-r--r--client/x11/pixels_source.cpp70
-rw-r--r--client/x11/pixels_source_p.h8
-rw-r--r--client/x11/red_drawable.cpp145
-rw-r--r--client/x11/red_pixmap_cairo.cpp186
-rw-r--r--client/x11/red_window.cpp1
11 files changed, 179 insertions, 249 deletions
diff --git a/client/cursor_channel.cpp b/client/cursor_channel.cpp
index 289c059f..db020a06 100644
--- a/client/cursor_channel.cpp
+++ b/client/cursor_channel.cpp
@@ -112,7 +112,7 @@ void UnsupportedCursor::draw(RedDrawable& dest, int x, int y, const SpiceRect& a
AlphaCursor::AlphaCursor(const SpiceCursorHeader& header, const uint8_t* data)
: _pixmap (new RedPixmapCairo(header.width, header.height,
- RedPixmap::ARGB32, true, NULL))
+ RedDrawable::ARGB32, true, NULL))
{
int stride = _pixmap->get_stride();
uint8_t* dest = _pixmap->get_data();
@@ -131,7 +131,7 @@ MonoCursor::MonoCursor(const SpiceCursorHeader& header, const uint8_t* data)
: _pixmap (NULL)
, _height (header.height)
{
- _pixmap.reset(new RedPixmapCairo(header.width, _height * 2, RedPixmap::A1,
+ _pixmap.reset(new RedPixmapCairo(header.width, _height * 2, RedDrawable::A1,
true, NULL));
int dest_stride = _pixmap->get_stride();
@@ -176,10 +176,10 @@ private:
ColorCursor::ColorCursor(const SpiceCursorHeader& header)
: _pixmap (new RedPixmapCairo(header.width, header.height,
- RedPixmap::ARGB32, true, NULL))
+ RedDrawable::ARGB32, true, NULL))
, _invers (NULL)
{
- _invers.reset(new RedPixmapCairo(header.width, header.height, RedPixmap::A1,
+ _invers.reset(new RedPixmapCairo(header.width, header.height, RedDrawable::A1,
true, NULL));
}
diff --git a/client/gui/gui.cpp b/client/gui/gui.cpp
index 30b864d3..3e0f257b 100644
--- a/client/gui/gui.cpp
+++ b/client/gui/gui.cpp
@@ -888,7 +888,7 @@ GUI::GUI(Application& app, Application::State state)
: ScreenLayer (SCREEN_LAYER_GUI, false)
, _app (app)
, _state (state)
- , _pixmap (new RedPixmapCairo(MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT, RedDrawable::RGB32, true, NULL))
+ , _pixmap (new RedPixmapCairo(MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT, RedDrawable::RGB32, true, 0))
, _renderer (new CEGUI::SoftRenderer(_pixmap->get_data(), MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT,
_pixmap->get_stride()))
, _gui_system (new CEGUI::System(_renderer, new CEGUIResourceProvider()))
diff --git a/client/red_cairo_canvas.cpp b/client/red_cairo_canvas.cpp
index 9338d9ff..b795acff 100644
--- a/client/red_cairo_canvas.cpp
+++ b/client/red_cairo_canvas.cpp
@@ -34,7 +34,7 @@ CCanvas::CCanvas(bool onscreen,
{
if (onscreen) {
_pixmap = new RedPixmapCairo(width, height,
- RedPixmap::format_from_surface(format),
+ RedDrawable::format_from_surface(format),
true, win);
_canvas = canvas_create_for_data(width, height, format,
_pixmap->get_data(),
diff --git a/client/red_pixmap_cairo.h b/client/red_pixmap_cairo.h
index 7f9523e8..7f285326 100644
--- a/client/red_pixmap_cairo.h
+++ b/client/red_pixmap_cairo.h
@@ -23,7 +23,7 @@
class RedPixmapCairo: public RedPixmap {
public:
- RedPixmapCairo(int width, int height, Format format, bool top_bottom, RedWindow *win);
+ RedPixmapCairo(int width, int height, Format format, bool top_bottom, RedWindow *window);
~RedPixmapCairo();
};
diff --git a/client/screen.cpp b/client/screen.cpp
index a1ce8886..c2bd4e71 100644
--- a/client/screen.cpp
+++ b/client/screen.cpp
@@ -172,7 +172,7 @@ void RedScreen::create_composit_area()
{
destroy_composit_area();
_composit_area = new RedPixmapCairo(_size.x, _size.y, _window.get_format(),
- false, -1);
+ false, &_window);
}
void RedScreen::adjust_window_rect(int x, int y)
diff --git a/client/windows/red_pixmap_cairo.cpp b/client/windows/red_pixmap_cairo.cpp
index 35fe89b8..aa4e5cba 100644
--- a/client/windows/red_pixmap_cairo.cpp
+++ b/client/windows/red_pixmap_cairo.cpp
@@ -29,7 +29,7 @@ struct RedPixmap_p {
HBITMAP prev_bitmap;
};
-RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
+RedPixmapCairo::RedPixmapCairo(int width, int height, RedDrawable::Format format,
bool top_bottom, RedWindow *win)
: RedPixmap(width, height, format, top_bottom)
{
diff --git a/client/x11/pixels_source.cpp b/client/x11/pixels_source.cpp
index 0ec39bdf..a2d49f39 100644
--- a/client/x11/pixels_source.cpp
+++ b/client/x11/pixels_source.cpp
@@ -24,50 +24,28 @@
#include "res.h"
-static void create_image(const PixmapHeader* pixmap, PixelsSource_p& pixels_source,
+static void create_pixmap(const PixmapHeader* pixmap, PixelsSource_p& pixels_source,
pixman_format_code_t format)
{
pixman_image_t *pixman_image;
- XImage *image = new XImage;
-
- memset(image, 0, sizeof(*image));
- image->width = pixmap->width;
- image->height = pixmap->height;
-
- image->data = (char*)pixmap->data;
- image->byte_order = LSBFirst;
- image->bitmap_unit = 32;
- image->bitmap_bit_order = LSBFirst;
- image->bitmap_pad = 32;
- image->bytes_per_line = pixmap->stride;
-
- image->depth = XPlatform::get_vinfo()[0]->depth;
- image->format = ZPixmap;
- image->bits_per_pixel = 32;
- image->red_mask = 0x00ff0000;
- image->green_mask = 0x0000ff00;
- image->blue_mask = 0x000000ff;
-
- try {
- if (!XInitImage(image)) {
- THROW("init image failed");
- }
-
- pixman_image = pixman_image_create_bits(format,
- pixmap->width, pixmap->height,
- (uint32_t *)pixmap->data,
- pixmap->stride);
- if (pixman_image == NULL) {
- THROW("surf create failed");
- }
- } catch (...) {
- delete image;
- throw;
+
+ pixman_image = pixman_image_create_bits(format,
+ pixmap->width, pixmap->height,
+ (uint32_t *)pixmap->data,
+ pixmap->stride);
+ if (pixman_image == NULL) {
+ THROW("surf create failed");
}
pixels_source.type = PIXELS_SOURCE_TYPE_PIXMAP;
- pixels_source.pixmap.x_image = image;
pixels_source.pixmap.pixman_image = pixman_image;
+ pixels_source.pixmap.x_image = NULL;
+ pixels_source.pixmap.shminfo = NULL;
+ if (format == PIXMAN_a8r8g8b8) {
+ pixels_source.pixmap.format = RedDrawable::ARGB32;
+ } else {
+ pixels_source.pixmap.format = RedDrawable::RGB32;
+ }
}
PixelsSource::PixelsSource()
@@ -86,21 +64,20 @@ ImageFromRes::ImageFromRes(int res_id)
if (!pixmap) {
THROW("no image %d", res_id);
}
- create_image(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_x8r8g8b8);
+ create_pixmap(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_x8r8g8b8);
}
ImageFromRes::~ImageFromRes()
{
pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
- delete ((PixelsSource_p*)get_opaque())->pixmap.x_image;
}
SpicePoint ImageFromRes::get_size()
{
- XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image;
+ pixman_image_t *image = ((PixelsSource_p*)get_opaque())->pixmap.pixman_image;
SpicePoint pt;
- pt.x = image->width;
- pt.y = image->height;
+ pt.x = pixman_image_get_width(image);
+ pt.y = pixman_image_get_height(image);
return pt;
}
@@ -110,21 +87,20 @@ AlphaImageFromRes::AlphaImageFromRes(int res_id)
if (!pixmap) {
THROW("no image %d", res_id);
}
- create_image(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_a8r8g8b8);
+ create_pixmap(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_a8r8g8b8);
}
AlphaImageFromRes::~AlphaImageFromRes()
{
pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
- delete ((PixelsSource_p*)get_opaque())->pixmap.x_image;
}
SpicePoint AlphaImageFromRes::get_size()
{
- XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image;
+ pixman_image_t *image = ((PixelsSource_p*)get_opaque())->pixmap.pixman_image;
SpicePoint pt;
- pt.x = image->width;
- pt.y = image->height;
+ pt.x = pixman_image_get_width(image);
+ pt.y = pixman_image_get_height(image);
return pt;
}
diff --git a/client/x11/pixels_source_p.h b/client/x11/pixels_source_p.h
index 050c19a6..a3e4cfbc 100644
--- a/client/x11/pixels_source_p.h
+++ b/client/x11/pixels_source_p.h
@@ -28,7 +28,6 @@
enum {
PIXELS_SOURCE_TYPE_INVALID,
PIXELS_SOURCE_TYPE_X_DRAWABLE,
- PIXELS_SOURCE_TYPE_XSHM_DRAWABLE,
PIXELS_SOURCE_TYPE_PIXMAP,
PIXELS_SOURCE_TYPE_GL_TEXTURE,
PIXELS_SOURCE_TYPE_GL_DRAWABLE,
@@ -39,6 +38,7 @@ struct PixelsSource_p {
union {
struct {
Drawable drawable;
+ int screen;
GC gc;
int width, height;
RenderType rendertype;
@@ -53,11 +53,7 @@ struct PixelsSource_p {
XImage* x_image;
XShmSegmentInfo *shminfo;
pixman_image_t* pixman_image;
- } x_shm_drawable;
-
- struct {
- XImage* x_image;
- pixman_image_t* pixman_image;
+ RedDrawable::Format format;
} pixmap;
struct {
diff --git a/client/x11/red_drawable.cpp b/client/x11/red_drawable.cpp
index 94ae523a..32754da9 100644
--- a/client/x11/red_drawable.cpp
+++ b/client/x11/red_drawable.cpp
@@ -111,11 +111,11 @@ static inline void copy_to_gldrawable_from_pixmap(const RedDrawable_p* dest,
glDisable(GL_TEXTURE_2D);
}
- glPixelStorei(GL_UNPACK_ROW_LENGTH, source->pixmap.x_image->bytes_per_line / 4);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, pixman_image_get_stride(source->pixmap.pixman_image) / 4);
glPixelZoom(1, -1);
- addr = (uint8_t *)source->pixmap.x_image->data;
- addr += (src_x * 4 + src_y * source->pixmap.x_image->bytes_per_line);
+ addr = (uint8_t *)pixman_image_get_data(source->pixmap.pixman_image);
+ addr += (src_x * 4 + src_y * pixman_image_get_stride(source->pixmap.pixman_image));
glWindowPos2i(area.left + offset.x, dest->source.x_drawable.height -
(area.top + offset.y)); //+ (area.bottom - area.top)));
glDrawPixels(area.right - area.left, area.bottom - area.top,
@@ -149,37 +149,106 @@ static inline void copy_to_drawable_from_drawable(const RedDrawable_p* dest,
area.left + offset.x, area.top + offset.y);
}
+static XImage *create_temp_image(int screen, int width, int height,
+ pixman_image_t **pixman_image_out,
+ XShmSegmentInfo **shminfo_out)
+{
+ XImage *image;
+ XShmSegmentInfo *shminfo;
+ RedDrawable::Format format;
+ pixman_image_t *pixman_image;
+ XVisualInfo *vinfo;
+
+ image = NULL;
+ shminfo = NULL;
+
+ vinfo = XPlatform::get_vinfo()[screen];
+ format = XPlatform::get_screen_format(screen);
+
+ image = XPlatform::create_x_image(format, width, height, vinfo->depth,
+ vinfo->visual, &shminfo);
+
+ pixman_image = pixman_image_create_bits(RedDrawable::format_to_pixman(format),
+ width, height,
+ (uint32_t *)image->data, image->bytes_per_line);
+ if (pixman_image == NULL) {
+ THROW("surf create failed");
+ }
+ *pixman_image_out = pixman_image;
+ *shminfo_out = shminfo;
+ return image;
+}
+
+static void free_temp_image(XImage *image, XShmSegmentInfo *shminfo, pixman_image_t *pixman_image)
+{
+ XPlatform::free_x_image(image, shminfo);
+ pixman_image_unref(pixman_image);
+}
+
+
static inline void copy_to_drawable_from_pixmap(const RedDrawable_p* dest,
const SpiceRect& area,
const SpicePoint& offset,
const PixelsSource_p* source,
int src_x, int src_y)
{
+ pixman_image_t *src_surface = source->pixmap.pixman_image;
XGCValues gc_vals;
gc_vals.function = GXcopy;
+ RedDrawable::Format screen_format;
+ XImage *image;
+ XShmSegmentInfo *shminfo;
+ pixman_image_t *pixman_image;
+ int screen;
+
+ screen = dest->source.x_drawable.screen;
+ screen_format = XPlatform::get_screen_format(screen);
XChangeGC(XPlatform::get_display(), dest->source.x_drawable.gc, GCFunction, &gc_vals);
- XPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
- dest->source.x_drawable.gc, source->pixmap.x_image, src_x,
- src_y, area.left + offset.x, area.top + offset.y,
- area.right - area.left, area.bottom - area.top);
-}
-static inline void copy_to_drawable_from_shmdrawable(const RedDrawable_p* dest,
- const SpiceRect& area,
- const SpicePoint& offset,
- const PixelsSource_p* source,
- int src_x, int src_y)
-{
- XGCValues gc_vals;
- gc_vals.function = GXcopy;
+ if (source->pixmap.x_image != NULL &&
+ RedDrawable::format_copy_compatible(source->pixmap.format, screen_format)) {
+ if (source->pixmap.shminfo) {
+ XShmPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
+ dest->source.x_drawable.gc, source->pixmap.x_image,
+ src_x, src_y, area.left + offset.x, area.top + offset.y,
+ area.right - area.left, area.bottom - area.top, false);
+ XSync(XPlatform::get_display(), 0);
+ } else {
+ XPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
+ dest->source.x_drawable.gc, source->pixmap.x_image, src_x,
+ src_y, area.left + offset.x, area.top + offset.y,
+ area.right - area.left, area.bottom - area.top);
+ }
+ } else {
+ image = create_temp_image(screen,
+ area.right - area.left, area.bottom - area.top,
+ &pixman_image, &shminfo);
- XChangeGC(XPlatform::get_display(), dest->source.x_drawable.gc, GCFunction, &gc_vals);
- XShmPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
- dest->source.x_drawable.gc, source->x_shm_drawable.x_image,
- src_x, src_y, area.left + offset.x, area.top + offset.y,
- area.right - area.left, area.bottom - area.top, false);
- XSync(XPlatform::get_display(), 0);
+ pixman_image_composite32(PIXMAN_OP_SRC,
+ src_surface, NULL, pixman_image,
+ src_x + offset.x,
+ src_y + offset.y,
+ 0, 0,
+ 0, 0,
+ area.right - area.left,
+ area.bottom - area.top);
+
+ if (shminfo) {
+ XShmPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
+ dest->source.x_drawable.gc, image,
+ 0, 0, area.left + offset.x, area.top + offset.y,
+ area.right - area.left, area.bottom - area.top, false);
+ XSync(XPlatform::get_display(), 0);
+ } else {
+ XPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
+ dest->source.x_drawable.gc, image,
+ 0, 0, area.left + offset.x, area.top + offset.y,
+ area.right - area.left, area.bottom - area.top);
+ }
+
+ free_temp_image(image, shminfo, pixman_image);
+ }
}
static inline void copy_to_x_drawable(const RedDrawable_p* dest,
@@ -195,9 +264,6 @@ static inline void copy_to_x_drawable(const RedDrawable_p* dest,
case PIXELS_SOURCE_TYPE_PIXMAP:
copy_to_drawable_from_pixmap(dest, area, offset, source, src_x, src_y);
break;
- case PIXELS_SOURCE_TYPE_XSHM_DRAWABLE:
- copy_to_drawable_from_shmdrawable(dest, area, offset, source, src_x, src_y);
- break;
default:
THROW("invalid source type %d", source->type);
}
@@ -230,26 +296,6 @@ static inline void copy_to_pixmap_from_drawable(const RedDrawable_p* dest,
LOG_WARN("not implemented");
}
-static inline void copy_to_pixmap_from_shmdrawable(const RedDrawable_p* dest,
- const SpiceRect& area,
- const SpicePoint& offset,
- const PixelsSource_p* source,
- int src_x, int src_y)
-{
- pixman_image_t *dest_surface = dest->source.pixmap.pixman_image;
- pixman_image_t *src_surface = source->x_shm_drawable.pixman_image;
-
- pixman_image_composite32(PIXMAN_OP_SRC,
- src_surface, NULL, dest_surface,
- src_x + offset.x,
- src_y + offset.y,
- 0, 0,
- area.left + offset.x,
- area.top + offset.y,
- area.right - area.left,
- area.bottom - area.top);
-}
-
static inline void copy_to_pixmap_from_pixmap(const RedDrawable_p* dest,
const SpiceRect& area,
const SpicePoint& offset,
@@ -297,15 +343,15 @@ static inline void copy_to_pixmap_from_gltexture(const RedDrawable_p* dest,
}
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
glPixelStorei(GL_PACK_ROW_LENGTH,
- dest->source.pixmap.x_image->bytes_per_line / 4);
+ pixman_image_get_stride(dest->source.pixmap.pixman_image) / 4);
while (height > 0) {
glReadPixels(src_x, y - height, area.right - area.left, 1,
GL_BGRA, GL_UNSIGNED_BYTE,
- dest->source.pixmap.x_image->data +
+ (uint8_t *)pixman_image_get_stride(dest->source.pixmap.pixman_image) +
(area.left + offset.x) * 4 +
(area.top + offset.y + height - 1) *
- dest->source.pixmap.x_image->bytes_per_line);
+ pixman_image_get_stride(dest->source.pixmap.pixman_image));
height--;
}
if (rendertype != RENDER_TYPE_FBO) {
@@ -330,9 +376,6 @@ static inline void copy_to_pixmap(const RedDrawable_p* dest,
case PIXELS_SOURCE_TYPE_PIXMAP:
copy_to_pixmap_from_pixmap(dest, area, offset, source, src_x, src_y);
break;
- case PIXELS_SOURCE_TYPE_XSHM_DRAWABLE:
- copy_to_pixmap_from_shmdrawable(dest, area, offset, source, src_x, src_y);
- break;
default:
THROW("invalid source type %d", source->type);
}
diff --git a/client/x11/red_pixmap_cairo.cpp b/client/x11/red_pixmap_cairo.cpp
index 1974ebc4..863ed392 100644
--- a/client/x11/red_pixmap_cairo.cpp
+++ b/client/x11/red_pixmap_cairo.cpp
@@ -22,156 +22,70 @@
#include "utils.h"
#include "pixels_source_p.h"
#include "x_platform.h"
-#include <sys/shm.h>
-
-RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
+RedPixmapCairo::RedPixmapCairo(int width, int height, RedDrawable::Format format,
bool top_bottom, RedWindow *win)
: RedPixmap(width, height, format, top_bottom)
{
- ASSERT(format == RedPixmap::ARGB32 || format == RedPixmap::RGB32 ||
- format == RedPixmap::RGB16_555 || format == RedPixmap::RGB16_565 ||
- format == RedPixmap::A1);
+ ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32 ||
+ format == RedDrawable::RGB16_555 || format == RedDrawable::RGB16_565 ||
+ format == RedDrawable::A1);
ASSERT(sizeof(RedDrawable_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
pixman_image_t *pixman_image;
- XImage *image = NULL;
- XShmSegmentInfo *shminfo = NULL;
+ XImage *image;
+ XShmSegmentInfo *shminfo;
_data = NULL;
- XVisualInfo *vinfo = NULL;
- bool using_shm = false;
-
-
- try {
- pixman_format_code_t pixman_format;
-
- if (win) {
- vinfo = XPlatform::get_vinfo()[win->get_screen_num()];
- }
-
- using_shm = vinfo && XPlatform::is_x_shm_avail();
-
- if (using_shm) {
- int depth = RedPixmap::format_to_bpp(format);
- pixman_format = RedPixmap::format_to_pixman(format);
-
- shminfo = new XShmSegmentInfo;
- shminfo->shmid = -1;
- shminfo->shmaddr = 0;
- ((PixelsSource_p*)get_opaque())->type = PIXELS_SOURCE_TYPE_XSHM_DRAWABLE;
- memset(shminfo, 0, sizeof(XShmSegmentInfo));
- image = XShmCreateImage(XPlatform::get_display(), vinfo->visual,
- depth, ZPixmap, NULL, shminfo, width, height);
- if (!image) {
- THROW("XShmCreateImage failed");
- }
-
- shminfo->shmid = shmget(IPC_PRIVATE, height * _stride, IPC_CREAT | 0777);
- if (shminfo->shmid < 0) {
- THROW("shmget failed");
- }
- shminfo->shmaddr = (char *)shmat(shminfo->shmid, 0, 0);
- if (shmctl(shminfo->shmid, IPC_RMID, NULL) == -1) {
- LOG_WARN("shmctl IPC_RMID failed %s (%d)", strerror(errno), errno);
- }
- if (!shminfo->shmaddr) {
- THROW("shmat failed");
- }
- shminfo->readOnly = False;
- if (!XShmAttach(XPlatform::get_display(), shminfo)) {
- THROW("XShmAttach failed");
- }
-
- ((PixelsSource_p*)get_opaque())->x_shm_drawable.x_image = image;
- ((PixelsSource_p*)get_opaque())->x_shm_drawable.shminfo = shminfo;
- _data = (uint8_t *)shminfo->shmaddr;
- image->data = (char *)_data;
- } else {
- image = new XImage;
- _data = new uint8_t[height * _stride];
- ((PixelsSource_p*)get_opaque())->type = PIXELS_SOURCE_TYPE_PIXMAP;
- ((PixelsSource_p*)get_opaque())->pixmap.x_image = image;
- memset(image, 0, sizeof(*image));
- image->width = _width;
- image->height = _height;
-
- image->data = (char*)_data;
- image->byte_order = LSBFirst;
- image->bitmap_unit = 32;
- image->bitmap_bit_order = LSBFirst;
- image->bitmap_pad = 32;
-
- image->bytes_per_line = _stride;
- switch (format) {
- case RedPixmap::ARGB32:
- case RedPixmap::RGB32:
- image->depth = XPlatform::get_vinfo()[0]->depth;
- image->format = ZPixmap;
- image->bits_per_pixel = 32;
- image->red_mask = 0x00ff0000;
- image->green_mask = 0x0000ff00;
- image->blue_mask = 0x000000ff;
- pixman_format = format == RedPixmap::ARGB32 ? PIXMAN_a8r8g8b8 :
- PIXMAN_x8r8g8b8;
- break;
- case RedPixmap::A1:
- image->depth = 1;
- image->format = XYBitmap;
- pixman_format = PIXMAN_a1;
- break;
- default:
- THROW("unsupported format %d", format);
- }
-
- if (!XInitImage(image)) {
- THROW("init image failed");
- }
- }
- pixman_image = pixman_image_create_bits(pixman_format, _width, _height,
- (uint32_t *)_data, _stride);
- if (pixman_image == NULL) {
- THROW("surf create failed");
- }
+ XVisualInfo *vinfo;
+ int screen_num;
+ RedDrawable::Format screen_format;
+
+ screen_num = win ? win->get_screen_num() : 0;
+ vinfo = XPlatform::get_vinfo()[screen_num];
+ screen_format = XPlatform::get_screen_format(screen_num);
+
+ image = NULL;
+ shminfo = NULL;
+
+ /* Only create XImage if same format as screen (needs re-verifying at
+ draw time!) */
+ if (RedDrawable::format_copy_compatible(format, screen_format) ||
+ format == A1) {
+ image = XPlatform::create_x_image(format, width, height,
+ vinfo->depth, vinfo->visual,
+ &shminfo);
+ _stride = image->bytes_per_line;
+ _data = (uint8_t *)image->data;
+ } else {
+ _data = new uint8_t[height * _stride];
+ }
- if (!using_shm) {
- ((PixelsSource_p*)get_opaque())->pixmap.pixman_image = pixman_image;
- } else {
- ((PixelsSource_p*)get_opaque())->x_shm_drawable.pixman_image = pixman_image;
- }
- } catch (...) {
- if (using_shm) {
- if (image) {
- XDestroyImage(image);
- }
- if (shminfo) {
- if (shminfo->shmid >= 0) {
- shmctl(shminfo->shmid, IPC_RMID, NULL);
- }
- if (shminfo->shmaddr) {
- shmdt(shminfo->shmaddr);
- }
- }
- } else {
- delete image;
- delete _data;
- }
- throw;
+ pixman_image = pixman_image_create_bits(RedDrawable::format_to_pixman(format),
+ _width, _height,
+ (uint32_t *)_data, _stride);
+ if (pixman_image == NULL) {
+ THROW("surf create failed");
}
+
+ ((PixelsSource_p*)get_opaque())->type = PIXELS_SOURCE_TYPE_PIXMAP;
+ ((PixelsSource_p*)get_opaque())->pixmap.shminfo = shminfo;
+ ((PixelsSource_p*)get_opaque())->pixmap.x_image = image;
+ ((PixelsSource_p*)get_opaque())->pixmap.pixman_image = pixman_image;
+ ((PixelsSource_p*)get_opaque())->pixmap.format = format;
}
RedPixmapCairo::~RedPixmapCairo()
{
- if (((PixelsSource_p*)get_opaque())->type == PIXELS_SOURCE_TYPE_PIXMAP) {
- pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
- delete ((PixelsSource_p*)get_opaque())->pixmap.x_image;
- delete[] _data;
+ ASSERT(((PixelsSource_p*)get_opaque())->type == PIXELS_SOURCE_TYPE_PIXMAP);
+
+ XShmSegmentInfo *shminfo = ((PixelsSource_p*)get_opaque())->pixmap.shminfo;
+ XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image;
+
+ pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
+
+ if (image) {
+ XPlatform::free_x_image(image, shminfo);
} else {
- pixman_image_unref(((PixelsSource_p*)get_opaque())->x_shm_drawable.pixman_image);
- XShmSegmentInfo *shminfo = ((PixelsSource_p*)get_opaque())->x_shm_drawable.shminfo;
- XShmDetach(XPlatform::get_display(), shminfo);
- XDestroyImage(((PixelsSource_p*)get_opaque())->x_shm_drawable.x_image);
- XSync(XPlatform::get_display(), False);
- shmdt(shminfo->shmaddr);
- delete shminfo;
+ delete[] _data;
}
}
diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index 21567275..c9a16ec1 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -1164,6 +1164,7 @@ void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source, int
_expect_parent = false;
pix_source.type = PIXELS_SOURCE_TYPE_X_DRAWABLE;
pix_source.x_drawable.drawable = window;
+ pix_source.x_drawable.screen = _screen;
pix_source.x_drawable.gc = gc;
set_minmax(pix_source, width, height);
sync();