diff options
30 files changed, 296 insertions, 249 deletions
diff --git a/client/cursor_channel.cpp b/client/cursor_channel.cpp index 0dd9dcb6..289c059f 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, NULL)) + RedPixmap::ARGB32, true, NULL)) { int stride = _pixmap->get_stride(); uint8_t* dest = _pixmap->get_data(); @@ -131,9 +131,8 @@ MonoCursor::MonoCursor(const SpiceCursorHeader& header, const uint8_t* data) : _pixmap (NULL) , _height (header.height) { - rgb32_t pallete[2] = { rgb32_make(0x00, 0x00, 0x00), rgb32_make(0xff, 0xff, 0xff)}; _pixmap.reset(new RedPixmapCairo(header.width, _height * 2, RedPixmap::A1, - true, pallete, NULL)); + true, NULL)); int dest_stride = _pixmap->get_stride(); uint8_t *dest_line = _pixmap->get_data(); @@ -177,12 +176,11 @@ private: ColorCursor::ColorCursor(const SpiceCursorHeader& header) : _pixmap (new RedPixmapCairo(header.width, header.height, - RedPixmap::ARGB32, true, NULL, NULL)) + RedPixmap::ARGB32, true, NULL)) , _invers (NULL) { - rgb32_t pallete[2] = { rgb32_make(0x00, 0x00, 0x00), rgb32_make(0xff, 0xff, 0xff)}; _invers.reset(new RedPixmapCairo(header.width, header.height, RedPixmap::A1, - true, pallete, NULL)); + true, NULL)); } void ColorCursor::init_pixels(const SpiceCursorHeader& header, const uint8_t* pixels, diff --git a/client/display_channel.cpp b/client/display_channel.cpp index 719e7dfd..acbf5da7 100644 --- a/client/display_channel.cpp +++ b/client/display_channel.cpp @@ -1079,12 +1079,13 @@ void DisplayChannel::on_disconnect() (*sync_event)->wait(); } -bool DisplayChannel::create_cairo_canvas(int surface_id, int width, int height, int depth) +bool DisplayChannel::create_cairo_canvas(int surface_id, int width, int height, uint32_t format) { try { - CCanvas *canvas = new CCanvas(_pixmap_cache, _palette_cache, _glz_window, + CCanvas *canvas = new CCanvas(surface_id == 0, width, height, format, + screen()->get_window(), + _pixmap_cache, _palette_cache, _glz_window, surfaces_mngr.get_surfaces()); - canvas->set_mode(width, height, depth, screen()->get_window()); surfaces_mngr.add_canvas(surface_id, canvas); surfaces_mngr.add_surface(surface_id, canvas->get_internal_canvas()); if (surface_id == 0) { @@ -1097,21 +1098,19 @@ bool DisplayChannel::create_cairo_canvas(int surface_id, int width, int height, } #ifdef USE_OGL -bool DisplayChannel::create_ogl_canvas(int surface_id, int width, int height, int depth, +bool DisplayChannel::create_ogl_canvas(int surface_id, int width, int height, uint32_t format, bool recreate, RenderType rendertype) { try { RedWindow *win; - GCanvas *canvas = new GCanvas(_pixmap_cache, + win = screen()->get_window(); + GCanvas *canvas = new GCanvas(width, height, format, win, rendertype, + _pixmap_cache, _palette_cache, _glz_window, surfaces_mngr.get_surfaces()); - win = screen()->get_window(); - - canvas->set_mode(width, height, depth, win, rendertype); - screen()->untouch_context(); surfaces_mngr.add_canvas(surface_id, canvas); @@ -1129,12 +1128,12 @@ bool DisplayChannel::create_ogl_canvas(int surface_id, int width, int height, in #endif #ifdef WIN32 -bool DisplayChannel::create_gdi_canvas(int surface_id, int width, int height, int depth) +bool DisplayChannel::create_gdi_canvas(int surface_id, int width, int height, uint32_t format) { try { - GDICanvas *canvas = new GDICanvas(_pixmap_cache, _palette_cache, _glz_window, + GDICanvas *canvas = new GDICanvas(width, height, format, + _pixmap_cache, _palette_cache, _glz_window, surfaces_mngr.get_surfaces()); - canvas->set_mode(width, height, depth); surfaces_mngr.add_canvas(surface_id, canvas); surfaces_mngr.add_surface(surface_id, canvas->get_internal_canvas()); if (surface_id == 0) { @@ -1155,7 +1154,7 @@ void DisplayChannel::destroy_canvas(int surface_id) if (!surfaces_mngr.is_present_canvas(surface_id)) { return; } - + canvas = surfaces_mngr.get_canvas(surface_id); #ifdef USE_OGL @@ -1171,7 +1170,7 @@ void DisplayChannel::destroy_canvas(int surface_id) } void DisplayChannel::create_canvas(int surface_id, const std::vector<int>& canvas_types, int width, - int height, int depth) + int height, uint32_t format) { #ifdef USE_OGL bool recreate = true; @@ -1417,7 +1416,7 @@ void DisplayChannel::handle_stream_destroy_all(RedPeer::InMessage* message) destroy_strams(); } -void DisplayChannel::create_primary_surface(int width, int height, int depth) +void DisplayChannel::create_primary_surface(int width, int height, uint32_t format) { Canvas *canvas; _mark = false; diff --git a/client/display_channel.h b/client/display_channel.h index 2bb697c5..a5761b35 100644 --- a/client/display_channel.h +++ b/client/display_channel.h @@ -133,13 +133,13 @@ protected: private: void set_draw_handlers(); void clear_draw_handlers(); - bool create_cairo_canvas(int surface_id, int width, int height, int depth); + bool create_cairo_canvas(int surface_id, int width, int height, uint32_t format); #ifdef USE_OGL - bool create_ogl_canvas(int surface_id, int width, int height, int depth, bool recreate, + bool create_ogl_canvas(int surface_id, int width, int height, uint32_t format, bool recreate, RenderType rendertype); #endif #ifdef WIN32 - bool create_gdi_canvas(int surface_id, int width, int height, int depth); + bool create_gdi_canvas(int surface_id, int width, int height, uint32_t format); #endif void destroy_canvas(int surface_id); void create_canvas(int surface_id, const std::vector<int>& canvas_type, int width, int height, diff --git a/client/gui/gui.cpp b/client/gui/gui.cpp index 0ff442e5..6debdd1b 100644 --- a/client/gui/gui.cpp +++ b/client/gui/gui.cpp @@ -888,8 +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, RedPixmap::RGB32, true, NULL, - NULL)) + , _pixmap (new RedPixmapCairo(MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT, RedPixmap::RGB32, true, NULL)) , _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 96f76375..9338d9ff 100644 --- a/client/red_cairo_canvas.cpp +++ b/client/red_cairo_canvas.cpp @@ -25,36 +25,44 @@ #include "region.h" #include "red_pixmap_cairo.h" -CCanvas::CCanvas(PixmapCache& pixmap_cache, PaletteCache& palette_cache, +CCanvas::CCanvas(bool onscreen, + int width, int height, uint32_t format, RedWindow *win, + PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, CSurfaces& csurfaces) : Canvas (pixmap_cache, palette_cache, glz_decoder_window, csurfaces) , _pixmap (0) { + if (onscreen) { + _pixmap = new RedPixmapCairo(width, height, + RedPixmap::format_from_surface(format), + true, win); + _canvas = canvas_create_for_data(width, height, format, + _pixmap->get_data(), + _pixmap->get_stride(), + &pixmap_cache.base, + &palette_cache.base, + &csurfaces.base, + &glz_decoder()); + } else { + _canvas = canvas_create(width, height, format, + &pixmap_cache.base, + &palette_cache.base, + &csurfaces.base, + &glz_decoder()); + } + if (_canvas == NULL) { + THROW("create canvas failed"); + } } CCanvas::~CCanvas() { - destroy(); -} - -void CCanvas::destroy() -{ - if (_canvas) { - _canvas->ops->destroy(_canvas); - _canvas = NULL; + _canvas->ops->destroy(_canvas); + _canvas = NULL; + if (_pixmap) { + delete _pixmap; + _pixmap = NULL; } - destroy_pixmap(); -} - -void CCanvas::destroy_pixmap() -{ - delete _pixmap; - _pixmap = NULL; -} - -void CCanvas::create_pixmap(int width, int height, RedWindow *win) -{ - _pixmap = new RedPixmapCairo(width, height, RedPixmap::RGB32, true, NULL, win); } void CCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc) @@ -62,6 +70,8 @@ void CCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc) pixman_box32_t *rects; int num_rects; + ASSERT(_pixmap != NULL); + rects = pixman_region32_rectangles((pixman_region32_t *)®ion, &num_rects); for (int i = 0; i < num_rects; i++) { SpiceRect r; @@ -79,29 +89,6 @@ void CCanvas::copy_pixels(const QRegion& region, RedDrawable* dest_dc, const Pix copy_pixels(region, *dest_dc); } -void CCanvas::set_mode(int width, int height, int depth, RedWindow *win) -{ - pixman_image_t *surface; - - destroy(); - create_pixmap(width, height, win); - surface = pixman_image_create_bits(PIXMAN_x8r8g8b8, width, height, - (uint32_t *)_pixmap->get_data(), - _pixmap->get_stride()); - if (surface == NULL) { - THROW("create surface failed, out of memory"); - } - - if (!(_canvas = canvas_create(surface, depth, - &pixmap_cache().base, - &palette_cache().base, - &csurfaces().base, - &glz_decoder()))) { - THROW("create canvas failed"); - } - pixman_image_unref (surface); -} - CanvasType CCanvas::get_pixmap_type() { return CANVAS_TYPE_CAIRO; diff --git a/client/red_cairo_canvas.h b/client/red_cairo_canvas.h index 8d039bfb..9f4911bb 100644 --- a/client/red_cairo_canvas.h +++ b/client/red_cairo_canvas.h @@ -26,11 +26,12 @@ class RedPixmap; class CCanvas: public Canvas { public: - CCanvas(PixmapCache& pixmap_cache, PaletteCache& palette_cache, + CCanvas(bool onscreen, + int width, int height, uint32_t format, RedWindow *win, + PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces); virtual ~CCanvas(); - virtual void set_mode(int x, int y, int bits, RedWindow *win); virtual void thread_touch() {} virtual void copy_pixels(const QRegion& region, RedDrawable* dc, const PixmapHeader* pixmap); @@ -39,11 +40,6 @@ public: virtual CanvasType get_pixmap_type(); private: - void create_pixmap(int width, int height, RedWindow *win); - void destroy_pixmap(); - void destroy(); - -private: RedPixmap *_pixmap; unsigned long _base; unsigned long _max; diff --git a/client/red_gdi_canvas.cpp b/client/red_gdi_canvas.cpp index be7992c1..ae73ea2c 100644 --- a/client/red_gdi_canvas.cpp +++ b/client/red_gdi_canvas.cpp @@ -23,38 +23,33 @@ #include "region.h" #include "red_pixmap_gdi.h" -GDICanvas::GDICanvas(PixmapCache& pixmap_cache, PaletteCache& palette_cache, +GDICanvas::GDICanvas(int width, int height, uint32_t format, + PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces) : Canvas (pixmap_cache, palette_cache, glz_decoder_window, csurfaces) , _pixmap (0) { -} - -GDICanvas::~GDICanvas() -{ - destroy(); -} - -void GDICanvas::destroy() -{ - if (_canvas) { - _canvas->ops->destroy(_canvas); - _canvas = NULL; + _pixmap = new RedPixmapGdi(width, height, + RedPixmap::format_from_surface(format), + true, NULL); + if (!(_canvas = gdi_canvas_create(width, height, _pixmap->get_dc(), + &_pixmap->get_mutex(), + depth, &pixmap_cache().base, + &palette_cache().base, + &csurfaces().base, + &glz_decoder()))) { + THROW("create canvas failed"); } - destroy_pixmap(); } -void GDICanvas::destroy_pixmap() +GDICanvas::~GDICanvas() { + _canvas->ops->destroy(_canvas); + _canvas = NULL; delete _pixmap; _pixmap = NULL; } -void GDICanvas::create_pixmap(int width, int height) -{ - _pixmap = new RedPixmapGdi(width, height, RedPixmap::RGB32, true, NULL); -} - void GDICanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc) { pixman_box32_t *rects; @@ -80,15 +75,6 @@ void GDICanvas::copy_pixels(const QRegion& region, RedDrawable* dest_dc, const P void GDICanvas::set_mode(int width, int height, int depth) { destroy(); - create_pixmap(width, height); - if (!(_canvas = gdi_canvas_create(width, height, _pixmap->get_dc(), - &_pixmap->get_mutex(), - depth, &pixmap_cache().base, - &palette_cache().base, - &csurfaces().base, - &glz_decoder()))) { - THROW("create canvas failed"); - } } CanvasType GDICanvas::get_pixmap_type() diff --git a/client/red_gdi_canvas.h b/client/red_gdi_canvas.h index d117282b..643f3c6c 100644 --- a/client/red_gdi_canvas.h +++ b/client/red_gdi_canvas.h @@ -27,11 +27,11 @@ class RedPixmap; class GDICanvas: public Canvas { public: - GDICanvas(PixmapCache& pixmap_cache, PaletteCache& palette_cache, + GDICanvas(int width, int height, uint32_t format, + PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces); virtual ~GDICanvas(); - virtual void set_mode(int x, int y, int bits); virtual void thread_touch() {} virtual void copy_pixels(const QRegion& region, RedDrawable* dc, const PixmapHeader* pixmap); @@ -40,11 +40,6 @@ public: virtual CanvasType get_pixmap_type(); private: - void create_pixmap(int width, int height); - void destroy_pixmap(); - void destroy(); - -private: RedPixmapGdi *_pixmap; RedPixmapGdi *_helper_pixmap; HDC _dc; diff --git a/client/red_gl_canvas.cpp b/client/red_gl_canvas.cpp index 2d285a50..dc743cfb 100644 --- a/client/red_gl_canvas.cpp +++ b/client/red_gl_canvas.cpp @@ -24,42 +24,36 @@ #include "red_pixmap_gl.h" #include <GL/glx.h> -GCanvas::GCanvas(PixmapCache& pixmap_cache, PaletteCache& palette_cache, +GCanvas::GCanvas(int width, int height, uint32_t format, RedWindow *win, + RenderType rendertype, + PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces) : Canvas(pixmap_cache, palette_cache, glz_decoder_window, csurfaces) , _pixmap (0) , _textures_lost (false) { -} - -GCanvas::~GCanvas() -{ - destroy(); -} - -void GCanvas::destroy() -{ - if (_canvas) { - gl_canvas_set_textures_lost (_canvas, (int)_textures_lost); - _canvas->ops->destroy(_canvas); - _canvas = NULL; + _pixmap = new RedPixmapGL(width, height, + RedPixmap::format_from_surface(format), + true, win, rendertype); + if (!(_canvas = gl_canvas_create(width, height, + SPICE_SURFACE_FMT_DEPTH(format), + &pixmap_cache.base, + &palette_cache.base, + &csurfaces.base, + &glz_decoder()))) { + THROW("create canvas failed"); } - destroy_pixmap(); } -void GCanvas::destroy_pixmap() +GCanvas::~GCanvas() { + gl_canvas_set_textures_lost (_canvas, (int)_textures_lost); + _canvas->ops->destroy(_canvas); + _canvas = NULL; delete _pixmap; _pixmap = NULL; } -void GCanvas::create_pixmap(int width, int height, RedWindow *win, - RenderType rendertype) -{ - _pixmap = new RedPixmapGL(width, height, RedPixmap::RGB32, true, NULL, - win, rendertype); -} - void GCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc) { pixman_box32_t *rects; @@ -83,21 +77,6 @@ void GCanvas::copy_pixels(const QRegion& region, RedDrawable* dest_dc, const Pix copy_pixels(region, *dest_dc); } -void GCanvas::set_mode(int width, int height, int depth, RedWindow *win, - RenderType rendertype) -{ - destroy(); - - create_pixmap(width, height, win, rendertype); - if (!(_canvas = gl_canvas_create(width, height, depth, - &pixmap_cache().base, - &palette_cache().base, - &csurfaces().base, - &glz_decoder()))) { - THROW("create canvas failed"); - } -} - void GCanvas::touched_bbox(const SpiceRect *bbox) { _pixmap->update_texture(bbox); diff --git a/client/red_gl_canvas.h b/client/red_gl_canvas.h index 22491c49..dfe53d61 100644 --- a/client/red_gl_canvas.h +++ b/client/red_gl_canvas.h @@ -28,12 +28,13 @@ class RedPixmapGL; class GCanvas: public Canvas { public: - GCanvas(PixmapCache& pixmap_cache, PaletteCache& palette_cache, + GCanvas(int width, int height, uint32_t format, RedWindow *win, + RenderType rendertype, + PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces); virtual ~GCanvas(); - void set_mode(int width, int height, int depth, RedWindow *win, - RenderType rendertype); + void set_mode(); void clear(); void thread_touch() {} void copy_pixels(const QRegion& region, RedDrawable* dc, diff --git a/client/red_pixmap.h b/client/red_pixmap.h index 1b469bdf..c81c2f77 100644 --- a/client/red_pixmap.h +++ b/client/red_pixmap.h @@ -20,17 +20,62 @@ #define _H_RED_PIXMAP #include "red_drawable.h" +#include "utils.h" +#include <pixman_utils.h> class RedPixmap: public RedDrawable { public: enum Format { ARGB32, RGB32, + RGB16_555, + RGB16_565, A1, }; - RedPixmap(int width, int height, Format format, bool top_bottom, - rgb32_t* pallete); + static int format_to_bpp(Format format) { + if (format == RedPixmap::A1) { + return 1; + } else if (format == RGB16_555 || format == RGB16_565) { + return 16; + } else { + return 32; + } + } + + static pixman_format_code_t format_to_pixman(Format format) { + switch (format) { + case RedPixmap::ARGB32: + return PIXMAN_a8r8g8b8; + case RedPixmap::RGB32: + return PIXMAN_x8r8g8b8; + case RedPixmap::RGB16_555: + return PIXMAN_x1r5g5b5; + case RedPixmap::RGB16_565: + return PIXMAN_r5g6b5; + case RedPixmap::A1: + return PIXMAN_a1; + default: + THROW("unsupported format %d", format); + } + } + + static Format format_from_surface(uint32_t format) { + switch (format) { + case SPICE_SURFACE_FMT_16_555: + return RedPixmap::RGB16_555; + case SPICE_SURFACE_FMT_16_565: + return RedPixmap::RGB16_565; + case SPICE_SURFACE_FMT_32_xRGB: + return RedPixmap::RGB32; + case SPICE_SURFACE_FMT_32_ARGB: + return RedPixmap::ARGB32; + default: + THROW("Unsupported RedPixman format"); + } + } + + RedPixmap(int width, int height, Format format, bool top_bottom); virtual ~RedPixmap(); virtual SpicePoint get_size() { SpicePoint pt = {_width, _height}; return pt;} diff --git a/client/red_pixmap_cairo.h b/client/red_pixmap_cairo.h index 3f89db8f..7f9523e8 100644 --- a/client/red_pixmap_cairo.h +++ b/client/red_pixmap_cairo.h @@ -23,8 +23,7 @@ class RedPixmapCairo: public RedPixmap { public: - RedPixmapCairo(int width, int height, Format format, bool top_bottom, - rgb32_t *pallete, RedWindow *win); + RedPixmapCairo(int width, int height, Format format, bool top_bottom, RedWindow *win); ~RedPixmapCairo(); }; diff --git a/client/red_pixmap_gdi.h b/client/red_pixmap_gdi.h index 9e10adc1..524e6f31 100644 --- a/client/red_pixmap_gdi.h +++ b/client/red_pixmap_gdi.h @@ -25,8 +25,7 @@ class RecurciveMutex; class RedPixmapGdi: public RedPixmap { public: - RedPixmapGdi(int width, int height, Format format, bool top_bottom, - rgb32_t *pallete); + RedPixmapGdi(int width, int height, Format format, bool top_bottom); HDC get_dc(); void *get_memptr(); ~RedPixmapGdi(); diff --git a/client/red_pixmap_gl.h b/client/red_pixmap_gl.h index f322d52c..f7a14af9 100644 --- a/client/red_pixmap_gl.h +++ b/client/red_pixmap_gl.h @@ -29,7 +29,7 @@ enum RenderType { class RedPixmapGL: public RedPixmap { public: RedPixmapGL(int width, int height, Format format, bool top_bottom, - rgb32_t *pallete, RedWindow *win, RenderType rendertype); + RedWindow *win, RenderType rendertype); void textures_lost(); void touch_context(); diff --git a/client/screen.cpp b/client/screen.cpp index f31a9a60..7edca121 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, RedPixmap::RGB32, - false, NULL, NULL); + false, NULL); } void RedScreen::adjust_window_rect(int x, int y) diff --git a/client/windows/red_pixmap.cpp b/client/windows/red_pixmap.cpp index 1ec41faf..574d2851 100644 --- a/client/windows/red_pixmap.cpp +++ b/client/windows/red_pixmap.cpp @@ -21,11 +21,11 @@ #include "utils.h" RedPixmap::RedPixmap(int width, int height, RedPixmap::Format format, - bool top_bottom, rgb32_t* pallet) + bool top_bottom) : _format (format) , _width (width) , _height (height) - , _stride (SPICE_ALIGN(width * (_format == RedPixmap::A1 ? 1: 32), 32) / 8) + , _stride (SPICE_ALIGN(width * format_to_bpp(format), 32) / 8) , _top_bottom (top_bottom) , _data (NULL) { diff --git a/client/windows/red_pixmap_cairo.cpp b/client/windows/red_pixmap_cairo.cpp index 6ed58068..793d21ed 100644 --- a/client/windows/red_pixmap_cairo.cpp +++ b/client/windows/red_pixmap_cairo.cpp @@ -29,14 +29,9 @@ struct RedPixmap_p { HBITMAP prev_bitmap; }; -static inline int format_to_bpp(RedPixmap::Format format) -{ - return ((format == RedPixmap::A1) ? 1 : 32); -} - -RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format, bool top_bottom, - rgb32_t* pallet, RedWindow *win) - : RedPixmap(width, height, format, top_bottom, pallet) +RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format, + bool top_bottom, RedWindow *win) + : RedPixmap(width, height, format, top_bottom) { ASSERT(format == RedPixmap::ARGB32 || format == RedPixmap::RGB32 || format == RedPixmap::A1); ASSERT(sizeof(RedPixmap_p) <= PIXELES_SOURCE_OPAQUE_SIZE); @@ -65,15 +60,16 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format, #endif*/ bitmap_info.inf.bmiHeader.biPlanes = 1; - bitmap_info.inf.bmiHeader.biBitCount = format_to_bpp(format); + bitmap_info.inf.bmiHeader.biBitCount = RedPixmap::format_to_bpp(format); bitmap_info.inf.bmiHeader.biCompression = BI_RGB; switch (format) { case RedPixmap::A1: - for (int i = 0; i < (1 << format_to_bpp(format)); i++) { - bitmap_info.inf.bmiColors[i].rgbRed = rgb32_get_red(pallet[i]); - bitmap_info.inf.bmiColors[i].rgbGreen = rgb32_get_green(pallet[i]); - bitmap_info.inf.bmiColors[i].rgbBlue = rgb32_get_blue(pallet[i]); - } + bitmap_info.inf.bmiColors[0].rgbRed = 0; + bitmap_info.inf.bmiColors[0].rgbGreen = 0; + bitmap_info.inf.bmiColors[0].rgbBlue = 0; + bitmap_info.inf.bmiColors[1].rgbRed = 0xff; + bitmap_info.inf.bmiColors[1].rgbGreen = 0xff; + bitmap_info.inf.bmiColors[1].rgbBlue = 0xff; break; } AutoDC dc(create_compatible_dc()); diff --git a/client/windows/red_pixmap_gdi.cpp b/client/windows/red_pixmap_gdi.cpp index d4913c49..1c90f3d5 100644 --- a/client/windows/red_pixmap_gdi.cpp +++ b/client/windows/red_pixmap_gdi.cpp @@ -29,13 +29,7 @@ struct RedPixmap_p { HBITMAP prev_bitmap; }; -static inline int format_to_bpp(RedPixmap::Format format) -{ - return ((format == RedPixmap::A1) ? 1 : 32); -} - -RedPixmapGdi::RedPixmapGdi(int width, int height, RedPixmap::Format format, bool top_bottom, - rgb32_t* pallet) +RedPixmapGdi::RedPixmapGdi(int width, int height, RedPixmap::Format format, bool top_bottom) : RedPixmap(width, height, format, top_bottom, pallet) { ASSERT(format == RedPixmap::ARGB32 || format == RedPixmap::RGB32 || format == RedPixmap::A1); @@ -52,15 +46,16 @@ RedPixmapGdi::RedPixmapGdi(int width, int height, RedPixmap::Format format, bool bitmap_info.inf.bmiHeader.biHeight = top_bottom ? -_height : _height; bitmap_info.inf.bmiHeader.biPlanes = 1; - bitmap_info.inf.bmiHeader.biBitCount = format_to_bpp(format); + bitmap_info.inf.bmiHeader.biBitCount = RedPixmap::format_to_bpp(format); bitmap_info.inf.bmiHeader.biCompression = BI_RGB; switch (format) { case RedPixmap::A1: - for (int i = 0; i < (1 << format_to_bpp(format)); i++) { - bitmap_info.inf.bmiColors[i].rgbRed = rgb32_get_red(pallet[i]); - bitmap_info.inf.bmiColors[i].rgbGreen = rgb32_get_green(pallet[i]); - bitmap_info.inf.bmiColors[i].rgbBlue = rgb32_get_blue(pallet[i]); - } + bitmap_info.inf.bmiColors[0].rgbRed = 0; + bitmap_info.inf.bmiColors[0].rgbGreen = 0; + bitmap_info.inf.bmiColors[0].rgbBlue = 0; + bitmap_info.inf.bmiColors[1].rgbRed = 0xff; + bitmap_info.inf.bmiColors[1].rgbGreen = 0xff; + bitmap_info.inf.bmiColors[1].rgbBlue = 0xff; break; } AutoDC dc(create_compatible_dc()); diff --git a/client/x11/red_pixmap.cpp b/client/x11/red_pixmap.cpp index 09455dd3..2a0eb99b 100644 --- a/client/x11/red_pixmap.cpp +++ b/client/x11/red_pixmap.cpp @@ -21,11 +21,11 @@ #include "utils.h" RedPixmap::RedPixmap(int width, int height, RedPixmap::Format format, - bool top_bottom, rgb32_t* pallet) + bool top_bottom) : _format (format) , _width (width) , _height (height) - , _stride (SPICE_ALIGN(width * (_format == RedPixmap::A1 ? 1 : 32), 32) / 8) + , _stride (SPICE_ALIGN(width * format_to_bpp(format), 32) / 8) , _top_bottom (top_bottom) , _data (NULL) { diff --git a/client/x11/red_pixmap_cairo.cpp b/client/x11/red_pixmap_cairo.cpp index e73b8b41..1974ebc4 100644 --- a/client/x11/red_pixmap_cairo.cpp +++ b/client/x11/red_pixmap_cairo.cpp @@ -26,10 +26,12 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format, - bool top_bottom, rgb32_t* pallet, RedWindow *win) - : RedPixmap(width, height, format, top_bottom, pallet) + bool top_bottom, RedWindow *win) + : RedPixmap(width, height, format, top_bottom) { - ASSERT(format == RedPixmap::ARGB32 || format == RedPixmap::RGB32 || format == RedPixmap::A1); + ASSERT(format == RedPixmap::ARGB32 || format == RedPixmap::RGB32 || + format == RedPixmap::RGB16_555 || format == RedPixmap::RGB16_565 || + format == RedPixmap::A1); ASSERT(sizeof(RedDrawable_p) <= PIXELES_SOURCE_OPAQUE_SIZE); pixman_image_t *pixman_image; XImage *image = NULL; @@ -49,22 +51,8 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format, using_shm = vinfo && XPlatform::is_x_shm_avail(); if (using_shm) { - int depth; - - switch (format) { - case RedPixmap::ARGB32: - case RedPixmap::RGB32: - depth = XPlatform::get_vinfo()[0]->depth; - pixman_format = format == RedPixmap::ARGB32 ? PIXMAN_a8r8g8b8 : - PIXMAN_x8r8g8b8; - break; - case RedPixmap::A1: - depth = 1; - pixman_format = PIXMAN_a1; - break; - default: - THROW("unsupported format %d", format); - } + int depth = RedPixmap::format_to_bpp(format); + pixman_format = RedPixmap::format_to_pixman(format); shminfo = new XShmSegmentInfo; shminfo->shmid = -1; diff --git a/client/x11/red_pixmap_gl.cpp b/client/x11/red_pixmap_gl.cpp index 2722476d..a3096517 100644 --- a/client/x11/red_pixmap_gl.cpp +++ b/client/x11/red_pixmap_gl.cpp @@ -31,9 +31,9 @@ RedPixmapGL::RedPixmapGL(int width, int height, RedPixmap::Format format, - bool top_bottom, rgb32_t* pallet, RedWindow *win, + bool top_bottom, RedWindow *win, RenderType rendertype) - : RedPixmap(width, height, format, top_bottom, pallet) + : RedPixmap(width, height, format, top_bottom) { GLuint fbo; GLuint tex; diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c index 38a7081e..fde43d7f 100644 --- a/common/cairo_canvas.c +++ b/common/cairo_canvas.c @@ -1074,7 +1074,8 @@ static void canvas_destroy(SpiceCanvas *spice_canvas) static int need_init = 1; static SpiceCanvasOps cairo_canvas_ops; -SpiceCanvas *canvas_create(pixman_image_t *image, int bits +static SpiceCanvas *canvas_create_common(pixman_image_t *image, + uint32_t format #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache @@ -1098,7 +1099,7 @@ SpiceCanvas *canvas_create(pixman_image_t *image, int bits init_ok = canvas_base_init(&canvas->base, &cairo_canvas_ops, pixman_image_get_width (image), pixman_image_get_height (image), - bits + format #ifdef CAIRO_CANVAS_CACHE , bits_cache , palette_cache @@ -1114,11 +1115,80 @@ SpiceCanvas *canvas_create(pixman_image_t *image, int bits canvas->private_data = NULL; canvas->private_data_size = 0; - canvas->image = pixman_image_ref(image); + canvas->image = image; return (SpiceCanvas *)canvas; } +SpiceCanvas *canvas_create(int width, int height, uint32_t format +#ifdef CAIRO_CANVAS_CACHE + , SpiceImageCache *bits_cache + , SpicePaletteCache *palette_cache +#elif defined(CAIRO_CANVAS_IMAGE_CACHE) + , SpiceImageCache *bits_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder +#ifndef CAIRO_CANVAS_NO_CHUNKS + , SpiceVirtMapping *virt_mapping +#endif + ) +{ + pixman_image_t *image; + + image = pixman_image_create_bits(spice_surface_format_to_pixman (format), + width, height, NULL, 0); + + return canvas_create_common(image, format +#ifdef CAIRO_CANVAS_CACHE + , bits_cache + , palette_cache +#elif defined(CAIRO_CANVAS_IMAGE_CACHE) + , bits_cache +#endif + , surfaces + , glz_decoder +#ifndef CAIRO_CANVAS_NO_CHUNKS + , virt_mapping +#endif + ); +} + +SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, + uint8_t *data, size_t stride +#ifdef CAIRO_CANVAS_CACHE + , SpiceImageCache *bits_cache + , SpicePaletteCache *palette_cache +#elif defined(CAIRO_CANVAS_IMAGE_CACHE) + , SpiceImageCache *bits_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder +#ifndef CAIRO_CANVAS_NO_CHUNKS + , SpiceVirtMapping *virt_mapping +#endif + ) +{ + pixman_image_t *image; + + image = pixman_image_create_bits(spice_surface_format_to_pixman (format), + width, height, (uint32_t *)data, stride); + + return canvas_create_common(image, format +#ifdef CAIRO_CANVAS_CACHE + , bits_cache + , palette_cache +#elif defined(CAIRO_CANVAS_IMAGE_CACHE) + , bits_cache +#endif + , surfaces + , glz_decoder +#ifndef CAIRO_CANVAS_NO_CHUNKS + , virt_mapping +#endif + ); +} + void cairo_canvas_init() //unsafe global function { if (!need_init) { diff --git a/common/cairo_canvas.h b/common/cairo_canvas.h index 7f882b2a..c97380e2 100644 --- a/common/cairo_canvas.h +++ b/common/cairo_canvas.h @@ -26,7 +26,7 @@ #include "canvas_base.h" #include "region.h" -SpiceCanvas *canvas_create(pixman_image_t *image, int bits +SpiceCanvas *canvas_create(int width, int height, uint32_t format #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache @@ -40,6 +40,21 @@ SpiceCanvas *canvas_create(pixman_image_t *image, int bits #endif ); +SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, size_t stride +#ifdef CAIRO_CANVAS_CACHE + , SpiceImageCache *bits_cache + , SpicePaletteCache *palette_cache +#elif defined(CAIRO_CANVAS_IMAGE_CACHE) + , SpiceImageCache *bits_cache +#endif + , SpiceImageSurfaces *surfaces + , SpiceGlzDecoder *glz_decoder +#ifndef CAIRO_CANVAS_NO_CHUNKS + , SpiceVirtMapping *virt_mapping +#endif + ); + + void cairo_canvas_init(); #endif diff --git a/common/canvas_base.c b/common/canvas_base.c index 9852da9e..fb101fda 100644 --- a/common/canvas_base.c +++ b/common/canvas_base.c @@ -176,6 +176,7 @@ typedef struct CanvasBase { unsigned long max; #endif + uint32_t format; int width; int height; pixman_region32_t canvas_region; @@ -3175,7 +3176,7 @@ inline static void canvas_base_init_ops(SpiceCanvasOps *ops) } static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, - int width, int height, int depth + int width, int height, uint32_t format #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache @@ -3218,7 +3219,10 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, canvas->surfaces = surfaces; canvas->glz_data.decoder = glz_decoder; - if (depth == 16) { + canvas->format = format; + + /* TODO: This is all wrong now */ + if (SPICE_SURFACE_FMT_DEPTH(format) == 16) { canvas->color_shift = 5; canvas->color_mask = 0x1f; } else { diff --git a/common/canvas_utils.c b/common/canvas_utils.c index 1e97e872..4f2456d6 100644 --- a/common/canvas_utils.c +++ b/common/canvas_utils.c @@ -175,6 +175,11 @@ pixman_image_t * surface_create(pixman_format_code_t format, int width, int heig bitmap_info.inf.bmiHeader.biBitCount = 32; nstride = width * 4; break; + case PIXMAN_x1r5g5b5: + case PIXMAN_r5g6b5: + bitmap_info.inf.bmiHeader.biBitCount = 16; + nstride = SPICE_ALIGN(width * 2, 4); + break; case PIXMAN_a8: bitmap_info.inf.bmiHeader.biBitCount = 8; nstride = SPICE_ALIGN(width, 4); @@ -237,6 +242,10 @@ pixman_image_t * surface_create(pixman_format_code_t format, int width, int heig case PIXMAN_x8r8g8b8: stride = width * 4; break; + case PIXMAN_x1r5g5b5: + case PIXMAN_r5g6b5: + stride = SPICE_ALIGN(width * 2, 4); + break; case PIXMAN_a8: stride = SPICE_ALIGN(width, 4); break; diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c index ead94af0..c600419d 100644 --- a/common/gdi_canvas.c +++ b/common/gdi_canvas.c @@ -1884,7 +1884,7 @@ static int need_init = 1; static SpiceCanvasOps gdi_canvas_ops; SpiceCanvas *gdi_canvas_create(int width, int height, - HDC dc, RecurciveMutex* lock, int bits + HDC dc, RecurciveMutex* lock, uint32_t format #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache @@ -1903,7 +1903,7 @@ SpiceCanvas *gdi_canvas_create(int width, int height, } canvas = spice_new0(GdiCanvas, 1); init_ok = canvas_base_init(&canvas->base, &gdi_canvas_ops, - width, height, bits + width, height, format #ifdef CAIRO_CANVAS_CACHE ,bits_cache ,palette_cache diff --git a/common/gdi_canvas.h b/common/gdi_canvas.h index 43da189c..13d82efa 100644 --- a/common/gdi_canvas.h +++ b/common/gdi_canvas.h @@ -34,7 +34,7 @@ typedef struct { } GdiImage; SpiceCanvas *gdi_canvas_create(int width, int height, - HDC dc, class RecurciveMutex *lock, int bits, + HDC dc, class RecurciveMutex *lock, uint32_t format, SpiceImageCache *bits_cache, SpicePaletteCache *palette_cache, SpiceImageSurfaces *surfaces, diff --git a/common/gl_canvas.c b/common/gl_canvas.c index dd470bc5..9b017fa2 100644 --- a/common/gl_canvas.c +++ b/common/gl_canvas.c @@ -821,7 +821,7 @@ static void gl_canvas_set_access_params(SpiceCanvas *spice_canvas, unsigned long static int need_init = 1; static SpiceCanvasOps gl_canvas_ops; -SpiceCanvas *gl_canvas_create(int width, int height, int depth +SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache @@ -848,7 +848,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, int depth } canvas->private_data = NULL; init_ok = canvas_base_init(&canvas->base, &gl_canvas_ops, - width, height, depth + width, height, format #ifdef CAIRO_CANVAS_CACHE , bits_cache , palette_cache diff --git a/common/gl_canvas.h b/common/gl_canvas.h index 7c54cbfb..615ca895 100644 --- a/common/gl_canvas.h +++ b/common/gl_canvas.h @@ -21,7 +21,7 @@ #include "canvas_base.h" #include "region.h" -SpiceCanvas *gl_canvas_create(int width, int height, int depth +SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format #ifdef CAIRO_CANVAS_CACHE , SpiceImageCache *bits_cache , SpicePaletteCache *palette_cache diff --git a/server/red_worker.c b/server/red_worker.c index 28927285..af3a8883 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -7795,25 +7795,6 @@ static void red_migrate_display(RedWorker *worker) } } -static SpiceCanvas *create_cairo_context(RedWorker *worker, uint32_t width, uint32_t height, - int32_t stride, uint8_t depth, void *line_0) -{ - SpiceCanvas *canvas; - pixman_image_t *surface; - - surface = pixman_image_create_bits(PIXMAN_x8r8g8b8, width, height, - (uint32_t *)line_0, - stride); - if (surface == NULL) { - red_error("create cairo surface failed"); - } - canvas = canvas_create(surface, depth, &worker->image_cache.base, - &worker->image_surfaces, NULL, - &worker->preload_group_virt_mapping); - pixman_image_unref (surface); - return canvas; -} - static SpiceCanvas *create_ogl_context_common(RedWorker *worker, OGLCtx *ctx, uint32_t width, uint32_t height, int32_t stride, uint8_t depth) { @@ -7870,22 +7851,28 @@ static SpiceCanvas *create_ogl_pixmap_context(RedWorker *worker, uint32_t width, static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface *surface, uint32_t renderer, uint32_t width, uint32_t height, - int32_t stride, uint8_t depth, void *line_0) + int32_t stride, uint32_t format, void *line_0) { SpiceCanvas *canvas; switch (renderer) { case RED_RENDERER_CAIRO: - canvas = create_cairo_context(worker, width, height, stride, depth, line_0); + canvas = canvas_create_for_data(width, height, format, + line_0, stride, + &worker->image_cache.base, + &worker->image_surfaces, NULL, + &worker->preload_group_virt_mapping); surface->context.top_down = TRUE; surface->context.canvas_draws_on_surface = TRUE; return canvas; case RED_RENDERER_OGL_PBUF: - canvas = create_ogl_pbuf_context(worker, width, height, stride, depth); + canvas = create_ogl_pbuf_context(worker, width, height, stride, + SPICE_SURFACE_FMT_DEPTH(format)); surface->context.top_down = FALSE; return canvas; case RED_RENDERER_OGL_PIXMAP: - canvas = create_ogl_pixmap_context(worker, width, height, stride, depth); + canvas = create_ogl_pixmap_context(worker, width, height, stride, + SPICE_SURFACE_FMT_DEPTH(format)); surface->context.top_down = FALSE; return canvas; default: |