diff options
126 files changed, 252 insertions, 27873 deletions
diff --git a/.gitmodules b/.gitmodules index f7de75dd..0c618ee1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "spice-protocol"] - path = spice-protocol - url = ../spice-protocol +[submodule "spice-common"] + path = spice-common + url = ../spice-common diff --git a/Makefile.am b/Makefile.am index 6c277506..69714259 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ +NULL = ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = common server python_modules -DIST_SUBDIRS = spice-protocol $(SUBDIRS) +SUBDIRS = spice-common server if SUPPORT_CLIENT SUBDIRS += client @@ -10,9 +10,11 @@ endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = spice-server.pc -DISTCLEANFILES = \ - spice-server.pc - -EXTRA_DIST = spice.proto spice1.proto spice_codegen.py - -DISTCHECK_CONFIGURE_FLAGS=--enable-opengl --enable-gui --enable-tunnel --enable-smartcard --with-sasl --enable-automated-tests +DISTCHECK_CONFIGURE_FLAGS = \ + --enable-automated-tests \ + --enable-gui \ + --enable-opengl \ + --enable-smartcard \ + --enable-tunnel \ + --with-sasl \ + $(NULL) @@ -8,8 +8,7 @@ test -z "$srcdir" && srcdir=. olddir=`pwd` cd "$srcdir" -git submodule init -git submodule update +git submodule update --init --recursive mkdir -p m4 autoreconf --verbose --force --install diff --git a/client/Makefile.am b/client/Makefile.am index c4b5fe1f..4913c1ee 100644 --- a/client/Makefile.am +++ b/client/Makefile.am @@ -2,27 +2,6 @@ NULL = bin_PROGRAMS = spicec -BUILT_SOURCES = \ - generated_demarshallers.cpp \ - generated_marshallers.cpp \ - generated_demarshallers1.cpp \ - generated_marshallers1.cpp \ - $(NULL) - -generated_demarshallers.cpp: $(top_srcdir)/spice.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h --include messages.h $(top_srcdir)/spice.proto generated_demarshallers.cpp - -generated_demarshallers1.cpp: $(top_srcdir)/spice1.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --client --include common.h --include messages.h --prefix 1 --ptrsize 8 $(top_srcdir)/spice1.proto generated_demarshallers1.cpp - -generated_marshallers.cpp: $(top_srcdir)/spice.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include "common.h" --include messages.h --include marshallers.h --client $(top_srcdir)/spice.proto generated_marshallers.cpp - -generated_marshallers1.cpp: $(top_srcdir)/spice1.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers -P --include "common.h" --include messages.h --include marshallers.h --client --prefix 1 --ptrsize 8 $(top_srcdir)/spice1.proto generated_marshallers1.cpp - -MAINTAINERCLEANFILES = $(BUILT_SOURCES) - spicec_SOURCES = \ application.cpp \ application.h \ @@ -43,7 +22,6 @@ spicec_SOURCES = \ cursor_channel.cpp \ cursor_channel.h \ debug.h \ - demarshallers.h \ display_channel.cpp \ display_channel.h \ event_sources.h \ @@ -63,7 +41,6 @@ spicec_SOURCES = \ inputs_handler.h \ jpeg_decoder.cpp \ jpeg_decoder.h \ - marshallers.h \ menu.cpp \ menu.h \ mjpeg_decoder.cpp \ @@ -230,7 +207,7 @@ INCLUDES = \ $(GL_CFLAGS) \ $(MISC_X_CFLAGS) \ $(PIXMAN_CFLAGS) \ - $(PROTOCOL_CFLAGS) \ + $(COMMON_CFLAGS) \ $(SPICE_NONPKGCONFIG_CFLAGS) \ $(SMARTCARD_CFLAGS) \ $(SSL_CFLAGS) \ @@ -243,24 +220,25 @@ INCLUDES = \ spicec_LDFLAGS = $(SPICEC_STATIC_LINKAGE_BSTATIC) -spicec_LDADD = \ - $(top_builddir)/common/libspice-common.la \ - $(ALSA_LIBS) \ - $(CEGUI_LIBS) \ - $(CEGUI06_LIBS) \ - $(CELT051_LIBS) \ - $(GL_LIBS) \ - $(JPEG_LIBS) \ - $(MISC_X_LIBS) \ - $(PIXMAN_LIBS) \ - $(SMARTCARD_LIBS) \ - $(SPICE_NONPKGCONFIG_LIBS) \ - $(SSL_LIBS) \ - $(XFIXES_LIBS) \ - $(XRANDR_LIBS) \ - $(Z_LIBS) \ - $(XINERAMA_LIBS) \ - $(spicec_resource_LDADD) \ +spicec_LDADD = \ + $(top_builddir)/spice-common/common/libspice-common.la \ + $(top_builddir)/spice-common/common/libspice-common-client.la \ + $(ALSA_LIBS) \ + $(CEGUI_LIBS) \ + $(CEGUI06_LIBS) \ + $(CELT051_LIBS) \ + $(GL_LIBS) \ + $(JPEG_LIBS) \ + $(MISC_X_LIBS) \ + $(PIXMAN_LIBS) \ + $(SMARTCARD_LIBS) \ + $(SPICE_NONPKGCONFIG_LIBS) \ + $(SSL_LIBS) \ + $(XFIXES_LIBS) \ + $(XRANDR_LIBS) \ + $(Z_LIBS) \ + $(XINERAMA_LIBS) \ + $(spicec_resource_LDADD) \ $(NULL) EXTRA_DIST = \ diff --git a/client/application.cpp b/client/application.cpp index 34ef729f..43fe7fa7 100644 --- a/client/application.cpp +++ b/client/application.cpp @@ -23,6 +23,10 @@ #include <io.h> #endif +#include "common/quic.h" +#include "common/mutex.h" +#include "common/rect.h" + #include "application.h" #include "screen.h" #include "utils.h" @@ -38,13 +42,10 @@ #ifdef USE_OPENGL #include "red_gl_canvas.h" #endif -#include "quic.h" -#include "mutex.h" #include "cmd_line_parser.h" #ifdef USE_TUNNEL #include "tunnel_channel.h" #endif -#include "rect.h" #ifdef USE_GUI #include "gui/gui.h" #endif diff --git a/client/canvas.h b/client/canvas.h index 51f28003..cd6a89b9 100644 --- a/client/canvas.h +++ b/client/canvas.h @@ -19,18 +19,20 @@ #ifndef _H_CANVAS #define _H_CANVAS +#include <map> + +#include "common/region.h" +#include "common/messages.h" +#include "common/canvas_utils.h" + #include "common.h" #include "debug.h" -#include "region.h" -#include "messages.h" #include "cache.hpp" #include "shared_cache.hpp" -#include "canvas_utils.h" #include "glz_decoded_image.h" #include "glz_decoder.h" #include "jpeg_decoder.h" #include "zlib_decoder.h" -#include <map> enum CanvasType { CANVAS_TYPE_INVALID, diff --git a/client/cursor.h b/client/cursor.h index 16b7fc52..3210f1e9 100644 --- a/client/cursor.h +++ b/client/cursor.h @@ -18,8 +18,8 @@ #ifndef _H_CURSOR_ #define _H_CURSOR_ +#include "common/messages.h" #include "threads.h" -#include "messages.h" #include "red_window_p.h" class CursorOpaque { diff --git a/client/cursor_channel.cpp b/client/cursor_channel.cpp index e317dfa2..48786e38 100644 --- a/client/cursor_channel.cpp +++ b/client/cursor_channel.cpp @@ -18,6 +18,8 @@ #include <config.h> #endif +#include "common/rect.h" + #include "common.h" #include "cursor_channel.h" #include "display_channel.h" @@ -28,7 +30,6 @@ #include "utils.h" #include "screen.h" #include "red_pixmap_sw.h" -#include "rect.h" static inline uint8_t revers_bits(uint8_t byte) { diff --git a/client/demarshallers.h b/client/demarshallers.h deleted file mode 100644 index 90084cf2..00000000 --- a/client/demarshallers.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - Copyright (C) 2010 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifndef _H_DEMARSHAL -#define _H_DEMARSHAL - -typedef void (*message_destructor_t)(uint8_t *message); -typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, - size_t *size_out, message_destructor_t *free_message); - -spice_parse_channel_func_t spice_get_server_channel_parser(uint32_t channel, unsigned int *max_message_type); -spice_parse_channel_func_t spice_get_server_channel_parser1(uint32_t channel, unsigned int *max_message_type); - -#endif diff --git a/client/display_channel.cpp b/client/display_channel.cpp index 173f012e..ebeacd2c 100644 --- a/client/display_channel.cpp +++ b/client/display_channel.cpp @@ -20,7 +20,6 @@ #endif #include "common.h" -#include "canvas.h" #include "red_pixmap.h" #ifdef USE_OPENGL #include "red_pixmap_gl.h" diff --git a/client/display_channel.h b/client/display_channel.h index 7cdd55c8..72856f59 100644 --- a/client/display_channel.h +++ b/client/display_channel.h @@ -19,9 +19,10 @@ #ifndef _H_DISPLAY_CHANNEL #define _H_DISPLAY_CHANNEL +#include "common/region.h" + #include "common.h" #include "canvas.h" -#include "region.h" #include "red_channel.h" #include "cache.hpp" #include "screen_layer.h" diff --git a/client/glz_decoder.h b/client/glz_decoder.h index a0352cc1..0d505fdb 100644 --- a/client/glz_decoder.h +++ b/client/glz_decoder.h @@ -19,7 +19,7 @@ #ifndef _H_GLZ_DECODER #define _H_GLZ_DECODER -#include "lz_common.h" +#include "common/lz_common.h" #include "glz_decoder_config.h" #include "glz_decoder_window.h" #include "red_canvas_base.h" diff --git a/client/glz_decoder_config.h b/client/glz_decoder_config.h index 52fa52d3..c15f012b 100644 --- a/client/glz_decoder_config.h +++ b/client/glz_decoder_config.h @@ -20,13 +20,11 @@ #include <exception> #include <sstream> - -#include "lz_common.h" - #include <stdio.h> #include <spice/types.h> #include <spice/macros.h> +#include "common/lz_common.h" class GlzException: public std::exception { public: diff --git a/client/jpeg_decoder.h b/client/jpeg_decoder.h index 8f7e1bb8..ae76f504 100644 --- a/client/jpeg_decoder.h +++ b/client/jpeg_decoder.h @@ -30,6 +30,11 @@ extern "C" { #include <jpeglib.h> +#ifdef HAVE_STDLIB_H +/* on mingw, there is a hack, + and we also include config.h from spice-common, which redefine it */ +#undef HAVE_STDLIB_H +#endif } class RGBConverter { diff --git a/client/marshallers.h b/client/marshallers.h deleted file mode 100644 index 47faefff..00000000 --- a/client/marshallers.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2010 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_MARSHALLERS -#define _H_MARSHALLERS - -#include <spice/protocol.h> -#include <marshaller.h> -#include <messages.h> - -typedef struct { - void (*msg_SpiceMsgEmpty)(SpiceMarshaller *m, SpiceMsgEmpty *msg); - void (*msg_SpiceMsgData)(SpiceMarshaller *m, SpiceMsgData *msg); - void (*msg_SpiceMsgAudioVolume)(SpiceMarshaller *m, SpiceMsgAudioVolume *msg); - void (*msg_SpiceMsgAudioMute)(SpiceMarshaller *m, SpiceMsgAudioMute *msg); - void (*msgc_ack_sync)(SpiceMarshaller *m, SpiceMsgcAckSync *msg); - void (*msgc_pong)(SpiceMarshaller *m, SpiceMsgPing *msg); - void (*msgc_disconnecting)(SpiceMarshaller *m, SpiceMsgDisconnect *msg); - void (*msgc_main_client_info)(SpiceMarshaller *m, SpiceMsgcClientInfo *msg); - void (*msgc_main_mouse_mode_request)(SpiceMarshaller *m, SpiceMsgcMainMouseModeRequest *msg); - void (*msgc_main_agent_start)(SpiceMarshaller *m, SpiceMsgcMainAgentStart *msg); - void (*msgc_main_agent_token)(SpiceMarshaller *m, SpiceMsgcMainAgentTokens *msg); - void (*msgc_display_init)(SpiceMarshaller *m, SpiceMsgcDisplayInit *msg); - void (*msgc_inputs_key_down)(SpiceMarshaller *m, SpiceMsgcKeyDown *msg); - void (*msgc_inputs_key_up)(SpiceMarshaller *m, SpiceMsgcKeyUp *msg); - void (*msgc_inputs_key_modifiers)(SpiceMarshaller *m, SpiceMsgcKeyModifiers *msg); - void (*msgc_inputs_mouse_motion)(SpiceMarshaller *m, SpiceMsgcMouseMotion *msg); - void (*msgc_inputs_mouse_position)(SpiceMarshaller *m, SpiceMsgcMousePosition *msg); - void (*msgc_inputs_mouse_press)(SpiceMarshaller *m, SpiceMsgcMousePress *msg); - void (*msgc_inputs_mouse_release)(SpiceMarshaller *m, SpiceMsgcMouseRelease *msg); - void (*msgc_record_data)(SpiceMarshaller *m, SpiceMsgcRecordPacket *msg); - void (*msgc_record_mode)(SpiceMarshaller *m, SpiceMsgcRecordMode *msg); - void (*msgc_record_start_mark)(SpiceMarshaller *m, SpiceMsgcRecordStartMark *msg); - void (*msgc_tunnel_service_add)(SpiceMarshaller *m, SpiceMsgcTunnelAddGenericService *msg, SpiceMarshaller **name_out, SpiceMarshaller **description_out); - void (*msgc_tunnel_service_remove)(SpiceMarshaller *m, SpiceMsgcTunnelRemoveService *msg); - void (*msgc_tunnel_socket_open_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenAck *msg); - void (*msgc_tunnel_socket_open_nack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketOpenNack *msg); - void (*msgc_tunnel_socket_fin)(SpiceMarshaller *m, SpiceMsgcTunnelSocketFin *msg); - void (*msgc_tunnel_socket_closed)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosed *msg); - void (*msgc_tunnel_socket_closed_ack)(SpiceMarshaller *m, SpiceMsgcTunnelSocketClosedAck *msg); - void (*msgc_tunnel_socket_data)(SpiceMarshaller *m, SpiceMsgcTunnelSocketData *msg); - void (*msgc_tunnel_socket_token)(SpiceMarshaller *m, SpiceMsgcTunnelSocketTokens *msg); -} SpiceMessageMarshallers; - -SpiceMessageMarshallers *spice_message_marshallers_get(void); -SpiceMessageMarshallers *spice_message_marshallers_get1(void); - -#endif diff --git a/client/monitor.h b/client/monitor.h index b8d7c88b..bbaaf17c 100644 --- a/client/monitor.h +++ b/client/monitor.h @@ -18,7 +18,7 @@ #ifndef _H_MONITOR #define _H_MONITOR -#include "draw.h" +#include "common/draw.h" class Monitor { public: diff --git a/client/pixels_source.h b/client/pixels_source.h index 1f4d1965..55841a65 100644 --- a/client/pixels_source.h +++ b/client/pixels_source.h @@ -18,7 +18,7 @@ #ifndef _H_PIXELS_SOURCE #define _H_PIXELS_SOURCE -#include "draw.h" +#include "common/draw.h" #define PIXELES_SOURCE_OPAQUE_SIZE (20 * sizeof(void*)) diff --git a/client/red_canvas_base.h b/client/red_canvas_base.h index bd59109c..15060552 100644 --- a/client/red_canvas_base.h +++ b/client/red_canvas_base.h @@ -19,7 +19,7 @@ #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "canvas_base.h" +#include "common/canvas_base.h" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/client/red_channel.h b/client/red_channel.h index a8390214..3cf51602 100644 --- a/client/red_channel.h +++ b/client/red_channel.h @@ -18,14 +18,15 @@ #ifndef _H_REDCHANNEL #define _H_REDCHANNEL +#include "common/client_demarshallers.h" +#include "common/client_marshallers.h" + #include "common.h" #include "utils.h" #include "threads.h" #include "red_peer.h" #include "platform.h" #include "process_loop.h" -#include "demarshallers.h" -#include "marshallers.h" enum { PASSIVE_STATE, diff --git a/client/red_client.cpp b/client/red_client.cpp index 04544083..8f86d3ef 100644 --- a/client/red_client.cpp +++ b/client/red_client.cpp @@ -18,15 +18,16 @@ #include <config.h> #endif -#include "common.h" +#include <algorithm> #include <math.h> +#include "common/client_marshallers.h" + +#include "common.h" #include "red_client.h" #include "application.h" #include "process_loop.h" #include "utils.h" #include "debug.h" -#include "marshallers.h" -#include <algorithm> #ifndef INFINITY #define INFINITY HUGE diff --git a/client/red_client.h b/client/red_client.h index 577ccb7a..a2f00c41 100644 --- a/client/red_client.h +++ b/client/red_client.h @@ -19,6 +19,7 @@ #define _H_REDCLIENT #include <list> +#include "common/messages.h" #include "common.h" #include "red_peer.h" @@ -27,7 +28,6 @@ #include "inputs_channel.h" #include "cursor_channel.h" #include "audio_channels.h" -#include "messages.h" #include <spice/vd_agent.h> #include "process_loop.h" diff --git a/client/red_drawable.h b/client/red_drawable.h index 660ff4e8..8ad3d4c4 100644 --- a/client/red_drawable.h +++ b/client/red_drawable.h @@ -18,7 +18,7 @@ #ifndef _H_RED_DRAWABLE #define _H_RED_DRAWABLE -#include <pixman_utils.h> +#include "common/pixman_utils.h" #include "pixels_source.h" #include "utils.h" diff --git a/client/red_gdi_canvas.cpp b/client/red_gdi_canvas.cpp index 2e42510a..09a15532 100644 --- a/client/red_gdi_canvas.cpp +++ b/client/red_gdi_canvas.cpp @@ -21,20 +21,24 @@ #include <config.h> #endif -#include "common.h" +#ifdef WIN32 +#include <winsock2.h> +#endif #include <stdint.h> -#include "red_gdi_canvas.h" -#include "utils.h" -#include "debug.h" -#include "region.h" -#include "red_pixmap_gdi.h" +#include "common/region.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "gdi_canvas.c" +#include "common/gdi_canvas.c" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL +#include "common.h" +#include "red_gdi_canvas.h" +#include "utils.h" +#include "debug.h" +#include "red_pixmap_gdi.h" + GDICanvas::GDICanvas(int width, int height, uint32_t format, PixmapCache& pixmap_cache, PaletteCache& palette_cache, GlzDecoderWindow &glz_decoder_window, SurfacesCache &csurfaces) diff --git a/client/red_gdi_canvas.h b/client/red_gdi_canvas.h index 77adcf7b..dbebe331 100644 --- a/client/red_gdi_canvas.h +++ b/client/red_gdi_canvas.h @@ -21,7 +21,7 @@ #include "canvas.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "gdi_canvas.h" +#include "common/gdi_canvas.h" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL #include "red_pixmap_gdi.h" diff --git a/client/red_gl_canvas.cpp b/client/red_gl_canvas.cpp index 59c8f06b..81203d99 100644 --- a/client/red_gl_canvas.cpp +++ b/client/red_gl_canvas.cpp @@ -18,21 +18,22 @@ #include <config.h> #endif -#include "common.h" #include <stdint.h> -#include "red_gl_canvas.h" -#include "utils.h" -#include "debug.h" -#include "region.h" -#include "red_pixmap_gl.h" #include <GL/glx.h> +#include "common/region.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "gl_canvas.c" +#include "common/gl_canvas.c" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL +#include "common.h" +#include "red_gl_canvas.h" +#include "utils.h" +#include "debug.h" +#include "red_pixmap_gl.h" + GCanvas::GCanvas(int width, int height, uint32_t format, RedWindow *win, RenderType rendertype, PixmapCache& pixmap_cache, PaletteCache& palette_cache, diff --git a/client/red_gl_canvas.h b/client/red_gl_canvas.h index a57ea480..e78b1cc8 100644 --- a/client/red_gl_canvas.h +++ b/client/red_gl_canvas.h @@ -21,8 +21,8 @@ #include "canvas.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "sw_canvas.h" -#include "gl_canvas.h" +#include "common/sw_canvas.h" +#include "common/gl_canvas.h" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/client/red_peer.cpp b/client/red_peer.cpp index 17fcb456..64e43d5b 100644 --- a/client/red_peer.cpp +++ b/client/red_peer.cpp @@ -19,15 +19,19 @@ #include <config.h> #endif -#include "common.h" +#ifdef WIN32 +#include <winsock2.h> +#endif #include <openssl/x509.h> #include <openssl/x509v3.h> #include <spice/protocol.h> +#include "common/ssl_verify.h" + +#include "common.h" #include "red_peer.h" #include "utils.h" #include "debug.h" #include "platform_utils.h" -#include "ssl_verify.h" static void ssl_error() { diff --git a/client/red_peer.h b/client/red_peer.h index 5e2b2b91..b0faa9d7 100644 --- a/client/red_peer.h +++ b/client/red_peer.h @@ -21,14 +21,15 @@ #include <openssl/ssl.h> #include <openssl/err.h> -#include "common.h" #include <spice/protocol.h> +#include "common/marshaller.h" +#include "common/ssl_verify.h" + +#include "common.h" #include "process_loop.h" #include "threads.h" #include "platform_utils.h" -#include "marshaller.h" #include "debug.h" -#include "ssl_verify.h" class RedPeer: protected EventSources::Socket { public: diff --git a/client/red_sw_canvas.cpp b/client/red_sw_canvas.cpp index 5f86dca1..d18af0f9 100644 --- a/client/red_sw_canvas.cpp +++ b/client/red_sw_canvas.cpp @@ -19,21 +19,25 @@ #include <config.h> #endif -#include "common.h" #include <stdint.h> -#include "red_window.h" -#include "red_sw_canvas.h" -#include "utils.h" -#include "debug.h" -#include "region.h" -#include "red_pixmap_sw.h" +#ifdef WIN32 +#include <winsock2.h> +#endif +#include "common/region.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "sw_canvas.c" +#include "common/sw_canvas.c" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL +#include "common.h" +#include "red_window.h" +#include "red_sw_canvas.h" +#include "utils.h" +#include "debug.h" +#include "red_pixmap_sw.h" + SCanvas::SCanvas(bool onscreen, int width, int height, uint32_t format, RedWindow *win, PixmapCache& pixmap_cache, PaletteCache& palette_cache, diff --git a/client/red_sw_canvas.h b/client/red_sw_canvas.h index eb577aca..a192c47b 100644 --- a/client/red_sw_canvas.h +++ b/client/red_sw_canvas.h @@ -22,7 +22,7 @@ #include "canvas.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_CACHE -#include "sw_canvas.h" +#include "common/sw_canvas.h" #undef SW_CANVAS_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/client/screen.h b/client/screen.h index d7bb4c27..4093006f 100644 --- a/client/screen.h +++ b/client/screen.h @@ -18,8 +18,9 @@ #ifndef _H_SCREEN #define _H_SCREEN +#include "common/region.h" + #include "common.h" -#include "region.h" #include "red_key.h" #ifdef USE_OPENGL #include "GL/gl.h" diff --git a/client/screen_layer.h b/client/screen_layer.h index e8ad4217..1168b245 100644 --- a/client/screen_layer.h +++ b/client/screen_layer.h @@ -18,8 +18,8 @@ #ifndef _H_SCREEN_LAYER #define _H_SCREEN_LAYER +#include "common/region.h" #include "threads.h" -#include "region.h" class RedScreen; class Application; diff --git a/client/smartcard_channel.cpp b/client/smartcard_channel.cpp index 09659c21..720b879f 100644 --- a/client/smartcard_channel.cpp +++ b/client/smartcard_channel.cpp @@ -19,9 +19,9 @@ #endif #include <spice/enums.h> +#include "common/mutex.h" #include "red_client.h" -#include "mutex.h" extern "C" { #include <vscard_common.h> diff --git a/client/x11/pixels_source_p.h b/client/x11/pixels_source_p.h index 000fe4d0..64b0c50e 100644 --- a/client/x11/pixels_source_p.h +++ b/client/x11/pixels_source_p.h @@ -29,7 +29,8 @@ #ifdef USE_OPENGL #include "red_pixmap_gl.h" #endif // USE_OPENGL -#include "pixman_utils.h" + +#include "common/pixman_utils.h" enum { PIXELS_SOURCE_TYPE_INVALID, diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp index f535d6da..f35d5374 100644 --- a/client/x11/platform.cpp +++ b/client/x11/platform.cpp @@ -48,20 +48,21 @@ #include <sys/time.h> #endif +#include <spice/vd_agent.h> +#include "common/rect.h" + #include "platform.h" #include "application.h" #include "utils.h" #include "x_platform.h" #include "debug.h" #include "monitor.h" -#include "rect.h" #include "record.h" #include "playback.h" #include "resource.h" #include "res.h" #include "cursor.h" #include "process_loop.h" -#include <spice/vd_agent.h> #define DWORD uint32_t #define BOOL bool diff --git a/client/x11/red_drawable.cpp b/client/x11/red_drawable.cpp index fd5d4a16..bb8ceb44 100644 --- a/client/x11/red_drawable.cpp +++ b/client/x11/red_drawable.cpp @@ -26,7 +26,7 @@ #include "utils.h" #ifdef USE_OPENGL -#include "gl_utils.h" +#include "common/gl_utils.h" #include <GL/gl.h> #include <GL/glu.h> #include <GL/glext.h> diff --git a/client/x11/red_pixmap_gl.cpp b/client/x11/red_pixmap_gl.cpp index 1e1e6e0f..8d81c31a 100644 --- a/client/x11/red_pixmap_gl.cpp +++ b/client/x11/red_pixmap_gl.cpp @@ -22,12 +22,12 @@ #include <GL/glu.h> #include <GL/glext.h> #include <X11/Xlib.h> +#include "common/gl_utils.h" #include "common.h" #include "red_pixmap_gl.h" #include "debug.h" #include "utils.h" -#include "gl_utils.h" #include "pixels_source_p.h" #include "x_platform.h" #include "red_window_p.h" diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp index fda90d59..83144a54 100644 --- a/client/x11/red_window.cpp +++ b/client/x11/red_window.cpp @@ -33,21 +33,22 @@ #endif // USE_OPENGL #include <stdio.h> +#include <spice/protocol.h> +#include "common/region.h" + +#ifdef USE_OPENGL +#include "common/gl_utils.h" +#include "red_pixmap_gl.h" +#endif // USE_OPENGL + #include "red_window.h" #include "utils.h" #include "debug.h" #include "platform.h" #include "x_platform.h" #include "pixels_source_p.h" -#include <spice/protocol.h> -#include "region.h" -#ifdef USE_OPENGL -#include "gl_utils.h" -#include "red_pixmap_gl.h" -#endif // USE_OPENGL #include "x_icon.h" - #define X_RETRIES 10 #define X_RETRY_DELAY_MICRO (1000 * 100) #define RAISE_RETRIES X_RETRIES diff --git a/common/.gitignore b/common/.gitignore deleted file mode 100644 index d033f47d..00000000 --- a/common/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -*.la -*.lo -*.loT -*.o -.deps -.dirstamp -.libs -Makefile -Makefile.in diff --git a/common/Makefile.am b/common/Makefile.am deleted file mode 100644 index 4189dc1f..00000000 --- a/common/Makefile.am +++ /dev/null @@ -1,76 +0,0 @@ -if OS_WIN32 -SUBDIRS = win -endif - -NULL = - -noinst_LTLIBRARIES = libspice-common.la -libspice_common_la_SOURCES = \ - bitops.h \ - canvas_utils.c \ - canvas_utils.h \ - draw.h \ - lines.c \ - lines.h \ - lz.c \ - lz.h \ - lz_common.h \ - lz_config.h \ - marshaller.c \ - marshaller.h \ - mem.c \ - mem.h \ - messages.h \ - mutex.h \ - pixman_utils.c \ - pixman_utils.h \ - quic.c \ - quic.h \ - quic_config.h \ - rect.h \ - region.c \ - region.h \ - ring.h \ - rop3.c \ - rop3.h \ - spice_common.h \ - ssl_verify.c \ - ssl_verify.h \ - backtrace.c \ - backtrace.h \ - $(NULL) - -if SUPPORT_GL -libspice_common_la_SOURCES += \ - gl_utils.h \ - glc.h \ - glc.c \ - ogl_ctx.h \ - ogl_ctx.c \ - $(NULL) -endif - -INCLUDES = \ - $(GL_CFLAGS) \ - $(PIXMAN_CFLAGS) \ - $(PROTOCOL_CFLAGS) \ - $(VISIBILITY_HIDDEN_CFLAGS) \ - $(WARN_CFLAGS) \ - -std=gnu99 \ - $(NULL) - -EXTRA_DIST = \ - canvas_base.c \ - canvas_base.h \ - gdi_canvas.c \ - gdi_canvas.h \ - gl_canvas.c \ - gl_canvas.h \ - sw_canvas.c \ - sw_canvas.h \ - lz_compress_tmpl.c \ - lz_decompress_tmpl.c \ - quic_family_tmpl.c \ - quic_rgb_tmpl.c \ - quic_tmpl.c \ - $(NULL) diff --git a/common/backtrace.c b/common/backtrace.c deleted file mode 100644 index c8f46263..00000000 --- a/common/backtrace.c +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2011 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -/* - * Taken from xserver os/backtrace.c: - * Copyright (C) 2008 Red Hat, Inc. - */ - -#include <config.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <sys/types.h> -#ifndef __MINGW32__ -#include <sys/wait.h> -#endif - -#include "spice_common.h" - -#define GSTACK_PATH "/usr/bin/gstack" - -#if HAVE_EXECINFO_H -#include <execinfo.h> - -static void spice_backtrace_backtrace(void) -{ - void *array[100]; - int size; - - size = backtrace(array, sizeof(array)/sizeof(array[0])); - backtrace_symbols_fd(array, size, STDERR_FILENO); -} -#else -static void spice_backtrace_backtrace(void) -{ -} -#endif - -/* XXX perhaps gstack can be available in windows but pipe/waitpid isn't, - * so until it is ported properly just compile it out, we lose the - * backtrace only. */ -#ifndef __MINGW32__ -static int spice_backtrace_gstack(void) -{ - pid_t kidpid; - int pipefd[2]; - - if (pipe(pipefd) != 0) { - return -1; - } - - kidpid = fork(); - - if (kidpid == -1) { - /* ERROR */ - return -1; - } else if (kidpid == 0) { - /* CHILD */ - char parent[16]; - - seteuid(0); - close(STDIN_FILENO); - close(STDOUT_FILENO); - dup2(pipefd[1],STDOUT_FILENO); - close(STDERR_FILENO); - - snprintf(parent, sizeof(parent), "%d", getppid()); - execle(GSTACK_PATH, "gstack", parent, NULL, NULL); - exit(1); - } else { - /* PARENT */ - char btline[256]; - int kidstat; - int bytesread; - int done = 0; - - close(pipefd[1]); - - while (!done) { - bytesread = read(pipefd[0], btline, sizeof(btline) - 1); - - if (bytesread > 0) { - btline[bytesread] = 0; - fprintf(stderr, "%s", btline); - } - else if ((bytesread == 0) || - ((errno != EINTR) && (errno != EAGAIN))) { - done = 1; - } - } - close(pipefd[0]); - waitpid(kidpid, &kidstat, 0); - if (kidstat != 0) - return -1; - } - return 0; -} -#else -static int spice_backtrace_gstack(void) -{ - /* empty failing implementation */ - return -1; -} -#endif - -void spice_backtrace(void) -{ - int ret = -1; - - if (!access(GSTACK_PATH, X_OK)) { - ret = spice_backtrace_gstack(); - } - if (ret != 0) { - spice_backtrace_backtrace(); - } -} diff --git a/common/backtrace.h b/common/backtrace.h deleted file mode 100644 index 894c0277..00000000 --- a/common/backtrace.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2011 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef BACKTRACE_H -#define BACKTRACE_H - -#include <spice/macros.h> - -SPICE_BEGIN_DECLS - -#if defined(WIN32) && !defined(__MINGW32__) -#define spice_backtrace() -#else -void spice_backtrace(void); -#endif - -SPICE_END_DECLS - -#endif // BACKTRACE_H diff --git a/common/bitops.h b/common/bitops.h deleted file mode 100644 index bdd862a3..00000000 --- a/common/bitops.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef BITOPS_H -#define BITOPS_H - -#include <spice/macros.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -static inline int spice_bit_find_msb(unsigned int val) -{ - int ret; - - asm ("bsrl %1,%0\n\t" - "jnz 1f\n\t" - "movl $-1,%0\n" - "1:" - : "=r"(ret) : "r"(val)); - return ret + 1; -} - -#elif defined(WIN32) && !defined(_WIN64) -static INLINE int spice_bit_find_msb(uint32_t val) -{ - uint32_t r; - __asm { - bsr eax, val - jnz found - mov eax, -1 - -found: - mov r, eax - } - return r + 1; -} - -#else -static INLINE int spice_bit_find_msb(unsigned int val) -{ - signed char index = 31; - - if(val == 0) { - return 0; - } - - do { - if(val & 0x80000000) { - break; - } - val <<= 1; - } while(--index >= 0); - - return index+1; -} - -#endif - -static INLINE int spice_bit_next_pow2(unsigned int val) -{ - if ((val & (val - 1)) == 0) { - return val; - } - return 1 << spice_bit_find_msb(val); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/canvas_base.c b/common/canvas_base.c deleted file mode 100644 index c4203dd7..00000000 --- a/common/canvas_base.c +++ /dev/null @@ -1,3394 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef SPICE_CANVAS_INTERNAL -#error "This file shouldn't be compiled directly" -#endif - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdarg.h> -#include <stdlib.h> -#include <setjmp.h> -#include <stdio.h> -#include <math.h> - -#include <spice/macros.h> -#include "quic.h" -#include "lz.h" -#include "canvas_base.h" -#include "pixman_utils.h" -#include "canvas_utils.h" -#include "rect.h" -#include "lines.h" -#include "rop3.h" -#include "mem.h" - -#include "mutex.h" - -#ifndef CANVAS_ERROR -#define CANVAS_ERROR(format, ...) { \ - printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__); \ - abort(); \ -} -#endif - -#ifndef WARN -#define WARN(x) printf("warning: %s\n", x) -#endif - -#ifndef DBG -#define DBG(level, format, ...) printf("%s: debug: " format "\n", __FUNCTION__, ## __VA_ARGS__); -#endif - -#define ROUND(_x) ((int)floor((_x) + 0.5)) - -#define IS_IMAGE_LOSSY(descriptor) \ - (((descriptor)->type == SPICE_IMAGE_TYPE_JPEG) || \ - ((descriptor)->type == SPICE_IMAGE_TYPE_JPEG_ALPHA)) - - static inline int fix_to_int(SPICE_FIXED28_4 fixed) -{ - int val, rem; - - rem = fixed & 0x0f; - val = fixed >> 4; - if (rem > 8) { - val++; - } - return val; -} - - static inline SPICE_FIXED28_4 int_to_fix(int v) -{ - return v << 4; -} - -static inline double fix_to_double(SPICE_FIXED28_4 fixed) -{ - return (double)(fixed & 0x0f) / 0x0f + (fixed >> 4); -} - -static inline uint16_t rgb_32_to_16_555(uint32_t color) -{ - return - (((color) >> 3) & 0x001f) | - (((color) >> 6) & 0x03e0) | - (((color) >> 9) & 0x7c00); -} -static inline uint16_t rgb_32_to_16_565(uint32_t color) -{ - return - (((color) >> 3) & 0x001f) | - (((color) >> 5) & 0x07e0) | - (((color) >> 8) & 0xf800); -} - -static inline uint32_t canvas_16bpp_to_32bpp(uint32_t color) -{ - uint32_t ret; - - ret = ((color & 0x001f) << 3) | ((color & 0x001c) >> 2); - ret |= ((color & 0x03e0) << 6) | ((color & 0x0380) << 1); - ret |= ((color & 0x7c00) << 9) | ((color & 0x7000) << 4); - - return ret; -} -#if defined(WIN32) && defined(GDI_CANVAS) -static HDC create_compatible_dc() -{ - HDC dc = CreateCompatibleDC(NULL); - if (!dc) { - CANVAS_ERROR("create compatible DC failed"); - } - return dc; -} - -#endif - -typedef struct LzData { - LzUsrContext usr; - LzContext *lz; - LzDecodeUsrData decode_data; - jmp_buf jmp_env; - char message_buf[512]; -} LzData; - -typedef struct GlzData { - SpiceGlzDecoder *decoder; - LzDecodeUsrData decode_data; -} GlzData; - -typedef struct QuicData { - QuicUsrContext usr; - QuicContext *quic; - jmp_buf jmp_env; - char message_buf[512]; - SpiceChunks *chunks; - uint32_t current_chunk; -} QuicData; - -typedef struct CanvasBase { - SpiceCanvas parent; - uint32_t color_shift; - uint32_t color_mask; - QuicData quic_data; - - uint32_t format; - int width; - int height; - pixman_region32_t canvas_region; - -#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) - SpiceImageCache *bits_cache; -#endif -#ifdef SW_CANVAS_CACHE - SpicePaletteCache *palette_cache; -#endif -#ifdef WIN32 - HDC dc; -#endif - - SpiceImageSurfaces *surfaces; - - LzData lz_data; - GlzData glz_data; - SpiceJpegDecoder* jpeg; - SpiceZlibDecoder* zlib; - - void *usr_data; - spice_destroy_fn_t usr_data_destroy; -} CanvasBase; - -typedef enum { - ROP_INPUT_SRC, - ROP_INPUT_BRUSH, - ROP_INPUT_DEST -} ROPInput; - -static SpiceROP ropd_descriptor_to_rop(int desc, - ROPInput src_input, - ROPInput dest_input) -{ - int old; - int invert_masks[] = { - SPICE_ROPD_INVERS_SRC, - SPICE_ROPD_INVERS_BRUSH, - SPICE_ROPD_INVERS_DEST - }; - - old = desc; - - desc &= ~(SPICE_ROPD_INVERS_SRC | SPICE_ROPD_INVERS_DEST); - if (old & invert_masks[src_input]) { - desc |= SPICE_ROPD_INVERS_SRC; - } - - if (old & invert_masks[dest_input]) { - desc |= SPICE_ROPD_INVERS_DEST; - } - - if (desc & SPICE_ROPD_OP_PUT) { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_RES) { - return SPICE_ROP_COPY; - } - return SPICE_ROP_COPY_INVERTED; - } else { - if (desc & SPICE_ROPD_INVERS_RES) { - return SPICE_ROP_COPY_INVERTED; - } - return SPICE_ROP_COPY; - } - } else if (desc & SPICE_ROPD_OP_OR) { - - if (desc & SPICE_ROPD_INVERS_RES) { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !(!src or !dest) == src and dest*/ - return SPICE_ROP_AND; - } else { - /* ! (!src or dest) = src and !dest*/ - return SPICE_ROP_AND_REVERSE; - } - } else { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !(src or !dest) == !src and dest */ - return SPICE_ROP_AND_INVERTED; - } else { - /* !(src or dest) */ - return SPICE_ROP_NOR; - } - } - } else { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !src or !dest == !(src and dest)*/ - return SPICE_ROP_NAND; - } else { - /* !src or dest */ - return SPICE_ROP_OR_INVERTED; - } - } else { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* src or !dest */ - return SPICE_ROP_OR_REVERSE; - } else { - /* src or dest */ - return SPICE_ROP_OR; - } - } - } - - } else if (desc & SPICE_ROPD_OP_AND) { - - if (desc & SPICE_ROPD_INVERS_RES) { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !(!src and !dest) == src or dest*/ - return SPICE_ROP_OR; - } else { - /* ! (!src and dest) = src or !dest*/ - return SPICE_ROP_OR_REVERSE; - } - } else { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !(src and !dest) == !src or dest */ - return SPICE_ROP_OR_INVERTED; - } else { - /* !(src and dest) */ - return SPICE_ROP_NAND; - } - } - } else { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !src and !dest == !(src or dest)*/ - return SPICE_ROP_NOR; - } else { - /* !src and dest */ - return SPICE_ROP_AND_INVERTED; - } - } else { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* src and !dest */ - return SPICE_ROP_AND_REVERSE; - } else { - /* src and dest */ - return SPICE_ROP_AND; - } - } - } - - } else if (desc & SPICE_ROPD_OP_XOR) { - - if (desc & SPICE_ROPD_INVERS_RES) { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !(!src xor !dest) == !src xor dest */ - return SPICE_ROP_EQUIV; - } else { - /* ! (!src xor dest) = src xor dest*/ - return SPICE_ROP_XOR; - } - } else { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !(src xor !dest) == src xor dest */ - return SPICE_ROP_XOR; - } else { - /* !(src xor dest) */ - return SPICE_ROP_EQUIV; - } - } - } else { - if (desc & SPICE_ROPD_INVERS_SRC) { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* !src xor !dest == src xor dest */ - return SPICE_ROP_XOR; - } else { - /* !src xor dest */ - return SPICE_ROP_EQUIV; - } - } else { - if (desc & SPICE_ROPD_INVERS_DEST) { - /* src xor !dest */ - return SPICE_ROP_EQUIV; - } else { - /* src xor dest */ - return SPICE_ROP_XOR; - } - } - } - - } else if (desc & SPICE_ROPD_OP_BLACKNESS) { - return SPICE_ROP_CLEAR; - } else if (desc & SPICE_ROPD_OP_WHITENESS) { - return SPICE_ROP_SET; - } else if (desc & SPICE_ROPD_OP_INVERS) { - return SPICE_ROP_INVERT; - } - return SPICE_ROP_COPY; -} - -//#define DEBUG_DUMP_COMPRESS -#ifdef DEBUG_DUMP_COMPRESS -static void dump_surface(pixman_image_t *surface, int cache); -#endif - - -static pixman_format_code_t canvas_get_target_format(CanvasBase *canvas, - int source_has_alpha) -{ - pixman_format_code_t format; - - /* Convert to target surface format */ - format = spice_surface_format_to_pixman (canvas->format); - - if (source_has_alpha) { - /* Even though the destination has no alpha, we make the source - * remember there are alpha bits instead of throwing away this - * information. The results are the same if alpha is not - * interpreted, and if need to interpret alpha, don't use - * conversion to target format. - * This is needed for instance when doing the final - * canvas_get_target_format() in canvas_get_image_internal - * as otherwise we wouldn't know if the bitmap source - * really had alpha. - */ - if (format == PIXMAN_x8r8g8b8) { - format = PIXMAN_a8r8g8b8; - } - } else { /* !source_has_alpha */ - /* If the source doesn't have alpha, but the destination has, - don't convert to alpha, since that would just do an unnecessary - copy to fill the alpha bytes with 0xff which is not expected if - we just use the raw bits, (and handled implicitly by pixman if - we're interpreting data) */ - if (format == PIXMAN_a8r8g8b8) { - format = PIXMAN_x8r8g8b8; - } - } - - return format; -} - -static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceImage *image, - int invers, int want_original) -{ - pixman_image_t *surface = NULL; - QuicData *quic_data = &canvas->quic_data; - QuicImageType type, as_type; - pixman_format_code_t pixman_format; - uint8_t *dest; - int stride; - int width; - int height; - - if (setjmp(quic_data->jmp_env)) { - pixman_image_unref(surface); - CANVAS_ERROR("quic error, %s", quic_data->message_buf); - } - - quic_data->chunks = image->u.quic.data; - quic_data->current_chunk = 0; - - if (quic_decode_begin(quic_data->quic, - (uint32_t *)image->u.quic.data->chunk[0].data, - image->u.quic.data->chunk[0].len >> 2, - &type, &width, &height) == QUIC_ERROR) { - CANVAS_ERROR("quic decode begin failed"); - } - - switch (type) { - case QUIC_IMAGE_TYPE_RGBA: - as_type = QUIC_IMAGE_TYPE_RGBA; - pixman_format = PIXMAN_a8r8g8b8; - break; - case QUIC_IMAGE_TYPE_RGB32: - case QUIC_IMAGE_TYPE_RGB24: - as_type = QUIC_IMAGE_TYPE_RGB32; - pixman_format = PIXMAN_x8r8g8b8; - break; - case QUIC_IMAGE_TYPE_RGB16: - if (!want_original && - (canvas->format == SPICE_SURFACE_FMT_32_xRGB || - canvas->format == SPICE_SURFACE_FMT_32_ARGB)) { - as_type = QUIC_IMAGE_TYPE_RGB32; - pixman_format = PIXMAN_x8r8g8b8; - } else { - as_type = QUIC_IMAGE_TYPE_RGB16; - pixman_format = PIXMAN_x1r5g5b5; - } - break; - case QUIC_IMAGE_TYPE_INVALID: - case QUIC_IMAGE_TYPE_GRAY: - default: - CANVAS_ERROR("unexpected image type"); - } - - ASSERT((uint32_t)width == image->descriptor.width); - ASSERT((uint32_t)height == image->descriptor.height); - - surface = surface_create( -#ifdef WIN32 - canvas->dc, -#endif - pixman_format, - width, height, FALSE); - - if (surface == NULL) { - CANVAS_ERROR("create surface failed"); - } - - dest = (uint8_t *)pixman_image_get_data(surface); - stride = pixman_image_get_stride(surface); - if (quic_decode(quic_data->quic, as_type, - dest, stride) == QUIC_ERROR) { - pixman_image_unref(surface); - CANVAS_ERROR("quic decode failed"); - } - - if (invers) { - uint8_t *end = dest + height * stride; - for (; dest != end; dest += stride) { - uint32_t *pix; - uint32_t *end_pix; - - pix = (uint32_t *)dest; - end_pix = pix + width; - for (; pix < end_pix; pix++) { - *pix ^= 0xffffffff; - } - } - } - -#ifdef DEBUG_DUMP_COMPRESS - dump_surface(surface, 0); -#endif - return surface; -} - - -//#define DUMP_JPEG -#ifdef DUMP_JPEG -static int jpeg_id = 0; -static void dump_jpeg(uint8_t* data, int data_size) -{ - char file_str[200]; - uint32_t id = ++jpeg_id; - -#ifdef WIN32 - sprintf(file_str, "c:\\tmp\\spice_dump\\%u.jpg", id); -#else - sprintf(file_str, "/tmp/spice_dump/%u.jpg", id); -#endif - - FILE *f = fopen(file_str, "wb"); - if (!f) { - return; - } - - fwrite(data, 1, data_size, f); - fclose(f); -} -#endif - -static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceImage *image, int invers) -{ - pixman_image_t *surface = NULL; - int stride; - int width; - int height; - uint8_t *dest; - - ASSERT(image->u.jpeg.data->num_chunks == 1); /* TODO: Handle chunks */ - canvas->jpeg->ops->begin_decode(canvas->jpeg, image->u.jpeg.data->chunk[0].data, image->u.jpeg.data->chunk[0].len, - &width, &height); - ASSERT((uint32_t)width == image->descriptor.width); - ASSERT((uint32_t)height == image->descriptor.height); - - surface = surface_create( -#ifdef WIN32 - canvas->dc, -#endif - PIXMAN_x8r8g8b8, - width, height, FALSE); - if (surface == NULL) { - CANVAS_ERROR("create surface failed"); - } - - dest = (uint8_t *)pixman_image_get_data(surface); - stride = pixman_image_get_stride(surface); - - canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT); - - if (invers) { - uint8_t *end = dest + height * stride; - for (; dest != end; dest += stride) { - uint32_t *pix; - uint32_t *end_pix; - - pix = (uint32_t *)dest; - end_pix = pix + width; - for (; pix < end_pix; pix++) { - *pix ^= 0x00ffffff; - } - } - } -#ifdef DUMP_JPEG - dump_jpeg(image->u.jpeg.data, image->u.jpeg.data_size); -#endif - return surface; -} - -static pixman_image_t *canvas_get_jpeg_alpha(CanvasBase *canvas, - SpiceImage *image, int invers) -{ - pixman_image_t *surface = NULL; - int stride; - int width; - int height; - uint8_t *dest; - int alpha_top_down = FALSE; - LzData *lz_data = &canvas->lz_data; - LzImageType lz_alpha_type; - uint8_t *comp_alpha_buf = NULL; - uint8_t *decomp_alpha_buf = NULL; - int alpha_size; - int lz_alpha_width, lz_alpha_height, n_comp_pixels, lz_alpha_top_down; - - ASSERT(image->u.jpeg_alpha.data->num_chunks == 1); - canvas->jpeg->ops->begin_decode(canvas->jpeg, - image->u.jpeg_alpha.data->chunk[0].data, - image->u.jpeg_alpha.jpeg_size, - &width, &height); - ASSERT((uint32_t)width == image->descriptor.width); - ASSERT((uint32_t)height == image->descriptor.height); - - if (image->u.jpeg_alpha.flags & SPICE_JPEG_ALPHA_FLAGS_TOP_DOWN) { - alpha_top_down = TRUE; - } - -#ifdef WIN32 - lz_data->decode_data.dc = canvas->dc; -#endif - surface = alloc_lz_image_surface(&lz_data->decode_data, PIXMAN_a8r8g8b8, - width, height, width*height, alpha_top_down); - - if (surface == NULL) { - CANVAS_ERROR("create surface failed"); - } - - dest = (uint8_t *)pixman_image_get_data(surface); - stride = pixman_image_get_stride(surface); - - canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT); - - comp_alpha_buf = image->u.jpeg_alpha.data->chunk[0].data + image->u.jpeg_alpha.jpeg_size; - alpha_size = image->u.jpeg_alpha.data_size - image->u.jpeg_alpha.jpeg_size; - - lz_decode_begin(lz_data->lz, comp_alpha_buf, alpha_size, &lz_alpha_type, - &lz_alpha_width, &lz_alpha_height, &n_comp_pixels, - &lz_alpha_top_down, NULL); - ASSERT(lz_alpha_type == LZ_IMAGE_TYPE_XXXA); - ASSERT(!!lz_alpha_top_down == !!alpha_top_down); - ASSERT(lz_alpha_width == width); - ASSERT(lz_alpha_height == height); - ASSERT(n_comp_pixels == width * height); - - if (!alpha_top_down) { - decomp_alpha_buf = dest + stride * (height - 1); - } else { - decomp_alpha_buf = dest; - } - lz_decode(lz_data->lz, LZ_IMAGE_TYPE_XXXA, decomp_alpha_buf); - - if (invers) { - uint8_t *end = dest + height * stride; - for (; dest != end; dest += stride) { - uint32_t *pix; - uint32_t *end_pix; - - pix = (uint32_t *)dest; - end_pix = pix + width; - for (; pix < end_pix; pix++) { - *pix ^= 0x00ffffff; - } - } - } -#ifdef DUMP_JPEG - dump_jpeg(image->u.jpeg_alpha.data, image->u.jpeg_alpha.jpeg_size); -#endif - return surface; -} - -static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap* bitmap, - SpicePalette *palette, int want_original) -{ - uint8_t* src; - pixman_image_t *image; - pixman_format_code_t format; - - spice_chunks_linearize(bitmap->data); - - src = bitmap->data->chunk[0].data; - - if (want_original) { - format = spice_bitmap_format_to_pixman(bitmap->format, canvas->format); - } else { - format = canvas_get_target_format(canvas, - bitmap->format == SPICE_BITMAP_FMT_RGBA); - } - - image = surface_create( -#ifdef WIN32 - canvas->dc, -#endif - format, - bitmap->x, bitmap->y, FALSE); - if (image == NULL) { - CANVAS_ERROR("create surface failed"); - } - - spice_bitmap_convert_to_pixman(format, image, - bitmap->format, - bitmap->flags, - bitmap->x, bitmap->y, - src, bitmap->stride, - canvas->format, palette); - return image; -} - - -#ifdef SW_CANVAS_CACHE - -static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags) -{ - SpicePalette *palette; - - if (flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE) { - palette = canvas->palette_cache->ops->get(canvas->palette_cache, palette_id); - } else { - palette = base_palette; - if (palette != NULL && flags & SPICE_BITMAP_FLAGS_PAL_CACHE_ME) { - canvas->palette_cache->ops->put(canvas->palette_cache, palette); - } - } - return palette; -} - -static inline SpicePalette *canvas_get_localized_palette(CanvasBase *canvas, SpicePalette *base_palette, uint64_t palette_id, uint8_t flags, int *free_palette) -{ - SpicePalette *palette = canvas_get_palette(canvas, base_palette, palette_id, flags); - SpicePalette *copy; - uint32_t *now, *end; - size_t size; - - if (canvas->format == SPICE_SURFACE_FMT_32_xRGB || - canvas->format == SPICE_SURFACE_FMT_32_ARGB) { - return palette; - } - - size = sizeof(SpicePalette) + palette->num_ents * 4; - copy = (SpicePalette *)spice_malloc(size); - memcpy(copy, palette, size); - - switch (canvas->format) { - case SPICE_SURFACE_FMT_32_xRGB: - case SPICE_SURFACE_FMT_32_ARGB: - /* Won't happen */ - break; - case SPICE_SURFACE_FMT_16_555: - now = copy->ents; - end = now + copy->num_ents; - for (; now < end; now++) { - *now = canvas_16bpp_to_32bpp(*now); - } - break; - case SPICE_SURFACE_FMT_16_565: - default: - PANIC("Unsupported palette depth"); - } - *free_palette = TRUE; - return copy; -} - -static pixman_image_t *canvas_get_lz(CanvasBase *canvas, SpiceImage *image, int invers, - int want_original) -{ - LzData *lz_data = &canvas->lz_data; - uint8_t *comp_buf = NULL; - int comp_size; - uint8_t *decomp_buf = NULL; - uint8_t *src; - pixman_format_code_t pixman_format; - LzImageType type, as_type; - SpicePalette *palette; - int n_comp_pixels; - int width; - int height; - int top_down; - int stride; - int free_palette; - - if (setjmp(lz_data->jmp_env)) { - free(decomp_buf); - CANVAS_ERROR("lz error, %s", lz_data->message_buf); - } - - free_palette = FALSE; - if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB) { - ASSERT(image->u.lz_rgb.data->num_chunks == 1); /* TODO: Handle chunks */ - comp_buf = image->u.lz_rgb.data->chunk[0].data; - comp_size = image->u.lz_rgb.data->chunk[0].len; - palette = NULL; - } else if (image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) { - ASSERT(image->u.lz_plt.data->num_chunks == 1); /* TODO: Handle chunks */ - comp_buf = image->u.lz_plt.data->chunk[0].data; - comp_size = image->u.lz_plt.data->chunk[0].len; - palette = canvas_get_localized_palette(canvas, image->u.lz_plt.palette, image->u.lz_plt.palette_id, image->u.lz_plt.flags, &free_palette); - } else { - CANVAS_ERROR("unexpected image type"); - } - - lz_decode_begin(lz_data->lz, comp_buf, comp_size, &type, - &width, &height, &n_comp_pixels, &top_down, palette); - - switch (type) { - case LZ_IMAGE_TYPE_RGBA: - as_type = LZ_IMAGE_TYPE_RGBA; - pixman_format = PIXMAN_a8r8g8b8; - break; - case LZ_IMAGE_TYPE_RGB32: - case LZ_IMAGE_TYPE_RGB24: - case LZ_IMAGE_TYPE_PLT1_LE: - case LZ_IMAGE_TYPE_PLT1_BE: - case LZ_IMAGE_TYPE_PLT4_LE: - case LZ_IMAGE_TYPE_PLT4_BE: - case LZ_IMAGE_TYPE_PLT8: - as_type = LZ_IMAGE_TYPE_RGB32; - pixman_format = PIXMAN_x8r8g8b8; - break; - case LZ_IMAGE_TYPE_RGB16: - if (!want_original && - (canvas->format == SPICE_SURFACE_FMT_32_xRGB || - canvas->format == SPICE_SURFACE_FMT_32_ARGB)) { - as_type = LZ_IMAGE_TYPE_RGB32; - pixman_format = PIXMAN_x8r8g8b8; - } else { - as_type = LZ_IMAGE_TYPE_RGB16; - pixman_format = PIXMAN_x1r5g5b5; - } - break; - default: - CANVAS_ERROR("unexpected LZ image type"); - } - - ASSERT((unsigned)width == image->descriptor.width); - ASSERT((unsigned)height == image->descriptor.height); - - ASSERT((image->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) || (n_comp_pixels == width * height)); -#ifdef WIN32 - lz_data->decode_data.dc = canvas->dc; -#endif - - - alloc_lz_image_surface(&lz_data->decode_data, pixman_format, - width, height, n_comp_pixels, top_down); - - src = (uint8_t *)pixman_image_get_data(lz_data->decode_data.out_surface); - - stride = (n_comp_pixels / height) * 4; - if (!top_down) { - stride = -stride; - decomp_buf = src + stride * (height - 1); - } else { - decomp_buf = src; - } - - lz_decode(lz_data->lz, as_type, decomp_buf); - - if (invers) { - uint8_t *line = src; - uint8_t *end = src + height * stride; - for (; line != end; line += stride) { - uint32_t *pix; - uint32_t *end_pix; - - pix = (uint32_t *)line; - end_pix = pix + width; - for (; pix < end_pix; pix++) { - *pix ^= 0xffffffff; - } - } - } - - if (free_palette) { - free(palette); - } - - return lz_data->decode_data.out_surface; -} - -static pixman_image_t *canvas_get_glz_rgb_common(CanvasBase *canvas, uint8_t *data, - int want_original) -{ - if (canvas->glz_data.decoder == NULL) { - CANVAS_ERROR("glz not supported"); - } - - canvas->glz_data.decoder->ops->decode(canvas->glz_data.decoder, - data, NULL, - &canvas->glz_data.decode_data); - - /* global_decode calls alloc_lz_image, which sets canvas->glz_data.surface */ - return (canvas->glz_data.decode_data.out_surface); -} - -// don't handle plts since bitmaps with plt can be decoded globally to RGB32 (because -// same byte sequence can be transformed to different RGB pixels by different plts) -static pixman_image_t *canvas_get_glz(CanvasBase *canvas, SpiceImage *image, - int want_original) -{ - ASSERT(image->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB); -#ifdef WIN32 - canvas->glz_data.decode_data.dc = canvas->dc; -#endif - - ASSERT(image->u.lz_rgb.data->num_chunks == 1); /* TODO: Handle chunks */ - return canvas_get_glz_rgb_common(canvas, image->u.lz_rgb.data->chunk[0].data, want_original); -} - -static pixman_image_t *canvas_get_zlib_glz_rgb(CanvasBase *canvas, SpiceImage *image, - int want_original) -{ - uint8_t *glz_data; - pixman_image_t *surface; - - if (canvas->zlib == NULL) { - CANVAS_ERROR("zlib not supported"); - } - - ASSERT(image->u.zlib_glz.data->num_chunks == 1); /* TODO: Handle chunks */ - glz_data = (uint8_t*)spice_malloc(image->u.zlib_glz.glz_data_size); - canvas->zlib->ops->decode(canvas->zlib, image->u.zlib_glz.data->chunk[0].data, - image->u.zlib_glz.data->chunk[0].len, - glz_data, image->u.zlib_glz.glz_data_size); - surface = canvas_get_glz_rgb_common(canvas, glz_data, want_original); - free(glz_data); - return surface; -} - -//#define DEBUG_DUMP_BITMAP - -#ifdef DEBUG_DUMP_BITMAP -static void dump_bitmap(SpiceBitmap *bitmap, SpicePalette *palette) -{ - uint8_t* data = (uint8_t *)SPICE_GET_ADDRESS(bitmap->data); - static uint32_t file_id = 0; - uint32_t i, j; - char file_str[200]; - uint32_t id = ++file_id; - -#ifdef WIN32 - sprintf(file_str, "c:\\tmp\\spice_dump\\%u.%ubpp", id, bitmap->format); -#else - sprintf(file_str, "/tmp/spice_dump/%u.%ubpp", id, bitmap->format); -#endif - FILE *f = fopen(file_str, "wb"); - if (!f) { - return; - } - - fprintf(f, "%d\n", bitmap->format); // 1_LE,1_BE,.... - fprintf(f, "%d %d\n", bitmap->x, bitmap->y); // width and height - fprintf(f, "%d\n", palette->num_ents); // #plt entries - for (i = 0; i < palette->num_ents; i++) { - fwrite(&(palette->ents[i]), 4, 1, f); - } - fprintf(f, "\n"); - - for (i = 0; i < bitmap->y; i++, data += bitmap->stride) { - uint8_t *now = data; - for (j = 0; j < bitmap->x; j++) { - fwrite(now, 1, 1, f); - now++; - } - } -} - -#endif - -static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap, - int want_original) -{ - pixman_image_t* surface; - SpicePalette *palette; - - palette = canvas_get_palette(canvas, bitmap->palette, bitmap->palette_id, bitmap->flags); -#ifdef DEBUG_DUMP_BITMAP - if (palette) { - dump_bitmap(bitmap, palette); - } -#endif - - surface = canvas_bitmap_to_surface(canvas, bitmap, palette, want_original); - - if (palette && (bitmap->flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) { - canvas->palette_cache->ops->release(canvas->palette_cache, palette); - } - - return surface; -} - -#else - - -static pixman_image_t *canvas_get_bits(CanvasBase *canvas, SpiceBitmap *bitmap, - int want_original) -{ - SpicePalette *palette; - - if (!bitmap->palette) { - return canvas_bitmap_to_surface(canvas, bitmap, NULL, want_original); - } - palette = (SpicePalette *)SPICE_GET_ADDRESS(bitmap->palette); - return canvas_bitmap_to_surface(canvas, bitmap, palette, want_original); -} - -#endif - - - -// caution: defining DEBUG_DUMP_SURFACE will dump both cached & non-cached -// images to disk. it will reduce performance dramatically & eat -// disk space rapidly. use it only for debugging. -//#define DEBUG_DUMP_SURFACE - -#if defined(DEBUG_DUMP_SURFACE) || defined(DEBUG_DUMP_COMPRESS) - -static void dump_surface(pixman_image_t *surface, int cache) -{ - static uint32_t file_id = 0; - int i, j; - char file_str[200]; - int depth = pixman_image_get_depth(surface); - - if (depth != 24 && depth != 32) { - return; - } - - uint8_t *data = (uint8_t *)pixman_image_get_data(surface); - int width = pixman_image_get_width(surface); - int height = pixman_image_get_height(surface); - int stride = pixman_image_surface_get_stride(surface); - - uint32_t id = ++file_id; -#ifdef WIN32 - sprintf(file_str, "c:\\tmp\\spice_dump\\%d\\%u.ppm", cache, id); -#else - sprintf(file_str, "/tmp/spice_dump/%u.ppm", id); -#endif - FILE *f = fopen(file_str, "wb"); - if (!f) { - return; - } - fprintf(f, "P6\n"); - fprintf(f, "%d %d\n", width, height); - fprintf(f, "#spicec dump\n"); - fprintf(f, "255\n"); - for (i = 0; i < height; i++, data += stride) { - uint8_t *now = data; - for (j = 0; j < width; j++) { - fwrite(&now[2], 1, 1, f); - fwrite(&now[1], 1, 1, f); - fwrite(&now[0], 1, 1, f); - now += 4; - } - } - fclose(f); -} - -#endif - -static SpiceCanvas *canvas_get_surface_internal(CanvasBase *canvas, SpiceImage *image) -{ - if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { - SpiceSurface *surface = &image->u.surface; - return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id); - } - return NULL; -} - -static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SpiceImage *image) -{ - if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) { - SpiceSurface *surface = &image->u.surface; - return canvas->surfaces->ops->get(canvas->surfaces, surface->surface_id); - } - return NULL; -} - -#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) - -//#define DEBUG_LZ - -/* If real get is FALSE, then only do whatever is needed but don't return an image. For instance, - * if we need to read it to cache it we do. - * - * This generally converts the image to the right type for the canvas. - * However, if want_original is set the real source format is returned, and - * you have to be able to handle any image format. This is useful to avoid - * e.g. losing alpha when blending a argb32 image on a rgb16 surface. - */ -static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image, - int want_original, int real_get) -{ - SpiceImageDescriptor *descriptor = &image->descriptor; - pixman_image_t *surface, *converted; - pixman_format_code_t wanted_format, surface_format; - int saved_want_original; -#ifdef DEBUG_LZ - LOG_DEBUG("canvas_get_image image type: " << (int)descriptor->type); -#endif - - /* When touching, only really allocate if we need to cache, or - * if we're loading a GLZ stream (since those need inter-thread communication - * to happen which breaks if we don't. */ - if (!real_get && - !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME) && -#ifdef SW_CANVAS_CACHE - !(descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) && -#endif - (descriptor->type != SPICE_IMAGE_TYPE_GLZ_RGB) && - (descriptor->type != SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB)) { - return NULL; - } - - saved_want_original = want_original; - if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME -#ifdef SW_CANVAS_CACHE - || descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME -#endif - ) { - want_original = TRUE; - } - - switch (descriptor->type) { - case SPICE_IMAGE_TYPE_QUIC: { - surface = canvas_get_quic(canvas, image, 0, want_original); - break; - } -#if defined(SW_CANVAS_CACHE) - case SPICE_IMAGE_TYPE_LZ_PLT: { - surface = canvas_get_lz(canvas, image, 0, want_original); - break; - } - case SPICE_IMAGE_TYPE_LZ_RGB: { - surface = canvas_get_lz(canvas, image, 0, want_original); - break; - } -#endif - case SPICE_IMAGE_TYPE_JPEG: { - surface = canvas_get_jpeg(canvas, image, 0); - break; - } - case SPICE_IMAGE_TYPE_JPEG_ALPHA: { - surface = canvas_get_jpeg_alpha(canvas, image, 0); - break; - } -#if defined(SW_CANVAS_CACHE) - case SPICE_IMAGE_TYPE_GLZ_RGB: { - surface = canvas_get_glz(canvas, image, want_original); - break; - } - case SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB: { - surface = canvas_get_zlib_glz_rgb(canvas, image, want_original); - break; - } -#endif - case SPICE_IMAGE_TYPE_FROM_CACHE: - surface = canvas->bits_cache->ops->get(canvas->bits_cache, descriptor->id); - break; -#ifdef SW_CANVAS_CACHE - case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: - surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, descriptor->id); - break; -#endif - case SPICE_IMAGE_TYPE_BITMAP: { - surface = canvas_get_bits(canvas, &image->u.bitmap, want_original); - break; - } - default: - CANVAS_ERROR("invalid image type"); - } - - surface_format = spice_pixman_image_get_format(surface); - - if (descriptor->flags & SPICE_IMAGE_FLAGS_HIGH_BITS_SET && - descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE && -#ifdef SW_CANVAS_CACHE - descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS && -#endif - surface_format == PIXMAN_x8r8g8b8) { - spice_pixman_fill_rect_rop(surface, - 0, 0, - pixman_image_get_width(surface), - pixman_image_get_height(surface), - 0xff000000U, SPICE_ROP_OR); - } - - if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME && -#ifdef SW_CANVAS_CACHE - descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS && -#endif - descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE ) { -#ifdef SW_CANVAS_CACHE - if (!IS_IMAGE_LOSSY(descriptor)) { - canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); - } else { - canvas->bits_cache->ops->put_lossy(canvas->bits_cache, descriptor->id, surface); - } -#else - canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface); -#endif -#ifdef DEBUG_DUMP_SURFACE - dump_surface(surface, 1); -#endif -#ifdef SW_CANVAS_CACHE - } else if (descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_REPLACE_ME) { - if (IS_IMAGE_LOSSY(descriptor)) { - CANVAS_ERROR("invalid cache replace request: the image is lossy"); - } - canvas->bits_cache->ops->replace_lossy(canvas->bits_cache, descriptor->id, surface); -#ifdef DEBUG_DUMP_SURFACE - dump_surface(surface, 1); -#endif -#endif -#ifdef DEBUG_DUMP_SURFACE - } else if (descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE -#ifdef SW_CANVAS_CACHE - && descriptor->type != SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS -#endif - ) { - - dump_surface(surface, 0); -#endif - } - - if (!real_get) { - pixman_image_unref(surface); - return NULL; - } - - if (!saved_want_original) { - /* Conversion to canvas format was requested, but maybe it didn't - happen above (due to save/load to cache for instance, or - maybe the reader didn't support conversion). - If so we convert here. */ - - wanted_format = canvas_get_target_format(canvas, - surface_format == PIXMAN_a8r8g8b8); - - if (surface_format != wanted_format) { - converted = surface_create( -#ifdef WIN32 - canvas->dc, -#endif - wanted_format, - pixman_image_get_width(surface), - pixman_image_get_height(surface), - TRUE); - pixman_image_composite32 (PIXMAN_OP_SRC, - surface, NULL, converted, - 0, 0, - 0, 0, - 0, 0, - pixman_image_get_width(surface), - pixman_image_get_height(surface)); - pixman_image_unref (surface); - surface = converted; - } - } - - return surface; -} - -#else - -static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SpiceImage *image, - int want_original, int real_get) -{ - SpiceImageDescriptor *descriptor = &image->descriptor; - pixman_format_code_t format; - - /* When touching, never load image. */ - if (!real_get) { - return NULL; - } - - switch (descriptor->type) { - case SPICE_IMAGE_TYPE_QUIC: { - return canvas_get_quic(canvas, image, 0); - } - case SPICE_IMAGE_TYPE_BITMAP: { - return canvas_get_bits(canvas, &image->u.bitmap, want_original, &format); - } - default: - CANVAS_ERROR("invalid image type"); - } -} - -#endif - -static SpiceCanvas *canvas_get_surface_mask(CanvasBase *canvas, SpiceImage *image) -{ - return canvas_get_surface_mask_internal(canvas, image); -} - -static SpiceCanvas *canvas_get_surface(CanvasBase *canvas, SpiceImage *image) -{ - return canvas_get_surface_internal(canvas, image); -} - -static pixman_image_t *canvas_get_image(CanvasBase *canvas, SpiceImage *image, - int want_original) -{ - return canvas_get_image_internal(canvas, image, want_original, TRUE); -} - -static void canvas_touch_image(CanvasBase *canvas, SpiceImage *image) -{ - canvas_get_image_internal(canvas, image, TRUE, FALSE); -} - -static pixman_image_t* canvas_get_image_from_self(SpiceCanvas *canvas, - int x, int y, - int32_t width, int32_t height) -{ - CanvasBase *canvas_base = (CanvasBase *)canvas; - pixman_image_t *surface; - uint8_t *dest; - int dest_stride; - SpiceRect area; - - surface = pixman_image_create_bits(spice_surface_format_to_pixman (canvas_base->format), - width, height, NULL, 0); - if (surface == NULL) { - CANVAS_ERROR("create surface failed"); - } - - dest = (uint8_t *)pixman_image_get_data(surface); - dest_stride = pixman_image_get_stride(surface); - - area.left = x; - area.top = y; - area.right = x + width; - area.bottom = y + height; - - canvas->ops->read_bits(canvas, dest, dest_stride, &area); - - return surface; -} - -static inline uint8_t revers_bits(uint8_t byte) -{ - uint8_t ret = 0; - int i; - - for (i = 0; i < 4; i++) { - int shift = 7 - i * 2; - ret |= (byte & (1 << i)) << shift; - ret |= (byte & (0x80 >> i)) >> shift; - } - return ret; -} - -static pixman_image_t *canvas_get_bitmap_mask(CanvasBase *canvas, SpiceBitmap* bitmap, int invers) -{ - pixman_image_t *surface; - uint8_t *src_line; - uint8_t *end_line; - uint8_t *dest_line; - int src_stride; - int line_size; - int dest_stride; - - surface = surface_create( -#ifdef WIN32 - canvas->dc, -#endif - PIXMAN_a1, bitmap->x, bitmap->y, TRUE); - if (surface == NULL) { - CANVAS_ERROR("create surface failed"); - } - - spice_chunks_linearize(bitmap->data); - src_line = bitmap->data->chunk[0].data; - src_stride = bitmap->stride; - end_line = src_line + (bitmap->y * src_stride); - line_size = SPICE_ALIGN(bitmap->x, 8) >> 3; - - dest_stride = pixman_image_get_stride(surface); - dest_line = (uint8_t *)pixman_image_get_data(surface); -#if defined(GL_CANVAS) - if ((bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { -#else - if (!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { -#endif - ASSERT(bitmap->y > 0); - dest_line += dest_stride * ((int)bitmap->y - 1); - dest_stride = -dest_stride; - } - - if (invers) { - switch (bitmap->format) { -#if defined(GL_CANVAS) || defined(GDI_CANVAS) - case SPICE_BITMAP_FMT_1BIT_BE: -#else - case SPICE_BITMAP_FMT_1BIT_LE: -#endif - for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { - uint8_t *dest = dest_line; - uint8_t *now = src_line; - uint8_t *end = now + line_size; - while (now < end) { - *(dest++) = ~*(now++); - } - } - break; -#if defined(GL_CANVAS) || defined(GDI_CANVAS) - case SPICE_BITMAP_FMT_1BIT_LE: -#else - case SPICE_BITMAP_FMT_1BIT_BE: -#endif - for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { - uint8_t *dest = dest_line; - uint8_t *now = src_line; - uint8_t *end = now + line_size; - - while (now < end) { - *(dest++) = ~revers_bits(*(now++)); - } - } - break; - default: - pixman_image_unref(surface); - surface = NULL; - CANVAS_ERROR("invalid bitmap format"); - } - } else { - switch (bitmap->format) { -#if defined(GL_CANVAS) || defined(GDI_CANVAS) - case SPICE_BITMAP_FMT_1BIT_BE: -#else - case SPICE_BITMAP_FMT_1BIT_LE: -#endif - for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { - memcpy(dest_line, src_line, line_size); - } - break; -#if defined(GL_CANVAS) || defined(GDI_CANVAS) - case SPICE_BITMAP_FMT_1BIT_LE: -#else - case SPICE_BITMAP_FMT_1BIT_BE: -#endif - for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { - uint8_t *dest = dest_line; - uint8_t *now = src_line; - uint8_t *end = now + line_size; - - while (now < end) { - *(dest++) = revers_bits(*(now++)); - } - } - break; - default: - pixman_image_unref(surface); - surface = NULL; - CANVAS_ERROR("invalid bitmap format"); - } - } - return surface; -} - -static inline pixman_image_t *canvas_A1_invers(pixman_image_t *src_surf) -{ - int width = pixman_image_get_width(src_surf); - int height = pixman_image_get_height(src_surf); - pixman_image_t * invers; - uint8_t *src_line, *end_line, *dest_line; - int src_stride, line_size, dest_stride; - - ASSERT(pixman_image_get_depth(src_surf) == 1); - - invers = pixman_image_create_bits(PIXMAN_a1, width, height, NULL, 0); - if (invers == NULL) { - CANVAS_ERROR("create surface failed"); - } - - src_line = (uint8_t *)pixman_image_get_data(src_surf); - src_stride = pixman_image_get_stride(src_surf); - end_line = src_line + (height * src_stride); - line_size = SPICE_ALIGN(width, 8) >> 3; - dest_line = (uint8_t *)pixman_image_get_data(invers); - dest_stride = pixman_image_get_stride(invers); - - for (; src_line != end_line; src_line += src_stride, dest_line += dest_stride) { - uint8_t *dest = dest_line; - uint8_t *now = src_line; - uint8_t *end = now + line_size; - while (now < end) { - *(dest++) = ~*(now++); - } - } - return invers; -} - -static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int *needs_invert_out) -{ - SpiceImage *image; - pixman_image_t *surface; - int need_invers; - int is_invers; - int cache_me; - - if (needs_invert_out) { - *needs_invert_out = 0; - } - - image = mask->bitmap; - need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS; - -#ifdef SW_CANVAS_CACHE - cache_me = image->descriptor.flags & SPICE_IMAGE_FLAGS_CACHE_ME; -#else - cache_me = 0; -#endif - - switch (image->descriptor.type) { - case SPICE_IMAGE_TYPE_BITMAP: { - is_invers = need_invers && !cache_me; - surface = canvas_get_bitmap_mask(canvas, &image->u.bitmap, is_invers); - break; - } -#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) - case SPICE_IMAGE_TYPE_FROM_CACHE: - surface = canvas->bits_cache->ops->get(canvas->bits_cache, image->descriptor.id); - is_invers = 0; - break; -#endif -#ifdef SW_CANVAS_CACHE - case SPICE_IMAGE_TYPE_FROM_CACHE_LOSSLESS: - surface = canvas->bits_cache->ops->get_lossless(canvas->bits_cache, image->descriptor.id); - is_invers = 0; - break; -#endif - default: - CANVAS_ERROR("invalid image type"); - } - -#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) - if (cache_me) { - canvas->bits_cache->ops->put(canvas->bits_cache, image->descriptor.id, surface); - } - - if (need_invers && !is_invers) { // surface is in cache - if (needs_invert_out != NULL) { - *needs_invert_out = TRUE; - } else { - pixman_image_t *inv_surf; - inv_surf = canvas_A1_invers(surface); - pixman_image_unref(surface); - surface = inv_surf; - } - } -#endif - return surface; -} - -static inline void canvas_raster_glyph_box(const SpiceRasterGlyph *glyph, SpiceRect *r) -{ - ASSERT(r); - r->top = glyph->render_pos.y + glyph->glyph_origin.y; - r->bottom = r->top + glyph->height; - r->left = glyph->render_pos.x + glyph->glyph_origin.x; - r->right = r->left + glyph->width; -} - -#ifdef GL_CANVAS -static inline void __canvas_put_bits(uint8_t *dest, int offset, uint8_t val, int n) -{ - uint8_t mask; - int now; - - dest = dest + (offset >> 3); - offset &= 0x07; - now = MIN(8 - offset, n); - - mask = ~((1 << (8 - now)) - 1); - mask >>= offset; - *dest = ((val >> offset) & mask) | *dest; - - if ((n = n - now)) { - mask = ~((1 << (8 - n)) - 1); - dest++; - *dest = ((val << now) & mask) | *dest; - } -} - -#else -static inline void __canvas_put_bits(uint8_t *dest, int offset, uint8_t val, int n) -{ - uint8_t mask; - int now; - - dest = dest + (offset >> 3); - offset &= 0x07; - - now = MIN(8 - offset, n); - - mask = (1 << now) - 1; - mask <<= offset; - val = revers_bits(val); - *dest = ((val << offset) & mask) | *dest; - - if ((n = n - now)) { - mask = (1 << n) - 1; - dest++; - *dest = ((val >> now) & mask) | *dest; - } -} - -#endif - -static inline void canvas_put_bits(uint8_t *dest, int dest_offset, uint8_t *src, int n) -{ - while (n) { - int now = MIN(n, 8); - - n -= now; - __canvas_put_bits(dest, dest_offset, *src, now); - dest_offset += now; - src++; - } -} - -static void canvas_put_glyph_bits(SpiceRasterGlyph *glyph, int bpp, uint8_t *dest, int dest_stride, - SpiceRect *bounds) -{ - SpiceRect glyph_box; - uint8_t *src; - int lines; - int width; - - //todo: support SPICE_STRING_FLAGS_RASTER_TOP_DOWN - canvas_raster_glyph_box(glyph, &glyph_box); - ASSERT(glyph_box.top >= bounds->top && glyph_box.bottom <= bounds->bottom); - ASSERT(glyph_box.left >= bounds->left && glyph_box.right <= bounds->right); - rect_offset(&glyph_box, -bounds->left, -bounds->top); - - dest += glyph_box.top * dest_stride; - src = glyph->data; - lines = glyph_box.bottom - glyph_box.top; - width = glyph_box.right - glyph_box.left; - switch (bpp) { - case 1: { - int src_stride = SPICE_ALIGN(width, 8) >> 3; - int i; - - src += src_stride * (lines); - for (i = 0; i < lines; i++) { - src -= src_stride; - canvas_put_bits(dest, glyph_box.left, src, width); - dest += dest_stride; - } - break; - } - case 4: { - uint8_t *end; - int src_stride = SPICE_ALIGN(width * 4, 8) >> 3; - - src += src_stride * lines; - dest += glyph_box.left; - end = dest + dest_stride * lines; - for (; dest != end; dest += dest_stride) { - int i = 0; - uint8_t *now; - - src -= src_stride; - now = src; - while (i < (width & ~1)) { - dest[i] = MAX(dest[i], *now & 0xf0); - dest[i + 1] = MAX(dest[i + 1], *now << 4); - i += 2; - now++; - } - if (i < width) { - dest[i] = MAX(dest[i], *now & 0xf0); - now++; - } - } - break; - } - case 8: { - uint8_t *end; - src += width * lines; - dest += glyph_box.left; - end = dest + dest_stride * lines; - for (; dest != end; dest += dest_stride, src -= width) { - int i; - - for (i = 0; i < width; i++) { - dest[i] = MAX(dest[i], src[i]); - } - } - break; - } - default: - CANVAS_ERROR("invalid bpp"); - } -} - -static pixman_image_t *canvas_get_str_mask(CanvasBase *canvas, SpiceString *str, int bpp, SpicePoint *pos) -{ - SpiceRasterGlyph *glyph; - SpiceRect bounds; - pixman_image_t *str_mask; - uint8_t *dest; - int dest_stride; - int i; - - ASSERT(str->length > 0); - - glyph = str->glyphs[0]; - canvas_raster_glyph_box(glyph, &bounds); - - for (i = 1; i < str->length; i++) { - SpiceRect glyph_box; - - canvas_raster_glyph_box(str->glyphs[i], &glyph_box); - rect_union(&bounds, &glyph_box); - } - - str_mask = pixman_image_create_bits((bpp == 1) ? PIXMAN_a1 : PIXMAN_a8, - bounds.right - bounds.left, - bounds.bottom - bounds.top, NULL, 0); - if (str_mask == NULL) { - CANVAS_ERROR("create surface failed"); - } - dest = (uint8_t *)pixman_image_get_data(str_mask); - dest_stride = pixman_image_get_stride(str_mask); - for (i = 0; i < str->length; i++) { - glyph = str->glyphs[i]; -#if defined(GL_CANVAS) - canvas_put_glyph_bits(glyph, bpp, dest + (bounds.bottom - bounds.top - 1) * dest_stride, - -dest_stride, &bounds); -#else - canvas_put_glyph_bits(glyph, bpp, dest, dest_stride, &bounds); -#endif - } - - pos->x = bounds.left; - pos->y = bounds.top; - return str_mask; -} - -static pixman_image_t *canvas_scale_surface(pixman_image_t *src, const SpiceRect *src_area, int width, - int height, int scale_mode) -{ - pixman_image_t *surface; - pixman_transform_t transform; - double sx, sy; - - surface = pixman_image_create_bits(spice_pixman_image_get_format (src), - width, height, NULL, 0); - if (surface == NULL) { - CANVAS_ERROR("create surface failed"); - } - - sx = (double)(src_area->right - src_area->left) / width; - sy = (double)(src_area->bottom - src_area->top) / height; - - pixman_transform_init_scale(&transform, pixman_double_to_fixed(sx), pixman_double_to_fixed(sy)); - - pixman_image_set_transform (src, &transform); - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); - pixman_image_set_filter(src, - (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, - NULL, 0); - - pixman_image_composite32(PIXMAN_OP_SRC, - src, NULL, surface, - ROUND(src_area->left / sx), ROUND (src_area->top / sy), - 0, 0, /* mask */ - 0, 0, /* dst */ - width, height); - - pixman_transform_init_identity(&transform); - pixman_image_set_transform(src, &transform); - - return surface; -} - -static void quic_usr_error(QuicUsrContext *usr, const char *fmt, ...) -{ - QuicData *usr_data = (QuicData *)usr; - va_list ap; - - va_start(ap, fmt); - vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); - va_end(ap); - - longjmp(usr_data->jmp_env, 1); -} - -static void quic_usr_warn(QuicUsrContext *usr, const char *fmt, ...) -{ - QuicData *usr_data = (QuicData *)usr; - va_list ap; - - va_start(ap, fmt); - vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); - va_end(ap); -} - -static void *quic_usr_malloc(QuicUsrContext *usr, int size) -{ - return spice_malloc(size); -} - -static void quic_usr_free(QuicUsrContext *usr, void *ptr) -{ - free(ptr); -} - -static void lz_usr_warn(LzUsrContext *usr, const char *fmt, ...) -{ - LzData *usr_data = (LzData *)usr; - va_list ap; - - va_start(ap, fmt); - vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); - va_end(ap); -} - -static void lz_usr_error(LzUsrContext *usr, const char *fmt, ...) -{ - LzData *usr_data = (LzData *)usr; - va_list ap; - - va_start(ap, fmt); - vsnprintf(usr_data->message_buf, sizeof(usr_data->message_buf), fmt, ap); - va_end(ap); - - longjmp(usr_data->jmp_env, 1); -} - -static void *lz_usr_malloc(LzUsrContext *usr, int size) -{ - return spice_malloc(size); -} - -static void lz_usr_free(LzUsrContext *usr, void *ptr) -{ - free(ptr); -} - -static int lz_usr_more_space(LzUsrContext *usr, uint8_t **io_ptr) -{ - return 0; -} - -static int lz_usr_more_lines(LzUsrContext *usr, uint8_t **lines) -{ - return 0; -} - -static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed) -{ - QuicData *quic_data = (QuicData *)usr; - - if (quic_data->current_chunk == quic_data->chunks->num_chunks -1) { - return 0; - } - quic_data->current_chunk++; - - *io_ptr = (uint32_t *)quic_data->chunks->chunk[quic_data->current_chunk].data; - return quic_data->chunks->chunk[quic_data->current_chunk].len >> 2; -} - - -static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines) -{ - return 0; -} - -static void canvas_base_destroy(CanvasBase *canvas) -{ - quic_destroy(canvas->quic_data.quic); - lz_destroy(canvas->lz_data.lz); -#ifdef GDI_CANVAS - DeleteDC(canvas->dc); -#endif - - if (canvas->usr_data && canvas->usr_data_destroy) { - canvas->usr_data_destroy (canvas->usr_data); - canvas->usr_data = NULL; - } -} - -/* This is kind of lame, but it protects against multiple - instances of these functions. We really should stop including - canvas_base.c and build it separately instead */ -#ifdef CANVAS_SINGLE_INSTANCE - -void spice_canvas_set_usr_data(SpiceCanvas *spice_canvas, - void *data, - spice_destroy_fn_t destroy_fn) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - if (canvas->usr_data && canvas->usr_data_destroy) { - canvas->usr_data_destroy (canvas->usr_data); - } - canvas->usr_data = data; - canvas->usr_data_destroy = destroy_fn; -} - -void *spice_canvas_get_usr_data(SpiceCanvas *spice_canvas) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - return canvas->usr_data; -} -#endif - - -static void canvas_clip_pixman(CanvasBase *canvas, - pixman_region32_t *dest_region, - SpiceClip *clip) -{ - pixman_region32_intersect(dest_region, dest_region, &canvas->canvas_region); - - switch (clip->type) { - case SPICE_CLIP_TYPE_NONE: - break; - case SPICE_CLIP_TYPE_RECTS: { - uint32_t n = clip->rects->num_rects; - SpiceRect *now = clip->rects->rects; - - pixman_region32_t clip; - - if (spice_pixman_region32_init_rects(&clip, now, n)) { - pixman_region32_intersect(dest_region, dest_region, &clip); - pixman_region32_fini(&clip); - } - - break; - } - default: - CANVAS_ERROR("invalid clip type"); - } -} - -static void canvas_mask_pixman(CanvasBase *canvas, - pixman_region32_t *dest_region, - SpiceQMask *mask, int x, int y) -{ - SpiceCanvas *surface_canvas; - pixman_image_t *image, *subimage; - int needs_invert; - pixman_region32_t mask_region; - uint32_t *mask_data; - int mask_x, mask_y; - int mask_width, mask_height, mask_stride; - pixman_box32_t extents; - - if (!mask->bitmap) { - return; - } - - surface_canvas = canvas_get_surface_mask(canvas, mask->bitmap); - if (surface_canvas) { - needs_invert = mask->flags & SPICE_MASK_FLAGS_INVERS; - image = surface_canvas->ops->get_image(surface_canvas); - } else { - needs_invert = FALSE; - image = canvas_get_mask(canvas, - mask, - &needs_invert); - } - - mask_data = pixman_image_get_data(image); - mask_width = pixman_image_get_width(image); - mask_height = pixman_image_get_height(image); - mask_stride = pixman_image_get_stride(image); - - mask_x = mask->pos.x; - mask_y = mask->pos.y; - - /* We need to subset the area of the mask that we turn into a region, - because a cached mask may be much larger than what is used for - the clip operation. */ - extents = *pixman_region32_extents(dest_region); - - /* convert from destination pixels to mask pixels */ - extents.x1 -= x - mask_x; - extents.y1 -= y - mask_y; - extents.x2 -= x - mask_x; - extents.y2 -= y - mask_y; - - /* clip to mask size */ - if (extents.x1 < 0) { - extents.x1 = 0; - } - if (extents.x2 >= mask_width) { - extents.x2 = mask_width; - } - if (extents.x2 < extents.x1) { - extents.x2 = extents.x1; - } - if (extents.y1 < 0) { - extents.y1 = 0; - } - if (extents.y2 >= mask_height) { - extents.y2 = mask_height; - } - if (extents.y2 < extents.y1) { - extents.y2 = extents.y1; - } - - /* round down X to even 32 pixels (i.e. uint32_t) */ - extents.x1 = extents.x1 & ~(0x1f); - - mask_data = (uint32_t *)((uint8_t *)mask_data + mask_stride * extents.y1 + extents.x1 / 32); - mask_x -= extents.x1; - mask_y -= extents.y1; - mask_width = extents.x2 - extents.x1; - mask_height = extents.y2 - extents.y1; - - subimage = pixman_image_create_bits(PIXMAN_a1, mask_width, mask_height, - mask_data, mask_stride); - pixman_region32_init_from_image(&mask_region, - subimage); - pixman_image_unref(subimage); - - if (needs_invert) { - pixman_box32_t rect; - - rect.x1 = rect.y1 = 0; - rect.x2 = mask_width; - rect.y2 = mask_height; - - pixman_region32_inverse(&mask_region, &mask_region, &rect); - } - - pixman_region32_translate(&mask_region, - -mask_x + x, -mask_y + y); - - pixman_region32_intersect(dest_region, dest_region, &mask_region); - pixman_region32_fini(&mask_region); - - pixman_image_unref(image); -} - -static void draw_brush(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceBrush *brush, - SpiceROP rop) -{ - CanvasBase *canvas_base = (CanvasBase *)canvas; - uint32_t color; - SpicePattern *pattern; - pixman_image_t *tile; - int offset_x, offset_y; - pixman_box32_t *rects; - int n_rects; - - rects = pixman_region32_rectangles(region, &n_rects); - - switch (brush->type) { - case SPICE_BRUSH_TYPE_SOLID: - color = brush->u.color; - if (rop == SPICE_ROP_COPY) { - canvas->ops->fill_solid_rects(canvas, rects, n_rects, color); - } else { - canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, color, rop); - } - break; - case SPICE_BRUSH_TYPE_PATTERN: { - SpiceCanvas *surface_canvas; - - pattern = &brush->u.pattern; - offset_x = pattern->pos.x; - offset_y = pattern->pos.y; - - surface_canvas = canvas_get_surface(canvas_base, pattern->pat); - if (surface_canvas) { - if (rop == SPICE_ROP_COPY) { - canvas->ops->fill_tiled_rects_from_surface(canvas, rects, n_rects, surface_canvas, - offset_x, offset_y); - } else { - canvas->ops->fill_tiled_rects_rop_from_surface(canvas, rects, n_rects, - surface_canvas, offset_x, offset_y, - rop); - } - } else { - tile = canvas_get_image(canvas_base, pattern->pat, FALSE); - if (rop == SPICE_ROP_COPY) { - canvas->ops->fill_tiled_rects(canvas, rects, n_rects, tile, offset_x, offset_y); - } else { - canvas->ops->fill_tiled_rects_rop(canvas, rects, n_rects, - tile, offset_x, offset_y, rop); - } - pixman_image_unref(tile); - } - break; - } - case SPICE_BRUSH_TYPE_NONE: - /* Still need to do *something* here, because rop could be e.g invert dest */ - canvas->ops->fill_solid_rects_rop(canvas, rects, n_rects, 0, rop); - break; - default: - CANVAS_ERROR("invalid brush type"); - } -} - -/* If we're exiting early we may still have to load an image in case - it has to be cached or something */ -static void touch_brush(CanvasBase *canvas, SpiceBrush *brush) -{ - SpicePattern *pattern; - - if (brush->type == SPICE_BRUSH_TYPE_PATTERN) { - pattern = &brush->u.pattern; - canvas_touch_image(canvas, pattern->pat); - } -} - -static void canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - SpiceROP rop; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &fill->mask, - bbox->left, bbox->top); - - rop = ropd_descriptor_to_rop(fill->rop_descriptor, - ROP_INPUT_BRUSH, - ROP_INPUT_DEST); - - if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { - touch_brush(canvas, &fill->brush); - pixman_region32_fini(&dest_region); - return; - } - - draw_brush(spice_canvas, &dest_region, &fill->brush, rop); - - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - SpiceCanvas *surface_canvas; - pixman_image_t *src_image; - SpiceROP rop; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, ©->mask, - bbox->left, bbox->top); - - rop = ropd_descriptor_to_rop(copy->rop_descriptor, - ROP_INPUT_SRC, - ROP_INPUT_DEST); - - if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { - canvas_touch_image(canvas, copy->src_bitmap); - pixman_region32_fini(&dest_region); - return; - } - - surface_canvas = canvas_get_surface(canvas, copy->src_bitmap); - if (surface_canvas) { - if (rect_is_same_size(bbox, ©->src_area)) { - if (rop == SPICE_ROP_COPY) { - spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - bbox->left - copy->src_area.left, - bbox->top - copy->src_area.top); - } else { - spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region, - surface_canvas, - bbox->left - copy->src_area.left, - bbox->top - copy->src_area.top, - rop); - } - } else { - if (rop == SPICE_ROP_COPY) { - spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - copy->src_area.left, - copy->src_area.top, - copy->src_area.right - copy->src_area.left, - copy->src_area.bottom - copy->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - copy->scale_mode); - } else { - spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region, - surface_canvas, - copy->src_area.left, - copy->src_area.top, - copy->src_area.right - copy->src_area.left, - copy->src_area.bottom - copy->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - copy->scale_mode, - rop); - } - } - } else { - src_image = canvas_get_image(canvas, copy->src_bitmap, FALSE); - if (rect_is_same_size(bbox, ©->src_area)) { - if (rop == SPICE_ROP_COPY) { - spice_canvas->ops->blit_image(spice_canvas, &dest_region, - src_image, - bbox->left - copy->src_area.left, - bbox->top - copy->src_area.top); - } else { - spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region, - src_image, - bbox->left - copy->src_area.left, - bbox->top - copy->src_area.top, - rop); - } - } else { - if (rop == SPICE_ROP_COPY) { - spice_canvas->ops->scale_image(spice_canvas, &dest_region, - src_image, - copy->src_area.left, - copy->src_area.top, - copy->src_area.right - copy->src_area.left, - copy->src_area.bottom - copy->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - copy->scale_mode); - } else { - spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region, - src_image, - copy->src_area.left, - copy->src_area.top, - copy->src_area.right - copy->src_area.left, - copy->src_area.bottom - copy->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - copy->scale_mode, - rop); - } - } - pixman_image_unref(src_image); - } - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - SpiceCanvas *surface_canvas; - pixman_image_t *src_image; - pixman_region32_t dest_region; - uint32_t transparent_color; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - - if (pixman_region32_n_rects (&dest_region) == 0) { - canvas_touch_image(canvas, transparent->src_bitmap); - pixman_region32_fini(&dest_region); - return; - } - - switch (canvas->format) { - case SPICE_SURFACE_FMT_32_xRGB: - case SPICE_SURFACE_FMT_32_ARGB: - transparent_color = transparent->true_color; - break; - case SPICE_SURFACE_FMT_16_555: - transparent_color = rgb_32_to_16_555(transparent->true_color); - break; - case SPICE_SURFACE_FMT_16_565: - transparent_color = rgb_32_to_16_565(transparent->true_color); - break; - default: - transparent_color = 0; - } - - surface_canvas = canvas_get_surface(canvas, transparent->src_bitmap); - if (surface_canvas) { - if (rect_is_same_size(bbox, &transparent->src_area)) { - spice_canvas->ops->colorkey_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - bbox->left - transparent->src_area.left, - bbox->top - transparent->src_area.top, - transparent_color); - } else { - spice_canvas->ops->colorkey_scale_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - transparent->src_area.left, - transparent->src_area.top, - transparent->src_area.right - transparent->src_area.left, - transparent->src_area.bottom - transparent->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - transparent_color); - } - } else { - src_image = canvas_get_image(canvas, transparent->src_bitmap, FALSE); - if (rect_is_same_size(bbox, &transparent->src_area)) { - spice_canvas->ops->colorkey_image(spice_canvas, &dest_region, - src_image, - bbox->left - transparent->src_area.left, - bbox->top - transparent->src_area.top, - transparent_color); - } else { - spice_canvas->ops->colorkey_scale_image(spice_canvas, &dest_region, - src_image, - transparent->src_area.left, - transparent->src_area.top, - transparent->src_area.right - transparent->src_area.left, - transparent->src_area.bottom - transparent->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - transparent_color); - } - pixman_image_unref(src_image); - } - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - SpiceCanvas *surface_canvas; - pixman_image_t *src_image; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - - if (alpha_blend->alpha == 0 || - !pixman_region32_not_empty(&dest_region)) { - canvas_touch_image(canvas, alpha_blend->src_bitmap); - pixman_region32_fini(&dest_region); - return; - } - - surface_canvas = canvas_get_surface(canvas, alpha_blend->src_bitmap); - if (surface_canvas) { - if (rect_is_same_size(bbox, &alpha_blend->src_area)) { - spice_canvas->ops->blend_image_from_surface(spice_canvas, &dest_region, - alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, - surface_canvas, - alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA, - alpha_blend->src_area.left, - alpha_blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - alpha_blend->alpha); - } else { - spice_canvas->ops->blend_scale_image_from_surface(spice_canvas, &dest_region, - alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, - surface_canvas, - alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA, - alpha_blend->src_area.left, - alpha_blend->src_area.top, - alpha_blend->src_area.right - alpha_blend->src_area.left, - alpha_blend->src_area.bottom - alpha_blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - SPICE_IMAGE_SCALE_MODE_NEAREST, - alpha_blend->alpha); - } - } else { - src_image = canvas_get_image(canvas, alpha_blend->src_bitmap, TRUE); - if (rect_is_same_size(bbox, &alpha_blend->src_area)) { - spice_canvas->ops->blend_image(spice_canvas, &dest_region, - alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, - src_image, - alpha_blend->src_area.left, - alpha_blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - alpha_blend->alpha); - } else { - spice_canvas->ops->blend_scale_image(spice_canvas, &dest_region, - alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_DEST_HAS_ALPHA, - src_image, - alpha_blend->src_area.left, - alpha_blend->src_area.top, - alpha_blend->src_area.right - alpha_blend->src_area.left, - alpha_blend->src_area.bottom - alpha_blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - SPICE_IMAGE_SCALE_MODE_NEAREST, - alpha_blend->alpha); - } - - pixman_image_unref(src_image); - } - - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_image_t *src_image; - pixman_region32_t dest_region; - SpiceCanvas *surface_canvas; - SpiceROP rop; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &opaque->mask, - bbox->left, bbox->top); - - rop = ropd_descriptor_to_rop(opaque->rop_descriptor, - ROP_INPUT_BRUSH, - ROP_INPUT_SRC); - - if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { - canvas_touch_image(canvas, opaque->src_bitmap); - touch_brush(canvas, &opaque->brush); - pixman_region32_fini(&dest_region); - return; - } - - surface_canvas = canvas_get_surface(canvas, opaque->src_bitmap); - if (surface_canvas) { - if (rect_is_same_size(bbox, &opaque->src_area)) { - spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - bbox->left - opaque->src_area.left, - bbox->top - opaque->src_area.top); - } else { - spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - opaque->src_area.left, - opaque->src_area.top, - opaque->src_area.right - opaque->src_area.left, - opaque->src_area.bottom - opaque->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - opaque->scale_mode); - } - } else { - src_image = canvas_get_image(canvas, opaque->src_bitmap, FALSE); - - if (rect_is_same_size(bbox, &opaque->src_area)) { - spice_canvas->ops->blit_image(spice_canvas, &dest_region, - src_image, - bbox->left - opaque->src_area.left, - bbox->top - opaque->src_area.top); - } else { - spice_canvas->ops->scale_image(spice_canvas, &dest_region, - src_image, - opaque->src_area.left, - opaque->src_area.top, - opaque->src_area.right - opaque->src_area.left, - opaque->src_area.bottom - opaque->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - opaque->scale_mode); - } - pixman_image_unref(src_image); - } - - draw_brush(spice_canvas, &dest_region, &opaque->brush, rop); - - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - SpiceCanvas *surface_canvas; - pixman_image_t *src_image; - pixman_region32_t dest_region; - SpiceROP rop; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &blend->mask, - bbox->left, bbox->top); - - rop = ropd_descriptor_to_rop(blend->rop_descriptor, - ROP_INPUT_SRC, - ROP_INPUT_DEST); - - if (rop == SPICE_ROP_NOOP || !pixman_region32_not_empty(&dest_region)) { - canvas_touch_image(canvas, blend->src_bitmap); - pixman_region32_fini(&dest_region); - return; - } - - surface_canvas = canvas_get_surface(canvas, blend->src_bitmap); - if (surface_canvas) { - if (rect_is_same_size(bbox, &blend->src_area)) { - if (rop == SPICE_ROP_COPY) - spice_canvas->ops->blit_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - bbox->left - blend->src_area.left, - bbox->top - blend->src_area.top); - else - spice_canvas->ops->blit_image_rop_from_surface(spice_canvas, &dest_region, - surface_canvas, - bbox->left - blend->src_area.left, - bbox->top - blend->src_area.top, - rop); - } else { - if (rop == SPICE_ROP_COPY) { - spice_canvas->ops->scale_image_from_surface(spice_canvas, &dest_region, - surface_canvas, - blend->src_area.left, - blend->src_area.top, - blend->src_area.right - blend->src_area.left, - blend->src_area.bottom - blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - blend->scale_mode); - } else { - spice_canvas->ops->scale_image_rop_from_surface(spice_canvas, &dest_region, - surface_canvas, - blend->src_area.left, - blend->src_area.top, - blend->src_area.right - blend->src_area.left, - blend->src_area.bottom - blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - blend->scale_mode, rop); - } - } - } else { - src_image = canvas_get_image(canvas, blend->src_bitmap, FALSE); - if (rect_is_same_size(bbox, &blend->src_area)) { - if (rop == SPICE_ROP_COPY) - spice_canvas->ops->blit_image(spice_canvas, &dest_region, - src_image, - bbox->left - blend->src_area.left, - bbox->top - blend->src_area.top); - else - spice_canvas->ops->blit_image_rop(spice_canvas, &dest_region, - src_image, - bbox->left - blend->src_area.left, - bbox->top - blend->src_area.top, - rop); - } else { - if (rop == SPICE_ROP_COPY) { - spice_canvas->ops->scale_image(spice_canvas, &dest_region, - src_image, - blend->src_area.left, - blend->src_area.top, - blend->src_area.right - blend->src_area.left, - blend->src_area.bottom - blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - blend->scale_mode); - } else { - spice_canvas->ops->scale_image_rop(spice_canvas, &dest_region, - src_image, - blend->src_area.left, - blend->src_area.top, - blend->src_area.right - blend->src_area.left, - blend->src_area.bottom - blend->src_area.top, - bbox->left, - bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top, - blend->scale_mode, rop); - } - } - pixman_image_unref(src_image); - } - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - pixman_box32_t *rects; - int n_rects; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &blackness->mask, - bbox->left, bbox->top); - - if (!pixman_region32_not_empty(&dest_region)) { - pixman_region32_fini (&dest_region); - return; - } - - rects = pixman_region32_rectangles(&dest_region, &n_rects); - - spice_canvas->ops->fill_solid_rects(spice_canvas, rects, n_rects, 0x000000); - - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - pixman_box32_t *rects; - int n_rects; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &whiteness->mask, - bbox->left, bbox->top); - - if (!pixman_region32_not_empty(&dest_region)) { - pixman_region32_fini(&dest_region); - return; - } - - rects = pixman_region32_rectangles(&dest_region, &n_rects); - spice_canvas->ops->fill_solid_rects(spice_canvas, rects, n_rects, 0xffffffff); - - pixman_region32_fini(&dest_region); -} - -static void canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - pixman_box32_t *rects; - int n_rects; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &invers->mask, - bbox->left, bbox->top); - - if (!pixman_region32_not_empty(&dest_region)) { - pixman_region32_fini(&dest_region); - return; - } - - rects = pixman_region32_rectangles(&dest_region, &n_rects); - spice_canvas->ops->fill_solid_rects_rop(spice_canvas, rects, n_rects, 0x00000000, - SPICE_ROP_INVERT); - - pixman_region32_fini(&dest_region); -} - -typedef struct { - lineGC base; - SpiceCanvas *canvas; - pixman_region32_t dest_region; - SpiceROP fore_rop; - SpiceROP back_rop; - int solid; - uint32_t color; - int use_surface_canvas; - union { - SpiceCanvas *surface_canvas; - pixman_image_t *tile; - }; - int tile_offset_x; - int tile_offset_y; -} StrokeGC; - -static void stroke_fill_spans(lineGC * pGC, - int num_spans, - SpicePoint *points, - int *widths, - int sorted, - int foreground) -{ - SpiceCanvas *canvas; - StrokeGC *strokeGC; - int i; - SpiceROP rop; - - strokeGC = (StrokeGC *)pGC; - canvas = strokeGC->canvas; - - num_spans = spice_canvas_clip_spans(&strokeGC->dest_region, - points, widths, num_spans, - points, widths, sorted); - - if (foreground) { - rop = strokeGC->fore_rop; - } else { - rop = strokeGC->back_rop; - } - - if (strokeGC->solid) { - if (rop == SPICE_ROP_COPY) { - canvas->ops->fill_solid_spans(canvas, points, widths, num_spans, - strokeGC->color); - } else { - for (i = 0; i < num_spans; i++) { - pixman_box32_t r; - r.x1 = points[i].x; - r.y1 = points[i].y; - r.x2 = points[i].x + widths[i]; - r.y2 = r.y1 + 1; - canvas->ops->fill_solid_rects_rop(canvas, &r, 1, - strokeGC->color, rop); - } - } - } else { - if (rop == SPICE_ROP_COPY) { - for (i = 0; i < num_spans; i++) { - pixman_box32_t r; - r.x1 = points[i].x; - r.y1 = points[i].y; - r.x2 = points[i].x + widths[i]; - r.y2 = r.y1 + 1; - canvas->ops->fill_tiled_rects(canvas, &r, 1, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y); - } - } else { - for (i = 0; i < num_spans; i++) { - pixman_box32_t r; - r.x1 = points[i].x; - r.y1 = points[i].y; - r.x2 = points[i].x + widths[i]; - r.y2 = r.y1 + 1; - canvas->ops->fill_tiled_rects_rop(canvas, &r, 1, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y, rop); - } - } - } -} - -static void stroke_fill_rects(lineGC * pGC, - int num_rects, - pixman_rectangle32_t *rects, - int foreground) -{ - SpiceCanvas *canvas; - pixman_region32_t area; - pixman_box32_t *boxes; - StrokeGC *strokeGC; - SpiceROP rop; - int i; - pixman_box32_t *area_rects; - int n_area_rects; - - strokeGC = (StrokeGC *)pGC; - canvas = strokeGC->canvas; - - if (foreground) { - rop = strokeGC->fore_rop; - } else { - rop = strokeGC->back_rop; - } - - /* TODO: We can optimize this for more common cases where - dest is one rect */ - - boxes = spice_new(pixman_box32_t, num_rects); - for (i = 0; i < num_rects; i++) { - boxes[i].x1 = rects[i].x; - boxes[i].y1 = rects[i].y; - boxes[i].x2 = rects[i].x + rects[i].width; - boxes[i].y2 = rects[i].y + rects[i].height; - } - pixman_region32_init_rects(&area, boxes, num_rects); - pixman_region32_intersect(&area, &area, &strokeGC->dest_region); - free(boxes); - - area_rects = pixman_region32_rectangles(&area, &n_area_rects); - - if (strokeGC->solid) { - if (rop == SPICE_ROP_COPY) { - canvas->ops->fill_solid_rects(canvas, area_rects, n_area_rects, - strokeGC->color); - } else { - canvas->ops->fill_solid_rects_rop(canvas, area_rects, n_area_rects, - strokeGC->color, rop); - } - } else { - if (rop == SPICE_ROP_COPY) { - if (strokeGC->use_surface_canvas) { - canvas->ops->fill_tiled_rects_from_surface(canvas, area_rects, n_area_rects, - strokeGC->surface_canvas, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y); - } else { - canvas->ops->fill_tiled_rects(canvas, area_rects, n_area_rects, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y); - } - } else { - if (strokeGC->use_surface_canvas) { - canvas->ops->fill_tiled_rects_rop_from_surface(canvas, area_rects, n_area_rects, - strokeGC->surface_canvas, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y, - rop); - } else { - canvas->ops->fill_tiled_rects_rop(canvas, area_rects, n_area_rects, - strokeGC->tile, - strokeGC->tile_offset_x, - strokeGC->tile_offset_y, - rop); - } - } - } - - pixman_region32_fini(&area); -} - -typedef struct { - SpicePoint *points; - int num_points; - int size; -} StrokeLines; - -static void stroke_lines_init(StrokeLines *lines) -{ - lines->points = spice_new(SpicePoint, 10); - lines->size = 10; - lines->num_points = 0; -} - -static void stroke_lines_free(StrokeLines *lines) -{ - free(lines->points); -} - -static void stroke_lines_append(StrokeLines *lines, - int x, int y) -{ - if (lines->num_points == lines->size) { - lines->size *= 2; - lines->points = spice_renew(SpicePoint, lines->points, lines->size); - } - lines->points[lines->num_points].x = x; - lines->points[lines->num_points].y = y; - lines->num_points++; -} - -static void stroke_lines_append_fix(StrokeLines *lines, - SpicePointFix *point) -{ - stroke_lines_append(lines, - fix_to_int(point->x), - fix_to_int(point->y)); -} - -static inline int64_t dot(SPICE_FIXED28_4 x1, - SPICE_FIXED28_4 y1, - SPICE_FIXED28_4 x2, - SPICE_FIXED28_4 y2) -{ - return (((int64_t)x1) *((int64_t)x2) + - ((int64_t)y1) *((int64_t)y2)) >> 4; -} - -static inline int64_t dot2(SPICE_FIXED28_4 x, - SPICE_FIXED28_4 y) -{ - return (((int64_t)x) *((int64_t)x) + - ((int64_t)y) *((int64_t)y)) >> 4; -} - -static void subdivide_bezier(StrokeLines *lines, - SpicePointFix point0, - SpicePointFix point1, - SpicePointFix point2, - SpicePointFix point3) -{ - int64_t A2, B2, C2, AB, CB, h1, h2; - - A2 = dot2(point1.x - point0.x, - point1.y - point0.y); - B2 = dot2(point3.x - point0.x, - point3.y - point0.y); - C2 = dot2(point2.x - point3.x, - point2.y - point3.y); - - AB = dot(point1.x - point0.x, - point1.y - point0.y, - point3.x - point0.x, - point3.y - point0.y); - - CB = dot(point2.x - point3.x, - point2.y - point3.y, - point0.x - point3.x, - point0.y - point3.y); - - h1 = (A2*B2 - AB*AB) >> 3; - h2 = (C2*B2 - CB*CB) >> 3; - - if (h1 < B2 && h2 < B2) { - /* deviation squared less than half a pixel, use straight line */ - stroke_lines_append_fix(lines, &point3); - } else { - SpicePointFix point01, point23, point12, point012, point123, point0123; - - point01.x = (point0.x + point1.x) / 2; - point01.y = (point0.y + point1.y) / 2; - point12.x = (point1.x + point2.x) / 2; - point12.y = (point1.y + point2.y) / 2; - point23.x = (point2.x + point3.x) / 2; - point23.y = (point2.y + point3.y) / 2; - point012.x = (point01.x + point12.x) / 2; - point012.y = (point01.y + point12.y) / 2; - point123.x = (point12.x + point23.x) / 2; - point123.y = (point12.y + point23.y) / 2; - point0123.x = (point012.x + point123.x) / 2; - point0123.y = (point012.y + point123.y) / 2; - - subdivide_bezier(lines, point0, point01, point012, point0123); - subdivide_bezier(lines, point0123, point123, point23, point3); - } -} - -static void stroke_lines_append_bezier(StrokeLines *lines, - SpicePointFix *point1, - SpicePointFix *point2, - SpicePointFix *point3) -{ - SpicePointFix point0; - - point0.x = int_to_fix(lines->points[lines->num_points-1].x); - point0.y = int_to_fix(lines->points[lines->num_points-1].y); - - subdivide_bezier(lines, point0, *point1, *point2, *point3); -} - -static void stroke_lines_draw(StrokeLines *lines, - lineGC *gc, - int dashed) -{ - if (lines->num_points != 0) { - if (dashed) { - spice_canvas_zero_dash_line(gc, CoordModeOrigin, - lines->num_points, lines->points); - } else { - spice_canvas_zero_line(gc, CoordModeOrigin, - lines->num_points, lines->points); - } - lines->num_points = 0; - } -} - - -static void canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, - SpiceClip *clip, SpiceStroke *stroke) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - SpiceCanvas *surface_canvas = NULL; - StrokeGC gc = { { 0 } }; - lineGCOps ops = { - stroke_fill_spans, - stroke_fill_rects - }; - StrokeLines lines; - unsigned int i; - int dashed; - - pixman_region32_init_rect(&gc.dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &gc.dest_region, clip); - - if (!pixman_region32_not_empty(&gc.dest_region)) { - touch_brush(canvas, &stroke->brush); - pixman_region32_fini(&gc.dest_region); - return; - } - - gc.canvas = spice_canvas; - gc.fore_rop = ropd_descriptor_to_rop(stroke->fore_mode, - ROP_INPUT_BRUSH, - ROP_INPUT_DEST); - gc.back_rop = ropd_descriptor_to_rop(stroke->back_mode, - ROP_INPUT_BRUSH, - ROP_INPUT_DEST); - - gc.base.width = canvas->width; - gc.base.height = canvas->height; - gc.base.alu = gc.fore_rop; - gc.base.lineWidth = 0; - - /* dash */ - gc.base.dashOffset = 0; - gc.base.dash = NULL; - gc.base.numInDashList = 0; - gc.base.lineStyle = LineSolid; - /* win32 cosmetic lines are endpoint-exclusive, so use CapNotLast */ - gc.base.capStyle = CapNotLast; - gc.base.joinStyle = JoinMiter; - gc.base.ops = &ops; - - dashed = 0; - if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) { - SPICE_FIXED28_4 *style = stroke->attr.style; - int nseg; - - dashed = 1; - - nseg = stroke->attr.style_nseg; - - /* To truly handle back_mode we should use LineDoubleDash here - and treat !foreground as back_rop using the same brush. - However, using the same brush for that seems wrong. - The old cairo backend was stroking the non-dashed line with - rop_mode before enabling dashes for the foreground which is - not right either. The gl an gdi backend don't use back_mode - at all */ - gc.base.lineStyle = LineOnOffDash; - gc.base.dash = (unsigned char *)spice_malloc(nseg); - gc.base.numInDashList = nseg; - - if (stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP) { - gc.base.dash[stroke->attr.style_nseg - 1] = fix_to_int(style[0]); - for (i = 0; i < (unsigned int)(stroke->attr.style_nseg - 1); i++) { - gc.base.dash[i] = fix_to_int(style[i+1]); - } - gc.base.dashOffset = gc.base.dash[0]; - } else { - for (i = 0; i < stroke->attr.style_nseg; i++) { - gc.base.dash[i] = fix_to_int(style[i]); - } - } - } - - switch (stroke->brush.type) { - case SPICE_BRUSH_TYPE_NONE: - gc.solid = TRUE; - gc.color = 0; - break; - case SPICE_BRUSH_TYPE_SOLID: - gc.solid = TRUE; - gc.color = stroke->brush.u.color; - break; - case SPICE_BRUSH_TYPE_PATTERN: - gc.solid = FALSE; - surface_canvas = canvas_get_surface(canvas, - stroke->brush.u.pattern.pat); - if (surface_canvas) { - gc.use_surface_canvas = TRUE; - gc.surface_canvas = surface_canvas; - } else { - gc.use_surface_canvas = FALSE; - gc.tile = canvas_get_image(canvas, - stroke->brush.u.pattern.pat, - FALSE); - } - gc.tile_offset_x = stroke->brush.u.pattern.pos.x; - gc.tile_offset_y = stroke->brush.u.pattern.pos.y; - break; - default: - CANVAS_ERROR("invalid brush type"); - } - - stroke_lines_init(&lines); - - for (i = 0; i < stroke->path->num_segments; i++) { - SpicePathSeg *seg = stroke->path->segments[i]; - SpicePointFix* point, *end_point; - - point = seg->points; - end_point = point + seg->count; - - if (seg->flags & SPICE_PATH_BEGIN) { - stroke_lines_draw(&lines, (lineGC *)&gc, dashed); - stroke_lines_append_fix(&lines, point); - point++; - } - - if (seg->flags & SPICE_PATH_BEZIER) { - ASSERT((point - end_point) % 3 == 0); - for (; point + 2 < end_point; point += 3) { - stroke_lines_append_bezier(&lines, - &point[0], - &point[1], - &point[2]); - } - } else - { - for (; point < end_point; point++) { - stroke_lines_append_fix(&lines, point); - } - } - if (seg->flags & SPICE_PATH_END) { - if (seg->flags & SPICE_PATH_CLOSE) { - stroke_lines_append(&lines, - lines.points[0].x, lines.points[0].y); - } - stroke_lines_draw(&lines, (lineGC *)&gc, dashed); - } - } - - stroke_lines_draw(&lines, (lineGC *)&gc, dashed); - - free(gc.base.dash); - stroke_lines_free(&lines); - - if (!gc.solid && gc.tile && !surface_canvas) { - pixman_image_unref(gc.tile); - } - - pixman_region32_fini(&gc.dest_region); -} - - -//need surfaces handling here !!! -static void canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, - SpiceClip *clip, SpiceRop3 *rop3) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - SpiceCanvas *surface_canvas; - pixman_region32_t dest_region; - pixman_image_t *d; - pixman_image_t *s; - SpicePoint src_pos; - int width; - int heigth; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - canvas_mask_pixman(canvas, &dest_region, &rop3->mask, - bbox->left, bbox->top); - - width = bbox->right - bbox->left; - heigth = bbox->bottom - bbox->top; - - d = canvas_get_image_from_self(spice_canvas, bbox->left, bbox->top, width, heigth); - surface_canvas = canvas_get_surface(canvas, rop3->src_bitmap); - if (surface_canvas) { - s = surface_canvas->ops->get_image(surface_canvas); - } else { - s = canvas_get_image(canvas, rop3->src_bitmap, FALSE); - } - - if (!rect_is_same_size(bbox, &rop3->src_area)) { - pixman_image_t *scaled_s = canvas_scale_surface(s, &rop3->src_area, width, heigth, - rop3->scale_mode); - pixman_image_unref(s); - s = scaled_s; - src_pos.x = 0; - src_pos.y = 0; - } else { - src_pos.x = rop3->src_area.left; - src_pos.y = rop3->src_area.top; - } - if (pixman_image_get_width(s) - src_pos.x < width || - pixman_image_get_height(s) - src_pos.y < heigth) { - CANVAS_ERROR("bad src bitmap size"); - } - if (rop3->brush.type == SPICE_BRUSH_TYPE_PATTERN) { - SpiceCanvas *_surface_canvas; - pixman_image_t *p; - - _surface_canvas = canvas_get_surface(canvas, rop3->brush.u.pattern.pat); - if (_surface_canvas) { - p = _surface_canvas->ops->get_image(_surface_canvas); - } else { - p = canvas_get_image(canvas, rop3->brush.u.pattern.pat, FALSE); - } - SpicePoint pat_pos; - - pat_pos.x = (bbox->left - rop3->brush.u.pattern.pos.x) % pixman_image_get_width(p); - pat_pos.y = (bbox->top - rop3->brush.u.pattern.pos.y) % pixman_image_get_height(p); - do_rop3_with_pattern(rop3->rop3, d, s, &src_pos, p, &pat_pos); - pixman_image_unref(p); - } else { - do_rop3_with_color(rop3->rop3, d, s, &src_pos, rop3->brush.u.color); - } - pixman_image_unref(s); - - spice_canvas->ops->blit_image(spice_canvas, &dest_region, d, - bbox->left, - bbox->top); - - pixman_image_unref(d); - - pixman_region32_fini(&dest_region); -} - -static void canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_t dest_region; - int dx, dy; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(canvas, &dest_region, clip); - - dx = bbox->left - src_pos->x; - dy = bbox->top - src_pos->y; - - if (dx != 0 || dy != 0) { - pixman_region32_t src_region; - - /* Clip so we don't read outside canvas */ - pixman_region32_init_rect(&src_region, - dx, dy, - canvas->width, - canvas->height); - pixman_region32_intersect(&dest_region, &dest_region, &src_region); - pixman_region32_fini(&src_region); - - spice_canvas->ops->copy_region(spice_canvas, &dest_region, dx, dy); - } - - pixman_region32_fini(&dest_region); -} - - - -static void canvas_base_group_start(SpiceCanvas *spice_canvas, QRegion *region) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_fini(&canvas->canvas_region); - - /* Make sure we always clip to canvas size */ - pixman_region32_init_rect(&canvas->canvas_region, - 0, 0, - canvas->width, - canvas->height); - - pixman_region32_intersect(&canvas->canvas_region, &canvas->canvas_region, region); -} - -static void canvas_base_group_end(SpiceCanvas *spice_canvas) -{ - CanvasBase *canvas = (CanvasBase *)spice_canvas; - pixman_region32_fini(&canvas->canvas_region); - pixman_region32_init_rect(&canvas->canvas_region, - 0, 0, - canvas->width, - canvas->height); -} - - -static void unimplemented_op(SpiceCanvas *canvas) -{ - PANIC("unimplemented canvas operation"); -} - -inline static void canvas_base_init_ops(SpiceCanvasOps *ops) -{ - void **ops_cast; - unsigned i; - - ops_cast = (void **)ops; - for (i = 0; i < sizeof(SpiceCanvasOps) / sizeof(void *); i++) { - ops_cast[i] = (void *) unimplemented_op; - } - - ops->draw_fill = canvas_draw_fill; - ops->draw_copy = canvas_draw_copy; - ops->draw_opaque = canvas_draw_opaque; - ops->copy_bits = canvas_copy_bits; - ops->draw_blend = canvas_draw_blend; - ops->draw_blackness = canvas_draw_blackness; - ops->draw_whiteness = canvas_draw_whiteness; - ops->draw_invers = canvas_draw_invers; - ops->draw_transparent = canvas_draw_transparent; - ops->draw_alpha_blend = canvas_draw_alpha_blend; - ops->draw_stroke = canvas_draw_stroke; - ops->draw_rop3 = canvas_draw_rop3; - ops->group_start = canvas_base_group_start; - ops->group_end = canvas_base_group_end; -} - -static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops, - int width, int height, uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ) -{ - canvas->parent.ops = ops; - canvas->quic_data.usr.error = quic_usr_error; - canvas->quic_data.usr.warn = quic_usr_warn; - canvas->quic_data.usr.info = quic_usr_warn; - canvas->quic_data.usr.malloc = quic_usr_malloc; - canvas->quic_data.usr.free = quic_usr_free; - canvas->quic_data.usr.more_space = quic_usr_more_space; - canvas->quic_data.usr.more_lines = quic_usr_more_lines; - if (!(canvas->quic_data.quic = quic_create(&canvas->quic_data.usr))) { - return 0; - } - - canvas->lz_data.usr.error = lz_usr_error; - canvas->lz_data.usr.warn = lz_usr_warn; - canvas->lz_data.usr.info = lz_usr_warn; - canvas->lz_data.usr.malloc = lz_usr_malloc; - canvas->lz_data.usr.free = lz_usr_free; - canvas->lz_data.usr.more_space = lz_usr_more_space; - canvas->lz_data.usr.more_lines = lz_usr_more_lines; - if (!(canvas->lz_data.lz = lz_create(&canvas->lz_data.usr))) { - return 0; - } - - canvas->surfaces = surfaces; - canvas->glz_data.decoder = glz_decoder; - canvas->jpeg = jpeg_decoder; - canvas->zlib = zlib_decoder; - - 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 { - canvas->color_shift = 8; - canvas->color_mask = 0xff; - } - - canvas->width = width; - canvas->height = height; - pixman_region32_init_rect(&canvas->canvas_region, - 0, 0, - canvas->width, - canvas->height); - -#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE) - canvas->bits_cache = bits_cache; -#endif -#ifdef SW_CANVAS_CACHE - canvas->palette_cache = palette_cache; -#endif - -#ifdef WIN32 - canvas->dc = NULL; -#endif - -#ifdef GDI_CANVAS - canvas->dc = create_compatible_dc(); - if (!canvas->dc) { - lz_destroy(canvas->lz_data.lz); - return 0; - } -#endif - return 1; -} diff --git a/common/canvas_base.h b/common/canvas_base.h deleted file mode 100644 index 861171ec..00000000 --- a/common/canvas_base.h +++ /dev/null @@ -1,327 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_CANVAS_BASE -#define _H_CANVAS_BASE - -#ifndef SPICE_CANVAS_INTERNAL -#error "This header shouldn't be included directly" -#endif - -#include "pixman_utils.h" -#include "lz.h" -#include "region.h" -#include "draw.h" -#ifdef WIN32 -#include <windows.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*spice_destroy_fn_t)(void *data); - -typedef struct _SpiceImageCache SpiceImageCache; -typedef struct _SpiceImageSurfaces SpiceImageSurfaces; -typedef struct _SpicePaletteCache SpicePaletteCache; -typedef struct _SpiceGlzDecoder SpiceGlzDecoder; -typedef struct _SpiceJpegDecoder SpiceJpegDecoder; -typedef struct _SpiceZlibDecoder SpiceZlibDecoder; -typedef struct _SpiceCanvas SpiceCanvas; - -typedef struct { - void (*put)(SpiceImageCache *cache, - uint64_t id, - pixman_image_t *surface); - pixman_image_t *(*get)(SpiceImageCache *cache, - uint64_t id); -#ifdef SW_CANVAS_CACHE - void (*put_lossy)(SpiceImageCache *cache, - uint64_t id, - pixman_image_t *surface); - void (*replace_lossy)(SpiceImageCache *cache, - uint64_t id, - pixman_image_t *surface); - pixman_image_t *(*get_lossless)(SpiceImageCache *cache, - uint64_t id); -#endif -} SpiceImageCacheOps; - -struct _SpiceImageCache { - SpiceImageCacheOps *ops; -}; - -typedef struct { - SpiceCanvas *(*get)(SpiceImageSurfaces *surfaces, - uint32_t surface_id); -} SpiceImageSurfacesOps; - -struct _SpiceImageSurfaces { - SpiceImageSurfacesOps *ops; -}; - -typedef struct { - void (*put)(SpicePaletteCache *cache, - SpicePalette *palette); - SpicePalette *(*get)(SpicePaletteCache *cache, - uint64_t id); - void (*release)(SpicePaletteCache *cache, - SpicePalette *palette); -} SpicePaletteCacheOps; - -struct _SpicePaletteCache { - SpicePaletteCacheOps *ops; -}; - -typedef struct { - void (*decode)(SpiceGlzDecoder *decoder, - uint8_t *data, - SpicePalette *plt, - void *usr_data); -} SpiceGlzDecoderOps; - -struct _SpiceGlzDecoder { - SpiceGlzDecoderOps *ops; -}; - - -typedef struct SpiceJpegDecoderOps { - void (*begin_decode)(SpiceJpegDecoder *decoder, - uint8_t* data, - int data_size, - int* out_width, - int* out_height); - void (*decode)(SpiceJpegDecoder *decoder, - uint8_t* dest, - int stride, - int format); -} SpiceJpegDecoderOps; - -struct _SpiceJpegDecoder { - SpiceJpegDecoderOps *ops; -}; - -typedef struct { - void (*decode)(SpiceZlibDecoder *decoder, - uint8_t *data, - int data_size, - uint8_t *dest, - int dest_size); -} SpiceZlibDecoderOps; - -struct _SpiceZlibDecoder { - SpiceZlibDecoderOps *ops; -}; - -typedef struct { - void (*draw_fill)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill); - void (*draw_copy)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy); - void (*draw_opaque)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque); - void (*copy_bits)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos); - void (*draw_text)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text); - void (*draw_stroke)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke); - void (*draw_rop3)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3); - void (*draw_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend); - void (*draw_blackness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness); - void (*draw_whiteness)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness); - void (*draw_invers)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers); - void (*draw_transparent)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent* transparent); - void (*draw_alpha_blend)(SpiceCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend); - void (*put_image)(SpiceCanvas *canvas, -#ifdef WIN32 - HDC dc, -#endif - const SpiceRect *dest, const uint8_t *src_data, - uint32_t src_width, uint32_t src_height, int src_stride, - const QRegion *clip); - void (*clear)(SpiceCanvas *canvas); - void (*read_bits)(SpiceCanvas *canvas, uint8_t *dest, int dest_stride, const SpiceRect *area); - void (*group_start)(SpiceCanvas *canvas, QRegion *region); - void (*group_end)(SpiceCanvas *canvas); - void (*destroy)(SpiceCanvas *canvas); - - /* Implementation vfuncs */ - void (*fill_solid_spans)(SpiceCanvas *canvas, - SpicePoint *points, - int *widths, - int n_spans, - uint32_t color); - void (*fill_solid_rects)(SpiceCanvas *canvas, - pixman_box32_t *rects, - int n_rects, - uint32_t color); - void (*fill_solid_rects_rop)(SpiceCanvas *canvas, - pixman_box32_t *rects, - int n_rects, - uint32_t color, - SpiceROP rop); - void (*fill_tiled_rects)(SpiceCanvas *canvas, - pixman_box32_t *rects, - int n_rects, - pixman_image_t *tile, - int offset_x, int offset_y); - void (*fill_tiled_rects_from_surface)(SpiceCanvas *canvas, - pixman_box32_t *rects, - int n_rects, - SpiceCanvas *tile, - int offset_x, int offset_y); - void (*fill_tiled_rects_rop)(SpiceCanvas *canvas, - pixman_box32_t *rects, - int n_rects, - pixman_image_t *tile, - int offset_x, int offset_y, - SpiceROP rop); - void (*fill_tiled_rects_rop_from_surface)(SpiceCanvas *canvas, - pixman_box32_t *rects, - int n_rects, - SpiceCanvas *tile, - int offset_x, int offset_y, - SpiceROP rop); - void (*blit_image)(SpiceCanvas *canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y); - void (*blit_image_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceCanvas *src_image, - int offset_x, int offset_y); - void (*blit_image_rop)(SpiceCanvas *canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y, - SpiceROP rop); - void (*blit_image_rop_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceCanvas *src_image, - int offset_x, int offset_y, - SpiceROP rop); - void (*scale_image)(SpiceCanvas *canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode); - void (*scale_image_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceCanvas *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode); - void (*scale_image_rop)(SpiceCanvas *canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, SpiceROP rop); - void (*scale_image_rop_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceCanvas *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, SpiceROP rop); - void (*blend_image)(SpiceCanvas *canvas, - pixman_region32_t *region, - int dest_has_alpha, - pixman_image_t *src_image, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - int overall_alpha); - void (*blend_image_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - int dest_has_alpha, - SpiceCanvas *src_image, - int src_has_alpha, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - int overall_alpha); - void (*blend_scale_image)(SpiceCanvas *canvas, - pixman_region32_t *region, - int dest_has_alpha, - pixman_image_t *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, - int overall_alpha); - void (*blend_scale_image_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - int dest_has_alpha, - SpiceCanvas *src_image, - int src_has_alpha, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, - int overall_alpha); - void (*colorkey_image)(SpiceCanvas *canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y, - uint32_t transparent_color); - void (*colorkey_image_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceCanvas *src_image, - int offset_x, int offset_y, - uint32_t transparent_color); - void (*colorkey_scale_image)(SpiceCanvas *canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - uint32_t transparent_color); - void (*colorkey_scale_image_from_surface)(SpiceCanvas *canvas, - pixman_region32_t *region, - SpiceCanvas *src_image, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - uint32_t transparent_color); - void (*copy_region)(SpiceCanvas *canvas, - pixman_region32_t *dest_region, - int dx, int dy); - pixman_image_t *(*get_image)(SpiceCanvas *canvas); -} SpiceCanvasOps; - -void spice_canvas_set_usr_data(SpiceCanvas *canvas, void *data, spice_destroy_fn_t destroy_fn); -void *spice_canvas_get_usr_data(SpiceCanvas *canvas); - -struct _SpiceCanvas { - SpiceCanvasOps *ops; -}; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/canvas_utils.c b/common/canvas_utils.c deleted file mode 100644 index 6632942e..00000000 --- a/common/canvas_utils.c +++ /dev/null @@ -1,299 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "canvas_utils.h" - -#include <spice/macros.h> - -#ifdef __GNUC__ -#include <stdlib.h> -#include <stdio.h> -#endif -#include "mem.h" - -#ifdef WIN32 -static int gdi_handlers = 0; -#endif - -#ifndef CANVAS_ERROR -#define CANVAS_ERROR(format, ...) { \ - printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__); \ - abort(); \ -} -#endif - -static void release_data(pixman_image_t *image, void *release_data) -{ - PixmanData *data = (PixmanData *)release_data; - -#ifdef WIN32 - if (data->bitmap) { - DeleteObject((HBITMAP)data->bitmap); - CloseHandle(data->mutex); - gdi_handlers--; - } -#endif - free(data->data); - - free(data); -} - -static PixmanData * -pixman_image_add_data(pixman_image_t *image) -{ - PixmanData *data; - - data = (PixmanData *)pixman_image_get_destroy_data(image); - if (data == NULL) { - data = (PixmanData *)calloc(1, sizeof(PixmanData)); - if (data == NULL) { - CANVAS_ERROR("out of memory"); - } - pixman_image_set_destroy_function(image, - release_data, - data); - } - - return data; -} - -void -spice_pixman_image_set_format(pixman_image_t *image, - pixman_format_code_t format) -{ - PixmanData *data; - - data = pixman_image_add_data(image); - data->format = format; -} - -pixman_format_code_t -spice_pixman_image_get_format(pixman_image_t *image) -{ - PixmanData *data; - - data = (PixmanData *)pixman_image_get_destroy_data(image); - if (data != NULL && - data->format != 0) - return data->format; - - CANVAS_ERROR("Unknown pixman image type"); -} - -static INLINE pixman_image_t *__surface_create_stride(pixman_format_code_t format, int width, int height, - int stride) -{ - uint8_t *data; - uint8_t *stride_data; - pixman_image_t *surface; - PixmanData *pixman_data; - - data = (uint8_t *)spice_malloc_n(abs(stride), height); - if (stride < 0) { - stride_data = data + (-stride) * (height - 1); - } else { - stride_data = data; - } - - surface = pixman_image_create_bits(format, width, height, (uint32_t *)stride_data, stride); - - if (surface == NULL) { - free(data); - CANVAS_ERROR("create surface failed, out of memory"); - } - - pixman_data = pixman_image_add_data(surface); - pixman_data->data = data; - pixman_data->format = format; - - return surface; -} - -#ifdef WIN32 -pixman_image_t *surface_create(HDC dc, pixman_format_code_t format, - int width, int height, int top_down) -#else -pixman_image_t * surface_create(pixman_format_code_t format, int width, int height, int top_down) -#endif -{ -#ifdef WIN32 - /* - * Windows xp allow only 10,000 of gdi handlers, considering the fact that - * we limit here the number to 5000, we dont use atomic operations to sync - * this calculation against the other canvases (in case of multiple - * monitors), in worst case there will be little more than 5000 gdi - * handlers. - */ - if (dc && gdi_handlers < 5000) { - uint8_t *data; - uint8_t *src; - struct { - BITMAPINFO inf; - RGBQUAD palette[255]; - } bitmap_info; - int nstride; - pixman_image_t *surface; - PixmanData *pixman_data; - HBITMAP bitmap; - HANDLE mutex; - - memset(&bitmap_info, 0, sizeof(bitmap_info)); - bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader); - bitmap_info.inf.bmiHeader.biWidth = width; - - bitmap_info.inf.bmiHeader.biHeight = (!top_down) ? height : -height; - - bitmap_info.inf.bmiHeader.biPlanes = 1; - switch (format) { - case PIXMAN_a8r8g8b8: - case PIXMAN_x8r8g8b8: - 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); - break; - case PIXMAN_a1: - bitmap_info.inf.bmiHeader.biBitCount = 1; - nstride = SPICE_ALIGN(width, 32) / 8; - break; - default: - CANVAS_ERROR("invalid format"); - } - - bitmap_info.inf.bmiHeader.biCompression = BI_RGB; - - mutex = CreateMutex(NULL, 0, NULL); - if (!mutex) { - CANVAS_ERROR("Unable to CreateMutex"); - } - - bitmap = CreateDIBSection(dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0); - if (!bitmap) { - CloseHandle(mutex); - CANVAS_ERROR("Unable to CreateDIBSection"); - } - - if (top_down) { - src = data; - } else { - src = data + nstride * (height - 1); - nstride = -nstride; - } - - surface = pixman_image_create_bits(format, width, height, (uint32_t *)src, nstride); - if (surface == NULL) { - CloseHandle(mutex); - DeleteObject(bitmap); - CANVAS_ERROR("create surface failed, out of memory"); - } - pixman_data = pixman_image_add_data(surface); - pixman_data->format = format; - pixman_data->bitmap = bitmap; - pixman_data->mutex = mutex; - gdi_handlers++; - return surface; - } else { -#endif - if (top_down) { - pixman_image_t *surface; - PixmanData *data; - - surface = pixman_image_create_bits(format, width, height, NULL, 0); - data = pixman_image_add_data(surface); - data->format = format; - return surface; - } else { - // NOTE: we assume here that the lz decoders always decode to RGB32. - int stride = 0; - switch (format) { - case PIXMAN_a8r8g8b8: - 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; - case PIXMAN_a1: - stride = SPICE_ALIGN(width, 32) / 8; - break; - default: - CANVAS_ERROR("invalid format"); - } - stride = -stride; - return __surface_create_stride(format, width, height, stride); - } -#ifdef WIN32 -} - -#endif -} - -#ifdef WIN32 -pixman_image_t *surface_create_stride(HDC dc, pixman_format_code_t format, int width, int height, - int stride) -#else -pixman_image_t *surface_create_stride(pixman_format_code_t format, int width, int height, - int stride) -#endif -{ -#ifdef WIN32 - if (dc) { - if (abs(stride) == (width * 4)) { - return surface_create(dc, format, width, height, (stride > 0)); - } - } -#endif - - return __surface_create_stride(format, width, height, stride); -} - -pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data, - pixman_format_code_t pixman_format, int width, - int height, int gross_pixels, int top_down) -{ - int stride; - pixman_image_t *surface = NULL; - - stride = (gross_pixels / height) * (PIXMAN_FORMAT_BPP (pixman_format) / 8); - - if (!top_down) { - stride = -stride; - } - - surface = surface_create_stride( -#ifdef WIN32 - canvas_data->dc, -#endif - pixman_format, width, height, stride); - canvas_data->out_surface = surface; - return surface; -} diff --git a/common/canvas_utils.h b/common/canvas_utils.h deleted file mode 100644 index 16ada459..00000000 --- a/common/canvas_utils.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_CANVAS_UTILS -#define _H_CANVAS_UTILS - -#ifdef WIN32 -#include <windows.h> -#endif - -#include <spice/types.h> - -#include "pixman_utils.h" -#include "lz.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct PixmanData { -#ifdef WIN32 - HBITMAP bitmap; - HANDLE mutex; -#endif - uint8_t *data; - pixman_format_code_t format; -} PixmanData; - -void spice_pixman_image_set_format(pixman_image_t *image, - pixman_format_code_t format); -pixman_format_code_t spice_pixman_image_get_format(pixman_image_t *image); - - -#ifdef WIN32 -pixman_image_t *surface_create(HDC dc, pixman_format_code_t format, - int width, int height, int top_down); -#else -pixman_image_t *surface_create(pixman_format_code_t format, int width, int height, int top_down); -#endif - -#ifdef WIN32 -pixman_image_t *surface_create_stride(HDC dc, pixman_format_code_t format, int width, int height, - int stride); -#else -pixman_image_t *surface_create_stride(pixman_format_code_t format, int width, int height, - int stride); -#endif - - -typedef struct LzDecodeUsrData { -#ifdef WIN32 - HDC dc; -#endif - pixman_image_t *out_surface; -} LzDecodeUsrData; - - -pixman_image_t *alloc_lz_image_surface(LzDecodeUsrData *canvas_data, - pixman_format_code_t pixman_format, int width, - int height, int gross_pixels, int top_down); -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/draw.h b/common/draw.h deleted file mode 100644 index 8b1206de..00000000 --- a/common/draw.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - Copyright (C) 2009 Red Hat, Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _H_SPICE_DRAW -#define _H_SPICE_DRAW - -#include <spice/types.h> -#include <spice/enums.h> -#include "mem.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define SPICE_GET_ADDRESS(addr) ((void *)(uintptr_t)(addr)) -#define SPICE_SET_ADDRESS(addr, val) ((addr) = (uintptr_t)(val)) - -typedef int32_t SPICE_FIXED28_4; - -typedef struct SpicePointFix { - SPICE_FIXED28_4 x; - SPICE_FIXED28_4 y; -} SpicePointFix; - -typedef struct SpicePoint { - int32_t x; - int32_t y; -} SpicePoint; - -typedef struct SpicePoint16 { - int16_t x; - int16_t y; -} SpicePoint16; - -typedef struct SpiceRect { - int32_t left; - int32_t top; - int32_t right; - int32_t bottom; -} SpiceRect; - -typedef struct SpicePathSeg { - uint32_t flags; - uint32_t count; - SpicePointFix points[0]; -} SpicePathSeg; - -typedef struct SpicePath { - uint32_t num_segments; - SpicePathSeg *segments[0]; -} SpicePath; - -typedef struct SpiceClipRects { - uint32_t num_rects; - SpiceRect rects[0]; -} SpiceClipRects; - -typedef struct SpiceClip { - uint32_t type; - SpiceClipRects *rects; -} SpiceClip; - -typedef struct SpicePalette { - uint64_t unique; - uint16_t num_ents; - uint32_t ents[0]; -} SpicePalette; - -#define SPICE_SURFACE_FMT_DEPTH(_d) ((_d) & 0x3f) - -typedef struct SpiceImageDescriptor { - uint64_t id; - uint8_t type; - uint8_t flags; - uint32_t width; - uint32_t height; -} SpiceImageDescriptor; - -typedef struct SpiceBitmap { - uint8_t format; - uint8_t flags; - uint32_t x; - uint32_t y; - uint32_t stride; - SpicePalette *palette; - uint64_t palette_id; - SpiceChunks *data; -} SpiceBitmap; - -typedef struct SpiceSurface { - uint32_t surface_id; -} SpiceSurface; - -typedef struct SpiceQUICData { - uint32_t data_size; - SpiceChunks *data; -} SpiceQUICData, SpiceLZRGBData, SpiceJPEGData; - -typedef struct SpiceLZPLTData { - uint8_t flags; - uint32_t data_size; - SpicePalette *palette; - uint64_t palette_id; - SpiceChunks *data; -} SpiceLZPLTData; - -typedef struct SpiceZlibGlzRGBData { - uint32_t glz_data_size; - uint32_t data_size; - SpiceChunks *data; -} SpiceZlibGlzRGBData; - -typedef struct SpiceJPEGAlphaData { - uint8_t flags; - uint32_t jpeg_size; - uint32_t data_size; - SpiceChunks *data; -} SpiceJPEGAlphaData; - - -typedef struct SpiceImage { - SpiceImageDescriptor descriptor; - union { - SpiceBitmap bitmap; - SpiceQUICData quic; - SpiceSurface surface; - SpiceLZRGBData lz_rgb; - SpiceLZPLTData lz_plt; - SpiceJPEGData jpeg; - SpiceZlibGlzRGBData zlib_glz; - SpiceJPEGAlphaData jpeg_alpha; - } u; -} SpiceImage; - -typedef struct SpicePattern { - SpiceImage *pat; - SpicePoint pos; -} SpicePattern; - -typedef struct SpiceBrush { - uint32_t type; - union { - uint32_t color; - SpicePattern pattern; - } u; -} SpiceBrush; - -typedef struct SpiceQMask { - uint8_t flags; - SpicePoint pos; - SpiceImage *bitmap; -} SpiceQMask; - -typedef struct SpiceFill { - SpiceBrush brush; - uint16_t rop_descriptor; - SpiceQMask mask; -} SpiceFill; - -typedef struct SpiceOpaque { - SpiceImage *src_bitmap; - SpiceRect src_area; - SpiceBrush brush; - uint16_t rop_descriptor; - uint8_t scale_mode; - SpiceQMask mask; -} SpiceOpaque; - -typedef struct SpiceCopy { - SpiceImage *src_bitmap; - SpiceRect src_area; - uint16_t rop_descriptor; - uint8_t scale_mode; - SpiceQMask mask; -} SpiceCopy, SpiceBlend; - -typedef struct SpiceTransparent { - SpiceImage *src_bitmap; - SpiceRect src_area; - uint32_t src_color; - uint32_t true_color; -} SpiceTransparent; - -typedef struct SpiceAlphaBlend { - uint16_t alpha_flags; - uint8_t alpha; - SpiceImage *src_bitmap; - SpiceRect src_area; -} SpiceAlphaBlend; - -typedef struct SpiceRop3 { - SpiceImage *src_bitmap; - SpiceRect src_area; - SpiceBrush brush; - uint8_t rop3; - uint8_t scale_mode; - SpiceQMask mask; -} SpiceRop3; - -typedef struct SpiceBlackness { - SpiceQMask mask; -} SpiceBlackness, SpiceInvers, SpiceWhiteness; - -typedef struct SpiceLineAttr { - uint8_t flags; - uint8_t style_nseg; - SPICE_FIXED28_4 *style; -} SpiceLineAttr; - -typedef struct SpiceStroke { - SpicePath *path; - SpiceLineAttr attr; - SpiceBrush brush; - uint16_t fore_mode; - uint16_t back_mode; -} SpiceStroke; - -typedef struct SpiceRasterGlyph { - SpicePoint render_pos; - SpicePoint glyph_origin; - uint16_t width; - uint16_t height; - uint8_t data[0]; -} SpiceRasterGlyph; - -typedef struct SpiceString { - uint16_t length; - uint16_t flags; - SpiceRasterGlyph *glyphs[0]; -} SpiceString; - -typedef struct SpiceText { - SpiceString *str; - SpiceRect back_area; - SpiceBrush fore_brush; - SpiceBrush back_brush; - uint16_t fore_mode; - uint16_t back_mode; -} SpiceText; - -typedef struct SpiceCursorHeader { - uint64_t unique; - uint16_t type; - uint16_t width; - uint16_t height; - uint16_t hot_spot_x; - uint16_t hot_spot_y; -} SpiceCursorHeader; - -#ifdef __cplusplus -} -#endif - -#endif /* _H_SPICE_DRAW */ diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c deleted file mode 100644 index d3e9c7ff..00000000 --- a/common/gdi_canvas.c +++ /dev/null @@ -1,1858 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#ifdef __MINGW32__ -#undef HAVE_STDLIB_H -#endif -#include <config.h> -#endif - -#ifndef SPICE_CANVAS_INTERNAL -#error "This file shouldn't be compiled directly" -#endif - -#include <windows.h> -#include <wingdi.h> -#include "gdi_canvas.h" -#define GDI_CANVAS -#include "canvas_base.c" -#include "rop3.h" -#include "rect.h" -#include "region.h" -#include "threads.h" - -typedef struct GdiCanvas GdiCanvas; - -struct GdiCanvas { - CanvasBase base; - HDC dc; - RecurciveMutex* lock; -}; - - -struct BitmapData { - HBITMAP hbitmap; - HBITMAP prev_hbitmap; - SpicePoint pos; - uint8_t flags; - HDC dc; - int cache; - int from_surface; -}; - -#define _rop3_brush 0xf0 -#define _rop3_src 0xcc -#define _rop3_dest 0xaa - -uint32_t raster_ops[] = { - 0x00000042, - 0x00010289, - 0x00020C89, - 0x000300AA, - 0x00040C88, - 0x000500A9, - 0x00060865, - 0x000702C5, - 0x00080F08, - 0x00090245, - 0x000A0329, - 0x000B0B2A, - 0x000C0324, - 0x000D0B25, - 0x000E08A5, - 0x000F0001, - 0x00100C85, - 0x001100A6, - 0x00120868, - 0x001302C8, - 0x00140869, - 0x001502C9, - 0x00165CCA, - 0x00171D54, - 0x00180D59, - 0x00191CC8, - 0x001A06C5, - 0x001B0768, - 0x001C06CA, - 0x001D0766, - 0x001E01A5, - 0x001F0385, - 0x00200F09, - 0x00210248, - 0x00220326, - 0x00230B24, - 0x00240D55, - 0x00251CC5, - 0x002606C8, - 0x00271868, - 0x00280369, - 0x002916CA, - 0x002A0CC9, - 0x002B1D58, - 0x002C0784, - 0x002D060A, - 0x002E064A, - 0x002F0E2A, - 0x0030032A, - 0x00310B28, - 0x00320688, - 0x00330008, - 0x003406C4, - 0x00351864, - 0x003601A8, - 0x00370388, - 0x0038078A, // PSDPoax - 0x00390604, // SPDnox - 0x003A0644, // SPDSxox - 0x003B0E24, // SPDnoan - 0x003C004A, // PSx - 0x003D18A4, // SPDSonox - 0x003E1B24, // SPDSnaox - 0x003F00EA, // PSan - 0x00400F0A, // PSDnaa - 0x00410249, // DPSxon - 0x00420D5D, // SDxPDxa - 0x00431CC4, // SPDSanaxn - 0x00440328, // SDna SRCERASE - 0x00450B29, // DPSnaon - 0x004606C6, // DSPDaox - 0x0047076A, // PSDPxaxn - 0x00480368, // SDPxa - 0x004916C5, // PDSPDaoxxn - 0x004A0789, // DPSDoax - 0x004B0605, // PDSnox - 0x004C0CC8, // SDPana - 0x004D1954, // SSPxDSxoxn - 0x004E0645, // PDSPxox - 0x004F0E25, // PDSnoan - 0x00500325, // PDna - 0x00510B26, // DSPnaon - 0x005206C9, // DPSDaox - 0x00530764, // SPDSxaxn - 0x005408A9, // DPSonon - 0x00550009, // Dn DSTINVERT - 0x005601A9, // DPSox - 0x00570389, // DPSoan - 0x00580785, // PDSPoax - 0x00590609, // DPSnox - 0x005A0049, // DPx PATINVERT - 0x005B18A9, // DPSDonox - 0x005C0649, // DPSDxox - 0x005D0E29, // DPSnoan - 0x005E1B29, // DPSDnaox - 0x005F00E9, // DPan - 0x00600365, // PDSxa - 0x006116C6, // DSPDSaoxxn - 0x00620786, // DSPDoax - 0x00630608, // SDPnox - 0x00640788, // SDPSoax - 0x00650606, // DSPnox - 0x00660046, // DSx SRCINVERT - 0x006718A8, // SDPSonox - 0x006858A6, // DSPDSonoxxn - 0x00690145, // PDSxxn - 0x006A01E9, // DPSax - 0x006B178A, // PSDPSoaxxn - 0x006C01E8, // SDPax - 0x006D1785, // PDSPDoaxxn - 0x006E1E28, // SDPSnoax - 0x006F0C65, // PDSxnan - 0x00700CC5, // PDSana - 0x00711D5C, // SSDxPDxaxn - 0x00720648, // SDPSxox - 0x00730E28, // SDPnoan - 0x00740646, // DSPDxox - 0x00750E26, // DSPnoan - 0x00761B28, // SDPSnaox - 0x007700E6, // DSan - 0x007801E5, // PDSax - 0x00791786, // DSPDSoaxxn - 0x007A1E29, // DPSDnoax - 0x007B0C68, // SDPxnan - 0x007C1E24, // SPDSnoax - 0x007D0C69, // DPSxnan - 0x007E0955, // SPxDSxo - 0x007F03C9, // DPSaan - 0x008003E9, // DPSaa - 0x00810975, // SPxDSxon - 0x00820C49, // DPSxna - 0x00831E04, // SPDSnoaxn - 0x00840C48, // SDPxna - 0x00851E05, // PDSPnoaxn - 0x008617A6, // DSPDSoaxx - 0x008701C5, // PDSaxn - 0x008800C6, // DSa SRCAND - 0x00891B08, // SDPSnaoxn - 0x008A0E06, // DSPnoa - 0x008B0666, // DSPDxoxn - 0x008C0E08, // SDPnoa - 0x008D0668, // SDPSxoxn - 0x008E1D7C, // SSDxPDxax - 0x008F0CE5, // PDSanan - 0x00900C45, // PDSxna - 0x00911E08, // SDPSnoaxn - 0x009217A9, // DPSDPoaxx - 0x009301C4, // SPDaxn - 0x009417AA, // PSDPSoaxx - 0x009501C9, // DPSaxn - 0x00960169, // DPSxx - 0x0097588A, // PSDPSonoxx - 0x00981888, // SDPSonoxn - 0x00990066, // DSxn - 0x009A0709, // DPSnax - 0x009B07A8, // SDPSoaxn - 0x009C0704, // SPDnax - 0x009D07A6, // DSPDoaxn - 0x009E16E6, // DSPDSaoxx - 0x009F0345, // PDSxan - 0x00A000C9, // DPa - 0x00A11B05, // PDSPnaoxn - 0x00A20E09, // DPSnoa - 0x00A30669, // DPSDxoxn - 0x00A41885, // PDSPonoxn - 0x00A50065, // PDxn - 0x00A60706, // DSPnax - 0x00A707A5, // PDSPoaxn - 0x00A803A9, // DPSoa - 0x00A90189, // DPSoxn - 0x00AA0029, // D - 0x00AB0889, // DPSono - 0x00AC0744, // SPDSxax - 0x00AD06E9, // DPSDaoxn - 0x00AE0B06, // DSPnao - 0x00AF0229, // DPno - 0x00B00E05, // PDSnoa - 0x00B10665, // PDSPxoxn - 0x00B21974, // SSPxDSxox - 0x00B30CE8, // SDPanan - 0x00B4070A, // PSDnax - 0x00B507A9, // DPSDoaxn - 0x00B616E9, // DPSDPaoxx - 0x00B70348, // SDPxan - 0x00B8074A, // PSDPxax - 0x00B906E6, // DSPDaoxn - 0x00BA0B09, // DPSnao - 0x00BB0226, // DSno MERGEPAINT - 0x00BC1CE4, // SPDSanax - 0x00BD0D7D, // SDxPDxan - 0x00BE0269, // DPSxo - 0x00BF08C9, // DPSano - 0x00C000CA, // PSa MERGECOPY - 0x00C11B04, // SPDSnaoxn - 0x00C21884, // SPDSonoxn - 0x00C3006A, // PSxn - 0x00C40E04, // SPDnoa - 0x00C50664, // SPDSxoxn - 0x00C60708, // SDPnax - 0x00C707AA, // PSDPoaxn - 0x00C803A8, // SDPoa - 0x00C90184, // SPDoxn - 0x00CA0749, // DPSDxax - 0x00CB06E4, // SPDSaoxn - 0x00CC0020, // S SRCCOPY - 0x00CD0888, // SDPono - 0x00CE0B08, // SDPnao - 0x00CF0224, // SPno - 0x00D00E0A, // PSDnoa - 0x00D1066A, // PSDPxoxn - 0x00D20705, // PDSnax - 0x00D307A4, // SPDSoaxn - 0x00D41D78, // SSPxPDxax - 0x00D50CE9, // DPSanan - 0x00D616EA, // PSDPSaoxx - 0x00D70349, // DPSxan - 0x00D80745, // PDSPxax - 0x00D906E8, // SDPSaoxn - 0x00DA1CE9, // DPSDanax - 0x00DB0D75, // SPxDSxan - 0x00DC0B04, // SPDnao - 0x00DD0228, // SDno - 0x00DE0268, // SDPxo - 0x00DF08C8, // SDPano - 0x00E003A5, // PDSoa - 0x00E10185, // PDSoxn - 0x00E20746, // DSPDxax - 0x00E306EA, // PSDPaoxn - 0x00E40748, // SDPSxax - 0x00E506E5, // PDSPaoxn - 0x00E61CE8, // SDPSanax - 0x00E70D79, // SPxPDxan - 0x00E81D74, // SSPxDSxax - 0x00E95CE6, // DSPDSanaxxn - 0x00EA02E9, // DPSao - 0x00EB0849, // DPSxno - 0x00EC02E8, // SDPao - 0x00ED0848, // SDPxno - 0x00EE0086, // DSo SRCPAINT - 0x00EF0A08, // SDPnoo - 0x00F00021, // P PATCOPY - 0x00F10885, // PDSono - 0x00F20B05, // PDSnao - 0x00F3022A, // PSno - 0x00F40B0A, // PSDnao - 0x00F50225, // PDno - 0x00F60265, // PDSxo - 0x00F708C5, // PDSano - 0x00F802E5, // PDSao - 0x00F90845, // PDSxno - 0x00FA0089, // DPo - 0x00FB0A09, // DPSnoo PATPAINT - 0x00FC008A, // PSo - 0x00FD0A0A, // PSDnoo - 0x00FE02A9, // DPSoo - 0x00FF0062 // 1 WHITENESS -}; - -static void set_path(GdiCanvas *canvas, SpicePath *s) -{ - unsigned int i; - - for (i = 0; i < s->num_segments; i++) { - SpicePathSeg* seg = s->segments[0]; - SpicePointFix* point = seg->points; - SpicePointFix* end_point = point + seg->count; - - if (seg->flags & SPICE_PATH_BEGIN) { - BeginPath(canvas->dc); - if (!MoveToEx(canvas->dc, (int)fix_to_double(point->x), (int)fix_to_double(point->y), - NULL)) { - CANVAS_ERROR("MoveToEx failed"); - return; - } - point++; - } - - if (seg->flags & SPICE_PATH_BEZIER) { - ASSERT((point - end_point) % 3 == 0); - for (; point + 2 < end_point; point += 3) { - POINT points[3]; - - points[0].x = (int)fix_to_double(point[0].x); - points[0].y = (int)fix_to_double(point[0].y); - points[1].x = (int)fix_to_double(point[1].x); - points[1].y = (int)fix_to_double(point[1].y); - points[2].x = (int)fix_to_double(point[2].x); - points[2].y = (int)fix_to_double(point[2].y); - if (!PolyBezierTo(canvas->dc, points, 3)) { - CANVAS_ERROR("PolyBezierTo failed"); - return; - } - } - } else { - for (; point < end_point; point++) { - if (!LineTo(canvas->dc, (int)fix_to_double(point->x), - (int)fix_to_double(point->y))) { - CANVAS_ERROR("LineTo failed"); - } - } - } - - if (seg->flags & SPICE_PATH_END) { - - if (seg->flags & SPICE_PATH_CLOSE) { - if (!CloseFigure(canvas->dc)) { - CANVAS_ERROR("CloseFigure failed"); - } - } - - if (!EndPath(canvas->dc)) { - CANVAS_ERROR("EndPath failed"); - } - } - - } -} - -static void set_scale_mode(GdiCanvas *canvas, uint8_t scale_mode) -{ - if (scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE) { - SetStretchBltMode(canvas->dc, HALFTONE); - } else if (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) { - SetStretchBltMode(canvas->dc, COLORONCOLOR); - } else { - CANVAS_ERROR("Unknown ScaleMode"); - } -} - -static void set_clip(GdiCanvas *canvas, SpiceClip *clip) -{ - switch (clip->type) { - case SPICE_CLIP_TYPE_NONE: - if (SelectClipRgn(canvas->dc, NULL) == ERROR) { - CANVAS_ERROR("SelectClipRgn failed"); - } - break; - case SPICE_CLIP_TYPE_RECTS: { - uint32_t n = clip->rects->num_rects; - - SpiceRect *now = clip->rects->rects; - SpiceRect *end = now + n; - - if (now < end) { - HRGN main_hrgn; - - main_hrgn = CreateRectRgn(now->left, now->top, now->right, now->bottom); - if (!main_hrgn) { - return; - } - now++; - for (; now < end; now++) { - HRGN combaine_hrgn; - combaine_hrgn = CreateRectRgn(now->left, now->top, now->right, - now->bottom); - if (!combaine_hrgn) { - CANVAS_ERROR("Unable to CreateRectRgn"); - DeleteObject(main_hrgn); - return; - } - if (CombineRgn(main_hrgn, main_hrgn, combaine_hrgn, RGN_OR) == ERROR) { - CANVAS_ERROR("Unable to CombineRgn"); - DeleteObject(combaine_hrgn); - return; - } - DeleteObject(combaine_hrgn); - } - if (SelectClipRgn(canvas->dc, main_hrgn) == ERROR) { - CANVAS_ERROR("Unable to SelectClipRgn"); - } - DeleteObject(main_hrgn); - } - break; - } - default: - CANVAS_ERROR("invalid clip type"); - } -} - -static void copy_bitmap(const uint8_t *src_image, int height, int src_stride, - uint8_t *dest_bitmap, int dest_stride) -{ - int copy_width = MIN(dest_stride, src_stride); - int y = 0; - - ASSERT(dest_stride >= 0 && src_stride >= 0); - while (y < height) { - memcpy(dest_bitmap, src_image, copy_width); - src_image += src_stride; - dest_bitmap += dest_stride; - y++; - } -} - -static void copy_bitmap_alpha(const uint8_t *src_alpha, int height, int width, int src_stride, - uint8_t *dest_bitmap, int dest_stride, int alpha_bits_size) -{ - int y = 0; - uint8_t i_offset; - int i_count = 0; - int i = 0; - - if (alpha_bits_size == 1) { - i_offset = 1; - } else { - i_offset = 8; - } - - - while (y < height) { - int x; - - for (x = 0; x < width; ++x) { - uint8_t alphaval; - double alpha; - - alphaval = src_alpha[i]; - alphaval = alphaval >> (i_count * i_offset); - alphaval &= ((uint8_t)0xff >> (8 - i_offset)); - alphaval = ((255 * alphaval) / ((uint8_t)0xff >> (8 - i_offset))); - - dest_bitmap[x * 4 + 3] = alphaval; - alpha = (double)alphaval / 0xff; - dest_bitmap[x * 4 + 2] = (uint8_t)(alpha * dest_bitmap[x * 4 + 2]); - dest_bitmap[x * 4 + 1] = (uint8_t)(alpha * dest_bitmap[x * 4 + 1]); - dest_bitmap[x * 4] = (uint8_t)(alpha * dest_bitmap[x * 4]); - - i_count++; - if (i_count == (8 / i_offset)) { - i++; - i_count = 0; - } - } - - dest_bitmap += width * 4; - i = 0; - src_alpha += src_stride; - i_count = 0; - y++; - } -} - -static uint8_t *create_bitmap(HBITMAP *bitmap, HBITMAP *prev_bitmap, HDC *dc, - const uint8_t *bitmap_data, int width, int height, - int stride, int bits, int rotate) -{ - uint8_t *data; - const uint8_t *src_data; - uint32_t nstride; - struct { - BITMAPINFO inf; - RGBQUAD palette[255]; - } bitmap_info; - - memset(&bitmap_info, 0, sizeof(bitmap_info)); - bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader); - bitmap_info.inf.bmiHeader.biWidth = width; - if (stride < 0) { - bitmap_info.inf.bmiHeader.biHeight = height; - } else { - bitmap_info.inf.bmiHeader.biHeight = -height; - } - - if (rotate) { - bitmap_info.inf.bmiHeader.biHeight = -bitmap_info.inf.bmiHeader.biHeight; - } - - bitmap_info.inf.bmiHeader.biPlanes = 1; - bitmap_info.inf.bmiHeader.biBitCount = bits; - bitmap_info.inf.bmiHeader.biCompression = BI_RGB; - - *dc = create_compatible_dc(); - if (!*dc) { - CANVAS_ERROR("create_compatible_dc() failed"); - return NULL; - } - - *bitmap = CreateDIBSection(*dc, &bitmap_info.inf, 0, (VOID **)&data, NULL, 0); - if (!*bitmap) { - CANVAS_ERROR("Unable to CreateDIBSection"); - DeleteDC(*dc); - return NULL; - } - *prev_bitmap = (HBITMAP)SelectObject(*dc, *bitmap); - - if (stride < 0) { - src_data = bitmap_data - (height - 1) * -stride; - } else { - src_data = bitmap_data; - } - - switch (bits) { - case 1: - nstride = SPICE_ALIGN(width, 32) / 8; - break; - case 8: - nstride = SPICE_ALIGN(width, 4); - break; - case 16: - nstride = SPICE_ALIGN(width * 2, 4); - break; - case 32: - nstride = width * 4; - break; - default: - CANVAS_ERROR("invalid bitmap bits size"); - } - - if (bitmap_data) { - if (stride < 0) { - copy_bitmap(src_data, height, -stride, data, nstride); - } else { - copy_bitmap(src_data, height, stride, data, nstride); - } - } - - return data; -} - -static uint8_t *create_bitmap_from_pixman(HBITMAP *bitmap, HBITMAP *prev_bitmap, HDC *dc, - pixman_image_t *surface, int rotate) -{ - return create_bitmap(bitmap, prev_bitmap, dc, - (uint8_t*)pixman_image_get_data(surface), - pixman_image_get_width(surface), - pixman_image_get_height(surface), - pixman_image_get_stride(surface), - spice_pixman_image_get_bpp(surface), - rotate); -} - - -static void release_bitmap(HDC dc, HBITMAP bitmap, HBITMAP prev_bitmap, int cache) -{ - bitmap = (HBITMAP)SelectObject(dc, prev_bitmap); - if (!cache) { - DeleteObject(bitmap); - } - DeleteDC(dc); -} - -static inline uint8_t get_converted_color(uint8_t color) -{ - uint8_t msb; - - msb = color & 0xE0; - msb = msb >> 5; - color |= msb; - return color; -} - -static inline COLORREF get_color_ref(GdiCanvas *canvas, uint32_t color) -{ - int shift = canvas->base.color_shift == 8 ? 0 : 3; - uint8_t r, g, b; - - b = (color & canvas->base.color_mask); - color >>= canvas->base.color_shift; - g = (color & canvas->base.color_mask); - color >>= canvas->base.color_shift; - r = (color & canvas->base.color_mask); - if (shift) { - r = get_converted_color(r << shift); - g = get_converted_color(g << shift); - b = get_converted_color(b << shift); - } - return RGB(r, g, b); -} - -static HBRUSH get_brush(GdiCanvas *canvas, SpiceBrush *brush, RecurciveMutex **brush_lock) -{ - HBRUSH hbrush; - - *brush_lock = NULL; - - switch (brush->type) { - case SPICE_BRUSH_TYPE_SOLID: - if (!(hbrush = CreateSolidBrush(get_color_ref(canvas, brush->u.color)))) { - CANVAS_ERROR("CreateSolidBrush failed"); - } - return hbrush; - case SPICE_BRUSH_TYPE_PATTERN: { - GdiCanvas *gdi_surface = NULL; - HBRUSH hbrush; - pixman_image_t *surface = NULL; - HDC dc; - HBITMAP bitmap; - HBITMAP prev_bitmap; - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat); - if (gdi_surface) { - bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP); - if (!bitmap) { - CANVAS_ERROR("GetCurrentObject failed"); - } - *brush_lock = gdi_surface->lock; - } else { - surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE); - if (!create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, surface, 0)) { - CANVAS_ERROR("create_bitmap failed"); - return NULL; - } - } - - if (!(hbrush = CreatePatternBrush(bitmap))) { - CANVAS_ERROR("CreatePatternBrush failed"); - } - - if (!gdi_surface) { - release_bitmap(dc, bitmap, prev_bitmap, 0); - pixman_image_unref(surface); - } - return hbrush; - } - case SPICE_BRUSH_TYPE_NONE: - return NULL; - default: - CANVAS_ERROR("invalid brush type"); - return NULL; - } -} - -static HBRUSH set_brush(HDC dc, HBRUSH hbrush, SpiceBrush *brush) -{ - switch (brush->type) { - case SPICE_BRUSH_TYPE_SOLID: { - return (HBRUSH)SelectObject(dc, hbrush); - } - case SPICE_BRUSH_TYPE_PATTERN: { - HBRUSH prev_hbrush; - prev_hbrush = (HBRUSH)SelectObject(dc, hbrush); - if (!SetBrushOrgEx(dc, brush->u.pattern.pos.x, brush->u.pattern.pos.y, NULL)) { - CANVAS_ERROR("SetBrushOrgEx failed"); - } - return prev_hbrush; - } - default: - CANVAS_ERROR("invalid brush type"); - return NULL; - } -} - -static void unset_brush(HDC dc, HBRUSH prev_hbrush) -{ - if (!prev_hbrush) { - return; - } - prev_hbrush = (HBRUSH)SelectObject(dc, prev_hbrush); - DeleteObject(prev_hbrush); -} - -uint8_t calc_rop3(uint16_t rop3_bits, int brush) -{ - uint8_t rop3 = 0; - uint8_t rop3_src = _rop3_src; - uint8_t rop3_dest = _rop3_dest; - uint8_t rop3_brush = _rop3_brush; - uint8_t rop3_src_brush; - - if (rop3_bits & SPICE_ROPD_INVERS_SRC) { - rop3_src = ~rop3_src; - } - if (rop3_bits & SPICE_ROPD_INVERS_BRUSH) { - rop3_brush = ~rop3_brush; - } - if (rop3_bits & SPICE_ROPD_INVERS_DEST) { - rop3_dest = ~rop3_dest; - } - - if (brush) { - rop3_src_brush = rop3_brush; - } else { - rop3_src_brush = rop3_src; - } - - if (rop3_bits & SPICE_ROPD_OP_PUT) { - rop3 = rop3_src_brush; - } - if (rop3_bits & SPICE_ROPD_OP_OR) { - rop3 = rop3_src_brush | rop3_dest; - } - if (rop3_bits & SPICE_ROPD_OP_AND) { - rop3 = rop3_src_brush & rop3_dest; - } - if (rop3_bits & SPICE_ROPD_OP_XOR) { - rop3 = rop3_src_brush ^ rop3_dest; - } - if (rop3_bits & SPICE_ROPD_INVERS_RES) { - rop3 = ~rop3_dest; - } - - if (rop3_bits & SPICE_ROPD_OP_BLACKNESS || rop3_bits & SPICE_ROPD_OP_WHITENESS || - rop3_bits & SPICE_ROPD_OP_INVERS) { - CANVAS_ERROR("invalid rop3 type"); - } - return rop3; -} - -uint8_t calc_rop3_src_brush(uint16_t rop3_bits) -{ - uint8_t rop3 = 0; - uint8_t rop3_src = _rop3_src; - uint8_t rop3_brush = _rop3_brush; - - if (rop3_bits & SPICE_ROPD_INVERS_SRC) { - rop3_src = ~rop3_src; - } - if (rop3_bits & SPICE_ROPD_INVERS_BRUSH) { - rop3_brush = ~rop3_brush; - } - - if (rop3_bits & SPICE_ROPD_OP_OR) { - rop3 = rop3_src | rop3_brush; - } - if (rop3_bits & SPICE_ROPD_OP_AND) { - rop3 = rop3_src & rop3_brush; - } - if (rop3_bits & SPICE_ROPD_OP_XOR) { - rop3 = rop3_src ^ rop3_brush; - } - - return rop3; -} - -static struct BitmapData get_mask_bitmap(struct GdiCanvas *canvas, struct SpiceQMask *mask) -{ - GdiCanvas *gdi_surface; - pixman_image_t *surface; - struct BitmapData bitmap; - PixmanData *pixman_data; - - bitmap.hbitmap = NULL; - if (!mask->bitmap) { - return bitmap; - } - - gdi_surface = (GdiCanvas *)canvas_get_surface_mask(&canvas->base, mask->bitmap); - if (gdi_surface) { - HBITMAP _bitmap; - - _bitmap = (HBITMAP)GetCurrentObject(gdi_surface->dc, OBJ_BITMAP); - if (!_bitmap) { - CANVAS_ERROR ("GetCurrentObject failed"); - } - bitmap.dc = gdi_surface->dc; - bitmap.hbitmap = _bitmap; - bitmap.prev_hbitmap = (HBITMAP)0; - bitmap.cache = 0; - bitmap.from_surface = 1; - } else { - - if (!(surface = canvas_get_mask(&canvas->base, mask, NULL))) { - return bitmap; - } - - pixman_data = (PixmanData *)pixman_image_get_destroy_data (surface); - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - bitmap.dc = create_compatible_dc(); - bitmap.prev_hbitmap = (HBITMAP)SelectObject(bitmap.dc, pixman_data->bitmap); - bitmap.hbitmap = pixman_data->bitmap; - ReleaseMutex(pixman_data->mutex); - bitmap.cache = 1; - } else if (!create_bitmap_from_pixman(&bitmap.hbitmap, &bitmap.prev_hbitmap, &bitmap.dc, - surface, 0)) { - bitmap.hbitmap = NULL; - } else { - bitmap.cache = 0; - } - - bitmap.from_surface = 0; - } - - bitmap.flags = mask->flags; - bitmap.pos = mask->pos; - - return bitmap; -} - -static void gdi_draw_bitmap(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, - HDC src_dc, struct BitmapData *bitmapmask, uint32_t rop3_val) -{ - uint32_t rast_oper; - - rast_oper = raster_ops[rop3_val]; - - if (!bitmapmask || !bitmapmask->hbitmap) { - if ((dest->right - dest->left) == (src->right - src->left) && - (dest->bottom - dest->top) == (src->bottom - src->top)) { - if (!BitBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, - dest->bottom - dest->top, src_dc, src->left, src->top, rast_oper)) { - CANVAS_ERROR("BitBlt failed"); - } - } else { - if (!StretchBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, - dest->bottom - dest->top, src_dc, src->left, src->top, - src->right - src->left, src->bottom - src->top, rast_oper)) { - CANVAS_ERROR("StretchBlt failed"); - } - } - } else { - rast_oper = MAKEROP4(rast_oper, raster_ops[_rop3_dest]); - - if (!MaskBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, - dest->bottom - dest->top, src_dc, src->left, src->top, - bitmapmask->hbitmap, bitmapmask->pos.x, bitmapmask->pos.y, - rast_oper)) { - CANVAS_ERROR("MaskBlt failed"); - } - } -} - -static void gdi_draw_bitmap_redrop(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, - HDC src_dc, struct BitmapData *bitmapmask, - uint16_t rop, int brush) -{ - uint32_t rop3_val; - - rop3_val = calc_rop3(rop, brush); - gdi_draw_bitmap(dest_dc, src, dest, src_dc, bitmapmask, rop3_val); -} - -static void free_mask(struct BitmapData *bitmap) -{ - if (bitmap->hbitmap) { - if (!bitmap->from_surface) { - release_bitmap(bitmap->dc, bitmap->hbitmap, bitmap->prev_hbitmap, bitmap->cache); - } - } -} - -static void draw_str_mask_bitmap(struct GdiCanvas *canvas, - SpiceString *str, int n, SpiceRect *dest, - SpiceRect *src, SpiceBrush *brush) -{ - pixman_image_t *surface; - struct BitmapData bitmap; - SpicePoint pos; - int dest_stride; - uint8_t *bitmap_data; - HBRUSH prev_hbrush; - HBRUSH hbrush; - RecurciveMutex *brush_lock; - - bitmap.hbitmap = (HBITMAP)1; - if (!(surface = canvas_get_str_mask(&canvas->base, str, n, &pos))) { - CANVAS_ERROR("unable to canvas_get_str_mask"); - return; - } - - bitmap.from_surface = 0; - bitmap.cache = 0; - bitmap_data = create_bitmap(&bitmap.hbitmap, &bitmap.prev_hbitmap, - &bitmap.dc, NULL, - pixman_image_get_width(surface), - pixman_image_get_height(surface), - pixman_image_get_stride(surface), 32, 0); - - if (!bitmap_data) { - return; - } - - bitmap.flags = 0; - bitmap.pos.x = 0; - bitmap.pos.y = 0; - - dest->left = pos.x; - dest->top = pos.y; - dest->right = pos.x + pixman_image_get_width(surface); - dest->bottom = pos.y + pixman_image_get_height(surface); - src->left = 0; - src->top = 0; - src->right = pixman_image_get_width(surface); - src->bottom = pixman_image_get_height(surface); - - dest_stride = pixman_image_get_width(surface); - switch (n) { - case 1: - dest_stride = dest_stride / 8; - break; - case 4: - dest_stride = dest_stride / 2; - break; - case 32: - dest_stride = dest_stride * 4; - break; - default: - CANVAS_ERROR("unsupported bitmap bits size"); - } - dest_stride = dest_stride + 3; - dest_stride = dest_stride & ~3; - - hbrush = get_brush(canvas, brush, &brush_lock); - prev_hbrush = set_brush(bitmap.dc, hbrush, brush); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); - } else { - gdi_draw_bitmap(bitmap.dc, src, src, bitmap.dc, NULL, _rop3_brush); - } - - unset_brush(bitmap.dc, prev_hbrush); - - copy_bitmap_alpha((uint8_t *)pixman_image_get_data(surface), - pixman_image_get_height(surface), - pixman_image_get_width(surface), - pixman_image_get_stride(surface), - bitmap_data, dest_stride, n); - - BLENDFUNCTION bf = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; - - RecurciveLock lock(*canvas->lock); - AlphaBlend(canvas->dc, dest->left, dest->top, dest->right - dest->left, - dest->bottom - dest->top, bitmap.dc, src->left, src->top, - src->right - src->left, src->bottom - src->top, bf); - - free_mask(&bitmap); -} - -static void gdi_draw_image(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, - pixman_image_t *image, struct BitmapData *bitmapmask, uint16_t rop, - int rotate) -{ - HDC dc; - HBITMAP bitmap; - HBITMAP prev_bitmap; - - create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); - - gdi_draw_bitmap_redrop(dest_dc, src, dest, dc, bitmapmask, rop, 0); - - release_bitmap(dc, bitmap, prev_bitmap, 0); -} - -static void gdi_draw_image_rop3(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, - pixman_image_t *image, struct BitmapData *bitmapmask, uint8_t rop3, - int rotate) -{ - HDC dc; - HBITMAP bitmap; - HBITMAP prev_bitmap; - - create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); - - gdi_draw_bitmap(dest_dc, src, dest, dc, bitmapmask, rop3); - - release_bitmap(dc, bitmap, prev_bitmap, 0); -} - -static void gdi_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - HBRUSH prev_hbrush; - HBRUSH brush; - struct BitmapData bitmapmask; - RecurciveMutex *brush_lock; - - RecurciveLock lock(*canvas->lock); - - if (!(brush = get_brush(canvas, &fill->brush, &brush_lock))) { - CANVAS_ERROR("no braash"); - return; - } - - bitmapmask = get_mask_bitmap(canvas, &fill->mask); - - set_clip(canvas, clip); - prev_hbrush = set_brush(canvas->dc, brush, &fill->brush); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, - fill->rop_descriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); - } else { - gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, - fill->rop_descriptor, fill->brush.type != SPICE_BRUSH_TYPE_NONE); - } - - free_mask(&bitmapmask); - unset_brush(canvas->dc, prev_hbrush); -} - -static void gdi_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - GdiCanvas *gdi_surface; - pixman_image_t *surface; - struct BitmapData bitmapmask; - PixmanData *pixman_data; - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, copy->src_bitmap); - if (gdi_surface) { - RecurciveLock lock(*canvas->lock); - RecurciveLock s_lock(*gdi_surface->lock); - bitmapmask = get_mask_bitmap(canvas, ©->mask); - set_scale_mode(canvas, copy->scale_mode); - set_clip(canvas, clip); - gdi_draw_bitmap_redrop(canvas->dc, ©->src_area, bbox, gdi_surface->dc, - &bitmapmask, copy->rop_descriptor, 0); - } else { - surface = canvas_get_image(&canvas->base, copy->src_bitmap, FALSE); - pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - - RecurciveLock lock(*canvas->lock); - bitmapmask = get_mask_bitmap(canvas, ©->mask); - set_scale_mode(canvas, copy->scale_mode); - set_clip(canvas, clip); - - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - HDC dc; - HBITMAP prev_bitmap; - - dc = create_compatible_dc(); - prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - gdi_draw_bitmap_redrop(canvas->dc, ©->src_area, bbox, dc, - &bitmapmask, copy->rop_descriptor, 0); - SelectObject(dc, prev_bitmap); - DeleteObject(dc); - ReleaseMutex(pixman_data->mutex); - } else { - gdi_draw_image(canvas->dc, ©->src_area, bbox, surface, &bitmapmask, - copy->rop_descriptor, 0); - } - - pixman_image_unref(surface); - } - free_mask(&bitmapmask); -} - -static void gdi_canvas_put_image(SpiceCanvas *spice_canvas, HDC dc, const SpiceRect *dest, const uint8_t *src_data, - uint32_t src_width, uint32_t src_height, int src_stride, - const QRegion *clip) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - SpiceRect src; - src.top = 0; - src.bottom = src_height; - src.left = 0; - src.right = src_width; - int num_rects; - pixman_box32_t *rects; - - RecurciveLock lock(*canvas->lock); - set_scale_mode(canvas, SPICE_IMAGE_SCALE_MODE_NEAREST); - if (clip) { - rects = pixman_region32_rectangles((pixman_region32_t*)clip, &num_rects); - if (num_rects == 0) { - return; - } else { - HRGN main_hrgn; - int i; - - main_hrgn = CreateRectRgn(rects[0].x1, rects[0].y1, rects[0].x2, - rects[0].y2); - if (!main_hrgn) { - return; - } - - for (i = 1; i < num_rects; i++) { - HRGN combaine_hrgn; - - combaine_hrgn = CreateRectRgn(rects[i].x1, rects[i].y1, - rects[i].x2, - rects[i].y2); - if (!combaine_hrgn) { - CANVAS_ERROR("CreateRectRgn failed"); - DeleteObject(main_hrgn); - return; - } - if (!CombineRgn(main_hrgn, main_hrgn, combaine_hrgn, RGN_OR)) { - CANVAS_ERROR("CombineRgn failed in put_image"); - return; - } - DeleteObject(combaine_hrgn); - } - if (SelectClipRgn(canvas->dc, main_hrgn) == ERROR) { - CANVAS_ERROR("SelectClipRgn failed in put_image"); - DeleteObject(main_hrgn); - return; - } - DeleteObject(main_hrgn); - } - } else { - SelectClipRgn(canvas->dc, NULL); - } - - if (dc) { - gdi_draw_bitmap_redrop(canvas->dc, &src, dest, dc, - NULL, SPICE_ROPD_OP_PUT, 0); - } else { - pixman_image_t *image = pixman_image_create_bits(PIXMAN_a8r8g8b8, src_width, src_height, - (uint32_t *)src_data, src_stride); - gdi_draw_image(canvas->dc, &src, dest, image, NULL, SPICE_ROPD_OP_PUT, 0); - pixman_image_unref(image); - } -} - -static void gdi_draw_bitmap_transparent(GdiCanvas *canvas, HDC dest_dc, const SpiceRect *src, - const SpiceRect *dest, HDC src_dc, uint32_t color) -{ - TransparentBlt(dest_dc, dest->left, dest->top, dest->right - dest->left, - dest->bottom - dest->top, src_dc, src->left, src->top, - src->right - src->left, src->bottom - src->top, - RGB(((uint8_t*)&color)[2], ((uint8_t*)&color)[1], ((uint8_t*)&color)[0])); -} - -static void gdi_draw_image_transparent(GdiCanvas *canvas, HDC dest_dc, const SpiceRect *src, - const SpiceRect *dest, pixman_image_t *image, - uint32_t color, int rotate) -{ - HDC dc; - HBITMAP bitmap; - HBITMAP prev_bitmap; - - create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); - - gdi_draw_bitmap_transparent(canvas, dest_dc, src, dest, dc, color); - - release_bitmap(dc, bitmap, prev_bitmap, 0); -} - -static void gdi_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, - SpiceTransparent* transparent) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - GdiCanvas *gdi_surface; - pixman_image_t *surface; - PixmanData *pixman_data; - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, transparent->src_bitmap); - if (gdi_surface) { - RecurciveLock lock(*canvas->lock); - RecurciveLock s_lock(*gdi_surface->lock); - set_clip(canvas, clip); - gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, - gdi_surface->dc, transparent->true_color); - } else { - surface = canvas_get_image(&canvas->base, transparent->src_bitmap, FALSE); - pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - RecurciveLock lock(*canvas->lock); - set_clip(canvas, clip); - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - HDC dc; - HBITMAP prev_bitmap; - - dc = create_compatible_dc(); - prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - gdi_draw_bitmap_transparent(canvas, canvas->dc, &transparent->src_area, bbox, dc, - transparent->true_color); - - SelectObject(dc, prev_bitmap); - DeleteObject(dc); - ReleaseMutex(pixman_data->mutex); - } else { - gdi_draw_image_transparent(canvas, canvas->dc, &transparent->src_area, bbox, surface, - transparent->true_color, 0); - } - - pixman_image_unref(surface); - } -} - -static void gdi_draw_bitmap_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, - HDC src_dc, uint8_t alpha, int use_bitmap_alpha) -{ - BLENDFUNCTION bf; - - bf.BlendOp = AC_SRC_OVER; - bf.BlendFlags = 0; - bf.SourceConstantAlpha = alpha; - - if (use_bitmap_alpha) { - bf.AlphaFormat = AC_SRC_ALPHA; - } else { - bf.AlphaFormat = 0; - } - - if (!AlphaBlend(dest_dc, dest->left, dest->top, dest->right - dest->left, - dest->bottom - dest->top, src_dc, src->left, src->top, - src->right - src->left, src->bottom - src->top, bf)) { - CANVAS_ERROR("AlphaBlend failed"); - } -} - -static void gdi_draw_image_alpha(HDC dest_dc, const SpiceRect *src, const SpiceRect *dest, - pixman_image_t *image, uint8_t alpha, - int rotate, int use_bitmap_alpha) -{ - HDC dc; - HBITMAP bitmap; - HBITMAP prev_bitmap; - - create_bitmap_from_pixman(&bitmap, &prev_bitmap, &dc, image, rotate); - - gdi_draw_bitmap_alpha(dest_dc, src, dest, dc, alpha, use_bitmap_alpha); - - release_bitmap(dc, bitmap, prev_bitmap, 0); -} - -static void gdi_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend* alpha_blend) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - GdiCanvas *gdi_surface; - pixman_image_t *surface; - PixmanData *pixman_data; - int use_bitmap_alpha; - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, alpha_blend->src_bitmap); - if (gdi_surface) { - RecurciveLock lock(*canvas->lock); - RecurciveLock s_lock(*gdi_surface->lock); - set_clip(canvas, clip); - use_bitmap_alpha = alpha_blend->alpha_flags & SPICE_ALPHA_FLAGS_SRC_SURFACE_HAS_ALPHA; - gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, gdi_surface->dc, - alpha_blend->alpha, use_bitmap_alpha); - } else { - surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap, TRUE); - use_bitmap_alpha = pixman_image_get_depth(surface) == 32; - pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - - RecurciveLock lock(*canvas->lock); - set_clip(canvas, clip); - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - HDC dc; - HBITMAP prev_bitmap; - - dc = create_compatible_dc(); - prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - gdi_draw_bitmap_alpha(canvas->dc, &alpha_blend->src_area, bbox, dc, alpha_blend->alpha, - use_bitmap_alpha); - SelectObject(dc, prev_bitmap); - DeleteObject(dc); - ReleaseMutex(pixman_data->mutex); - } else { - gdi_draw_image_alpha(canvas->dc, &alpha_blend->src_area, bbox, surface, - alpha_blend->alpha, 0, use_bitmap_alpha); - } - - pixman_image_unref(surface); - } -} - -static void gdi_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque) -{ - GdiCanvas *gdi_surface; - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - pixman_image_t *surface; - struct BitmapData bitmapmask; - PixmanData *pixman_data; - HBRUSH prev_hbrush; - HBRUSH hbrush; - uint8_t rop3; - RecurciveMutex *brush_lock; - - rop3 = calc_rop3_src_brush(opaque->rop_descriptor); - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, opaque->src_bitmap); - if (gdi_surface) { - RecurciveLock lock(*canvas->lock); - RecurciveLock s_lock(*gdi_surface->lock); - bitmapmask = get_mask_bitmap(canvas, &opaque->mask); - hbrush = get_brush(canvas, &opaque->brush, &brush_lock); - set_scale_mode(canvas, opaque->scale_mode); - set_clip(canvas, clip); - prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3); - } else { - gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, gdi_surface->dc, &bitmapmask, rop3); - } - unset_brush(canvas->dc, prev_hbrush); - } else { - surface = canvas_get_image(&canvas->base, opaque->src_bitmap, FALSE); - pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - - RecurciveLock lock(*canvas->lock); - bitmapmask = get_mask_bitmap(canvas, &opaque->mask); - hbrush = get_brush(canvas, &opaque->brush, &brush_lock); - set_scale_mode(canvas, opaque->scale_mode); - set_clip(canvas, clip); - prev_hbrush = set_brush(canvas->dc, hbrush, &opaque->brush); - - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - HDC dc; - HBITMAP prev_bitmap; - - dc = create_compatible_dc(); - prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3); - } else { - gdi_draw_bitmap(canvas->dc, &opaque->src_area, bbox, dc, &bitmapmask, rop3); - } - SelectObject(dc, prev_bitmap); - DeleteObject(dc); - ReleaseMutex(pixman_data->mutex); - } else { - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, surface, &bitmapmask, rop3, 0); - } else { - gdi_draw_image_rop3(canvas->dc, &opaque->src_area, bbox, surface, &bitmapmask, rop3, 0); - } - } - unset_brush(canvas->dc, prev_hbrush); - pixman_image_unref(surface); - } - - free_mask(&bitmapmask); -} - -static void gdi_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend) -{ - GdiCanvas *gdi_surface; - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - pixman_image_t *surface; - struct BitmapData bitmapmask; - PixmanData *pixman_data; - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, blend->src_bitmap); - if (gdi_surface) { - RecurciveLock lock(*canvas->lock); - RecurciveLock s_lock(*gdi_surface->lock); - bitmapmask = get_mask_bitmap(canvas, &blend->mask); - set_scale_mode(canvas, blend->scale_mode); - set_clip(canvas, clip); - gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, gdi_surface->dc, - &bitmapmask, blend->rop_descriptor, 0); - } else { - surface = canvas_get_image(&canvas->base, blend->src_bitmap, FALSE); - pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - - RecurciveLock lock(*canvas->lock); - bitmapmask = get_mask_bitmap(canvas, &blend->mask); - set_scale_mode(canvas, blend->scale_mode); - set_clip(canvas, clip); - - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - HDC dc; - HBITMAP prev_bitmap; - - dc = create_compatible_dc(); - prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - gdi_draw_bitmap_redrop(canvas->dc, &blend->src_area, bbox, dc, - &bitmapmask, blend->rop_descriptor, 0); - SelectObject(dc, prev_bitmap); - DeleteObject(dc); - ReleaseMutex(pixman_data->mutex); - } else { - gdi_draw_image(canvas->dc, &blend->src_area, bbox, surface, - &bitmapmask, blend->rop_descriptor, 0); - } - - pixman_image_unref(surface); - } - - free_mask(&bitmapmask); -} - -static void gdi_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - struct BitmapData bitmapmask; - - RecurciveLock lock(*canvas->lock); - bitmapmask = get_mask_bitmap(canvas, &blackness->mask); - set_clip(canvas, clip); - gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x0); - - free_mask(&bitmapmask); -} - -static void gdi_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - struct BitmapData bitmapmask; - - RecurciveLock lock(*canvas->lock); - bitmapmask = get_mask_bitmap(canvas, &invers->mask); - set_clip(canvas, clip); - gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0x55); - - free_mask(&bitmapmask); -} - -static void gdi_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - struct BitmapData bitmapmask; - - RecurciveLock lock(*canvas->lock); - bitmapmask = get_mask_bitmap(canvas, &whiteness->mask); - set_clip(canvas, clip); - gdi_draw_bitmap(canvas->dc, bbox, bbox, canvas->dc, &bitmapmask, 0xff); - - free_mask(&bitmapmask); -} - -static void gdi_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3) -{ - GdiCanvas *gdi_surface; - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - pixman_image_t *surface; - struct BitmapData bitmapmask; - HBRUSH prev_hbrush; - HBRUSH hbrush; - PixmanData *pixman_data; - RecurciveMutex *brush_lock; - - gdi_surface = (GdiCanvas *)canvas_get_surface(&canvas->base, rop3->src_bitmap); - if (gdi_surface) { - RecurciveLock lock(*canvas->lock); - RecurciveLock s_lock(*gdi_surface->lock); - hbrush = get_brush(canvas, &rop3->brush, &brush_lock); - bitmapmask = get_mask_bitmap(canvas, &rop3->mask); - set_scale_mode(canvas, rop3->scale_mode); - set_clip(canvas, clip); - prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc, - &bitmapmask, rop3->rop3); - } else { - gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, gdi_surface->dc, - &bitmapmask, rop3->rop3); - } - unset_brush(canvas->dc, prev_hbrush); - } else { - surface = canvas_get_image(&canvas->base, rop3->src_bitmap, FALSE); - pixman_data = (PixmanData *)pixman_image_get_destroy_data(surface); - RecurciveLock lock(*canvas->lock); - hbrush = get_brush(canvas, &rop3->brush, &brush_lock); - bitmapmask = get_mask_bitmap(canvas, &rop3->mask); - set_scale_mode(canvas, rop3->scale_mode); - set_clip(canvas, clip); - prev_hbrush = set_brush(canvas->dc, hbrush, &rop3->brush); - - if (pixman_data && (WaitForSingleObject(pixman_data->mutex, INFINITE) != WAIT_FAILED)) { - HDC dc; - HBITMAP prev_bitmap; - - dc = create_compatible_dc(); - prev_bitmap = (HBITMAP)SelectObject(dc, pixman_data->bitmap); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc, - &bitmapmask, rop3->rop3); - } else { - gdi_draw_bitmap(canvas->dc, &rop3->src_area, bbox, dc, - &bitmapmask, rop3->rop3); - } - SelectObject(dc, prev_bitmap); - DeleteObject(dc); - ReleaseMutex(pixman_data->mutex); - } else { - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, surface, &bitmapmask, rop3->rop3, 0); - } else { - gdi_draw_image_rop3(canvas->dc, &rop3->src_area, bbox, surface, &bitmapmask, rop3->rop3, 0); - } - } - - unset_brush(canvas->dc, prev_hbrush); - pixman_image_unref(surface); - } - - free_mask(&bitmapmask); -} - -static void gdi_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - RecurciveLock lock(*canvas->lock); - - set_clip(canvas, clip); - - BitBlt(canvas->dc, bbox->left, bbox->top, bbox->right - bbox->left, - bbox->bottom - bbox->top, canvas->dc, src_pos->x, src_pos->y, SRCCOPY); -} - -static void gdi_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - SpiceString *str; - RecurciveMutex *brush_lock; - - RecurciveLock lock(*canvas->lock); - set_clip(canvas, clip); - lock.unlock(); - - if (!rect_is_empty(&text->back_area)) { - HBRUSH prev_hbrush; - HBRUSH hbrush; - - RecurciveLock lock(*canvas->lock); - hbrush = get_brush(canvas, &text->back_brush, &brush_lock); - prev_hbrush = set_brush(canvas->dc, hbrush, &text->back_brush); - if (brush_lock) { - RecurciveLock b_lock(*brush_lock); - gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL, - text->back_mode, 1); - } else { - gdi_draw_bitmap_redrop(canvas->dc, bbox, bbox, canvas->dc, NULL, - text->back_mode, 1); - } - unset_brush(canvas->dc, prev_hbrush); - } - - str = (SpiceString *)SPICE_GET_ADDRESS(text->str); - - if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) { - SpiceRect dest; - SpiceRect src; - - draw_str_mask_bitmap(canvas, str, 1, &dest, &src, &text->fore_brush); - } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) { - SpiceRect dest; - SpiceRect src; - - draw_str_mask_bitmap(canvas, str, 4, &dest, &src, &text->fore_brush); - } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) { - WARN("untested path A8 glyphs, doing nothing"); - if (0) { - SpiceRect dest; - SpiceRect src; - - draw_str_mask_bitmap(canvas, str, 8, &dest, &src, &text->fore_brush); - } - } else { - WARN("untested path vector glyphs, doing nothing"); - if (0) { - } - } -} - -static uint32_t *gdi_get_userstyle(GdiCanvas *canvas, uint8_t nseg, SPICE_FIXED28_4* style, int start_is_gap) -{ - uint32_t *local_style; - int i; - - if (nseg == 0) { - CANVAS_ERROR("bad nseg"); - } - local_style = spice_new(uint32_t , nseg); - - if (start_is_gap) { - local_style[nseg - 1] = (uint32_t)fix_to_double(*style); - style++; - - for (i = 0; i < nseg - 1; i++, style++) { - local_style[i] = (uint32_t)fix_to_double(*style); - } - } else { - for (i = 0; i < nseg; i++, style++) { - local_style[i] = (uint32_t)fix_to_double(*style); - } - } - - return local_style; -} - -static void gdi_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - HPEN hpen; - HPEN prev_hpen; - LOGBRUSH logbrush; - uint32_t *user_style = NULL; - pixman_image_t *surface = NULL; - - if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) { - surface = canvas_get_image(&canvas->base, stroke->brush.u.pattern.pat, FALSE); - } - - RecurciveLock lock(*canvas->lock); - set_clip(canvas, clip); - - switch (stroke->fore_mode) { - case SPICE_ROPD_OP_WHITENESS: - SetROP2(canvas->dc, R2_WHITE); //0 - break; - case SPICE_ROPD_OP_BLACKNESS: - SetROP2(canvas->dc, R2_BLACK); //1 - break; - case SPICE_ROPD_OP_INVERS: - SetROP2(canvas->dc, R2_NOT); //Dn - break; - case SPICE_ROPD_OP_PUT: - SetROP2(canvas->dc, R2_COPYPEN); //P - break; - case SPICE_ROPD_OP_OR: - SetROP2(canvas->dc, R2_MERGEPEN); //DPo - break; - case SPICE_ROPD_OP_XOR: - SetROP2(canvas->dc, R2_XORPEN); //DPx - break; - case SPICE_ROPD_OP_AND: - SetROP2(canvas->dc, R2_MASKPEN); //DPa - break; - case SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_PUT: //Pn - SetROP2(canvas->dc, R2_NOTCOPYPEN); - break; - case SPICE_ROPD_OP_XOR | SPICE_ROPD_INVERS_RES: - SetROP2(canvas->dc, R2_NOTXORPEN); //DPxn - break; - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_RES: - SetROP2(canvas->dc, R2_NOTMERGEPEN); //DPon - break; - case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_RES: - SetROP2(canvas->dc, R2_NOTMASKPEN); //DPan - break; - case SPICE_ROPD_INVERS_DEST | SPICE_ROPD_OP_AND: - SetROP2(canvas->dc, R2_MASKPENNOT); //PDna - break; - case SPICE_ROPD_INVERS_BRUSH | SPICE_ROPD_OP_AND: - SetROP2(canvas->dc, R2_MASKNOTPEN); //DPna - break; - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_BRUSH: - SetROP2(canvas->dc, R2_MERGENOTPEN); //DPno - break; - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_DEST: - SetROP2(canvas->dc, R2_MERGEPENNOT); //PDno - break; - default: - SetROP2(canvas->dc, R2_NOP); //D - } - - - if (stroke->brush.type == SPICE_BRUSH_TYPE_SOLID) { - logbrush.lbStyle = BS_SOLID | DIB_RGB_COLORS; - logbrush.lbHatch = 0; - logbrush.lbColor = get_color_ref(canvas, stroke->brush.u.color); - } else if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) { -#if 0 - struct { - BITMAPINFO inf; - RGBQUAD palette[255]; - } bitmap_info; - GdiImage image; -#endif - //CANVAS_ERROR("untested path stroke brush with pattern"); -#if 0 - ASSERT(surface) - surface_to_image(surface, &image); - - memset(&bitmap_info, 0, sizeof(bitmap_info)); - bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader); - bitmap_info.inf.bmiHeader.biWidth = image.width; - if (image.stride < 0) { - bitmap_info.inf.bmiHeader.biHeight = image.height; - } else { - bitmap_info.inf.bmiHeader.biHeight = -image.height; - } - bitmap_info.inf.bmiHeader.biPlanes = 1; - bitmap_info.inf.bmiHeader.biBitCount = 32; - bitmap_info.inf.bmiHeader.biCompression = BI_RGB; - - if (image.stride < 0) { - logbrush.lbHatch = (LONG)GlobalAlloc(GMEM_MOVEABLE, - image.height * -image.stride + sizeof(BITMAPINFO)); - if (!logbrush.lbHatch) { - CANVAS_ERROR("GlobalAlloc failed"); - } - copy_bitmap(image.pixels - (image.height - 1) * -image.stride, - image.height, -image.stride, - (uint8_t *)logbrush.lbHatch, image.width); - } else { - logbrush.lbHatch = (LONG)GlobalAlloc(GMEM_MOVEABLE, - image.height * image.stride + sizeof(BITMAPINFO)); - if (!logbrush.lbHatch) { - CANVAS_ERROR("GlobalAlloc failed"); - } - copy_bitmap(image.pixels, image.height, image.stride, - (uint8_t *)logbrush.lbHatch, image.width); - } - - memcpy((void *)logbrush.lbHatch, &bitmap_info.inf, sizeof(BITMAPINFO)); - - logbrush.lbStyle = BS_DIBPATTERN | DIB_RGB_COLORS; - logbrush.lbColor = 0; -#endif - pixman_image_unref(surface); - } - - if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) { - user_style = gdi_get_userstyle(canvas, stroke->attr.style_nseg, - stroke->attr.style, - !!(stroke->attr.flags & SPICE_LINE_FLAGS_START_WITH_GAP)); - hpen = ExtCreatePen(PS_COSMETIC | PS_USERSTYLE, - 1, - &logbrush, stroke->attr.style_nseg, (DWORD *)user_style); - } else { - hpen = ExtCreatePen(PS_COSMETIC, - 1, - &logbrush, 0, NULL); - } - prev_hpen = (HPEN)SelectObject(canvas->dc, hpen); - - set_path(canvas, stroke->path); - - StrokePath(canvas->dc); - - SelectObject(canvas->dc, prev_hpen); - DeleteObject(hpen); - -#if 0 - if (stroke->brush.type == SPICE_BRUSH_TYPE_PATTERN) { - GlobalFree((HGLOBAL)logbrush.lbHatch); - } -#endif - - free(user_style); -} - -static void gdi_canvas_clear(SpiceCanvas *spice_canvas) -{ -} - -static void gdi_canvas_destroy(SpiceCanvas *spice_canvas) -{ - GdiCanvas *canvas = (GdiCanvas *)spice_canvas; - if (!canvas) { - return; - } - canvas_base_destroy(&canvas->base); - free(canvas); -} - -static int need_init = 1; -static SpiceCanvasOps gdi_canvas_ops; - -SpiceCanvas *gdi_canvas_create(int width, int height, - HDC dc, RecurciveMutex* lock, uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ) -{ - GdiCanvas *canvas; - - if (need_init) { - return NULL; - } - canvas = spice_new0(GdiCanvas, 1); - canvas_base_init(&canvas->base, &gdi_canvas_ops, - width, height, format, -#ifdef SW_CANVAS_CACHE - bits_cache, - palette_cache, -#elif defined(SW_CANVAS_IMAGE_CACHE) - bits_cache, -#endif - surfaces, - glz_decoder, - jpeg_decoder, - zlib_decoder); - canvas->dc = dc; - canvas->lock = lock; - return (SpiceCanvas *)canvas; -} - -void gdi_canvas_init(void) //unsafe global function -{ - if (!need_init) { - return; - } - need_init = 0; - - canvas_base_init_ops(&gdi_canvas_ops); - gdi_canvas_ops.draw_fill = gdi_canvas_draw_fill; - gdi_canvas_ops.draw_copy = gdi_canvas_draw_copy; - gdi_canvas_ops.draw_opaque = gdi_canvas_draw_opaque; - gdi_canvas_ops.copy_bits = gdi_canvas_copy_bits; - gdi_canvas_ops.draw_text = gdi_canvas_draw_text; - gdi_canvas_ops.draw_stroke = gdi_canvas_draw_stroke; - gdi_canvas_ops.draw_rop3 = gdi_canvas_draw_rop3; - gdi_canvas_ops.draw_blend = gdi_canvas_draw_blend; - gdi_canvas_ops.draw_blackness = gdi_canvas_draw_blackness; - gdi_canvas_ops.draw_whiteness = gdi_canvas_draw_whiteness; - gdi_canvas_ops.draw_invers = gdi_canvas_draw_invers; - gdi_canvas_ops.draw_transparent = gdi_canvas_draw_transparent; - gdi_canvas_ops.draw_alpha_blend = gdi_canvas_draw_alpha_blend; - gdi_canvas_ops.put_image = gdi_canvas_put_image; - gdi_canvas_ops.clear = gdi_canvas_clear; - gdi_canvas_ops.destroy = gdi_canvas_destroy; - - rop3_init(); -} diff --git a/common/gdi_canvas.h b/common/gdi_canvas.h deleted file mode 100644 index f92c042b..00000000 --- a/common/gdi_canvas.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H__GDI_CANVAS -#define _H__GDI_CANVAS - -#ifndef SPICE_CANVAS_INTERNAL -#error "This header shouldn't be included directly" -#endif - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#include "pixman_utils.h" -#include "canvas_base.h" -#include "region.h" - -SpiceCanvas *gdi_canvas_create(int width, int height, - HDC dc, class RecurciveMutex *lock, uint32_t format, - SpiceImageCache *bits_cache, - SpicePaletteCache *palette_cache, - SpiceImageSurfaces *surfaces, - SpiceGlzDecoder *glz_decoder, - SpiceJpegDecoder *jpeg_decoder, - SpiceZlibDecoder *zlib_decoder); - -void gdi_canvas_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/gl_canvas.c b/common/gl_canvas.c deleted file mode 100644 index ffc6b52d..00000000 --- a/common/gl_canvas.c +++ /dev/null @@ -1,906 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifndef SPICE_CANVAS_INTERNAL -#error "This file shouldn't be compiled directly" -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "quic.h" -#include "rop3.h" -#include "region.h" - -#define GL_CANVAS -#include "canvas_base.c" - -typedef struct GLCanvas GLCanvas; - -struct GLCanvas { - CanvasBase base; - GLCCtx glc; - void *private_data; - int private_data_size; - int textures_lost; -}; - -static inline uint8_t *copy_opposite_image(GLCanvas *canvas, void *data, int stride, int height) -{ - uint8_t *ret_data = (uint8_t *)data; - uint8_t *dest; - uint8_t *src; - int i; - - if (!canvas->private_data) { - canvas->private_data = spice_malloc_n(height, stride); - if (!canvas->private_data) { - return ret_data; - } - canvas->private_data_size = stride * height; - } - - if (canvas->private_data_size < (stride * height)) { - free(canvas->private_data); - canvas->private_data = spice_malloc_n(height, stride); - if (!canvas->private_data) { - return ret_data; - } - canvas->private_data_size = stride * height; - } - - dest = (uint8_t *)canvas->private_data; - src = (uint8_t *)data + (height - 1) * stride; - - for (i = 0; i < height; ++i) { - memcpy(dest, src, stride); - dest += stride; - src -= stride; - } - return (uint8_t *)canvas->private_data; -} - -static pixman_image_t *canvas_surf_to_trans_surf(GLCImage *image, - uint32_t trans_color) -{ - int width = image->width; - int height = image->height; - uint8_t *src_line; - uint8_t *end_src_line; - int src_stride; - uint8_t *dest_line; - int dest_stride; - pixman_image_t *ret; - int i; - - ret = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, NULL, 0); - if (ret == NULL) { - CANVAS_ERROR("create surface failed"); - } - - src_line = image->pixels; - src_stride = image->stride; - end_src_line = src_line + src_stride * height; - - dest_line = (uint8_t *)pixman_image_get_data(ret); - dest_stride = pixman_image_get_stride(ret); - - for (; src_line < end_src_line; src_line += src_stride, dest_line += dest_stride) { - for (i = 0; i < width; i++) { - if ((((uint32_t*)src_line)[i] & 0x00ffffff) == trans_color) { - ((uint32_t*)dest_line)[i] = 0; - } else { - ((uint32_t*)dest_line)[i] = (((uint32_t*)src_line)[i]) | 0xff000000; - } - } - } - - return ret; -} - -static GLCPath get_path(GLCanvas *canvas, SpicePath *s) -{ - GLCPath path = glc_path_create(canvas->glc); - int i; - - for (i = 0; i < s->num_segments; i++) { - SpicePathSeg* seg = s->segments[i]; - SpicePointFix* point = seg->points; - SpicePointFix* end_point = point + seg->count; - - if (seg->flags & SPICE_PATH_BEGIN) { - glc_path_move_to(path, fix_to_double(point->x), fix_to_double(point->y)); - point++; - } - - if (seg->flags & SPICE_PATH_BEZIER) { - ASSERT((point - end_point) % 3 == 0); - for (; point + 2 < end_point; point += 3) { - glc_path_curve_to(path, - fix_to_double(point[0].x), fix_to_double(point[0].y), - fix_to_double(point[1].x), fix_to_double(point[1].y), - fix_to_double(point[2].x), fix_to_double(point[2].y)); - } - } else { - for (; point < end_point; point++) { - glc_path_line_to(path, fix_to_double(point->x), fix_to_double(point->y)); - } - } - if (seg->flags & SPICE_PATH_END) { - if (seg->flags & SPICE_PATH_CLOSE) { - glc_path_close(path); - } - } - } - - return path; -} - -#define SET_GLC_RECT(dest, src) { \ - (dest)->x = (src)->left; \ - (dest)->y = (src)->top; \ - (dest)->width = (src)->right - (src)->left; \ - (dest)->height = (src)->bottom - (src)->top; \ -} - -#define SET_GLC_BOX(dest, src) { \ - (dest)->x = (src)->x1; \ - (dest)->y = (src)->y1; \ - (dest)->width = (src)->x2 - (src)->x1; \ - (dest)->height = (src)->y2 - (src)->y1; \ -} - -static void set_clip(GLCanvas *canvas, SpiceRect *bbox, SpiceClip *clip) -{ - GLCRect rect; - glc_clip_reset(canvas->glc); - - switch (clip->type) { - case SPICE_CLIP_TYPE_NONE: - break; - case SPICE_CLIP_TYPE_RECTS: { - uint32_t n = clip->rects->num_rects; - SpiceRect *now = clip->rects->rects; - SpiceRect *end = now + n; - - if (n == 0) { - rect.x = rect.y = 0; - rect.width = rect.height = 0; - glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET); - break; - } else { - SET_GLC_RECT(&rect, now); - glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET); - } - - for (now++; now < end; now++) { - SET_GLC_RECT(&rect, now); - glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_OR); - } - break; - } - default: - CANVAS_ERROR("invalid clip type"); - } -} - -static void set_mask(GLCanvas *canvas, SpiceQMask *mask, int x, int y) -{ - pixman_image_t *image; - - if (!(image = canvas_get_mask(&canvas->base, mask, NULL))) { - glc_clear_mask(canvas->glc, GLC_MASK_A); - return; - } - - - glc_set_mask(canvas->glc, x - mask->pos.x, y - mask->pos.y, - pixman_image_get_width(image), - pixman_image_get_height(image), - pixman_image_get_stride(image), - (uint8_t *)pixman_image_get_data(image), GLC_MASK_A); -} - -static inline void surface_to_image(GLCanvas *canvas, pixman_image_t *surface, GLCImage *image, - int ignore_stride) -{ - int depth = pixman_image_get_depth(surface); - - ASSERT(depth == 32 || depth == 24); - image->format = (depth == 24) ? GLC_IMAGE_RGB32 : GLC_IMAGE_ARGB32; - image->width = pixman_image_get_width(surface); - image->height = pixman_image_get_height(surface); - image->stride = pixman_image_get_stride(surface); - image->pixels = (uint8_t *)pixman_image_get_data(surface); - image->pallet = NULL; - if (ignore_stride) { - return; - } - if (image->stride < 0) { - image->stride = -image->stride; - image->pixels = image->pixels - (image->height - 1) * image->stride; - } else { - image->pixels = copy_opposite_image(canvas, image->pixels, image->stride, image->height); - } -} - -static void set_brush(GLCanvas *canvas, SpiceBrush *brush) -{ - switch (brush->type) { - case SPICE_BRUSH_TYPE_SOLID: { - uint32_t color = brush->u.color; - double r, g, b; - - b = (double)(color & canvas->base.color_mask) / canvas->base.color_mask; - color >>= canvas->base.color_shift; - g = (double)(color & canvas->base.color_mask) / canvas->base.color_mask; - color >>= canvas->base.color_shift; - r = (double)(color & canvas->base.color_mask) / canvas->base.color_mask; - glc_set_rgb(canvas->glc, r, g, b); - break; - } - case SPICE_BRUSH_TYPE_PATTERN: { - GLCImage image; - GLCPattern pattern; - pixman_image_t *surface; - - surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE); - surface_to_image(canvas, surface, &image, 0); - - pattern = glc_pattern_create(canvas->glc, -brush->u.pattern.pos.x, - -brush->u.pattern.pos.y, &image); - - glc_set_pattern(canvas->glc, pattern); - glc_pattern_destroy(pattern); - pixman_image_unref (surface); - } - case SPICE_BRUSH_TYPE_NONE: - return; - default: - CANVAS_ERROR("invalid brush type"); - } -} - -static void set_op(GLCanvas *canvas, uint16_t rop_decriptor) -{ - GLCOp op; - - switch (rop_decriptor) { - case SPICE_ROPD_OP_PUT: - op = GLC_OP_COPY; - break; - case SPICE_ROPD_OP_XOR: - op = GLC_OP_XOR; - break; - case SPICE_ROPD_OP_BLACKNESS: - op = GLC_OP_CLEAR; - break; - case SPICE_ROPD_OP_WHITENESS: - op = GLC_OP_SET; - break; - case SPICE_ROPD_OP_PUT | SPICE_ROPD_INVERS_BRUSH: - case SPICE_ROPD_OP_PUT | SPICE_ROPD_INVERS_SRC: - op = GLC_OP_COPY_INVERTED; - break; - case SPICE_ROPD_OP_INVERS: - op = GLC_OP_INVERT; - break; - case SPICE_ROPD_OP_AND: - op = GLC_OP_AND; - break; - case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_RES: - op = GLC_OP_NAND; - break; - case SPICE_ROPD_OP_OR: - op = GLC_OP_OR; - break; - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_RES: - op = GLC_OP_NOR; - break; - case SPICE_ROPD_OP_XOR | SPICE_ROPD_INVERS_RES: - op = GLC_OP_EQUIV; - break; - case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_DEST: - op = GLC_OP_AND_REVERSE; - break; - case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_BRUSH: - case SPICE_ROPD_OP_AND | SPICE_ROPD_INVERS_SRC: - op = GLC_OP_AND_INVERTED; - break; - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_DEST: - op = GLC_OP_OR_REVERSE; - break; - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_BRUSH: - case SPICE_ROPD_OP_OR | SPICE_ROPD_INVERS_SRC: - op = GLC_OP_OR_INVERTED; - break; - default: - WARN("GLC_OP_NOOP"); - op = GLC_OP_NOOP; - } - glc_set_op(canvas->glc, op); -} - -static void gl_canvas_draw_fill(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceFill *fill) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - GLCRect rect; - set_clip(canvas, bbox, clip); - set_mask(canvas, &fill->mask, bbox->left, bbox->top); - set_brush(canvas, &fill->brush); - set_op(canvas, fill->rop_descriptor); - SET_GLC_RECT(&rect, bbox); - - glc_fill_rect(canvas->glc, &rect); - glc_flush(canvas->glc); -} - -static void gl_canvas_draw_copy(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceCopy *copy) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - pixman_image_t *surface; - GLCRecti src; - GLCRecti dest; - GLCImage image; - - set_clip(canvas, bbox, clip); - set_mask(canvas, ©->mask, bbox->left, bbox->top); - set_op(canvas, copy->rop_descriptor); - - //todo: optimize get_image (use ogl conversion + remove unnecessary copy of 32bpp) - surface = canvas_get_image(&canvas->base, copy->src_bitmap, FALSE); - surface_to_image(canvas, surface, &image, 0); - SET_GLC_RECT(&dest, bbox); - SET_GLC_RECT(&src, ©->src_area); - glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1); - - pixman_image_unref(surface); - glc_flush(canvas->glc); -} - -static void gl_canvas_draw_opaque(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceOpaque *opaque) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - pixman_image_t *surface; - GLCRecti src; - GLCRecti dest; - GLCRect fill_rect; - GLCImage image; - - set_clip(canvas, bbox, clip); - set_mask(canvas, &opaque->mask, bbox->left, bbox->top); - - glc_set_op(canvas->glc, (opaque->rop_descriptor & SPICE_ROPD_INVERS_SRC) ? GLC_OP_COPY_INVERTED : - GLC_OP_COPY); - surface = canvas_get_image(&canvas->base, opaque->src_bitmap, FALSE); - surface_to_image(canvas, surface, &image, 0); - SET_GLC_RECT(&dest, bbox); - SET_GLC_RECT(&src, &opaque->src_area); - glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1); - pixman_image_unref(surface); - - set_brush(canvas, &opaque->brush); - set_op(canvas, opaque->rop_descriptor & ~SPICE_ROPD_INVERS_SRC); - SET_GLC_RECT(&fill_rect, bbox); - glc_fill_rect(canvas->glc, &fill_rect); - - glc_flush(canvas->glc); -} - -static void gl_canvas_draw_alpha_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceAlphaBlend *alpha_blend) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - pixman_image_t *surface; - GLCRecti src; - GLCRecti dest; - GLCImage image; - - set_clip(canvas, bbox, clip); - glc_clear_mask(canvas->glc, GLC_MASK_A); - glc_set_op(canvas->glc, GLC_OP_COPY); - - surface = canvas_get_image(&canvas->base, alpha_blend->src_bitmap, FALSE); - surface_to_image(canvas, surface, &image, 0); - SET_GLC_RECT(&dest, bbox); - SET_GLC_RECT(&src, &alpha_blend->src_area); - glc_draw_image(canvas->glc, &dest, &src, &image, 0, (double)alpha_blend->alpha / 0xff); - - pixman_image_unref(surface); - glc_flush(canvas->glc); -} - -static void gl_canvas_draw_blend(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlend *blend) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - pixman_image_t *surface; - GLCRecti src; - GLCRecti dest; - GLCImage image; - - set_clip(canvas, bbox, clip); - set_mask(canvas, &blend->mask, bbox->left, bbox->top); - set_op(canvas, blend->rop_descriptor); - - surface = canvas_get_image(&canvas->base, blend->src_bitmap, FALSE); - SET_GLC_RECT(&dest, bbox); - SET_GLC_RECT(&src, &blend->src_area); - surface_to_image(canvas, surface, &image, 0); - glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1); - - pixman_image_unref(surface); - glc_flush(canvas->glc); -} - -static void gl_canvas_draw_transparent(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceTransparent *transparent) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - pixman_image_t *surface; - pixman_image_t *trans_surf; - GLCImage image; - GLCRecti src; - GLCRecti dest; - - set_clip(canvas, bbox, clip); - glc_clear_mask(canvas->glc, GLC_MASK_A); - glc_set_op(canvas->glc, GLC_OP_COPY); - - surface = canvas_get_image(&canvas->base, transparent->src_bitmap, FALSE); - surface_to_image(canvas, surface, &image, 0); - - trans_surf = canvas_surf_to_trans_surf(&image, transparent->true_color); - pixman_image_unref(surface); - - surface_to_image(canvas, trans_surf, &image, 1); - SET_GLC_RECT(&dest, bbox); - SET_GLC_RECT(&src, &transparent->src_area); - glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1); - - pixman_image_unref(trans_surf); - glc_flush(canvas->glc); -} - -static inline void fill_common(GLCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpiceQMask * mask, GLCOp op) -{ - GLCRect rect; - - set_clip(canvas, bbox, clip); - set_mask(canvas, mask, bbox->left, bbox->top); - glc_set_op(canvas->glc, op); - SET_GLC_RECT(&rect, bbox); - glc_fill_rect(canvas->glc, &rect); -} - -static void gl_canvas_draw_whiteness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceWhiteness *whiteness) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - fill_common(canvas, bbox, clip, &whiteness->mask, GLC_OP_SET); -} - -static void gl_canvas_draw_blackness(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceBlackness *blackness) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - fill_common(canvas, bbox, clip, &blackness->mask, GLC_OP_CLEAR); -} - -static void gl_canvas_draw_invers(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceInvers *invers) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - fill_common(canvas, bbox, clip, &invers->mask, GLC_OP_INVERT); -} - -static void gl_canvas_draw_rop3(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceRop3 *rop3) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - pixman_image_t *d; - pixman_image_t *s; - GLCImage image; - SpicePoint src_pos; - uint8_t *data_opp; - int src_stride; - - set_clip(canvas, bbox, clip); - set_mask(canvas, &rop3->mask, bbox->left, bbox->top); - - glc_set_op(canvas->glc, GLC_OP_COPY); - - image.format = GLC_IMAGE_RGB32; - image.width = bbox->right - bbox->left; - image.height = bbox->bottom - bbox->top; - - image.pallet = NULL; - - d = pixman_image_create_bits(PIXMAN_x8r8g8b8, image.width, image.height, NULL, 0); - if (d == NULL) { - CANVAS_ERROR("create surface failed"); - } - image.pixels = (uint8_t *)pixman_image_get_data(d); - image.stride = pixman_image_get_stride(d); - - glc_read_pixels(canvas->glc, bbox->left, bbox->top, &image); - data_opp = copy_opposite_image(canvas, image.pixels, - image.stride, - pixman_image_get_height(d)); - memcpy(image.pixels, data_opp, - image.stride * pixman_image_get_height(d)); - - s = canvas_get_image(&canvas->base, rop3->src_bitmap, FALSE); - src_stride = pixman_image_get_stride(s); - if (src_stride > 0) { - data_opp = copy_opposite_image(canvas, (uint8_t *)pixman_image_get_data(s), - src_stride, pixman_image_get_height(s)); - memcpy((uint8_t *)pixman_image_get_data(s), data_opp, - src_stride * pixman_image_get_height(s)); - } - - if (!rect_is_same_size(bbox, &rop3->src_area)) { - pixman_image_t *scaled_s = canvas_scale_surface(s, &rop3->src_area, image.width, - image.height, rop3->scale_mode); - pixman_image_unref(s); - s = scaled_s; - src_pos.x = 0; - src_pos.y = 0; - } else { - src_pos.x = rop3->src_area.left; - src_pos.y = rop3->src_area.top; - } - - if (pixman_image_get_width(s) - src_pos.x < image.width || - pixman_image_get_height(s) - src_pos.y < image.height) { - CANVAS_ERROR("bad src bitmap size"); - } - - if (rop3->brush.type == SPICE_BRUSH_TYPE_PATTERN) { - pixman_image_t *p = canvas_get_image(&canvas->base, rop3->brush.u.pattern.pat, FALSE); - SpicePoint pat_pos; - - pat_pos.x = (bbox->left - rop3->brush.u.pattern.pos.x) % pixman_image_get_width(p); - - pat_pos.y = (bbox->top - rop3->brush.u.pattern.pos.y) % pixman_image_get_height(p); - - //for now (bottom-top) - if (pat_pos.y < 0) { - pat_pos.y = pixman_image_get_height(p) + pat_pos.y; - } - pat_pos.y = (image.height + pat_pos.y) % pixman_image_get_height(p); - pat_pos.y = pixman_image_get_height(p) - pat_pos.y; - - do_rop3_with_pattern(rop3->rop3, d, s, &src_pos, p, &pat_pos); - pixman_image_unref(p); - } else { - uint32_t color = (canvas->base.color_shift) == 8 ? rop3->brush.u.color : - canvas_16bpp_to_32bpp(rop3->brush.u.color); - do_rop3_with_color(rop3->rop3, d, s, &src_pos, color); - } - - pixman_image_unref(s); - - GLCRecti dest; - GLCRecti src; - dest.x = bbox->left; - dest.y = bbox->top; - - image.pixels = copy_opposite_image(canvas, image.pixels, pixman_image_get_stride(d), - pixman_image_get_height(d)); - - src.x = src.y = 0; - dest.width = src.width = image.width; - dest.height = src.height = image.height; - glc_draw_image(canvas->glc, &dest, &src, &image, 0, 1); - pixman_image_unref(d); -} - -static void gl_canvas_draw_stroke(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceStroke *stroke) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - GLCPath path; - - set_clip(canvas, bbox, clip); - glc_clear_mask(canvas->glc, GLC_MASK_A); - set_op(canvas, stroke->fore_mode); - set_brush(canvas, &stroke->brush); - - if (stroke->attr.flags & SPICE_LINE_FLAGS_STYLED) { - WARN("SPICE_LINE_FLAGS_STYLED"); - } - glc_set_line_width(canvas->glc, 1.0); - - path = get_path(canvas, stroke->path); - glc_stroke_path(canvas->glc, path); - glc_path_destroy(path); -} - -static void gl_canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpiceText *text) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - GLCRect rect; - SpiceString *str; - - set_clip(canvas, bbox, clip); - glc_clear_mask(canvas->glc, GLC_MASK_A); - - if (!rect_is_empty(&text->back_area)) { - set_brush(canvas, &text->back_brush); - set_op(canvas, text->back_mode); - SET_GLC_RECT(&rect, bbox); - glc_fill_rect(canvas->glc, &rect); - } - - str = (SpiceString *)SPICE_GET_ADDRESS(text->str); - set_brush(canvas, &text->fore_brush); - set_op(canvas, text->fore_mode); - if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) { - SpicePoint pos; - pixman_image_t *mask = canvas_get_str_mask(&canvas->base, str, 1, &pos); - _glc_fill_mask(canvas->glc, pos.x, pos.y, - pixman_image_get_width(mask), - pixman_image_get_height(mask), - pixman_image_get_stride(mask), - (uint8_t *)pixman_image_get_data(mask)); - pixman_image_unref(mask); - } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) { - SpicePoint pos; - pixman_image_t *mask = canvas_get_str_mask(&canvas->base, str, 4, &pos); - glc_fill_alpha(canvas->glc, pos.x, pos.y, - pixman_image_get_width(mask), - pixman_image_get_height(mask), - pixman_image_get_stride(mask), - (uint8_t *)pixman_image_get_data(mask)); - - pixman_image_unref(mask); - } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) { - WARN("untested path A8 glyphs, doing nothing"); - if (0) { - SpicePoint pos; - pixman_image_t *mask = canvas_get_str_mask(&canvas->base, str, 8, &pos); - glc_fill_alpha(canvas->glc, pos.x, pos.y, - pixman_image_get_width(mask), - pixman_image_get_height(mask), - pixman_image_get_stride(mask), - (uint8_t *)pixman_image_get_data(mask)); - pixman_image_unref(mask); - } - } else { - WARN("untested path vector glyphs, doing nothing"); - if (0) { - //draw_vector_str(canvas, str, &text->fore_brush, text->fore_mode); - } - } - glc_flush(canvas->glc); -} - -static void gl_canvas_clear(SpiceCanvas *spice_canvas) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - glc_clear(canvas->glc); - glc_flush(canvas->glc); -} - -static void gl_canvas_copy_bits(SpiceCanvas *spice_canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - set_clip(canvas, bbox, clip); - glc_clear_mask(canvas->glc, GLC_MASK_A); - glc_set_op(canvas->glc, GLC_OP_COPY); - glc_copy_pixels(canvas->glc, bbox->left, bbox->top, src_pos->x, src_pos->y, - bbox->right - bbox->left, bbox->bottom - bbox->top); -} - -static void gl_canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest, int dest_stride, const SpiceRect *area) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - GLCImage image; - - ASSERT(dest_stride > 0); - image.format = GLC_IMAGE_RGB32; - image.height = area->bottom - area->top; - image.width = area->right - area->left; - image.pixels = dest; - image.stride = dest_stride; - glc_read_pixels(canvas->glc, area->left, area->top, &image); -} - -static void gl_canvas_group_start(SpiceCanvas *spice_canvas, QRegion *region) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - GLCRect *glc_rects; - GLCRect *now, *end; - int num_rect; - pixman_box32_t *rects; - - canvas_base_group_start(spice_canvas, region); - - rects = pixman_region32_rectangles(region, &num_rect); - - glc_rects = spice_new(GLCRect, num_rect); - now = glc_rects; - end = glc_rects + num_rect; - - for (; now < end; now++, rects++) { - SET_GLC_BOX(now, rects); - } - glc_mask_rects(canvas->glc, num_rect, glc_rects, GLC_MASK_B); - - free(glc_rects); -} - -static void gl_canvas_put_image(SpiceCanvas *spice_canvas, const SpiceRect *dest, const uint8_t *src_data, - uint32_t src_width, uint32_t src_height, int src_stride, - const QRegion *clip) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - GLCRecti src; - GLCRecti gldest; - GLCImage image; - uint32_t i; - - ASSERT(src_stride <= 0) - glc_clip_reset(canvas->glc); - - if (clip) { - int num_rects; - pixman_box32_t *rects = pixman_region32_rectangles((pixman_region32_t *)clip, - &num_rects); - GLCRect rect; - if (num_rects == 0) { - rect.x = rect.y = rect.width = rect.height = 0; - glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET); - } else { - SET_GLC_BOX(&rect, rects); - glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_SET); - for (i = 1; i < num_rects; i++) { - SET_GLC_BOX(&rect, rects + i); - glc_clip_rect(canvas->glc, &rect, GLC_CLIP_OP_OR); - } - } - } - - SET_GLC_RECT(&gldest, dest); - src.x = src.y = 0; - src.width = src_width; - src.height = src_height; - - image.format = GLC_IMAGE_RGB32; - image.width = src_width; - image.height = src_height; - src_stride = -src_stride; - image.stride = src_stride; - image.pixels = (uint8_t *)src_data - (src_height - 1) * src_stride; - image.pallet = NULL; - glc_draw_image(canvas->glc, &gldest, &src, &image, 0, 1); - - glc_flush(canvas->glc); -} - -static void gl_canvas_group_end(SpiceCanvas *spice_canvas) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - - canvas_base_group_end(spice_canvas); - glc_clear_mask(canvas->glc, GLC_MASK_B); -} - -static int need_init = 1; -static SpiceCanvasOps gl_canvas_ops; - -SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ) -{ - GLCanvas *canvas; - int init_ok; - - if (need_init) { - return NULL; - } - canvas = spice_new0(GLCanvas, 1); - - if (!(canvas->glc = glc_create(width, height))) { - goto error_1; - } - canvas->private_data = NULL; - init_ok = canvas_base_init(&canvas->base, &gl_canvas_ops, - width, height, format -#ifdef SW_CANVAS_CACHE - , bits_cache - , palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , bits_cache -#endif - , surfaces - , glz_decoder - , jpeg_decoder - , zlib_decoder - ); - if (!init_ok) { - goto error_2; - } - - return (SpiceCanvas *)canvas; - -error_2: - glc_destroy(canvas->glc, 0); -error_1: - free(canvas); - - return NULL; -} - -void gl_canvas_set_textures_lost(SpiceCanvas *spice_canvas, - int textures_lost) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - - canvas->textures_lost = textures_lost; -} - -static void gl_canvas_destroy(SpiceCanvas *spice_canvas) -{ - GLCanvas *canvas = (GLCanvas *)spice_canvas; - - if (!canvas) { - return; - } - canvas_base_destroy(&canvas->base); - glc_destroy(canvas->glc, canvas->textures_lost); - free(canvas->private_data); - free(canvas); -} - -void gl_canvas_init(void) //unsafe global function -{ - if (!need_init) { - return; - } - need_init = 0; - - canvas_base_init_ops(&gl_canvas_ops); - gl_canvas_ops.draw_fill = gl_canvas_draw_fill; - gl_canvas_ops.draw_copy = gl_canvas_draw_copy; - gl_canvas_ops.draw_opaque = gl_canvas_draw_opaque; - gl_canvas_ops.copy_bits = gl_canvas_copy_bits; - gl_canvas_ops.draw_text = gl_canvas_draw_text; - gl_canvas_ops.draw_stroke = gl_canvas_draw_stroke; - gl_canvas_ops.draw_rop3 = gl_canvas_draw_rop3; - gl_canvas_ops.draw_blend = gl_canvas_draw_blend; - gl_canvas_ops.draw_blackness = gl_canvas_draw_blackness; - gl_canvas_ops.draw_whiteness = gl_canvas_draw_whiteness; - gl_canvas_ops.draw_invers = gl_canvas_draw_invers; - gl_canvas_ops.draw_transparent = gl_canvas_draw_transparent; - gl_canvas_ops.draw_alpha_blend = gl_canvas_draw_alpha_blend; - gl_canvas_ops.put_image = gl_canvas_put_image; - gl_canvas_ops.clear = gl_canvas_clear; - gl_canvas_ops.read_bits = gl_canvas_read_bits; - gl_canvas_ops.group_start = gl_canvas_group_start; - gl_canvas_ops.group_end = gl_canvas_group_end; - gl_canvas_ops.destroy = gl_canvas_destroy; - - rop3_init(); -} diff --git a/common/gl_canvas.h b/common/gl_canvas.h deleted file mode 100644 index 400bedb2..00000000 --- a/common/gl_canvas.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#include "glc.h" -#include "canvas_base.h" -#include "region.h" - -#ifndef SPICE_CANVAS_INTERNAL -#error "This header shouldn't be included directly" -#endif - -#ifndef _H__GL_CANVAS -#define _H__GL_CANVAS - -#ifdef __cplusplus -extern "C" { -#endif - -SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ); -void gl_canvas_set_textures_lost(SpiceCanvas *canvas, int textures_lost); -void gl_canvas_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/gl_utils.h b/common/gl_utils.h deleted file mode 100644 index c30be166..00000000 --- a/common/gl_utils.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef GL_UTILS_H -#define GL_UTILS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef RED_DEBUG -#define GLC_ERROR_TEST_FLUSH { \ - GLenum gl_err; glFlush(); \ - if ((gl_err = glGetError()) != GL_NO_ERROR) { \ - printf("%s[%d]: opengl error: %s\n", __FUNCTION__, __LINE__, \ - gluErrorString(gl_err)); \ - abort(); \ - } \ -} - -#define GLC_ERROR_TEST_FINISH { \ - GLenum gl_err; glFinish(); \ - if ((gl_err = glGetError()) != GL_NO_ERROR) { \ - printf("%s[%d]: opengl error: %s\n", __FUNCTION__, __LINE__, \ - gluErrorString(gl_err)); \ - abort(); \ - } \ -} -#else -#define GLC_ERROR_TEST_FLUSH ; - -#define GLC_ERROR_TEST_FINISH ; -#endif - -#include "bitops.h" - -#define find_msb spice_bit_find_msb -#define gl_get_to_power_two spice_bit_next_pow2 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/glc.c b/common/glc.c deleted file mode 100644 index 1414bcff..00000000 --- a/common/glc.c +++ /dev/null @@ -1,1513 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <math.h> -#include <spice/macros.h> - -#include <GL/gl.h> -#include <GL/glu.h> -#include <GL/glext.h> - -#ifdef WIN32 -#include "glext.h" -#include "wglext.h" -#endif - -#include "mem.h" -#include "glc.h" -#include "gl_utils.h" -#include "spice_common.h" - -#define TESS_VERTEX_ALLOC_BUNCH 20 - -typedef struct InternaCtx InternaCtx; -typedef struct InternalPat { - InternaCtx *owner; - int refs; - GLuint texture; - int x_orign; - int y_orign; - int width; - int height; -} InternalPat; - -typedef struct Pathpath { - int start_point; - int num_segments; -} Path; - -enum { - GLC_PATH_SEG_LINES, - GLC_PATH_SEG_BEIZER, -}; - -//todo: flatten cache -typedef struct PathSegment { - int type; - int count; -} PathSegment; - -typedef struct PathPoint { - double x; - double y; - double z; -} PathPoint; - -typedef GLdouble Vertex[3]; - -typedef struct InternalPath { - InternaCtx *owner; - - Path *paths; - int paths_size; - int paths_pos; - - PathSegment *segments; - int segments_size; - int segments_pos; - - PathPoint *points; - int points_size; - int points_pos; - - Path *current_path; - PathSegment *current_segment; -} InternalPath; - -typedef struct TassVertex TassVertex; -struct TassVertex { - PathPoint point; - TassVertex *list_link; - TassVertex *next; -}; - -typedef struct TassVertexBuf TassVertexBuf; -struct TassVertexBuf { - TassVertexBuf *next; - TassVertex vertexs[0]; -}; - -#define USE_LINE_ANTIALIAS 0 - -typedef struct LineDash { - double *dashes; - int num_dashes; - double offset; - int cur_dash; - double dash_pos; -} LineDash; - -enum { - GLC_STROKE_NONACTIVE, - GLC_STROKE_FIRST, - GLC_STROKE_ACTIVE, -}; - -typedef struct PathStroke { - double x; - double y; - int state; -} PathStroke; - -struct InternaCtx { - int draw_mode; - int stencil_refs; - int stencil_mask; - int width; - int height; - GLfloat line_width; - LineDash line_dash; - PathStroke path_stroke; - InternalPat *pat; - int max_texture_size; - GLUtesselator* tesselator; - TassVertex *free_tess_vertex; - TassVertex *used_tess_vertex; - TassVertexBuf *vertex_bufs; - int private_tex_width; - int private_tex_height; - GLuint private_tex; -#ifdef WIN32 - PFNGLBLENDEQUATIONPROC glBlendEquation; -#endif -}; - -#define Y(y) -(y) -#define VERTEX2(x, y) glVertex2d(x, Y(y)) - -static void fill_rect(InternaCtx *ctx, void *rect); -static void fill_path(InternaCtx *ctx, void *path); -static void fill_mask(InternaCtx *ctx, int x_dest, int y_dest, int width, int height, int stride, - const uint8_t *bitmap); -static void set_pat(InternaCtx *ctx, InternalPat *pat); - -static inline void set_raster_pos(InternaCtx *ctx, int x, int y) -{ - if (x >= 0 && y >= 0 && x < ctx->width && y < ctx->height) { - glRasterPos2i(x, Y(y)); - return; - } - glRasterPos2i(0, 0); - glBitmap(0, 0, 0, 0, (GLfloat)x, (GLfloat)Y(y), NULL); -} - -static TassVertex *alloc_tess_vertex(InternaCtx *ctx) -{ - TassVertex *vertex; - - if (!ctx->free_tess_vertex) { - TassVertexBuf *buf; - int i; - - buf = (TassVertexBuf *)spice_malloc(sizeof(TassVertexBuf) + - sizeof(TassVertex) * TESS_VERTEX_ALLOC_BUNCH); - buf->next = ctx->vertex_bufs; - ctx->vertex_bufs = buf; - for (i = 0; i < TESS_VERTEX_ALLOC_BUNCH; i++) { - buf->vertexs[i].point.z = 0; - buf->vertexs[i].next = ctx->free_tess_vertex; - ctx->free_tess_vertex = &buf->vertexs[i]; - } - } - - vertex = ctx->free_tess_vertex; - ctx->free_tess_vertex = vertex->next; - vertex->next = ctx->used_tess_vertex; - ctx->used_tess_vertex = vertex; - return vertex; -} - -static void reset_tass_vertex(InternaCtx *ctx) -{ - TassVertex *vertex; - while ((vertex = ctx->used_tess_vertex)) { - ctx->used_tess_vertex = vertex->next; - vertex->next = ctx->free_tess_vertex; - ctx->free_tess_vertex = vertex; - } -} - -static void free_tass_vertex_bufs(InternaCtx *ctx) -{ - TassVertexBuf *buf; - - ctx->used_tess_vertex = NULL; - ctx->free_tess_vertex = NULL; - while ((buf = ctx->vertex_bufs)) { - ctx->vertex_bufs = buf->next; - free(buf); - } -} - -//naive bezier flattener -static TassVertex *bezier_flattener(InternaCtx *ctx, PathPoint *points) -{ - double ax, bx, cx; - double ay, by, cy; - const int num_points = 30; - double dt; - int i; - - TassVertex *vertex_list = NULL; - TassVertex *curr_vertex; - - for (i = 0; i < num_points - 2; i++) { - TassVertex *vertex; - - vertex = alloc_tess_vertex(ctx); - vertex->list_link = vertex_list; - vertex_list = vertex; - } - - curr_vertex = vertex_list; - - cx = 3.0 * (points[1].x - points[0].x); - bx = 3.0 * (points[2].x - points[1].x) - cx; - ax = points[3].x - points[0].x - cx - bx; - - cy = 3.0 * (points[1].y - points[0].y); - by = 3.0 * (points[2].y - points[1].y) - cy; - ay = points[3].y - points[0].y - cy - by; - - dt = 1.0 / (num_points - 1); - - for (i = 1; i < num_points - 1; i++, curr_vertex = curr_vertex->list_link) { - double tSquared, tCubed; - double t; - t = i * dt; - - tSquared = t * t; - tCubed = tSquared * t; - - curr_vertex->point.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + points[0].x; - curr_vertex->point.y = (ay * tCubed) + (by * tSquared) + (cy * t) + points[0].y; - } - - return vertex_list; -} - -#define MORE_X(path, Type, name) { \ - Type *name; \ - \ - name = spice_new0(Type, path->name##_size * 2); \ - memcpy(name, path->name, sizeof(*name) * path->name##_size); \ - free(path->name); \ - path->name = name; \ - path->name##_size *= 2; \ -} - -static void more_points(InternalPath *path) -{ - MORE_X(path, PathPoint, points); -} - -static void more_segments(InternalPath *path) -{ - MORE_X(path, PathSegment, segments); -} - -static void more_paths(InternalPath *path) -{ - MORE_X(path, Path, paths); -} - -static inline void put_point(InternalPath *path, double x, double y) -{ - path->points[path->points_pos].x = x; - path->points[path->points_pos].y = Y(y + 0.5); - path->points[path->points_pos++].z = 0; -} - -void glc_path_move_to(GLCPath path, double x, double y) -{ - InternalPath *internal = (InternalPath *)path; - - ASSERT(internal); - - if (internal->current_segment) { - internal->current_segment = NULL; - internal->current_path = NULL; - if (internal->points_pos == internal->points_size) { - more_points(internal); - } - internal->points_pos++; - } - internal->points[internal->points_pos - 1].x = x; - internal->points[internal->points_pos - 1].y = Y(y + 0.5); - internal->points[internal->points_pos - 1].z = 0; -} - -static void add_segment_common(InternalPath *internal, int type, int num_points) -{ - if (internal->points_size - internal->points_pos < num_points) { - more_points(internal); - } - - if (internal->current_segment) { - if (internal->current_segment->type == type) { - internal->current_segment->count++; - return; - } - if (internal->segments_pos == internal->segments_size) { - more_segments(internal); - } - internal->current_segment = &internal->segments[internal->segments_pos++]; - internal->current_segment->type = type; - internal->current_segment->count = 1; - internal->current_path->num_segments++; - return; - } - - if (internal->paths_pos == internal->paths_size) { - more_paths(internal); - } - - if (internal->segments_pos == internal->segments_size) { - more_segments(internal); - } - - internal->current_path = &internal->paths[internal->paths_pos++]; - internal->current_path->start_point = internal->points_pos - 1; - internal->current_path->num_segments = 1; - internal->current_segment = &internal->segments[internal->segments_pos++]; - internal->current_segment->type = type; - internal->current_segment->count = 1; -} - -void glc_path_line_to(GLCPath path, double x, double y) -{ - InternalPath *internal = (InternalPath *)path; - - ASSERT(internal); - - add_segment_common(internal, GLC_PATH_SEG_LINES, 1); - put_point(internal, x, y); -} - -void glc_path_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y, - double p3_x, double p3_y) -{ - InternalPath *internal = (InternalPath *)path; - - ASSERT(internal); - - add_segment_common(internal, GLC_PATH_SEG_BEIZER, 3); - put_point(internal, p1_x, p1_y); - put_point(internal, p2_x, p2_y); - put_point(internal, p3_x, p3_y); -} - -void glc_path_close(GLCPath path) -{ - InternalPath *internal = (InternalPath *)path; - - ASSERT(internal); - if (!internal->current_path) { - return; - } - PathPoint *end_point = &internal->points[internal->current_path->start_point]; - glc_path_line_to(path, end_point->x, Y(end_point->y)); - glc_path_move_to(path, end_point->x, Y(end_point->y)); -} - -void glc_path_cleare(GLCPath path) -{ - InternalPath *internal = (InternalPath *)path; - - ASSERT(internal); - internal->paths_pos = internal->segments_pos = 0; - internal->current_segment = NULL; - internal->current_path = NULL; - - internal->points[0].x = 0; - internal->points[0].y = 0; - internal->points_pos = 1; -} - -GLCPath glc_path_create(GLCCtx glc) -{ - InternaCtx *ctx = (InternaCtx *)glc; - InternalPath *path; - - ASSERT(ctx); - path = spice_new0(InternalPath, 1); - path->paths_size = 2; - path->paths = spice_new(Path, path->paths_size); - - path->segments_size = 4; - path->segments = spice_new(PathSegment, path->segments_size); - - path->points_size = 20; - path->points = spice_new(PathPoint, path->points_size); - - path->owner = ctx; - path->points_pos = 1; - return path; -} - -void glc_path_destroy(GLCPath path) -{ - InternalPath *internal = (InternalPath *)path; - - if (!path) { - return; - } - - free(internal->points); - free(internal->segments); - free(internal->paths); - free(internal); -} - -static inline void unref_pat(InternalPat *pat) -{ - if (!pat) { - return; - } - ASSERT(pat->refs > 0); - if (--pat->refs == 0) { - glFinish(); - glDeleteTextures(1, &pat->texture); - free(pat); - } - GLC_ERROR_TEST_FLUSH; -} - -static inline InternalPat *ref_pat(InternalPat *pat) -{ - pat->refs++; - return pat; -} - -static void scale(uint32_t *dest, uint32_t dest_width, uint32_t dest_height, - uint32_t *src, uint32_t src_width, uint32_t src_height, int src_stride) -{ - double x_scale = (double)src_width / dest_width; - double y_scale = (double)src_height / dest_height; - uint32_t i; - uint32_t j; - int prev_row = -1; - - for (i = 0; i < dest_height; i++) { - int row = (int)(y_scale * i); - if (row == prev_row) { - memcpy(dest, dest - dest_width, dest_width * sizeof(uint32_t)); - dest += dest_width; - continue; - } - for (j = 0; j < dest_width; j++) { - int col = (int)(x_scale * j); - *(dest++) = *(src + col); - } - prev_row = row; - src = (uint32_t *)((uint8_t *)src + src_stride); - } -} - -static inline void init_pattern(InternalPat *pat, int x_orign, int y_orign, const GLCImage *image) -{ - InternaCtx *ctx = pat->owner; - uint32_t *tmp_pixmap = NULL; - int width; - int height; - int width2; - int height2; - - const int pix_bytes = 4; - - ASSERT(image->format == GLC_IMAGE_RGB32); //for now - - width = image->width; - height = image->height; - width2 = gl_get_to_power_two(width); - height2 = gl_get_to_power_two(height); - - ASSERT(width > 0 && height > 0); - ASSERT(width > 0 && width <= pat->owner->max_texture_size); - ASSERT(height > 0 && height <= pat->owner->max_texture_size); - - if (width2 != width || height2 != height) { - tmp_pixmap = (uint32_t *)spice_malloc(width2 * height2 * sizeof(uint32_t)); - scale(tmp_pixmap, width2, height2, (uint32_t *)image->pixels, width, height, image->stride); - } - - glBindTexture(GL_TEXTURE_2D, pat->texture); - - //glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - if (tmp_pixmap) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, width2); - glTexImage2D(GL_TEXTURE_2D, 0, 4, width2, height2, 0, GL_BGRA, GL_UNSIGNED_BYTE, - tmp_pixmap); - free(tmp_pixmap); - } else { - ASSERT(image->stride % pix_bytes == 0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->stride / pix_bytes); - glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, - image->pixels); - } - - GLC_ERROR_TEST_FLUSH; - pat->x_orign = x_orign % width; - pat->y_orign = y_orign % height; - pat->width = width; - pat->height = height; - - if (ctx->pat == pat) { - set_pat(pat->owner, pat); - } else if (ctx->pat) { - glBindTexture(GL_TEXTURE_2D, ctx->pat->texture); - } -} - -GLCPattern glc_pattern_create(GLCCtx glc, int x_orign, int y_orign, const GLCImage *image) -{ - InternaCtx *ctx = (InternaCtx *)glc; - InternalPat *pat; - - ASSERT(ctx && image); - - pat = spice_new0(InternalPat, 1); - pat->refs = 1; - pat->owner = ctx; - glGenTextures(1, &pat->texture); - init_pattern(pat, x_orign, y_orign, image); - return pat; -} - -void glc_pattern_set(GLCPattern pattern, int x_orign, int y_orign, const GLCImage *image) -{ - InternalPat *pat = (InternalPat *)pattern; - ASSERT(pat && pat->owner); - - glFinish(); - init_pattern(pat, x_orign, y_orign, image); -} - -void glc_pattern_destroy(GLCPattern pat) -{ - unref_pat((InternalPat *)pat); - GLC_ERROR_TEST_FLUSH; -} - -static void set_pat(InternaCtx *ctx, InternalPat *pat) -{ - pat = ref_pat(pat); - unref_pat(ctx->pat); - ctx->pat = pat; - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, pat->texture); - - GLfloat s_gen_params[] = { (GLfloat)1.0 / pat->width, 0, 0, 0 }; - GLfloat t_gen_params[] = { 0, (GLfloat)1.0 / (GLfloat)pat->height, 0, 0 }; - glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen_params); - glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen_params); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glTranslatef((float)pat->x_orign / pat->width, (float)Y(pat->y_orign) / pat->height, 0); - GLC_ERROR_TEST_FLUSH; -} - -void glc_set_pattern(GLCCtx glc, GLCPattern pattern) -{ - InternaCtx *ctx = (InternaCtx *)glc; - InternalPat *pat = (InternalPat *)pattern; - - ASSERT(ctx && pat && pat->owner == ctx); - set_pat(ctx, pat); -} - -void glc_set_rgb(GLCCtx glc, double red, double green, double blue) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx); - - glDisable(GL_TEXTURE_2D); - unref_pat(ctx->pat); - ctx->pat = NULL; - glColor4d(red, green, blue, 1); - GLC_ERROR_TEST_FLUSH; -} - -void glc_set_op(GLCCtx glc, GLCOp op) -{ - if (op == GL_COPY) { - glDisable(GL_COLOR_LOGIC_OP); - return; - } - glLogicOp(op); - glEnable(GL_COLOR_LOGIC_OP); -} - -void glc_set_line_width(GLCCtx glc, double width) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx); - ctx->line_width = (GLfloat)width; - if (ctx->line_width > 0) { - glLineWidth(ctx->line_width); - } else { - ctx->line_width = 0; - } - GLC_ERROR_TEST_FLUSH; -} - -void glc_set_line_dash(GLCCtx glc, const double *dashes, int num_dashes, double offset) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx); - if (dashes && num_dashes >= 0 && offset >= 0) { - ctx->line_dash.dashes = spice_new(double, num_dashes); - memcpy(ctx->line_dash.dashes, dashes, sizeof(double) * num_dashes); - ctx->line_dash.num_dashes = num_dashes; - ctx->line_dash.offset = offset; - ctx->line_dash.cur_dash = offset ? -1 : 0; - ctx->line_dash.dash_pos = 0; - } else { - free(ctx->line_dash.dashes); - memset(&ctx->line_dash, 0, sizeof(ctx->line_dash)); - } -} - -void glc_set_fill_mode(GLCCtx glc, GLCFillMode fill_mode) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx); - int mode; - switch (fill_mode) { - case GLC_FILL_MODE_WINDING_ODD: - mode = GLU_TESS_WINDING_ODD; - break; - case GLC_FILL_MODE_WINDING_NONZERO: - mode = GLU_TESS_WINDING_NONZERO; - break; - default: - //warn - return; - } - gluTessProperty(ctx->tesselator, GLU_TESS_WINDING_RULE, mode); -} - -static inline void add_stencil_client(InternaCtx *ctx) -{ - if (!ctx->stencil_refs) { - glEnable(GL_STENCIL_TEST); - } - ctx->stencil_refs++; -} - -static inline void remove_stencil_client(InternaCtx *ctx) -{ - ctx->stencil_refs--; - if (!ctx->stencil_refs) { - glDisable(GL_STENCIL_TEST); - } -} - -void glc_set_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, - int stride, const uint8_t *bitmap, GLCMaskID id) -{ - InternaCtx *ctx = (InternaCtx *)glc; - uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08; - ASSERT(ctx && bitmap); - ASSERT(id == GLC_MASK_A || id == GLC_MASK_B); - - if (ctx->pat) { - glDisable(GL_TEXTURE_2D); - } - - glDisable(GL_BLEND); - - if (!(ctx->stencil_mask & mask)) { - add_stencil_client(ctx); - ctx->stencil_mask |= mask; - } - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - ctx->draw_mode = FALSE; - glStencilMask(mask); - glClear(GL_STENCIL_BUFFER_BIT); - - glStencilFunc(GL_ALWAYS, mask, mask); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - fill_mask(ctx, x_dest, y_dest, width, height, stride, bitmap); -} - -void glc_mask_rects(GLCCtx glc, int num_rect, GLCRect *rects, GLCMaskID id) -{ - InternaCtx *ctx = (InternaCtx *)glc; - uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08; - GLCRect *end; - ASSERT(ctx && rects); - ASSERT(id == GLC_MASK_A || id == GLC_MASK_B); - - if (ctx->pat) { - glDisable(GL_TEXTURE_2D); - } - - glDisable(GL_BLEND); - - if (!(ctx->stencil_mask & mask)) { - add_stencil_client(ctx); - ctx->stencil_mask |= mask; - } - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - ctx->draw_mode = FALSE; - glStencilMask(mask); - glClear(GL_STENCIL_BUFFER_BIT); - - glStencilFunc(GL_ALWAYS, mask, mask); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - end = rects + num_rect; - for (; rects < end; rects++) { - fill_rect(ctx, rects); - } -} - -void glc_clear_mask(GLCCtx glc, GLCMaskID id) -{ - InternaCtx *ctx = (InternaCtx *)glc; - uint32_t mask = (id == GLC_MASK_A) ? 0x04 : 0x08; - ASSERT(ctx); - ASSERT(id == GLC_MASK_A || id == GLC_MASK_B); - - if ((ctx->stencil_mask & mask)) { - ctx->stencil_mask &= ~mask; - remove_stencil_client(ctx); - } -} - -void glc_clip_reset(GLCCtx glc) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - if (!(ctx->stencil_mask & 0x03)) { - return; - } - remove_stencil_client(ctx); - ctx->stencil_mask &= ~0x03; - glStencilMask(0x03); - glClear(GL_STENCIL_BUFFER_BIT); - GLC_ERROR_TEST_FLUSH; -} - -static void clip_common(InternaCtx *ctx, GLCClipOp op, void (*fill_func)(InternaCtx *, void *), - void *data) -{ - int stencil_val; - - if (ctx->pat) { - glDisable(GL_TEXTURE_2D); - } - glDisable(GL_BLEND); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - ctx->draw_mode = FALSE; - - if (op == GLC_CLIP_OP_SET) { - glc_clip_reset(ctx); - add_stencil_client(ctx); - ctx->stencil_mask |= 0x01; - } else if (!(ctx->stencil_mask & 0x03)) { - GLCRect area; - if (op == GLC_CLIP_OP_OR) { - return; - } - area.x = area.y = 0; - area.width = ctx->width; - area.height = ctx->height; - clip_common(ctx, GLC_CLIP_OP_SET, fill_rect, &area); - } - glStencilMask(0x03); - switch (op) { - case GLC_CLIP_OP_SET: - case GLC_CLIP_OP_OR: - stencil_val = ctx->stencil_mask & 0x03; - glStencilFunc(GL_ALWAYS, stencil_val, stencil_val); - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); - fill_func(ctx, data); - break; - case GLC_CLIP_OP_AND: { - int clear_mask; - stencil_val = ctx->stencil_mask & 0x03; - glStencilFunc(GL_EQUAL, stencil_val, stencil_val); - if (stencil_val == 0x01) { - glStencilOp(GL_ZERO, GL_INCR, GL_INCR); - stencil_val = 0x02; - clear_mask = 0x01; - } else { - glStencilOp(GL_ZERO, GL_DECR, GL_DECR); - stencil_val = 0x01; - clear_mask = 0x02; - } - fill_func(ctx, data); - - glStencilMask(clear_mask); - glClear(GL_STENCIL_BUFFER_BIT); - ctx->stencil_mask = (ctx->stencil_mask & ~clear_mask) | stencil_val; - break; - } - case GLC_CLIP_OP_EXCLUDE: - stencil_val = ctx->stencil_mask & 0x03; - glStencilFunc(GL_EQUAL, stencil_val, stencil_val); - glStencilOp(GL_KEEP, GL_ZERO, GL_ZERO); - fill_func(ctx, data); - break; - } - GLC_ERROR_TEST_FLUSH; -} - -void glc_clip_rect(GLCCtx glc, const GLCRect *rect, GLCClipOp op) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx && rect); - clip_common(ctx, op, fill_rect, (void *)rect); -} - -void glc_clip_path(GLCCtx glc, GLCPath path, GLCClipOp op) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx && path); - clip_common(ctx, op, fill_path, path); -} - -typedef struct FillMaskInfo { - int x_dest; - int y_dest; - int width; - int height; - int stride; - const uint8_t *bitmap; -} FillMaskInfo; - -static void __fill_mask(InternaCtx *ctx, void *data) -{ - FillMaskInfo *info = (FillMaskInfo *)data; - fill_mask(ctx, info->x_dest, info->y_dest, info->width, info->height, info->stride, - info->bitmap); -} - -void glc_clip_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, - int stride, const uint8_t *bitmap, GLCClipOp op) -{ - InternaCtx *ctx = (InternaCtx *)glc; - FillMaskInfo mask_info; - - ASSERT(ctx && bitmap); - mask_info.x_dest = x_dest; - mask_info.y_dest = y_dest; - mask_info.width = width; - mask_info.height = height; - mask_info.stride = stride; - mask_info.bitmap = bitmap; - clip_common(ctx, op, __fill_mask, &mask_info); -} - -static inline void start_draw(InternaCtx *ctx) -{ - if (ctx->draw_mode) { - return; - } - ctx->draw_mode = TRUE; - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilFunc(GL_EQUAL, ctx->stencil_mask, ctx->stencil_mask); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - if (ctx->pat) { - glEnable(GL_TEXTURE_2D); - } else { - glDisable(GL_TEXTURE_2D); - } - GLC_ERROR_TEST_FLUSH; -} - -static void fill_rect(InternaCtx *ctx, void *r) -{ - GLCRect *rect = (GLCRect *)r; - glRectd(rect->x, Y(rect->y), rect->x + rect->width, Y(rect->y + rect->height)); - /*glBegin(GL_POLYGON); - VERTEX2(rect->x, rect->y); - VERTEX2 (rect->x + rect->width, rect->y); - VERTEX2 (rect->x + rect->width, rect->y + rect->height); - VERTEX2 (rect->x , rect->y + rect->height); - glEnd();*/ - GLC_ERROR_TEST_FLUSH; -} - -void glc_fill_rect(GLCCtx glc, const GLCRect *rect) -{ - InternaCtx *ctx = (InternaCtx *)glc; - GLCRect *r = (GLCRect *)rect; // to avoid bugs in gcc older than 4.3 - - ASSERT(ctx); - start_draw(ctx); - fill_rect(ctx, (void *)r); - GLC_ERROR_TEST_FLUSH; -} - -static void fill_path(InternaCtx *ctx, void *p) -{ - InternalPath *path = (InternalPath *)p; - - PathPoint *current_point = path->points; - PathSegment *current_segment = path->segments; - Path *current_path = path->paths; - Path *end_path = current_path + path->paths_pos; - reset_tass_vertex(ctx); - gluTessBeginPolygon(ctx->tesselator, ctx); - for (; current_path < end_path; current_path++) { - gluTessBeginContour(ctx->tesselator); - PathSegment *end_segment = current_segment + current_path->num_segments; - gluTessVertex(ctx->tesselator, (GLdouble *)current_point, current_point); - current_point++; - for (; current_segment < end_segment; current_segment++) { - PathPoint *end_point; - if (current_segment->type == GLC_PATH_SEG_BEIZER) { - end_point = current_point + current_segment->count * 3; - for (; current_point < end_point; current_point += 3) { - TassVertex *vertex = bezier_flattener(ctx, current_point - 1); - while (vertex) { - gluTessVertex(ctx->tesselator, (GLdouble *)&vertex->point, - (GLdouble *)&vertex->point); - vertex = vertex->list_link; - } - gluTessVertex(ctx->tesselator, (GLdouble *)¤t_point[2], - (GLdouble *)¤t_point[2]); - } - } else { - ASSERT(current_segment->type == GLC_PATH_SEG_LINES); - end_point = current_point + current_segment->count; - for (; current_point < end_point; current_point++) { - gluTessVertex(ctx->tesselator, (GLdouble *)current_point, - (GLdouble *)current_point); - } - } - } - gluTessEndContour(ctx->tesselator); - } - gluTessEndPolygon(ctx->tesselator); -} - -void glc_fill_path(GLCCtx glc, GLCPath path_ref) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx && path_ref); - start_draw(ctx); - fill_path(ctx, path_ref); -} - -static void fill_mask(InternaCtx *ctx, int x_dest, int y_dest, int width, int height, - int stride, const uint8_t *bitmap) -{ - set_raster_pos(ctx, x_dest, y_dest + height); - glPixelStorei(GL_UNPACK_ROW_LENGTH, stride * 8); - glBitmap(width, height, 0, 0, 0, 0, bitmap); -} - -void _glc_fill_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride, - const uint8_t *bitmap) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx && bitmap); - start_draw(ctx); - if (ctx->pat) { - WARN_ONCE("%s: unimplemented fill mask with pattern\n", __FUNCTION__); - } - fill_mask(ctx, x_dest, y_dest, width, height, stride, bitmap); -} - -void glc_fill_alpha(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride, - const uint8_t *alpha_mask) -{ - InternaCtx *ctx = (InternaCtx *)glc; - GLCRect r; - - ASSERT(ctx); - start_draw(ctx); - - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); - set_raster_pos(ctx, x_dest, y_dest + height); - glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); - glPixelZoom(1, 1); - glDrawPixels(width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_mask); - - r.x = x_dest; - r.y = y_dest; - r.width = width; - r.height = height; - - //todo: support color/texture alpah vals (GL_MODULATE) - glEnable(GL_BLEND); - glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - fill_rect(ctx, &r); - glDisable(GL_BLEND); -} - -void glc_stroke_rect(GLCCtx glc, const GLCRect *rect) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx); - if (ctx->line_width == 0) { - return; - } - - start_draw(ctx); - - glBegin(GL_LINES); - VERTEX2(rect->x, rect->y + 0.5); - VERTEX2(rect->x + rect->width, rect->y + 0.5); - VERTEX2(rect->x + rect->width - 0.5, rect->y); - VERTEX2(rect->x + rect->width - 0.5, rect->y + rect->height); - VERTEX2(rect->x + rect->width, rect->y + rect->height - 0.5); - VERTEX2(rect->x, rect->y + rect->height - 0.5); - VERTEX2(rect->x + 0.5, rect->y + rect->height); - VERTEX2(rect->x + 0.5, rect->y); - glEnd(); - GLC_ERROR_TEST_FLUSH; -} - -static void glc_stroke_line(double x1, double y1, double x2, double y2, double width) -{ - double ax, ay, bx, by, cx, cy, dx, dy; - double norm, tx; - - if (width == 1 || y1 == y2 || x1 == x2) { - glBegin(GL_LINES); - glVertex2d(x1, y1); - glVertex2d(x2, y2); - glEnd(); - return; - } - norm = (x1 - x2) / (y2 - y1); - tx = width / (2 * sqrt(1 + norm * norm)); - ax = x1 + tx; - ay = y1 + norm * (ax - x1); - bx = x2 + tx; - by = y2 + norm * (bx - x2); - cx = x2 - tx; - cy = y2 + norm * (cx - x2); - dx = x1 - tx; - dy = y1 + norm * (dx - x1); - glBegin(GL_POLYGON); - glVertex2d(ax, ay); - glVertex2d(bx, by); - glVertex2d(cx, cy); - glVertex2d(dx, dy); - glEnd(); -} - -static double glc_stroke_line_dash(double x1, double y1, double x2, double y2, - double width, LineDash *dash) -{ - double ax, ay, bx, by; - double mx, my, len; - double dash_len, total = 0; - - len = sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)); - if (!dash->dashes || !dash->num_dashes) { - glc_stroke_line(x1, y1, x2, y2, width); - return len; - } - mx = (x2 - x1) / len; - my = (y2 - y1) / len; - ax = x1; - ay = y1; - while (total < len) { - if (dash->cur_dash >= 0) { - dash_len = dash->dashes[dash->cur_dash % dash->num_dashes] - dash->dash_pos; - } else { - dash_len = dash->offset - dash->dash_pos; - } - total += dash_len; - if (total < len) { - bx = x1 + mx * total; - by = y1 + my * total; - dash->dash_pos = 0; - } else { - bx = x2; - by = y2; - dash->dash_pos = dash->dashes[dash->cur_dash % dash->num_dashes] - (total - len); - } - if (dash->cur_dash % 2 == 0) { - glc_stroke_line(ax, ay, bx, by, width); - } - if (dash->dash_pos == 0) { - dash->cur_dash = (dash->cur_dash + 1) % (2 * dash->num_dashes); - } - ax = bx; - ay = by; - } - return len; -} - -static void glc_vertex2d(InternaCtx *ctx, double x, double y) -{ - if (ctx->path_stroke.state == GLC_STROKE_ACTIVE) { - glc_stroke_line_dash(ctx->path_stroke.x, ctx->path_stroke.y, x, y, - ctx->line_width, &ctx->line_dash); - ctx->path_stroke.x = x; - ctx->path_stroke.y = y; - } else if (ctx->path_stroke.state == GLC_STROKE_FIRST) { - ctx->path_stroke.x = x; - ctx->path_stroke.y = y; - ctx->path_stroke.state = GLC_STROKE_ACTIVE; - } else { - ASSERT(ctx->path_stroke.state == GLC_STROKE_NONACTIVE); - //error - } -} - -static void glc_begin_path(InternaCtx *ctx) -{ - ctx->path_stroke.state = GLC_STROKE_FIRST; - ctx->line_dash.cur_dash = ctx->line_dash.offset ? -1 : 0; - ctx->line_dash.dash_pos = 0; -} - -static void glc_end_path(InternaCtx *ctx) -{ - ctx->path_stroke.state = GLC_STROKE_NONACTIVE; -} - -void glc_stroke_path(GLCCtx glc, GLCPath path_ref) -{ - InternaCtx *ctx = (InternaCtx *)glc; - InternalPath *path = (InternalPath *)path_ref; - - ASSERT(ctx && path); - if (ctx->line_width == 0) { - return; - } - start_draw(ctx); - - reset_tass_vertex(ctx); - PathPoint *current_point = path->points; - PathSegment *current_segment = path->segments; - Path *current_path = path->paths; - Path *end_path = current_path + path->paths_pos; - for (; current_path < end_path; current_path++) { - glc_begin_path(ctx); - PathSegment *end_segment = current_segment + current_path->num_segments; - glc_vertex2d(ctx, current_point->x, current_point->y); - current_point++; - for (; current_segment < end_segment; current_segment++) { - PathPoint *end_point; - if (current_segment->type == GLC_PATH_SEG_BEIZER) { - end_point = current_point + current_segment->count * 3; - for (; current_point < end_point; current_point += 3) { - TassVertex *vertex = bezier_flattener(ctx, current_point - 1); - while (vertex) { - glc_vertex2d(ctx, vertex->point.x, vertex->point.y); - vertex = vertex->list_link; - } - glc_vertex2d(ctx, current_point[2].x, current_point[2].y); - } - } else { - ASSERT(current_segment->type == GLC_PATH_SEG_LINES); - end_point = current_point + current_segment->count; - for (; current_point < end_point; current_point++) { - glc_vertex2d(ctx, current_point->x, current_point->y); - } - } - } - glc_end_path(ctx); - } -} - -void glc_draw_image(GLCCtx glc, const GLCRecti *dest, const GLCRecti *src, const GLCImage *image, - int scale_mode, double alpha) -{ - InternaCtx *ctx = (InternaCtx *)glc; - uint8_t *pixels; - const int pix_bytes = 4; - - ASSERT(ctx && image); - ASSERT(src->width > 0 && src->height > 0); - - ASSERT(image->format == GLC_IMAGE_RGB32 || image->format == GLC_IMAGE_ARGB32); //for now - start_draw(ctx); - if (ctx->pat) { - glDisable(GL_TEXTURE_2D); - } - set_raster_pos(ctx, dest->x, dest->y + dest->height); - - if (dest->width == src->width && src->height == dest->height) { - glPixelZoom(1, 1); - } else { - glPixelZoom((float)dest->width / src->width, (float)dest->height / src->height); - } - - pixels = image->pixels + src->x * 4 + (image->height - (src->y + src->height)) * image->stride; - if (image->format == GLC_IMAGE_ARGB32 || alpha != 1) { - glPixelTransferf(GL_ALPHA_SCALE, (GLfloat)alpha); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - } - ASSERT(image->stride % pix_bytes == 0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, image->stride / pix_bytes); - glDrawPixels(src->width, src->height, GL_BGRA, GL_UNSIGNED_BYTE, pixels); - - if (image->format == GLC_IMAGE_ARGB32 || alpha != 1) { - glDisable(GL_BLEND); - } - - if (ctx->pat) { - glEnable(GL_TEXTURE_2D); - } - GLC_ERROR_TEST_FLUSH; -} - -void glc_copy_pixels(GLCCtx glc, int x_dest, int y_dest, int x_src, int y_src, int width, - int height) -{ - InternaCtx *ctx = (InternaCtx *)glc; - int recreate = 0; - - ASSERT(ctx); -#ifdef USE_COPY_PIXELS - start_draw(ctx); - if (ctx->pat) { - glDisable(GL_TEXTURE_2D); - } - set_raster_pos(ctx, x_dest, y_dest + height); - glPixelZoom(1, 1); - glCopyPixels(x_src, ctx->height - (y_src + height), width, height, GL_COLOR); - if (ctx->pat) { - glEnable(GL_TEXTURE_2D); - } -#else - int width2 = gl_get_to_power_two(width); - int height2 = gl_get_to_power_two(height); - - start_draw(ctx); - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, 0); - - if (width2 > ctx->private_tex_width) { - ctx->private_tex_width = width2; - recreate = 1; - } - if (height2 > ctx->private_tex_height) { - ctx->private_tex_height = height2; - recreate = 1; - } - if (recreate) { - glDeleteTextures(1, &ctx->private_tex); - glGenTextures(1, &ctx->private_tex); - glBindTexture(GL_TEXTURE_2D, ctx->private_tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - ctx->private_tex_width = gl_get_to_power_two(width); - ctx->private_tex_height = gl_get_to_power_two(height); - glTexImage2D(GL_TEXTURE_2D, 0, 4, ctx->private_tex_width, - ctx->private_tex_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); - } - ASSERT(ctx->private_tex); - glBindTexture(GL_TEXTURE_2D, ctx->private_tex); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x_src, ctx->height - (y_src + height), - width2, height2, 0); - - GLfloat s_gen_params[] = { (GLfloat)1.0 / width2, 0, 0, 0 }; - GLfloat t_gen_params[] = { 0, (GLfloat)1.0 / height2, 0, 0 }; - glTexGenfv(GL_S, GL_OBJECT_PLANE, s_gen_params); - glTexGenfv(GL_T, GL_OBJECT_PLANE, t_gen_params); - - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glTranslatef((float)-x_dest / width2, (float)-Y(y_dest + height) / height2, 0); - - glRecti(x_dest, Y(y_dest), x_dest + width, Y(y_dest + height)); - glFlush(); - if (!ctx->pat) { - glDisable(GL_TEXTURE_2D); - } else { - set_pat(ctx, ctx->pat); - } -#endif - GLC_ERROR_TEST_FLUSH; -} - -void glc_read_pixels(GLCCtx glc, int x, int y, GLCImage *image) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx && image); - ASSERT(image->format == GLC_IMAGE_RGB32); //for now - ASSERT((image->stride % 4) == 0); //for now - glPixelStorei(GL_PACK_ROW_LENGTH, image->stride / 4); - glReadPixels(x, ctx->height - (y + image->height), image->width, image->height, - GL_BGRA, GL_UNSIGNED_BYTE, image->pixels); -} - -void glc_clear(GLCCtx glc) -{ - InternaCtx *ctx = (InternaCtx *)glc; - - ASSERT(ctx); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClear(GL_COLOR_BUFFER_BIT); -} - -void glc_flush(GLCCtx glc) -{ - glFlush(); - - GLC_ERROR_TEST_FLUSH; -} - -static void tessellation_combine(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], - GLdouble **data_out, void *usr_data) -{ - TassVertex *vertex; - - vertex = alloc_tess_vertex((InternaCtx *)usr_data); - vertex->point.x = coords[0]; - vertex->point.y = coords[1]; - //vertex->point.z = coords[2]; - *data_out = (GLdouble *)&vertex->point; -} - -static void tessellation_error(GLenum errorCode) -{ - printf("%s: %s\n", __FUNCTION__, gluErrorString(errorCode)); -} - -#ifdef WIN32 -#define TESS_CALL_BACK_TYPE void(CALLBACK *)() -#else -#define TESS_CALL_BACK_TYPE void(*)() -#endif - -static int init(InternaCtx *ctx, int width, int height) -{ -#ifdef WIN32 - if (!(ctx->glBlendEquation = (PFNGLBLENDEQUATIONPROC)wglGetProcAddress("glBlendEquation"))) { - return FALSE; - } -#endif - ctx->width = width; - ctx->height = height; - ctx->line_width = 1; - - glClearColor(0, 0, 0, 0); - glClearStencil(0); - - if (!(ctx->tesselator = gluNewTess())) { - return FALSE; - } - - glGenTextures(1, &ctx->private_tex); - glBindTexture(GL_TEXTURE_2D, ctx->private_tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, 4, gl_get_to_power_two(width), - gl_get_to_power_two(height), 0, - GL_BGRA, GL_UNSIGNED_BYTE, NULL); - ctx->private_tex_width = gl_get_to_power_two(width); - ctx->private_tex_height = gl_get_to_power_two(height); - glBindTexture(GL_TEXTURE_2D, 0); - - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, 0, height, -1, 1); - - gluTessProperty(ctx->tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); - gluTessCallback(ctx->tesselator, GLU_BEGIN, (TESS_CALL_BACK_TYPE)glBegin); - gluTessCallback(ctx->tesselator, GLU_VERTEX, (TESS_CALL_BACK_TYPE)glVertex3dv); - gluTessCallback(ctx->tesselator, GLU_END, (TESS_CALL_BACK_TYPE)glEnd); - gluTessCallback(ctx->tesselator, GLU_TESS_COMBINE_DATA, - (TESS_CALL_BACK_TYPE)tessellation_combine); - gluTessCallback(ctx->tesselator, GLU_TESS_ERROR, (TESS_CALL_BACK_TYPE)tessellation_error); - - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0, (GLfloat)height, 0); - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &ctx->max_texture_size); - - glPixelStorei(GL_PACK_ALIGNMENT, 1); - - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); - glPixelTransferf(GL_ALPHA_BIAS, 0); -#ifdef WIN32 - ctx->glBlendEquation(GL_FUNC_ADD); -#else - glBlendEquation(GL_FUNC_ADD); -#endif - - glStencilMask(0xff); - glClear(GL_STENCIL_BUFFER_BIT); - - glClear(GL_COLOR_BUFFER_BIT); - - return TRUE; -} - -GLCCtx glc_create(int width, int height) -{ - InternaCtx *ctx; - - ASSERT(sizeof(PathPoint) == sizeof(Vertex)); - - ctx = spice_new0(InternaCtx, 1); - if (!init(ctx, width, height)) { - free(ctx); - return NULL; - } - return ctx; -} - -/* - * In glx video mode change the textures will be destroyed, therefore - * if we will try to glDeleteTextures() them we might get seagfault. - * (this why we use the textures_lost parameter) - */ -void glc_destroy(GLCCtx glc, int textures_lost) -{ - InternaCtx *ctx; - - if (!(ctx = (InternaCtx *)glc)) { - return; - } - - if (!textures_lost) { - unref_pat(ctx->pat); - ctx->pat = NULL; - if (ctx->private_tex) { - glDeleteTextures(1, &ctx->private_tex); - } - } - - free_tass_vertex_bufs(ctx); - free(ctx->line_dash.dashes); - free(ctx); - GLC_ERROR_TEST_FINISH; -} - -/* - todo: - 1. test double vs float in gl calls - 2. int vs flat raster position - 3. pixels stride vs bytes stride - 4. improve non power of two. - glGetString(GL_EXTENSIONS); - ARB_texture_non_power_of_two - ARB_texture_rectangle - GL_TEXTURE_RECTANGLE_ARB - 5. scale - 6. origin - 7. fonts - 8. support more image formats - 9. use GLCImage in mask ops? -*/ diff --git a/common/glc.h b/common/glc.h deleted file mode 100644 index d77f003f..00000000 --- a/common/glc.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef _H_GL_CANVASE -#define _H_GL_CANVASE - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void * GLCCtx; -typedef void * GLCPattern; -typedef void * GLCPath; - -typedef struct GLCRect { - double x; - double y; - double width; - double height; -} GLCRect; - -typedef struct GLCRecti { - int x; - int y; - int width; - int height; -} GLCRecti; - -typedef enum { - GLC_IMAGE_RGB32, - GLC_IMAGE_ARGB32, -} GLCImageFormat; - -typedef struct GLCPImage { - GLCImageFormat format; - int width; - int height; - int stride; - uint8_t *pixels; - uint32_t *pallet; -} GLCImage; - -GLCPattern glc_pattern_create(GLCCtx glc, int x_orign, int y_orign, const GLCImage *image); -void glc_pattern_set(GLCPattern pattern, int x_orign, int y_orign, const GLCImage *image); -void glc_pattern_destroy(GLCPattern pattern); - -void glc_path_move_to(GLCPath path, double x, double y); -void glc_path_line_to(GLCPath path, double x, double y); -void glc_path_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y, - double p3_x, double p3_y); -void glc_path_rel_move_to(GLCPath path, double x, double y); -void glc_path_rel_line_to(GLCPath path, double x, double y); -void glc_path_rel_curve_to(GLCPath path, double p1_x, double p1_y, double p2_x, double p2_y, - double p3_x, double p3_y); -void glc_path_close(GLCPath path); - -void glc_path_cleare(GLCPath); -GLCPath glc_path_create(GLCCtx glc); -void glc_path_destroy(GLCPath path); - -void glc_set_rgb(GLCCtx glc, double red, double green, double blue); -void glc_set_rgba(GLCCtx glc, double red, double green, double blue, double alpha); -void glc_set_pattern(GLCCtx glc, GLCPattern pattern); - -typedef enum { - GLC_OP_CLEAR = 0x1500, - GLC_OP_SET = 0x150F, - GLC_OP_COPY = 0x1503, - GLC_OP_COPY_INVERTED = 0x150C, - GLC_OP_NOOP = 0x1505, - GLC_OP_INVERT = 0x150A, - GLC_OP_AND = 0x1501, - GLC_OP_NAND = 0x150E, - GLC_OP_OR = 0x1507, - GLC_OP_NOR = 0x1508, - GLC_OP_XOR = 0x1506, - GLC_OP_EQUIV = 0x1509, - GLC_OP_AND_REVERSE = 0x1502, - GLC_OP_AND_INVERTED = 0x1504, - GLC_OP_OR_REVERSE = 0x150B, - GLC_OP_OR_INVERTED = 0x150D, -} GLCOp; - -void glc_set_op(GLCCtx glc, GLCOp op); -void glc_set_alpha_factor(GLCCtx glc, double alpah); - -typedef enum { - GLC_FILL_MODE_WINDING_ODD, - GLC_FILL_MODE_WINDING_NONZERO, -} GLCFillMode; - -void glc_set_fill_mode(GLCCtx glc, GLCFillMode mode); -void glc_set_line_width(GLCCtx glc, double width); -void glc_set_line_end_cap(GLCCtx glc, int style); -void glc_set_line_join(GLCCtx glc, int style); -void glc_set_miter_limit(GLCCtx glc, int limit); -void glc_set_line_dash(GLCCtx glc, const double *dashes, int num_dashes, double offset); - -typedef enum { - GLC_MASK_A, - GLC_MASK_B, -} GLCMaskID; - -void glc_set_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, - int stride, const uint8_t *bitmap, GLCMaskID id); -void glc_mask_rects(GLCCtx glc, int num_rect, GLCRect *rects, GLCMaskID id); -void glc_clear_mask(GLCCtx glc, GLCMaskID id); - -typedef enum { - GLC_CLIP_OP_SET, - GLC_CLIP_OP_OR, - GLC_CLIP_OP_AND, - GLC_CLIP_OP_EXCLUDE, -} GLCClipOp; - -void glc_clip_rect(GLCCtx glc, const GLCRect *rect, GLCClipOp op); -void glc_clip_path(GLCCtx glc, GLCPath path, GLCClipOp op); -void glc_clip_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride, - const uint8_t *bitmap, GLCClipOp op); -void glc_clip_reset(GLCCtx glc); - -void glc_fill_rect(GLCCtx glc, const GLCRect *rect); -void glc_fill_path(GLCCtx glc, GLCPath path); -void _glc_fill_mask(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride, - const uint8_t *bitmap); -void glc_fill_alpha(GLCCtx glc, int x_dest, int y_dest, int width, int height, int stride, - const uint8_t *alpha_mask); - -void glc_stroke_rect(GLCCtx glc, const GLCRect *rect); -void glc_stroke_path(GLCCtx glc, GLCPath path); - -void glc_draw_image(GLCCtx glc, const GLCRecti *dest, const GLCRecti *src, const GLCImage *image, - int scale_mode, double alpha); - -void glc_copy_pixels(GLCCtx glc, int x_dest, int y_dest, int x_src, int y_src, int width, - int height); -void glc_read_pixels(GLCCtx glc, int x, int y, GLCImage *image); - -void glc_flush(GLCCtx glc); -void glc_clear(GLCCtx glc); -GLCCtx glc_create(int width, int height); -void glc_destroy(GLCCtx glc, int textures_lost); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/lines.c b/common/lines.c deleted file mode 100644 index 797d5d62..00000000 --- a/common/lines.c +++ /dev/null @@ -1,3613 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/*********************************************************** - -Copyright 1989, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <spice/macros.h> -#ifdef _XOPEN_SOURCE -#include <math.h> -#else -#define _XOPEN_SOURCE /* to get prototype for hypot on some systems */ -#include <math.h> -#undef _XOPEN_SOURCE -#endif -#include "lines.h" -#include "mem.h" - -#define xalloc(i) spice_malloc(i) -#define xrealloc(a,b) spice_realloc(a,b) -#define xfree(i) free(i) - -typedef unsigned int CARD32; -typedef int Boolean; -typedef pixman_rectangle32_t xRectangle; -typedef SpicePoint DDXPointRec; -typedef DDXPointRec *DDXPointPtr; -typedef struct lineGC *GCPtr; - -/* largest positive value that can fit into a component of a point. - * Assumes that the point structure is {type x, y;} where type is - * a signed type. - */ -#define MAX_COORDINATE 2147483647 -#define MIN_COORDINATE -2147483647 - -#define miZeroLine spice_canvas_zero_line -#define miZeroDashLine spice_canvas_zero_dash_line -#define miWideDash spice_canvas_wide_dash_line -#define miWideLine spice_canvas_wide_line - -static INLINE int ICEIL (double x) -{ - int _cTmp = (int)x; - return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp + 1; -} - -typedef struct { - int count; /* number of spans */ - DDXPointPtr points; /* pointer to list of start points */ - int *widths; /* pointer to list of widths */ -} Spans; - -typedef struct { - int size; /* Total number of *Spans allocated */ - int count; /* Number of *Spans actually in group */ - Spans *group; /* List of Spans */ - int ymin, ymax; /* Min, max y values encountered */ -} SpanGroup; - -/* Initialize SpanGroup. MUST BE DONE before use. */ -static void miInitSpanGroup (SpanGroup * /*spanGroup */ - ); - -/* Add a Spans to a SpanGroup. The spans MUST BE in y-sorted order */ -static void miAppendSpans (SpanGroup * /*spanGroup */ , - SpanGroup * /*otherGroup */ , - Spans * /*spans */ - ); - -/* Paint a span group, insuring that each pixel is painted at most once */ -static void miFillUniqueSpanGroup (GCPtr /*pGC */ , - SpanGroup * /*spanGroup */ , - Boolean /* foreground */ - ); - -/* Free up data in a span group. MUST BE DONE or you'll suffer memory leaks */ -static void miFreeSpanGroup (SpanGroup * /*spanGroup */ - ); - -/* Rops which must use span groups */ -#define miSpansCarefulRop(rop) (((rop) & 0xc) == 0x8 || ((rop) & 0x3) == 0x2) -#define miSpansEasyRop(rop) (!miSpansCarefulRop(rop)) - -/* - * Public definitions used for configuring basic pixelization aspects - * of the sample implementation line-drawing routines provided in - * {mfb,mi,cfb*} at run-time. - */ - -#define XDECREASING 4 -#define YDECREASING 2 -#define YMAJOR 1 - -#define OCTANT1 (1 << (YDECREASING)) -#define OCTANT2 (1 << (YDECREASING|YMAJOR)) -#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR)) -#define OCTANT4 (1 << (XDECREASING|YDECREASING)) -#define OCTANT5 (1 << (XDECREASING)) -#define OCTANT6 (1 << (XDECREASING|YMAJOR)) -#define OCTANT7 (1 << (YMAJOR)) -#define OCTANT8 (1 << (0)) - -#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8) - -#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5) - -/* - * Devices can configure the rendering of routines in mi, mfb, and cfb* - * by specifying a thin line bias to be applied to a particular screen - * using the following function. The bias parameter is an OR'ing of - * the appropriate OCTANT constants defined above to indicate which - * octants to bias a line to prefer an axial step when the Bresenham - * error term is exactly zero. The octants are mapped as follows: - * - * \ | / - * \ 3 | 2 / - * \ | / - * 4 \ | / 1 - * \|/ - * ----------- - * /|\ - * 5 / | \ 8 - * / | \ - * / 6 | 7 \ - * / | \ - * - * For more information, see "Ambiguities in Incremental Line Rastering," - * Jack E. Bresenham, IEEE CG&A, May 1987. - */ - -/* - * Private definitions needed for drawing thin (zero width) lines - * Used by the mi, mfb, and all cfb* components. - */ - -#define X_AXIS 0 -#define Y_AXIS 1 - -#define OUT_LEFT 0x08 -#define OUT_RIGHT 0x04 -#define OUT_ABOVE 0x02 -#define OUT_BELOW 0x01 - -#define OUTCODES(_result, _x, _y, _pbox) \ - if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \ - else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \ - if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \ - else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW; - -#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \ -{\ - if (x < xmin) outcode |= OUT_LEFT;\ - if (x > xmax) outcode |= OUT_RIGHT;\ - if (y < ymin) outcode |= OUT_ABOVE;\ - if (y > ymax) outcode |= OUT_BELOW;\ -} - -#define SWAPINT(i, j) \ -{ int _t = i; i = j; j = _t; } - -#define SWAPPT(i, j) \ -{ DDXPointRec _t; _t = i; i = j; j = _t; } - -#define SWAPINT_PAIR(x1, y1, x2, y2)\ -{ int t = x1; x1 = x2; x2 = t;\ - t = y1; y1 = y2; y2 = t;\ -} - -#define miGetZeroLineBias(_pScreen) (DEFAULTZEROLINEBIAS) - -#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \ - (_octant) = 0; \ - (_sx) = (_SX); \ - if (((_adx) = (_x2) - (_x1)) < 0) { \ - (_adx) = -(_adx); \ - (_sx = -(_sx)); \ - (_octant) |= XDECREASING; \ - } \ - (_sy) = (_SY); \ - if (((_ady) = (_y2) - (_y1)) < 0) { \ - (_ady) = -(_ady); \ - (_sy = -(_sy)); \ - (_octant) |= YDECREASING; \ - } - -#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR) - -#define FIXUP_ERROR(_e, _octant, _bias) \ - (_e) -= (((_bias) >> (_octant)) & 1) - -#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR)) -#define IsYMajorOctant(_octant) ((_octant) & YMAJOR) -#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING) -#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING) - -static int miZeroClipLine (int /*xmin */ , - int /*ymin */ , - int /*xmax */ , - int /*ymax */ , - int * /*new_x1 */ , - int * /*new_y1 */ , - int * /*new_x2 */ , - int * /*new_y2 */ , - unsigned int /*adx */ , - unsigned int /*ady */ , - int * /*pt1_clipped */ , - int * /*pt2_clipped */ , - int /*octant */ , - unsigned int /*bias */ , - int /*oc1 */ , - int /*oc2 */ - ); - -/* - * interface data to span-merging polygon filler - */ - -typedef struct _SpanData { - SpanGroup fgGroup, bgGroup; -} SpanDataRec, *SpanDataPtr; - -#define AppendSpanGroup(pGC, foreground, spanPtr, spanData) { \ - SpanGroup *group, *othergroup = NULL; \ - if (foreground) \ - { \ - group = &spanData->fgGroup; \ - if (pGC->lineStyle == LineDoubleDash) \ - othergroup = &spanData->bgGroup; \ - } \ - else \ - { \ - group = &spanData->bgGroup; \ - othergroup = &spanData->fgGroup; \ - } \ - miAppendSpans (group, othergroup, spanPtr); \ -} - -/* - * Polygon edge description for integer wide-line routines - */ - -typedef struct _PolyEdge { - int height; /* number of scanlines to process */ - int x; /* starting x coordinate */ - int stepx; /* fixed integral dx */ - int signdx; /* variable dx sign */ - int e; /* initial error term */ - int dy; - int dx; -} PolyEdgeRec, *PolyEdgePtr; - -#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */ - -/* - * types for general polygon routines - */ - -typedef struct _PolyVertex { - double x, y; -} PolyVertexRec, *PolyVertexPtr; - -typedef struct _PolySlope { - int dx, dy; - double k; /* x0 * dy - y0 * dx */ -} PolySlopeRec, *PolySlopePtr; - -/* - * Line face description for caps/joins - */ - -typedef struct _LineFace { - double xa, ya; - int dx, dy; - int x, y; - double k; -} LineFaceRec, *LineFacePtr; - -/* - * macros for polygon fillers - */ - -#define MIPOLYRELOADLEFT if (!left_height && left_count) { \ - left_height = left->height; \ - left_x = left->x; \ - left_stepx = left->stepx; \ - left_signdx = left->signdx; \ - left_e = left->e; \ - left_dy = left->dy; \ - left_dx = left->dx; \ - --left_count; \ - ++left; \ - } - -#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \ - right_height = right->height; \ - right_x = right->x; \ - right_stepx = right->stepx; \ - right_signdx = right->signdx; \ - right_e = right->e; \ - right_dy = right->dy; \ - right_dx = right->dx; \ - --right_count; \ - ++right; \ - } - -#define MIPOLYSTEPLEFT left_x += left_stepx; \ - left_e += left_dx; \ - if (left_e > 0) \ - { \ - left_x += left_signdx; \ - left_e -= left_dy; \ - } - -#define MIPOLYSTEPRIGHT right_x += right_stepx; \ - right_e += right_dx; \ - if (right_e > 0) \ - { \ - right_x += right_signdx; \ - right_e -= right_dy; \ - } - -static void miRoundJoinClip (LineFacePtr /*pLeft */ , - LineFacePtr /*pRight */ , - PolyEdgePtr /*edge1 */ , - PolyEdgePtr /*edge2 */ , - int * /*y1 */ , - int * /*y2 */ , - Boolean * /*left1 */ , - Boolean * /*left2 */ - ); - -static int miRoundCapClip (LineFacePtr /*face */ , - Boolean /*isInt */ , - PolyEdgePtr /*edge */ , - Boolean * /*leftEdge */ - ); - -static int miPolyBuildEdge (double x0, double y0, double k, int dx, int dy, - int xi, int yi, int left, PolyEdgePtr edge); -static int miPolyBuildPoly (PolyVertexPtr vertices, PolySlopePtr slopes, - int count, int xi, int yi, PolyEdgePtr left, - PolyEdgePtr right, int *pnleft, int *pnright, int *h); - - -static void -miStepDash (int dist, /* distance to step */ - int *pDashIndex, /* current dash */ - unsigned char *pDash, /* dash list */ - int numInDashList, /* total length of dash list */ - int *pDashOffset /* offset into current dash */ - ) -{ - int dashIndex, dashOffset; - int totallen; - int i; - - dashIndex = *pDashIndex; - dashOffset = *pDashOffset; - if (dist < pDash[dashIndex] - dashOffset) { - *pDashOffset = dashOffset + dist; - return; - } - dist -= pDash[dashIndex] - dashOffset; - if (++dashIndex == numInDashList) - dashIndex = 0; - totallen = 0; - for (i = 0; i < numInDashList; i++) - totallen += pDash[i]; - if (totallen <= dist) - dist = dist % totallen; - while (dist >= pDash[dashIndex]) { - dist -= pDash[dashIndex]; - if (++dashIndex == numInDashList) - dashIndex = 0; - } - *pDashIndex = dashIndex; - *pDashOffset = dist; -} - -/* - -These routines maintain lists of Spans, in order to implement the -``touch-each-pixel-once'' rules of wide lines and arcs. - -Written by Joel McCormack, Summer 1989. - -*/ - - -static void -miInitSpanGroup (SpanGroup * spanGroup) -{ - spanGroup->size = 0; - spanGroup->count = 0; - spanGroup->group = NULL; - spanGroup->ymin = MAX_COORDINATE; - spanGroup->ymax = MIN_COORDINATE; -} /* InitSpanGroup */ - -#define YMIN(spans) (spans->points[0].y) -#define YMAX(spans) (spans->points[spans->count-1].y) - -static void -miSubtractSpans (SpanGroup * spanGroup, Spans * sub) -{ - int i, subCount, spansCount; - int ymin, ymax, xmin, xmax; - Spans *spans; - DDXPointPtr subPt, spansPt; - int *subWid, *spansWid; - int extra; - - ymin = YMIN (sub); - ymax = YMAX (sub); - spans = spanGroup->group; - for (i = spanGroup->count; i; i--, spans++) { - if (YMIN (spans) <= ymax && ymin <= YMAX (spans)) { - subCount = sub->count; - subPt = sub->points; - subWid = sub->widths; - spansCount = spans->count; - spansPt = spans->points; - spansWid = spans->widths; - extra = 0; - for (;;) { - while (spansCount && spansPt->y < subPt->y) { - spansPt++; - spansWid++; - spansCount--; - } - if (!spansCount) - break; - while (subCount && subPt->y < spansPt->y) { - subPt++; - subWid++; - subCount--; - } - if (!subCount) - break; - if (subPt->y == spansPt->y) { - xmin = subPt->x; - xmax = xmin + *subWid; - if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) { - ; - } else if (xmin <= spansPt->x) { - if (xmax >= spansPt->x + *spansWid) { - memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1)); - memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1)); - spansPt--; - spansWid--; - spans->count--; - extra++; - } else { - *spansWid = *spansWid - (xmax - spansPt->x); - spansPt->x = xmax; - } - } else { - if (xmax >= spansPt->x + *spansWid) { - *spansWid = xmin - spansPt->x; - } else { - if (!extra) { - DDXPointPtr newPt; - int *newwid; - -#define EXTRA 8 - newPt = xrealloc (spans->points, - (spans->count + - EXTRA) * sizeof (DDXPointRec)); - if (!newPt) - break; - spansPt = newPt + (spansPt - spans->points); - spans->points = newPt; - newwid = xrealloc (spans->widths, - (spans->count + EXTRA) * sizeof (int)); - if (!newwid) - break; - spansWid = newwid + (spansWid - spans->widths); - spans->widths = newwid; - extra = EXTRA; - } - memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount)); - memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount)); - spans->count++; - extra--; - *spansWid = xmin - spansPt->x; - spansWid++; - spansPt++; - *spansWid = *spansWid - (xmax - spansPt->x); - spansPt->x = xmax; - } - } - } - spansPt++; - spansWid++; - spansCount--; - } - } - } -} - -static void -miAppendSpans (SpanGroup * spanGroup, SpanGroup * otherGroup, Spans * spans) -{ - int ymin, ymax; - int spansCount; - - spansCount = spans->count; - if (spansCount > 0) { - if (spanGroup->size == spanGroup->count) { - spanGroup->size = (spanGroup->size + 8) * 2; - spanGroup->group = - xrealloc (spanGroup->group, sizeof (Spans) * spanGroup->size); - } - - spanGroup->group[spanGroup->count] = *spans; - (spanGroup->count)++; - ymin = spans->points[0].y; - if (ymin < spanGroup->ymin) - spanGroup->ymin = ymin; - ymax = spans->points[spansCount - 1].y; - if (ymax > spanGroup->ymax) - spanGroup->ymax = ymax; - if (otherGroup && otherGroup->ymin < ymax && ymin < otherGroup->ymax) { - miSubtractSpans (otherGroup, spans); - } - } else { - xfree (spans->points); - xfree (spans->widths); - } -} /* AppendSpans */ - -static void -miFreeSpanGroup (SpanGroup * spanGroup) -{ - xfree (spanGroup->group); -} - -static void -QuickSortSpansX (DDXPointRec points[], int widths[], int numSpans) -{ - int x; - int i, j, m; - DDXPointPtr r; - -/* Always called with numSpans > 1 */ -/* Sorts only by x, as all y should be the same */ - -#define ExchangeSpans(a, b) \ -{ \ - DDXPointRec tpt; \ - int tw; \ - \ - tpt = points[a]; points[a] = points[b]; points[b] = tpt; \ - tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ -} - - do { - if (numSpans < 9) { - /* Do insertion sort */ - int xprev; - - xprev = points[0].x; - i = 1; - do { /* while i != numSpans */ - x = points[i].x; - if (xprev > x) { - /* points[i] is out of order. Move into proper location. */ - DDXPointRec tpt; - int tw, k; - - for (j = 0; x >= points[j].x; j++) { - } - tpt = points[i]; - tw = widths[i]; - for (k = i; k != j; k--) { - points[k] = points[k - 1]; - widths[k] = widths[k - 1]; - } - points[j] = tpt; - widths[j] = tw; - x = points[i].x; - } /* if out of order */ - xprev = x; - i++; - } while (i != numSpans); - return; - } - - /* Choose partition element, stick in location 0 */ - m = numSpans / 2; - if (points[m].x > points[0].x) - ExchangeSpans (m, 0); - if (points[m].x > points[numSpans - 1].x) - ExchangeSpans (m, numSpans - 1); - if (points[m].x > points[0].x) - ExchangeSpans (m, 0); - x = points[0].x; - - /* Partition array */ - i = 0; - j = numSpans; - do { - r = &(points[i]); - do { - r++; - i++; - } while (i != numSpans && r->x < x); - r = &(points[j]); - do { - r--; - j--; - } while (x < r->x); - if (i < j) - ExchangeSpans (i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeSpans (0, j); - - /* Recurse */ - if (numSpans - j - 1 > 1) - QuickSortSpansX (&points[j + 1], &widths[j + 1], numSpans - j - 1); - numSpans = j; - } while (numSpans > 1); -} /* QuickSortSpans */ - - -static int -UniquifySpansX (Spans * spans, DDXPointRec * newPoints, int *newWidths) -{ - int newx1, newx2, oldpt, i, y; - DDXPointRec *oldPoints; - int *oldWidths; - int *startNewWidths; - -/* Always called with numSpans > 1 */ -/* Uniquify the spans, and stash them into newPoints and newWidths. Return the - number of unique spans. */ - - - startNewWidths = newWidths; - - oldPoints = spans->points; - oldWidths = spans->widths; - - y = oldPoints->y; - newx1 = oldPoints->x; - newx2 = newx1 + *oldWidths; - - for (i = spans->count - 1; i != 0; i--) { - oldPoints++; - oldWidths++; - oldpt = oldPoints->x; - if (oldpt > newx2) { - /* Write current span, start a new one */ - newPoints->x = newx1; - newPoints->y = y; - *newWidths = newx2 - newx1; - newPoints++; - newWidths++; - newx1 = oldpt; - newx2 = oldpt + *oldWidths; - } else { - /* extend current span, if old extends beyond new */ - oldpt = oldpt + *oldWidths; - if (oldpt > newx2) - newx2 = oldpt; - } - } /* for */ - - /* Write final span */ - newPoints->x = newx1; - *newWidths = newx2 - newx1; - newPoints->y = y; - - return (newWidths - startNewWidths) + 1; -} /* UniquifySpansX */ - -static void -miDisposeSpanGroup (SpanGroup * spanGroup) -{ - int i; - Spans *spans; - - for (i = 0; i < spanGroup->count; i++) { - spans = spanGroup->group + i; - xfree (spans->points); - xfree (spans->widths); - } -} - -static void -miFillUniqueSpanGroup (GCPtr pGC, SpanGroup * spanGroup, Boolean foreground) -{ - int i; - Spans *spans; - Spans *yspans; - int *ysizes; - int ymin, ylength; - - /* Outgoing spans for one big call to FillSpans */ - DDXPointPtr points; - int *widths; - int count; - - if (spanGroup->count == 0) - return; - - if (spanGroup->count == 1) { - /* Already should be sorted, unique */ - spans = spanGroup->group; - (*pGC->ops->FillSpans) - (pGC, spans->count, spans->points, spans->widths, TRUE, foreground); - xfree (spans->points); - xfree (spans->widths); - } else { - /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */ - /* This seems to be the fastest thing to do. I've tried sorting on - both x and y at the same time rather than creating into all those - y buckets, but it was somewhat slower. */ - - ymin = spanGroup->ymin; - ylength = spanGroup->ymax - ymin + 1; - - /* Allocate Spans for y buckets */ - yspans = (Spans*)xalloc (ylength * sizeof (Spans)); - ysizes = (int *)xalloc (ylength * sizeof (int)); - - if (!yspans || !ysizes) { - xfree (yspans); - xfree (ysizes); - miDisposeSpanGroup (spanGroup); - return; - } - - for (i = 0; i != ylength; i++) { - ysizes[i] = 0; - yspans[i].count = 0; - yspans[i].points = NULL; - yspans[i].widths = NULL; - } - - /* Go through every single span and put it into the correct bucket */ - count = 0; - for (i = 0, spans = spanGroup->group; i != spanGroup->count; i++, spans++) { - int index; - int j; - - for (j = 0, points = spans->points, widths = spans->widths; - j != spans->count; j++, points++, widths++) { - index = points->y - ymin; - if (index >= 0 && index < ylength) { - Spans *newspans = &(yspans[index]); - if (newspans->count == ysizes[index]) { - DDXPointPtr newpoints; - int *newwidths; - ysizes[index] = (ysizes[index] + 8) * 2; - newpoints = xrealloc (newspans->points, - ysizes[index] * sizeof (DDXPointRec)); - newwidths = xrealloc (newspans->widths, - ysizes[index] * sizeof (int)); - if (!newpoints || !newwidths) { - int i; - - for (i = 0; i < ylength; i++) { - xfree (yspans[i].points); - xfree (yspans[i].widths); - } - xfree (yspans); - xfree (ysizes); - miDisposeSpanGroup (spanGroup); - return; - } - newspans->points = newpoints; - newspans->widths = newwidths; - } - newspans->points[newspans->count] = *points; - newspans->widths[newspans->count] = *widths; - (newspans->count)++; - } /* if y value of span in range */ - } /* for j through spans */ - count += spans->count; - xfree (spans->points); - spans->points = NULL; - xfree (spans->widths); - spans->widths = NULL; - } /* for i thorough Spans */ - - /* Now sort by x and uniquify each bucket into the final array */ - points = (DDXPointRec*)xalloc (count * sizeof (DDXPointRec)); - widths = (int *)xalloc (count * sizeof (int)); - if (!points || !widths) { - int i; - - for (i = 0; i < ylength; i++) { - xfree (yspans[i].points); - xfree (yspans[i].widths); - } - xfree (yspans); - xfree (ysizes); - xfree (points); - xfree (widths); - return; - } - count = 0; - for (i = 0; i != ylength; i++) { - int ycount = yspans[i].count; - if (ycount > 0) { - if (ycount > 1) { - QuickSortSpansX (yspans[i].points, yspans[i].widths, ycount); - count += UniquifySpansX (&(yspans[i]), &(points[count]), &(widths[count])); - } else { - points[count] = yspans[i].points[0]; - widths[count] = yspans[i].widths[0]; - count++; - } - xfree (yspans[i].points); - xfree (yspans[i].widths); - } - } - - (*pGC->ops->FillSpans) (pGC, count, points, widths, TRUE, foreground); - xfree (points); - xfree (widths); - xfree (yspans); - xfree (ysizes); /* use (DE)xalloc for these? */ - } - - spanGroup->count = 0; - spanGroup->ymin = MAX_COORDINATE; - spanGroup->ymax = MIN_COORDINATE; -} - -/* - -The bresenham error equation used in the mi/mfb/cfb line routines is: - - e = error - dx = difference in raw X coordinates - dy = difference in raw Y coordinates - M = # of steps in X direction - N = # of steps in Y direction - B = 0 to prefer diagonal steps in a given octant, - 1 to prefer axial steps in a given octant - - For X major lines: - e = 2Mdy - 2Ndx - dx - B - -2dx <= e < 0 - - For Y major lines: - e = 2Ndx - 2Mdy - dy - B - -2dy <= e < 0 - -At the start of the line, we have taken 0 X steps and 0 Y steps, -so M = 0 and N = 0: - - X major e = 2Mdy - 2Ndx - dx - B - = -dx - B - - Y major e = 2Ndx - 2Mdy - dy - B - = -dy - B - -At the end of the line, we have taken dx X steps and dy Y steps, -so M = dx and N = dy: - - X major e = 2Mdy - 2Ndx - dx - B - = 2dxdy - 2dydx - dx - B - = -dx - B - Y major e = 2Ndx - 2Mdy - dy - B - = 2dydx - 2dxdy - dy - B - = -dy - B - -Thus, the error term is the same at the start and end of the line. - -Let us consider clipping an X coordinate. There are 4 cases which -represent the two independent cases of clipping the start vs. the -end of the line and an X major vs. a Y major line. In any of these -cases, we know the number of X steps (M) and we wish to find the -number of Y steps (N). Thus, we will solve our error term equation. -If we are clipping the start of the line, we will find the smallest -N that satisfies our error term inequality. If we are clipping the -end of the line, we will find the largest number of Y steps that -satisfies the inequality. In that case, since we are representing -the Y steps as (dy - N), we will actually want to solve for the -smallest N in that equation. - -Case 1: X major, starting X coordinate moved by M steps - - -2dx <= 2Mdy - 2Ndx - dx - B < 0 - 2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B - 2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx - N <= (2Mdy + dx - B) / 2dx - -Since we are trying to find the smallest N that satisfies these -equations, we should use the > inequality to find the smallest: - - N = floor((2Mdy - dx - B) / 2dx) + 1 - = floor((2Mdy - dx - B + 2dx) / 2dx) - = floor((2Mdy + dx - B) / 2dx) - -Case 1b: X major, ending X coordinate moved to M steps - -Same derivations as Case 1, but we want the largest N that satisfies -the equations, so we use the <= inequality: - - N = floor((2Mdy + dx - B) / 2dx) - -Case 2: X major, ending X coordinate moved by M steps - - -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 - -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 - -2dx <= 2Ndx - 2Mdy - dx - B < 0 - 2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B - 2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx - N >= (2Mdy - dx + B) / 2dx - -Since we are trying to find the highest number of Y steps that -satisfies these equations, we need to find the smallest N, so -we should use the >= inequality to find the smallest: - - N = ceiling((2Mdy - dx + B) / 2dx) - = floor((2Mdy - dx + B + 2dx - 1) / 2dx) - = floor((2Mdy + dx + B - 1) / 2dx) - -Case 2b: X major, starting X coordinate moved to M steps from end - -Same derivations as Case 2, but we want the smallest number of Y -steps, so we want the highest N, so we use the < inequality: - - N = ceiling((2Mdy + dx + B) / 2dx) - 1 - = floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1 - = floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx) - = floor((2Mdy + dx + B - 1) / 2dx) - -Case 3: Y major, starting X coordinate moved by M steps - - -2dy <= 2Ndx - 2Mdy - dy - B < 0 - 2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B - 2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx - N >= (2Mdy - dy + B) / 2dx - -Since we are trying to find the smallest N that satisfies these -equations, we should use the >= inequality to find the smallest: - - N = ceiling((2Mdy - dy + B) / 2dx) - = floor((2Mdy - dy + B + 2dx - 1) / 2dx) - = floor((2Mdy - dy + B - 1) / 2dx) + 1 - -Case 3b: Y major, ending X coordinate moved to M steps - -Same derivations as Case 3, but we want the largest N that satisfies -the equations, so we use the < inequality: - - N = ceiling((2Mdy + dy + B) / 2dx) - 1 - = floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1 - = floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx) - = floor((2Mdy + dy + B - 1) / 2dx) - -Case 4: Y major, ending X coordinate moved by M steps - - -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 - -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 - -2dy <= 2Mdy - 2Ndx - dy - B < 0 - 2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B - 2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx - N <= (2Mdy + dy - B) / 2dx - -Since we are trying to find the highest number of Y steps that -satisfies these equations, we need to find the smallest N, so -we should use the > inequality to find the smallest: - - N = floor((2Mdy - dy - B) / 2dx) + 1 - -Case 4b: Y major, starting X coordinate moved to M steps from end - -Same analysis as Case 4, but we want the smallest number of Y steps -which means the largest N, so we use the <= inequality: - - N = floor((2Mdy + dy - B) / 2dx) - -Now let's try the Y coordinates, we have the same 4 cases. - -Case 5: X major, starting Y coordinate moved by N steps - - -2dx <= 2Mdy - 2Ndx - dx - B < 0 - 2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B - 2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy - M >= (2Ndx - dx + B) / 2dy - -Since we are trying to find the smallest M, we use the >= inequality: - - M = ceiling((2Ndx - dx + B) / 2dy) - = floor((2Ndx - dx + B + 2dy - 1) / 2dy) - = floor((2Ndx - dx + B - 1) / 2dy) + 1 - -Case 5b: X major, ending Y coordinate moved to N steps - -Same derivations as Case 5, but we want the largest M that satisfies -the equations, so we use the < inequality: - - M = ceiling((2Ndx + dx + B) / 2dy) - 1 - = floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1 - = floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy) - = floor((2Ndx + dx + B - 1) / 2dy) - -Case 6: X major, ending Y coordinate moved by N steps - - -2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0 - -2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0 - -2dx <= 2Ndx - 2Mdy - dx - B < 0 - 2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B - 2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy - M <= (2Ndx + dx - B) / 2dy - -Largest # of X steps means smallest M, so use the > inequality: - - M = floor((2Ndx - dx - B) / 2dy) + 1 - -Case 6b: X major, starting Y coordinate moved to N steps from end - -Same derivations as Case 6, but we want the smallest # of X steps -which means the largest M, so use the <= inequality: - - M = floor((2Ndx + dx - B) / 2dy) - -Case 7: Y major, starting Y coordinate moved by N steps - - -2dy <= 2Ndx - 2Mdy - dy - B < 0 - 2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B - 2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy - M <= (2Ndx + dy - B) / 2dy - -To find the smallest M, use the > inequality: - - M = floor((2Ndx - dy - B) / 2dy) + 1 - = floor((2Ndx - dy - B + 2dy) / 2dy) - = floor((2Ndx + dy - B) / 2dy) - -Case 7b: Y major, ending Y coordinate moved to N steps - -Same derivations as Case 7, but we want the largest M that satisfies -the equations, so use the <= inequality: - - M = floor((2Ndx + dy - B) / 2dy) - -Case 8: Y major, ending Y coordinate moved by N steps - - -2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0 - -2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0 - -2dy <= 2Mdy - 2Ndx - dy - B < 0 - 2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B - 2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy - M >= (2Ndx - dy + B) / 2dy - -To find the highest X steps, find the smallest M, use the >= inequality: - - M = ceiling((2Ndx - dy + B) / 2dy) - = floor((2Ndx - dy + B + 2dy - 1) / 2dy) - = floor((2Ndx + dy + B - 1) / 2dy) - -Case 8b: Y major, starting Y coordinate moved to N steps from the end - -Same derivations as Case 8, but we want to find the smallest # of X -steps which means the largest M, so we use the < inequality: - - M = ceiling((2Ndx + dy + B) / 2dy) - 1 - = floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1 - = floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy) - = floor((2Ndx + dy + B - 1) / 2dy) - -So, our equations are: - - 1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx) - 1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx) - 2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx) - 2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx) - - 3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1 - 3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx) - 4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1 - 4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx) - - 5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1 - 5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy) - 6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1 - 6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy) - - 7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy) - 7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy) - 8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy) - 8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy) - -We have the following constraints on all of the above terms: - - 0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine - 0 <= dx/dy <= 2^16 - 1 - 0 <= B <= 1 - -The floor in all of the above equations can be accomplished with a -simple C divide operation provided that both numerator and denominator -are positive. - -Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0 -and moving a Y coordinate implies dy != 0, we know that the denominators -are all > 0. - -For all lines, (-B) and (B-1) are both either 0 or -1, depending on the -bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1 -or > 0 to prove that the numerators are positive (or zero). - -For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the -constraints, the first four equations all have numerators >= 0. - -For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy -So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy -or (2Mdy + dy) > 0. So all of their numerators are >= 0. - -For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx) ->= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0. - -For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators -are > 0. - -To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This -is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1) - <= 2^16 * (2^16 - 1) + (2^16 - 1) - <= 2^32 - 2^16 + 2^16 - 1 - <= 2^32 - 1 -Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of -the numerator is therefore (2^32 - 1), which does not overflow an unsigned -32 bit variable. - -*/ - -/* Bit codes for the terms of the 16 clipping equations defined below. */ - -#define T_2NDX (1 << 0) -#define T_2MDY (0) /* implicit term */ -#define T_DXNOTY (1 << 1) -#define T_DYNOTX (0) /* implicit term */ -#define T_SUBDXORY (1 << 2) -#define T_ADDDX (T_DXNOTY) /* composite term */ -#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */ -#define T_ADDDY (T_DYNOTX) /* composite term */ -#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */ -#define T_BIASSUBONE (1 << 3) -#define T_SUBBIAS (0) /* implicit term */ -#define T_DIV2DX (1 << 4) -#define T_DIV2DY (0) /* implicit term */ -#define T_ADDONE (1 << 5) - -/* Bit masks defining the 16 equations used in miZeroClipLine. */ - -#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) -#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX) -#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) -#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX) - -#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE) -#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX) -#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE) -#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX) - -#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE) -#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY) -#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE) -#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY) - -#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) -#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY) -#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) -#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY) - -/* miZeroClipLine - * - * returns: 1 for partially clipped line - * -1 for completely clipped line - * - */ -static int -miZeroClipLine (int xmin, int ymin, int xmax, int ymax, - int *new_x1, int *new_y1, int *new_x2, int *new_y2, - unsigned int adx, unsigned int ady, - int *pt1_clipped, int *pt2_clipped, int octant, unsigned int bias, int oc1, int oc2) -{ - int swapped = 0; - int clipDone = 0; - CARD32 utmp = 0; - int clip1, clip2; - int x1, y1, x2, y2; - int x1_orig, y1_orig, x2_orig, y2_orig; - int xmajor; - int negslope = 0, anchorval = 0; - unsigned int eqn = 0; - - x1 = x1_orig = *new_x1; - y1 = y1_orig = *new_y1; - x2 = x2_orig = *new_x2; - y2 = y2_orig = *new_y2; - - clip1 = 0; - clip2 = 0; - - xmajor = IsXMajorOctant (octant); - bias = ((bias >> octant) & 1); - - while (1) { - if ((oc1 & oc2) != 0) { /* trivial reject */ - clipDone = -1; - clip1 = oc1; - clip2 = oc2; - break; - } else if ((oc1 | oc2) == 0) { /* trivial accept */ - clipDone = 1; - if (swapped) { - SWAPINT_PAIR (x1, y1, x2, y2); - SWAPINT (clip1, clip2); - } - break; - } else { /* have to clip */ - - /* only clip one point at a time */ - if (oc1 == 0) { - SWAPINT_PAIR (x1, y1, x2, y2); - SWAPINT_PAIR (x1_orig, y1_orig, x2_orig, y2_orig); - SWAPINT (oc1, oc2); - SWAPINT (clip1, clip2); - swapped = !swapped; - } - - clip1 |= oc1; - if (oc1 & OUT_LEFT) { - negslope = IsYDecreasingOctant (octant); - utmp = xmin - x1_orig; - if (utmp <= 32767) { /* clip based on near endpt */ - if (xmajor) - eqn = (swapped) ? EQN2 : EQN1; - else - eqn = (swapped) ? EQN4 : EQN3; - anchorval = y1_orig; - } else { /* clip based on far endpt */ - - utmp = x2_orig - xmin; - if (xmajor) - eqn = (swapped) ? EQN1B : EQN2B; - else - eqn = (swapped) ? EQN3B : EQN4B; - anchorval = y2_orig; - negslope = !negslope; - } - x1 = xmin; - } else if (oc1 & OUT_ABOVE) { - negslope = IsXDecreasingOctant (octant); - utmp = ymin - y1_orig; - if (utmp <= 32767) { /* clip based on near endpt */ - if (xmajor) - eqn = (swapped) ? EQN6 : EQN5; - else - eqn = (swapped) ? EQN8 : EQN7; - anchorval = x1_orig; - } else { /* clip based on far endpt */ - - utmp = y2_orig - ymin; - if (xmajor) - eqn = (swapped) ? EQN5B : EQN6B; - else - eqn = (swapped) ? EQN7B : EQN8B; - anchorval = x2_orig; - negslope = !negslope; - } - y1 = ymin; - } else if (oc1 & OUT_RIGHT) { - negslope = IsYDecreasingOctant (octant); - utmp = x1_orig - xmax; - if (utmp <= 32767) { /* clip based on near endpt */ - if (xmajor) - eqn = (swapped) ? EQN2 : EQN1; - else - eqn = (swapped) ? EQN4 : EQN3; - anchorval = y1_orig; - } else { /* clip based on far endpt */ - - /* - * Technically since the equations can handle - * utmp == 32768, this overflow code isn't - * needed since X11 protocol can't generate - * a line which goes more than 32768 pixels - * to the right of a clip rectangle. - */ - utmp = xmax - x2_orig; - if (xmajor) - eqn = (swapped) ? EQN1B : EQN2B; - else - eqn = (swapped) ? EQN3B : EQN4B; - anchorval = y2_orig; - negslope = !negslope; - } - x1 = xmax; - } else if (oc1 & OUT_BELOW) { - negslope = IsXDecreasingOctant (octant); - utmp = y1_orig - ymax; - if (utmp <= 32767) { /* clip based on near endpt */ - if (xmajor) - eqn = (swapped) ? EQN6 : EQN5; - else - eqn = (swapped) ? EQN8 : EQN7; - anchorval = x1_orig; - } else { /* clip based on far endpt */ - - /* - * Technically since the equations can handle - * utmp == 32768, this overflow code isn't - * needed since X11 protocol can't generate - * a line which goes more than 32768 pixels - * below the bottom of a clip rectangle. - */ - utmp = ymax - y2_orig; - if (xmajor) - eqn = (swapped) ? EQN5B : EQN6B; - else - eqn = (swapped) ? EQN7B : EQN8B; - anchorval = x2_orig; - negslope = !negslope; - } - y1 = ymax; - } - - if (swapped) - negslope = !negslope; - - utmp <<= 1; /* utmp = 2N or 2M */ - if (eqn & T_2NDX) - utmp = (utmp * adx); - else /* (eqn & T_2MDY) */ - utmp = (utmp * ady); - if (eqn & T_DXNOTY) - if (eqn & T_SUBDXORY) - utmp -= adx; - else - utmp += adx; - else /* (eqn & T_DYNOTX) */ if (eqn & T_SUBDXORY) - utmp -= ady; - else - utmp += ady; - if (eqn & T_BIASSUBONE) - utmp += bias - 1; - else /* (eqn & T_SUBBIAS) */ - utmp -= bias; - if (eqn & T_DIV2DX) - utmp /= (adx << 1); - else /* (eqn & T_DIV2DY) */ - utmp /= (ady << 1); - if (eqn & T_ADDONE) - utmp++; - - if (negslope) - utmp = (uint32_t)(-(int32_t)utmp); - - if (eqn & T_2NDX) /* We are calculating X steps */ - x1 = anchorval + utmp; - else /* else, Y steps */ - y1 = anchorval + utmp; - - oc1 = 0; - MIOUTCODES (oc1, x1, y1, xmin, ymin, xmax, ymax); - } - } - - *new_x1 = x1; - *new_y1 = y1; - *new_x2 = x2; - *new_y2 = y2; - - *pt1_clipped = clip1; - *pt2_clipped = clip2; - - return clipDone; -} - -/* Draw lineSolid, fillStyle-independent zero width lines. - * - * Must keep X and Y coordinates in "ints" at least until after they're - * translated and clipped to accomodate CoordModePrevious lines with very - * large coordinates. - * - * Draws the same pixels regardless of sign(dx) or sign(dy). - * - * Ken Whaley - * - */ - -#define MI_OUTPUT_POINT(xx, yy)\ -{\ - if ( !new_span && yy == current_y)\ - {\ - if (xx < spans->x)\ - spans->x = xx;\ - ++*widths;\ - }\ - else\ - {\ - ++Nspans;\ - ++spans;\ - ++widths;\ - spans->x = xx;\ - spans->y = yy;\ - *widths = 1;\ - current_y = yy;\ - new_span = FALSE;\ - }\ -} - -void -miZeroLine (GCPtr pGC, int mode, /* Origin or Previous */ - int npt, /* number of points */ - DDXPointPtr pptInit) -{ - int Nspans, current_y = 0; - DDXPointPtr ppt; - DDXPointPtr pspanInit, spans; - int *pwidthInit, *widths, list_len; - int xleft, ytop, xright, ybottom; - int new_x1, new_y1, new_x2, new_y2; - int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart; - int oc1, oc2; - int result; - int pt1_clipped, pt2_clipped = 0; - Boolean new_span; - int signdx, signdy; - int clipdx, clipdy; - int width, height; - int adx, ady; - int octant; - unsigned int bias = miGetZeroLineBias (screen); - int e, e1, e2, e3; /* Bresenham error terms */ - int length; /* length of lines == # of pixels on major axis */ - - xleft = 0; - ytop = 0; - xright = pGC->width - 1; - ybottom = pGC->height - 1; - - /* it doesn't matter whether we're in drawable or screen coordinates, - * FillSpans simply cannot take starting coordinates outside of the - * range of a DDXPointRec component. - */ - if (xright > MAX_COORDINATE) - xright = MAX_COORDINATE; - if (ybottom > MAX_COORDINATE) - ybottom = MAX_COORDINATE; - - /* since we're clipping to the drawable's boundaries & coordinate - * space boundaries, we're guaranteed that the larger of width/height - * is the longest span we'll need to output - */ - width = xright - xleft + 1; - height = ybottom - ytop + 1; - list_len = (height >= width) ? height : width; - pspanInit = (DDXPointRec *)xalloc (list_len * sizeof (DDXPointRec)); - pwidthInit = (int *)xalloc (list_len * sizeof (int)); - if (!pspanInit || !pwidthInit) - goto out; - - Nspans = 0; - new_span = TRUE; - spans = pspanInit - 1; - widths = pwidthInit - 1; - ppt = pptInit; - - xstart = ppt->x; - ystart = ppt->y; - - /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify - * iteration logic - */ - x2 = xstart; - y2 = ystart; - oc2 = 0; - MIOUTCODES (oc2, x2, y2, xleft, ytop, xright, ybottom); - - while (--npt > 0) { - if (Nspans > 0) - (*pGC->ops->FillSpans) (pGC, Nspans, pspanInit, pwidthInit, FALSE, TRUE); - Nspans = 0; - new_span = TRUE; - spans = pspanInit - 1; - widths = pwidthInit - 1; - - x1 = x2; - y1 = y2; - oc1 = oc2; - ++ppt; - - x2 = ppt->x; - y2 = ppt->y; - if (mode == CoordModePrevious) { - x2 += x1; - y2 += y1; - } - - oc2 = 0; - MIOUTCODES (oc2, x2, y2, xleft, ytop, xright, ybottom); - - CalcLineDeltas (x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); - - if (adx > ady) { - e1 = ady << 1; - e2 = e1 - (adx << 1); - e = e1 - adx; - length = adx; /* don't draw endpoint in main loop */ - - FIXUP_ERROR (e, octant, bias); - - new_x1 = x1; - new_y1 = y1; - new_x2 = x2; - new_y2 = y2; - pt1_clipped = 0; - pt2_clipped = 0; - - if ((oc1 | oc2) != 0) { - result = miZeroClipLine (xleft, ytop, xright, ybottom, - &new_x1, &new_y1, &new_x2, &new_y2, - adx, ady, - &pt1_clipped, &pt2_clipped, octant, bias, oc1, oc2); - if (result == -1) - continue; - - length = abs (new_x2 - new_x1); - - /* if we've clipped the endpoint, always draw the full length - * of the segment, because then the capstyle doesn't matter - */ - if (pt2_clipped) - length++; - - if (pt1_clipped) { - /* must calculate new error terms */ - clipdx = abs (new_x1 - x1); - clipdy = abs (new_y1 - y1); - e += (clipdy * e2) + ((clipdx - clipdy) * e1); - } - } - - /* draw the segment */ - - x = new_x1; - y = new_y1; - - e3 = e2 - e1; - e = e - e1; - - while (length--) { - MI_OUTPUT_POINT (x, y); - e += e1; - if (e >= 0) { - y += signdy; - e += e3; - } - x += signdx; - } - } else { /* Y major line */ - - e1 = adx << 1; - e2 = e1 - (ady << 1); - e = e1 - ady; - length = ady; /* don't draw endpoint in main loop */ - - SetYMajorOctant (octant); - FIXUP_ERROR (e, octant, bias); - - new_x1 = x1; - new_y1 = y1; - new_x2 = x2; - new_y2 = y2; - pt1_clipped = 0; - pt2_clipped = 0; - - if ((oc1 | oc2) != 0) { - result = miZeroClipLine (xleft, ytop, xright, ybottom, - &new_x1, &new_y1, &new_x2, &new_y2, - adx, ady, - &pt1_clipped, &pt2_clipped, octant, bias, oc1, oc2); - if (result == -1) - continue; - - length = abs (new_y2 - new_y1); - - /* if we've clipped the endpoint, always draw the full length - * of the segment, because then the capstyle doesn't matter - */ - if (pt2_clipped) - length++; - - if (pt1_clipped) { - /* must calculate new error terms */ - clipdx = abs (new_x1 - x1); - clipdy = abs (new_y1 - y1); - e += (clipdx * e2) + ((clipdy - clipdx) * e1); - } - } - - /* draw the segment */ - - x = new_x1; - y = new_y1; - - e3 = e2 - e1; - e = e - e1; - - while (length--) { - MI_OUTPUT_POINT (x, y); - e += e1; - if (e >= 0) { - x += signdx; - e += e3; - } - y += signdy; - } - } - } - - /* only do the capnotlast check on the last segment - * and only if the endpoint wasn't clipped. And then, if the last - * point is the same as the first point, do not draw it, unless the - * line is degenerate - */ - if ((!pt2_clipped) && (pGC->capStyle != CapNotLast) && - (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) { - MI_OUTPUT_POINT (x, y); - } - - if (Nspans > 0) - (*pGC->ops->FillSpans) (pGC, Nspans, pspanInit, pwidthInit, FALSE, TRUE); - -out: - xfree (pwidthInit); - xfree (pspanInit); -} - -void -miZeroDashLine (GCPtr pgc, int mode, int nptInit, /* number of points in polyline */ - DDXPointRec * pptInit /* points in the polyline */ - ) -{ - /* XXX kludge until real zero-width dash code is written */ - pgc->lineWidth = 1; - miWideDash (pgc, mode, nptInit, pptInit); - pgc->lineWidth = 0; -} - -static void miLineArc (GCPtr pGC, - Boolean foreground, SpanDataPtr spanData, - LineFacePtr leftFace, - LineFacePtr rightFace, double xorg, double yorg, Boolean isInt); - - -/* - * spans-based polygon filler - */ - -static void -miFillPolyHelper (GCPtr pGC, Boolean foreground, - SpanDataPtr spanData, int y, int overall_height, - PolyEdgePtr left, PolyEdgePtr right, int left_count, int right_count) -{ - int left_x = 0, left_e = 0; - int left_stepx = 0; - int left_signdx = 0; - int left_dy = 0, left_dx = 0; - - int right_x = 0, right_e = 0; - int right_stepx = 0; - int right_signdx = 0; - int right_dy = 0, right_dx = 0; - - int height = 0; - int left_height = 0, right_height = 0; - - DDXPointPtr ppt; - DDXPointPtr pptInit = NULL; - int *pwidth; - int *pwidthInit = NULL; - int xorg; - Spans spanRec; - - left_height = 0; - right_height = 0; - - if (!spanData) { - pptInit = (DDXPointRec *)xalloc (overall_height * sizeof (*ppt)); - if (!pptInit) - return; - pwidthInit = (int *)xalloc (overall_height * sizeof (*pwidth)); - if (!pwidthInit) { - xfree (pptInit); - return; - } - ppt = pptInit; - pwidth = pwidthInit; - } else { - spanRec.points = (DDXPointRec *)xalloc (overall_height * sizeof (*ppt)); - if (!spanRec.points) - return; - spanRec.widths = (int *)xalloc (overall_height * sizeof (int)); - if (!spanRec.widths) { - xfree (spanRec.points); - return; - } - ppt = spanRec.points; - pwidth = spanRec.widths; - } - - xorg = 0; - while ((left_count || left_height) && (right_count || right_height)) { - MIPOLYRELOADLEFT MIPOLYRELOADRIGHT height = left_height; - if (height > right_height) - height = right_height; - - left_height -= height; - right_height -= height; - - while (--height >= 0) { - if (right_x >= left_x) { - ppt->y = y; - ppt->x = left_x + xorg; - ppt++; - *pwidth++ = right_x - left_x + 1; - } - y++; - - MIPOLYSTEPLEFT MIPOLYSTEPRIGHT} - } - if (!spanData) { - (*pGC->ops->FillSpans) (pGC, ppt - pptInit, pptInit, pwidthInit, TRUE, foreground); - xfree (pwidthInit); - xfree (pptInit); - } else { - spanRec.count = ppt - spanRec.points; - AppendSpanGroup (pGC, foreground, &spanRec, spanData) - } -} - -static void -miFillRectPolyHelper (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, int x, int y, int w, int h) -{ - DDXPointPtr ppt; - int *pwidth; - Spans spanRec; - xRectangle rect; - - if (!spanData) { - rect.x = x; - rect.y = y; - rect.width = w; - rect.height = h; - (*pGC->ops->FillRects) (pGC, 1, &rect, foreground); - } else { - spanRec.points = (DDXPointRec *)xalloc (h * sizeof (*ppt)); - if (!spanRec.points) - return; - spanRec.widths = (int *)xalloc (h * sizeof (int)); - if (!spanRec.widths) { - xfree (spanRec.points); - return; - } - ppt = spanRec.points; - pwidth = spanRec.widths; - - while (h--) { - ppt->x = x; - ppt->y = y; - ppt++; - *pwidth++ = w; - y++; - } - spanRec.count = ppt - spanRec.points; - AppendSpanGroup (pGC, foreground, &spanRec, spanData) - } -} - -static int -miPolyBuildEdge (double x0, double y0, double k, /* x0 * dy - y0 * dx */ - int dx, int dy, int xi, int yi, int left, PolyEdgePtr edge) -{ - int x, y, e; - int xady; - - if (dy < 0) { - dy = -dy; - dx = -dx; - k = -k; - } -#ifdef NOTDEF - { - double realk, kerror; - realk = x0 * dy - y0 * dx; - kerror = Fabs (realk - k); - if (kerror > .1) - printf ("realk: %g k: %g\n", realk, k); - } -#endif - y = ICEIL (y0); - xady = ICEIL (k) + y * dx; - - if (xady <= 0) - x = -(-xady / dy) - 1; - else - x = (xady - 1) / dy; - - e = xady - x * dy; - - if (dx >= 0) { - edge->signdx = 1; - edge->stepx = dx / dy; - edge->dx = dx % dy; - } else { - edge->signdx = -1; - edge->stepx = -(-dx / dy); - edge->dx = -dx % dy; - e = dy - e + 1; - } - edge->dy = dy; - edge->x = x + left + xi; - edge->e = e - dy; /* bias to compare against 0 instead of dy */ - return y + yi; -} - -#define StepAround(v, incr, max) (((v) + (incr) < 0) ? (max - 1) : ((v) + (incr) == max) ? 0 : ((v) + (incr))) - -static int -miPolyBuildPoly (PolyVertexPtr vertices, - PolySlopePtr slopes, - int count, - int xi, - int yi, PolyEdgePtr left, PolyEdgePtr right, int *pnleft, int *pnright, int *h) -{ - int top, bottom; - double miny, maxy; - int i; - int j; - int clockwise; - int slopeoff; - int s; - int nright, nleft; - int y, lasty = 0, bottomy, topy = 0; - - /* find the top of the polygon */ - maxy = miny = vertices[0].y; - bottom = top = 0; - for (i = 1; i < count; i++) { - if (vertices[i].y < miny) { - top = i; - miny = vertices[i].y; - } - if (vertices[i].y >= maxy) { - bottom = i; - maxy = vertices[i].y; - } - } - clockwise = 1; - slopeoff = 0; - - i = top; - j = StepAround (top, -1, count); - - if (slopes[j].dy * slopes[i].dx > slopes[i].dy * slopes[j].dx) { - clockwise = -1; - slopeoff = -1; - } - - bottomy = ICEIL (maxy) + yi; - - nright = 0; - - s = StepAround (top, slopeoff, count); - i = top; - while (i != bottom) { - if (slopes[s].dy != 0) { - y = miPolyBuildEdge (vertices[i].x, vertices[i].y, - slopes[s].k, - slopes[s].dx, slopes[s].dy, xi, yi, 0, &right[nright]); - if (nright != 0) - right[nright - 1].height = y - lasty; - else - topy = y; - nright++; - lasty = y; - } - - i = StepAround (i, clockwise, count); - s = StepAround (s, clockwise, count); - } - if (nright != 0) - right[nright - 1].height = bottomy - lasty; - - if (slopeoff == 0) - slopeoff = -1; - else - slopeoff = 0; - - nleft = 0; - s = StepAround (top, slopeoff, count); - i = top; - while (i != bottom) { - if (slopes[s].dy != 0) { - y = miPolyBuildEdge (vertices[i].x, vertices[i].y, - slopes[s].k, slopes[s].dx, slopes[s].dy, xi, yi, 1, &left[nleft]); - - if (nleft != 0) - left[nleft - 1].height = y - lasty; - nleft++; - lasty = y; - } - i = StepAround (i, -clockwise, count); - s = StepAround (s, -clockwise, count); - } - if (nleft != 0) - left[nleft - 1].height = bottomy - lasty; - *pnleft = nleft; - *pnright = nright; - *h = bottomy - topy; - return topy; -} - -static void -miLineOnePoint (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, int x, int y) -{ - DDXPointRec pt; - int wid; - - wid = 1; - pt.x = x; - pt.y = y; - (*pGC->ops->FillSpans) (pGC, 1, &pt, &wid, TRUE, foreground); -} - -static void -miLineJoin (GCPtr pGC, Boolean foreground, SpanDataPtr spanData, LineFacePtr pLeft, LineFacePtr pRight) -{ - double mx = 0, my = 0; - double denom = 0.0; - PolyVertexRec vertices[4]; - PolySlopeRec slopes[4]; - int edgecount; - PolyEdgeRec left[4], right[4]; - int nleft, nright; - int y, height; - int swapslopes; - int joinStyle = pGC->joinStyle; - int lw = pGC->lineWidth; - - if (lw == 1 && !spanData) { - /* See if one of the lines will draw the joining pixel */ - if (pLeft->dx > 0 || (pLeft->dx == 0 && pLeft->dy > 0)) - return; - if (pRight->dx > 0 || (pRight->dx == 0 && pRight->dy > 0)) - return; - if (joinStyle != JoinRound) { - denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy; - if (denom == 0) - return; /* no join to draw */ - } - if (joinStyle != JoinMiter) { - miLineOnePoint (pGC, foreground, spanData, pLeft->x, pLeft->y); - return; - } - } else { - if (joinStyle == JoinRound) { - miLineArc (pGC, foreground, spanData, pLeft, pRight, (double) 0.0, (double) 0.0, TRUE); - return; - } - denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy; - if (denom == 0.0) - return; /* no join to draw */ - } - - swapslopes = 0; - if (denom > 0) { - pLeft->xa = -pLeft->xa; - pLeft->ya = -pLeft->ya; - pLeft->dx = -pLeft->dx; - pLeft->dy = -pLeft->dy; - } else { - swapslopes = 1; - pRight->xa = -pRight->xa; - pRight->ya = -pRight->ya; - pRight->dx = -pRight->dx; - pRight->dy = -pRight->dy; - } - - vertices[0].x = pRight->xa; - vertices[0].y = pRight->ya; - slopes[0].dx = -pRight->dy; - slopes[0].dy = pRight->dx; - slopes[0].k = 0; - - vertices[1].x = 0; - vertices[1].y = 0; - slopes[1].dx = pLeft->dy; - slopes[1].dy = -pLeft->dx; - slopes[1].k = 0; - - vertices[2].x = pLeft->xa; - vertices[2].y = pLeft->ya; - - if (joinStyle == JoinMiter) { - my = (pLeft->dy * (pRight->xa * pRight->dy - pRight->ya * pRight->dx) - - pRight->dy * (pLeft->xa * pLeft->dy - pLeft->ya * pLeft->dx)) / denom; - if (pLeft->dy != 0) { - mx = pLeft->xa + (my - pLeft->ya) * (double) pLeft->dx / (double) pLeft->dy; - } else { - mx = pRight->xa + (my - pRight->ya) * (double) pRight->dx / (double) pRight->dy; - } - /* check miter limit */ - if ((mx * mx + my * my) * 4 > SQSECANT * lw * lw) - joinStyle = JoinBevel; - } - - if (joinStyle == JoinMiter) { - slopes[2].dx = pLeft->dx; - slopes[2].dy = pLeft->dy; - slopes[2].k = pLeft->k; - if (swapslopes) { - slopes[2].dx = -slopes[2].dx; - slopes[2].dy = -slopes[2].dy; - slopes[2].k = -slopes[2].k; - } - vertices[3].x = mx; - vertices[3].y = my; - slopes[3].dx = pRight->dx; - slopes[3].dy = pRight->dy; - slopes[3].k = pRight->k; - if (swapslopes) { - slopes[3].dx = -slopes[3].dx; - slopes[3].dy = -slopes[3].dy; - slopes[3].k = -slopes[3].k; - } - edgecount = 4; - } else { - double scale, dx, dy, adx, ady; - - adx = dx = pRight->xa - pLeft->xa; - ady = dy = pRight->ya - pLeft->ya; - if (adx < 0) - adx = -adx; - if (ady < 0) - ady = -ady; - scale = ady; - if (adx > ady) - scale = adx; - slopes[2].dx = (int) ((dx * 65536) / scale); - slopes[2].dy = (int) ((dy * 65536) / scale); - slopes[2].k = ((pLeft->xa + pRight->xa) * slopes[2].dy - - (pLeft->ya + pRight->ya) * slopes[2].dx) / 2.0; - edgecount = 3; - } - - y = miPolyBuildPoly (vertices, slopes, edgecount, pLeft->x, pLeft->y, - left, right, &nleft, &nright, &height); - miFillPolyHelper (pGC, foreground, spanData, y, height, left, right, nleft, nright); -} - -static int -miLineArcI (GCPtr pGC, int xorg, int yorg, DDXPointPtr points, int *widths) -{ - DDXPointPtr tpts, bpts; - int *twids, *bwids; - int x, y, e, ex, slw; - - tpts = points; - twids = widths; - slw = pGC->lineWidth; - if (slw == 1) { - tpts->x = xorg; - tpts->y = yorg; - *twids = 1; - return 1; - } - bpts = tpts + slw; - bwids = twids + slw; - y = (slw >> 1) + 1; - if (slw & 1) - e = -((y << 2) + 3); - else - e = -(y << 3); - ex = -4; - x = 0; - while (y) { - e += (y << 3) - 4; - while (e >= 0) { - x++; - e += (ex = -((x << 3) + 4)); - } - y--; - slw = (x << 1) + 1; - if ((e == ex) && (slw > 1)) - slw--; - tpts->x = xorg - x; - tpts->y = yorg - y; - tpts++; - *twids++ = slw; - if ((y != 0) && ((slw > 1) || (e != ex))) { - bpts--; - bpts->x = xorg - x; - bpts->y = yorg + y; - *--bwids = slw; - } - } - return (pGC->lineWidth); -} - -#define CLIPSTEPEDGE(edgey,edge,edgeleft) \ - if (ybase == edgey) \ - { \ - if (edgeleft) \ - { \ - if (edge->x > xcl) \ - xcl = edge->x; \ - } \ - else \ - { \ - if (edge->x < xcr) \ - xcr = edge->x; \ - } \ - edgey++; \ - edge->x += edge->stepx; \ - edge->e += edge->dx; \ - if (edge->e > 0) \ - { \ - edge->x += edge->signdx; \ - edge->e -= edge->dy; \ - } \ - } - -static int -miLineArcD (GCPtr pGC, - double xorg, - double yorg, - DDXPointPtr points, - int *widths, - PolyEdgePtr edge1, - int edgey1, Boolean edgeleft1, PolyEdgePtr edge2, int edgey2, Boolean edgeleft2) -{ - DDXPointPtr pts; - int *wids; - double radius, x0, y0, el, er, yk, xlk, xrk, k; - int xbase, ybase, y, boty, xl, xr, xcl, xcr; - int ymin, ymax; - Boolean edge1IsMin, edge2IsMin; - int ymin1, ymin2; - - pts = points; - wids = widths; - xbase = (int)floor (xorg); - x0 = xorg - xbase; - ybase = ICEIL (yorg); - y0 = yorg - ybase; - xlk = x0 + x0 + 1.0; - xrk = x0 + x0 - 1.0; - yk = y0 + y0 - 1.0; - radius = ((double) pGC->lineWidth) / 2.0; - y = (int)floor (radius - y0 + 1.0); - ybase -= y; - ymin = ybase; - ymax = 65536; - edge1IsMin = FALSE; - ymin1 = edgey1; - if (edge1->dy >= 0) { - if (!edge1->dy) { - if (edgeleft1) - edge1IsMin = TRUE; - else - ymax = edgey1; - edgey1 = 65536; - } else { - if ((edge1->signdx < 0) == edgeleft1) - edge1IsMin = TRUE; - } - } - edge2IsMin = FALSE; - ymin2 = edgey2; - if (edge2->dy >= 0) { - if (!edge2->dy) { - if (edgeleft2) - edge2IsMin = TRUE; - else - ymax = edgey2; - edgey2 = 65536; - } else { - if ((edge2->signdx < 0) == edgeleft2) - edge2IsMin = TRUE; - } - } - if (edge1IsMin) { - ymin = ymin1; - if (edge2IsMin && ymin1 > ymin2) - ymin = ymin2; - } else if (edge2IsMin) - ymin = ymin2; - el = radius * radius - ((y + y0) * (y + y0)) - (x0 * x0); - er = el + xrk; - xl = 1; - xr = 0; - if (x0 < 0.5) { - xl = 0; - el -= xlk; - } - boty = (y0 < -0.5) ? 1 : 0; - if (ybase + y - boty > ymax) - boty = ymax - ybase - y; - while (y > boty) { - k = (y << 1) + yk; - er += k; - while (er > 0.0) { - xr++; - er += xrk - (xr << 1); - } - el += k; - while (el >= 0.0) { - xl--; - el += (xl << 1) - xlk; - } - y--; - ybase++; - if (ybase < ymin) - continue; - xcl = xl + xbase; - xcr = xr + xbase; - CLIPSTEPEDGE (edgey1, edge1, edgeleft1); - CLIPSTEPEDGE (edgey2, edge2, edgeleft2); - if (xcr >= xcl) { - pts->x = xcl; - pts->y = ybase; - pts++; - *wids++ = xcr - xcl + 1; - } - } - er = xrk - (xr << 1) - er; - el = (xl << 1) - xlk - el; - boty = (int)floor (-y0 - radius + 1.0); - if (ybase + y - boty > ymax) - boty = ymax - ybase - y; - while (y > boty) { - k = (y << 1) + yk; - er -= k; - while ((er >= 0.0) && (xr >= 0)) { - xr--; - er += xrk - (xr << 1); - } - el -= k; - while ((el > 0.0) && (xl <= 0)) { - xl++; - el += (xl << 1) - xlk; - } - y--; - ybase++; - if (ybase < ymin) - continue; - xcl = xl + xbase; - xcr = xr + xbase; - CLIPSTEPEDGE (edgey1, edge1, edgeleft1); - CLIPSTEPEDGE (edgey2, edge2, edgeleft2); - if (xcr >= xcl) { - pts->x = xcl; - pts->y = ybase; - pts++; - *wids++ = xcr - xcl + 1; - } - } - return (pts - points); -} - -static int -miRoundJoinFace (LineFacePtr face, PolyEdgePtr edge, Boolean * leftEdge) -{ - int y; - int dx, dy; - double xa, ya; - Boolean left; - - dx = -face->dy; - dy = face->dx; - xa = face->xa; - ya = face->ya; - left = 1; - if (ya > 0) { - ya = 0.0; - xa = 0.0; - } - if (dy < 0 || (dy == 0 && dx > 0)) { - dx = -dx; - dy = -dy; - left = !left; - } - if (dx == 0 && dy == 0) - dy = 1; - if (dy == 0) { - y = ICEIL (face->ya) + face->y; - edge->x = -32767; - edge->stepx = 0; - edge->signdx = 0; - edge->e = -1; - edge->dy = 0; - edge->dx = 0; - edge->height = 0; - } else { - y = miPolyBuildEdge (xa, ya, 0.0, dx, dy, face->x, face->y, !left, edge); - edge->height = 32767; - } - *leftEdge = !left; - return y; -} - -static void -miRoundJoinClip (LineFacePtr pLeft, LineFacePtr pRight, - PolyEdgePtr edge1, PolyEdgePtr edge2, int *y1, int *y2, Boolean * left1, Boolean * left2) -{ - double denom; - - denom = -pLeft->dx * (double) pRight->dy + pRight->dx * (double) pLeft->dy; - - if (denom >= 0) { - pLeft->xa = -pLeft->xa; - pLeft->ya = -pLeft->ya; - } else { - pRight->xa = -pRight->xa; - pRight->ya = -pRight->ya; - } - *y1 = miRoundJoinFace (pLeft, edge1, left1); - *y2 = miRoundJoinFace (pRight, edge2, left2); -} - -static int -miRoundCapClip (LineFacePtr face, Boolean isInt, PolyEdgePtr edge, Boolean * leftEdge) -{ - int y; - int dx, dy; - double xa, ya, k; - Boolean left; - - dx = -face->dy; - dy = face->dx; - xa = face->xa; - ya = face->ya; - k = 0.0; - if (!isInt) - k = face->k; - left = 1; - if (dy < 0 || (dy == 0 && dx > 0)) { - dx = -dx; - dy = -dy; - xa = -xa; - ya = -ya; - left = !left; - } - if (dx == 0 && dy == 0) - dy = 1; - if (dy == 0) { - y = ICEIL (face->ya) + face->y; - edge->x = -32767; - edge->stepx = 0; - edge->signdx = 0; - edge->e = -1; - edge->dy = 0; - edge->dx = 0; - edge->height = 0; - } else { - y = miPolyBuildEdge (xa, ya, k, dx, dy, face->x, face->y, !left, edge); - edge->height = 32767; - } - *leftEdge = !left; - return y; -} - -static void -miLineArc (GCPtr pGC, - Boolean foreground, - SpanDataPtr spanData, - LineFacePtr leftFace, LineFacePtr rightFace, double xorg, double yorg, Boolean isInt) -{ - DDXPointPtr points; - int *widths; - int xorgi = 0, yorgi = 0; - Spans spanRec; - int n; - PolyEdgeRec edge1, edge2; - int edgey1, edgey2; - Boolean edgeleft1, edgeleft2; - - if (isInt) { - xorgi = leftFace ? leftFace->x : rightFace->x; - yorgi = leftFace ? leftFace->y : rightFace->y; - } - edgey1 = 65536; - edgey2 = 65536; - edge1.x = 0; /* not used, keep memory checkers happy */ - edge1.dy = -1; - edge2.x = 0; /* not used, keep memory checkers happy */ - edge2.dy = -1; - edgeleft1 = FALSE; - edgeleft2 = FALSE; - if ((pGC->lineStyle != LineSolid || pGC->lineWidth > 2) && - ((pGC->capStyle == CapRound && pGC->joinStyle != JoinRound) || - (pGC->joinStyle == JoinRound && pGC->capStyle == CapButt))) { - if (isInt) { - xorg = (double) xorgi; - yorg = (double) yorgi; - } - if (leftFace && rightFace) { - miRoundJoinClip (leftFace, rightFace, &edge1, &edge2, - &edgey1, &edgey2, &edgeleft1, &edgeleft2); - } else if (leftFace) { - edgey1 = miRoundCapClip (leftFace, isInt, &edge1, &edgeleft1); - } else if (rightFace) { - edgey2 = miRoundCapClip (rightFace, isInt, &edge2, &edgeleft2); - } - isInt = FALSE; - } - if (!spanData) { - points = (DDXPointRec *)xalloc (sizeof (DDXPointRec) * pGC->lineWidth); - if (!points) - return; - widths = (int *)xalloc (sizeof (int) * pGC->lineWidth); - if (!widths) { - xfree (points); - return; - } - } else { - points = (DDXPointRec *)xalloc (pGC->lineWidth * sizeof (DDXPointRec)); - if (!points) - return; - widths = (int *)xalloc (pGC->lineWidth * sizeof (int)); - if (!widths) { - xfree (points); - return; - } - spanRec.points = points; - spanRec.widths = widths; - } - if (isInt) - n = miLineArcI (pGC, xorgi, yorgi, points, widths); - else - n = miLineArcD (pGC, xorg, yorg, points, widths, - &edge1, edgey1, edgeleft1, &edge2, edgey2, edgeleft2); - - if (!spanData) { - (*pGC->ops->FillSpans) (pGC, n, points, widths, TRUE, foreground); - xfree (widths); - xfree (points); - } else { - spanRec.count = n; - AppendSpanGroup (pGC, foreground, &spanRec, spanData) - } -} - -static void -miLineProjectingCap (GCPtr pGC, Boolean foreground, - SpanDataPtr spanData, LineFacePtr face, Boolean isLeft, - double xorg, double yorg, Boolean isInt) -{ - int xorgi = 0, yorgi = 0; - int lw; - PolyEdgeRec lefts[2], rights[2]; - int lefty, righty, topy, bottomy; - PolyEdgePtr left, right; - PolyEdgePtr top, bottom; - double xa, ya; - double k; - double xap, yap; - int dx, dy; - double projectXoff, projectYoff; - double maxy; - int finaly; - - if (isInt) { - xorgi = face->x; - yorgi = face->y; - } - lw = pGC->lineWidth; - dx = face->dx; - dy = face->dy; - k = face->k; - if (dy == 0) { - lefts[0].height = lw; - lefts[0].x = xorgi; - if (isLeft) - lefts[0].x -= (lw >> 1); - lefts[0].stepx = 0; - lefts[0].signdx = 1; - lefts[0].e = -lw; - lefts[0].dx = 0; - lefts[0].dy = lw; - rights[0].height = lw; - rights[0].x = xorgi; - if (!isLeft) - rights[0].x += ((lw + 1) >> 1); - rights[0].stepx = 0; - rights[0].signdx = 1; - rights[0].e = -lw; - rights[0].dx = 0; - rights[0].dy = lw; - miFillPolyHelper (pGC, foreground, spanData, yorgi - (lw >> 1), lw, lefts, rights, 1, 1); - } else if (dx == 0) { - if (dy < 0) { - dy = -dy; - isLeft = !isLeft; - } - topy = yorgi; - bottomy = yorgi + dy; - if (isLeft) - topy -= (lw >> 1); - else - bottomy += (lw >> 1); - lefts[0].height = bottomy - topy; - lefts[0].x = xorgi - (lw >> 1); - lefts[0].stepx = 0; - lefts[0].signdx = 1; - lefts[0].e = -dy; - lefts[0].dx = dx; - lefts[0].dy = dy; - - rights[0].height = bottomy - topy; - rights[0].x = lefts[0].x + (lw - 1); - rights[0].stepx = 0; - rights[0].signdx = 1; - rights[0].e = -dy; - rights[0].dx = dx; - rights[0].dy = dy; - miFillPolyHelper (pGC, foreground, spanData, topy, bottomy - topy, lefts, rights, 1, 1); - } else { - xa = face->xa; - ya = face->ya; - projectXoff = -ya; - projectYoff = xa; - if (dx < 0) { - right = &rights[1]; - left = &lefts[0]; - top = &rights[0]; - bottom = &lefts[1]; - } else { - right = &rights[0]; - left = &lefts[1]; - top = &lefts[0]; - bottom = &rights[1]; - } - if (isLeft) { - righty = miPolyBuildEdge (xa, ya, k, dx, dy, xorgi, yorgi, 0, right); - - xa = -xa; - ya = -ya; - k = -k; - lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, xorgi, yorgi, 1, left); - if (dx > 0) { - ya = -ya; - xa = -xa; - } - xap = xa - projectXoff; - yap = ya - projectYoff; - topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, xorgi, yorgi, dx > 0, top); - bottomy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, yorgi, dx < 0, bottom); - maxy = -ya; - } else { - righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, xorgi, yorgi, 0, right); - - xa = -xa; - ya = -ya; - k = -k; - lefty = miPolyBuildEdge (xa, ya, k, dx, dy, xorgi, yorgi, 1, left); - if (dx > 0) { - ya = -ya; - xa = -xa; - } - xap = xa - projectXoff; - yap = ya - projectYoff; - topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, xorgi, xorgi, dx > 0, top); - bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, xorgi, xorgi, dx < 0, bottom); - maxy = -ya + projectYoff; - } - finaly = ICEIL (maxy) + yorgi; - if (dx < 0) { - left->height = bottomy - lefty; - right->height = finaly - righty; - top->height = righty - topy; - } else { - right->height = bottomy - righty; - left->height = finaly - lefty; - top->height = lefty - topy; - } - bottom->height = finaly - bottomy; - miFillPolyHelper (pGC, foreground, spanData, topy, - bottom->height + bottomy - topy, lefts, rights, 2, 2); - } -} - -static void -miWideSegment (GCPtr pGC, - Boolean foreground, - SpanDataPtr spanData, - int x1, - int y1, - int x2, - int y2, - Boolean projectLeft, Boolean projectRight, LineFacePtr leftFace, LineFacePtr rightFace) -{ - double l, L, r; - double xa, ya; - double projectXoff = 0.0, projectYoff = 0.0; - double k; - double maxy; - int x, y; - int dx, dy; - int finaly; - PolyEdgePtr left, right; - PolyEdgePtr top, bottom; - int lefty, righty, topy, bottomy; - int signdx; - PolyEdgeRec lefts[2], rights[2]; - LineFacePtr tface; - int lw = pGC->lineWidth; - - /* draw top-to-bottom always */ - if (y2 < y1 || (y2 == y1 && x2 < x1)) { - x = x1; - x1 = x2; - x2 = x; - - y = y1; - y1 = y2; - y2 = y; - - x = projectLeft; - projectLeft = projectRight; - projectRight = x; - - tface = leftFace; - leftFace = rightFace; - rightFace = tface; - } - - dy = y2 - y1; - signdx = 1; - dx = x2 - x1; - if (dx < 0) - signdx = -1; - - leftFace->x = x1; - leftFace->y = y1; - leftFace->dx = dx; - leftFace->dy = dy; - - rightFace->x = x2; - rightFace->y = y2; - rightFace->dx = -dx; - rightFace->dy = -dy; - - if (dy == 0) { - rightFace->xa = 0; - rightFace->ya = (double) lw / 2.0; - rightFace->k = -(double) (lw * dx) / 2.0; - leftFace->xa = 0; - leftFace->ya = -rightFace->ya; - leftFace->k = rightFace->k; - x = x1; - if (projectLeft) - x -= (lw >> 1); - y = y1 - (lw >> 1); - dx = x2 - x; - if (projectRight) - dx += ((lw + 1) >> 1); - dy = lw; - miFillRectPolyHelper (pGC, foreground, spanData, x, y, dx, dy); - } else if (dx == 0) { - leftFace->xa = (double) lw / 2.0; - leftFace->ya = 0; - leftFace->k = (double) (lw * dy) / 2.0; - rightFace->xa = -leftFace->xa; - rightFace->ya = 0; - rightFace->k = leftFace->k; - y = y1; - if (projectLeft) - y -= lw >> 1; - x = x1 - (lw >> 1); - dy = y2 - y; - if (projectRight) - dy += ((lw + 1) >> 1); - dx = lw; - miFillRectPolyHelper (pGC, foreground, spanData, x, y, dx, dy); - } else { - l = ((double) lw) / 2.0; - L = hypot ((double) dx, (double) dy); - - if (dx < 0) { - right = &rights[1]; - left = &lefts[0]; - top = &rights[0]; - bottom = &lefts[1]; - } else { - right = &rights[0]; - left = &lefts[1]; - top = &lefts[0]; - bottom = &rights[1]; - } - r = l / L; - - /* coord of upper bound at integral y */ - ya = -r * dx; - xa = r * dy; - - if (projectLeft | projectRight) { - projectXoff = -ya; - projectYoff = xa; - } - - /* xa * dy - ya * dx */ - k = l * L; - - leftFace->xa = xa; - leftFace->ya = ya; - leftFace->k = k; - rightFace->xa = -xa; - rightFace->ya = -ya; - rightFace->k = k; - - if (projectLeft) - righty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, x1, y1, 0, right); - else - righty = miPolyBuildEdge (xa, ya, k, dx, dy, x1, y1, 0, right); - - /* coord of lower bound at integral y */ - ya = -ya; - xa = -xa; - - /* xa * dy - ya * dx */ - k = -k; - - if (projectLeft) - lefty = miPolyBuildEdge (xa - projectXoff, ya - projectYoff, - k, dx, dy, x1, y1, 1, left); - else - lefty = miPolyBuildEdge (xa, ya, k, dx, dy, x1, y1, 1, left); - - /* coord of top face at integral y */ - - if (signdx > 0) { - ya = -ya; - xa = -xa; - } - - if (projectLeft) { - double xap = xa - projectXoff; - double yap = ya - projectYoff; - topy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, -dy, dx, x1, y1, dx > 0, top); - } else - topy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x1, y1, dx > 0, top); - - /* coord of bottom face at integral y */ - - if (projectRight) { - double xap = xa + projectXoff; - double yap = ya + projectYoff; - bottomy = miPolyBuildEdge (xap, yap, xap * dx + yap * dy, - -dy, dx, x2, y2, dx < 0, bottom); - maxy = -ya + projectYoff; - } else { - bottomy = miPolyBuildEdge (xa, ya, 0.0, -dy, dx, x2, y2, dx < 0, bottom); - maxy = -ya; - } - - finaly = ICEIL (maxy) + y2; - - if (dx < 0) { - left->height = bottomy - lefty; - right->height = finaly - righty; - top->height = righty - topy; - } else { - right->height = bottomy - righty; - left->height = finaly - lefty; - top->height = lefty - topy; - } - bottom->height = finaly - bottomy; - miFillPolyHelper (pGC, foreground, spanData, topy, - bottom->height + bottomy - topy, lefts, rights, 2, 2); - } -} - -static SpanDataPtr -miSetupSpanData (GCPtr pGC, SpanDataPtr spanData, int npt) -{ - if ((npt < 3 && pGC->capStyle != CapRound) || miSpansEasyRop (pGC->alu)) - return (SpanDataPtr) NULL; - if (pGC->lineStyle == LineDoubleDash) - miInitSpanGroup (&spanData->bgGroup); - miInitSpanGroup (&spanData->fgGroup); - return spanData; -} - -static void -miCleanupSpanData (GCPtr pGC, SpanDataPtr spanData) -{ - if (pGC->lineStyle == LineDoubleDash) { - miFillUniqueSpanGroup (pGC, &spanData->bgGroup, FALSE); - miFreeSpanGroup (&spanData->bgGroup); - } - miFillUniqueSpanGroup (pGC, &spanData->fgGroup, TRUE); - miFreeSpanGroup (&spanData->fgGroup); -} - -void -miWideLine (GCPtr pGC, int mode, int npt, DDXPointPtr pPts) -{ - int x1, y1, x2, y2; - SpanDataRec spanDataRec; - SpanDataPtr spanData; - Boolean projectLeft, projectRight; - LineFaceRec leftFace, rightFace, prevRightFace; - LineFaceRec firstFace; - int first; - Boolean somethingDrawn = FALSE; - Boolean selfJoin; - - spanData = miSetupSpanData (pGC, &spanDataRec, npt); - x2 = pPts->x; - y2 = pPts->y; - first = TRUE; - selfJoin = FALSE; - if (npt > 1) { - if (mode == CoordModePrevious) { - int nptTmp; - DDXPointPtr pPtsTmp; - - x1 = x2; - y1 = y2; - nptTmp = npt; - pPtsTmp = pPts + 1; - while (--nptTmp) { - x1 += pPtsTmp->x; - y1 += pPtsTmp->y; - ++pPtsTmp; - } - if (x2 == x1 && y2 == y1) - selfJoin = TRUE; - } else if (x2 == pPts[npt - 1].x && y2 == pPts[npt - 1].y) { - selfJoin = TRUE; - } - } - projectLeft = pGC->capStyle == CapProjecting && !selfJoin; - projectRight = FALSE; - while (--npt) { - x1 = x2; - y1 = y2; - ++pPts; - x2 = pPts->x; - y2 = pPts->y; - if (mode == CoordModePrevious) { - x2 += x1; - y2 += y1; - } - if (x1 != x2 || y1 != y2) { - somethingDrawn = TRUE; - if (npt == 1 && pGC->capStyle == CapProjecting && !selfJoin) - projectRight = TRUE; - miWideSegment (pGC, TRUE, spanData, x1, y1, x2, y2, - projectLeft, projectRight, &leftFace, &rightFace); - if (first) { - if (selfJoin) - firstFace = leftFace; - else if (pGC->capStyle == CapRound) { - if (pGC->lineWidth == 1 && !spanData) - miLineOnePoint (pGC, TRUE, spanData, x1, y1); - else - miLineArc (pGC, TRUE, spanData, - &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE); - } - } else { - miLineJoin (pGC, TRUE, spanData, &leftFace, &prevRightFace); - } - prevRightFace = rightFace; - first = FALSE; - projectLeft = FALSE; - } - if (npt == 1 && somethingDrawn) { - if (selfJoin) - miLineJoin (pGC, TRUE, spanData, &firstFace, &rightFace); - else if (pGC->capStyle == CapRound) { - if (pGC->lineWidth == 1 && !spanData) - miLineOnePoint (pGC, TRUE, spanData, x2, y2); - else - miLineArc (pGC, TRUE, spanData, - (LineFacePtr) NULL, &rightFace, (double) 0.0, (double) 0.0, TRUE); - } - } - } - /* handle crock where all points are coincedent */ - if (!somethingDrawn) { - projectLeft = pGC->capStyle == CapProjecting; - miWideSegment (pGC, TRUE, spanData, - x2, y2, x2, y2, projectLeft, projectLeft, &leftFace, &rightFace); - if (pGC->capStyle == CapRound) { - miLineArc (pGC, TRUE, spanData, - &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE); - rightFace.dx = -1; /* sleezy hack to make it work */ - miLineArc (pGC, TRUE, spanData, - (LineFacePtr) NULL, &rightFace, (double) 0.0, (double) 0.0, TRUE); - } - } - if (spanData) - miCleanupSpanData (pGC, spanData); -} - -#define V_TOP 0 -#define V_RIGHT 1 -#define V_BOTTOM 2 -#define V_LEFT 3 - -static void -miWideDashSegment (GCPtr pGC, - SpanDataPtr spanData, - int *pDashOffset, - int *pDashIndex, - int x1, - int y1, - int x2, - int y2, - Boolean projectLeft, Boolean projectRight, LineFacePtr leftFace, LineFacePtr rightFace) -{ - int dashIndex, dashRemain; - unsigned char *pDash; - double L, l; - double k; - PolyVertexRec vertices[4]; - PolyVertexRec saveRight = { 0 }, saveBottom; - PolySlopeRec slopes[4]; - PolyEdgeRec left[2], right[2]; - LineFaceRec lcapFace, rcapFace; - int nleft, nright; - int h; - int y; - int dy, dx; - Boolean foreground; - double LRemain; - double r; - double rdx, rdy; - double dashDx, dashDy; - double saveK = 0.0; - Boolean first = TRUE; - double lcenterx, lcentery, rcenterx = 0.0, rcentery = 0.0; - - dx = x2 - x1; - dy = y2 - y1; - dashIndex = *pDashIndex; - pDash = pGC->dash; - dashRemain = pDash[dashIndex] - *pDashOffset; - - l = ((double) pGC->lineWidth) / 2.0; - if (dx == 0) { - L = dy; - rdx = 0; - rdy = l; - if (dy < 0) { - L = -dy; - rdy = -l; - } - } else if (dy == 0) { - L = dx; - rdx = l; - rdy = 0; - if (dx < 0) { - L = -dx; - rdx = -l; - } - } else { - L = hypot ((double) dx, (double) dy); - r = l / L; - - rdx = r * dx; - rdy = r * dy; - } - k = l * L; - LRemain = L; - /* All position comments are relative to a line with dx and dy > 0, - * but the code does not depend on this */ - /* top */ - slopes[V_TOP].dx = dx; - slopes[V_TOP].dy = dy; - slopes[V_TOP].k = k; - /* right */ - slopes[V_RIGHT].dx = -dy; - slopes[V_RIGHT].dy = dx; - slopes[V_RIGHT].k = 0; - /* bottom */ - slopes[V_BOTTOM].dx = -dx; - slopes[V_BOTTOM].dy = -dy; - slopes[V_BOTTOM].k = k; - /* left */ - slopes[V_LEFT].dx = dy; - slopes[V_LEFT].dy = -dx; - slopes[V_LEFT].k = 0; - - /* preload the start coordinates */ - vertices[V_RIGHT].x = vertices[V_TOP].x = rdy; - vertices[V_RIGHT].y = vertices[V_TOP].y = -rdx; - - vertices[V_BOTTOM].x = vertices[V_LEFT].x = -rdy; - vertices[V_BOTTOM].y = vertices[V_LEFT].y = rdx; - - if (projectLeft) { - vertices[V_TOP].x -= rdx; - vertices[V_TOP].y -= rdy; - - vertices[V_LEFT].x -= rdx; - vertices[V_LEFT].y -= rdy; - - slopes[V_LEFT].k = rdx * dx + rdy * dy; - } - - lcenterx = x1; - lcentery = y1; - - if (pGC->capStyle == CapRound) { - lcapFace.dx = dx; - lcapFace.dy = dy; - lcapFace.x = x1; - lcapFace.y = y1; - - rcapFace.dx = -dx; - rcapFace.dy = -dy; - rcapFace.x = x1; - rcapFace.y = y1; - } - while (LRemain > dashRemain) { - dashDx = (dashRemain * dx) / L; - dashDy = (dashRemain * dy) / L; - - rcenterx = lcenterx + dashDx; - rcentery = lcentery + dashDy; - - vertices[V_RIGHT].x += dashDx; - vertices[V_RIGHT].y += dashDy; - - vertices[V_BOTTOM].x += dashDx; - vertices[V_BOTTOM].y += dashDy; - - slopes[V_RIGHT].k = vertices[V_RIGHT].x * dx + vertices[V_RIGHT].y * dy; - - if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) { - if (pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapProjecting) { - saveRight = vertices[V_RIGHT]; - saveBottom = vertices[V_BOTTOM]; - saveK = slopes[V_RIGHT].k; - - if (!first) { - vertices[V_TOP].x -= rdx; - vertices[V_TOP].y -= rdy; - - vertices[V_LEFT].x -= rdx; - vertices[V_LEFT].y -= rdy; - - slopes[V_LEFT].k = vertices[V_LEFT].x * - slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx; - } - - vertices[V_RIGHT].x += rdx; - vertices[V_RIGHT].y += rdy; - - vertices[V_BOTTOM].x += rdx; - vertices[V_BOTTOM].y += rdy; - - slopes[V_RIGHT].k = vertices[V_RIGHT].x * - slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx; - } - y = miPolyBuildPoly (vertices, slopes, 4, x1, y1, left, right, &nleft, &nright, &h); - foreground = (dashIndex & 1) == 0; - miFillPolyHelper (pGC, foreground, spanData, y, h, left, right, nleft, nright); - - if (pGC->lineStyle == LineOnOffDash) { - switch (pGC->capStyle) { - case CapProjecting: - vertices[V_BOTTOM] = saveBottom; - vertices[V_RIGHT] = saveRight; - slopes[V_RIGHT].k = saveK; - break; - case CapRound: - if (!first) { - if (dx < 0) { - lcapFace.xa = -vertices[V_LEFT].x; - lcapFace.ya = -vertices[V_LEFT].y; - lcapFace.k = slopes[V_LEFT].k; - } else { - lcapFace.xa = vertices[V_TOP].x; - lcapFace.ya = vertices[V_TOP].y; - lcapFace.k = -slopes[V_LEFT].k; - } - miLineArc (pGC, foreground, spanData, - &lcapFace, (LineFacePtr) NULL, lcenterx, lcentery, FALSE); - } - if (dx < 0) { - rcapFace.xa = vertices[V_BOTTOM].x; - rcapFace.ya = vertices[V_BOTTOM].y; - rcapFace.k = slopes[V_RIGHT].k; - } else { - rcapFace.xa = -vertices[V_RIGHT].x; - rcapFace.ya = -vertices[V_RIGHT].y; - rcapFace.k = -slopes[V_RIGHT].k; - } - miLineArc (pGC, foreground, spanData, - (LineFacePtr) NULL, &rcapFace, rcenterx, rcentery, FALSE); - break; - } - } - } - LRemain -= dashRemain; - ++dashIndex; - if (dashIndex == pGC->numInDashList) - dashIndex = 0; - dashRemain = pDash[dashIndex]; - - lcenterx = rcenterx; - lcentery = rcentery; - - vertices[V_TOP] = vertices[V_RIGHT]; - vertices[V_LEFT] = vertices[V_BOTTOM]; - slopes[V_LEFT].k = -slopes[V_RIGHT].k; - first = FALSE; - } - - if (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1)) { - vertices[V_TOP].x -= dx; - vertices[V_TOP].y -= dy; - - vertices[V_LEFT].x -= dx; - vertices[V_LEFT].y -= dy; - - vertices[V_RIGHT].x = rdy; - vertices[V_RIGHT].y = -rdx; - - vertices[V_BOTTOM].x = -rdy; - vertices[V_BOTTOM].y = rdx; - - - if (projectRight) { - vertices[V_RIGHT].x += rdx; - vertices[V_RIGHT].y += rdy; - - vertices[V_BOTTOM].x += rdx; - vertices[V_BOTTOM].y += rdy; - slopes[V_RIGHT].k = vertices[V_RIGHT].x * - slopes[V_RIGHT].dy - vertices[V_RIGHT].y * slopes[V_RIGHT].dx; - } else - slopes[V_RIGHT].k = 0; - - if (!first && pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapProjecting) { - vertices[V_TOP].x -= rdx; - vertices[V_TOP].y -= rdy; - - vertices[V_LEFT].x -= rdx; - vertices[V_LEFT].y -= rdy; - slopes[V_LEFT].k = vertices[V_LEFT].x * - slopes[V_LEFT].dy - vertices[V_LEFT].y * slopes[V_LEFT].dx; - } else - slopes[V_LEFT].k += dx * dx + dy * dy; - - - y = miPolyBuildPoly (vertices, slopes, 4, x2, y2, left, right, &nleft, &nright, &h); - - foreground = (dashIndex & 1) == 0; - miFillPolyHelper (pGC, foreground, spanData, y, h, left, right, nleft, nright); - if (!first && pGC->lineStyle == LineOnOffDash && pGC->capStyle == CapRound) { - lcapFace.x = x2; - lcapFace.y = y2; - if (dx < 0) { - lcapFace.xa = -vertices[V_LEFT].x; - lcapFace.ya = -vertices[V_LEFT].y; - lcapFace.k = slopes[V_LEFT].k; - } else { - lcapFace.xa = vertices[V_TOP].x; - lcapFace.ya = vertices[V_TOP].y; - lcapFace.k = -slopes[V_LEFT].k; - } - miLineArc (pGC, foreground, spanData, - &lcapFace, (LineFacePtr) NULL, rcenterx, rcentery, FALSE); - } - } - dashRemain = (int)(((double) dashRemain) - LRemain); - if (dashRemain == 0) { - dashIndex++; - if (dashIndex == pGC->numInDashList) - dashIndex = 0; - dashRemain = pDash[dashIndex]; - } - - leftFace->x = x1; - leftFace->y = y1; - leftFace->dx = dx; - leftFace->dy = dy; - leftFace->xa = rdy; - leftFace->ya = -rdx; - leftFace->k = k; - - rightFace->x = x2; - rightFace->y = y2; - rightFace->dx = -dx; - rightFace->dy = -dy; - rightFace->xa = -rdy; - rightFace->ya = rdx; - rightFace->k = k; - - *pDashIndex = dashIndex; - *pDashOffset = pDash[dashIndex] - dashRemain; -} - -void -miWideDash (GCPtr pGC, int mode, int npt, DDXPointPtr pPts) -{ - int x1, y1, x2, y2; - Boolean foreground; - Boolean projectLeft, projectRight; - LineFaceRec leftFace, rightFace, prevRightFace; - LineFaceRec firstFace; - int first; - int dashIndex, dashOffset; - int prevDashIndex; - SpanDataRec spanDataRec; - SpanDataPtr spanData; - Boolean somethingDrawn = FALSE; - Boolean selfJoin; - Boolean endIsFg = FALSE, startIsFg = FALSE; - Boolean firstIsFg = FALSE, prevIsFg = FALSE; - - if (npt == 0) - return; - spanData = miSetupSpanData (pGC, &spanDataRec, npt); - x2 = pPts->x; - y2 = pPts->y; - first = TRUE; - selfJoin = FALSE; - if (mode == CoordModePrevious) { - int nptTmp; - DDXPointPtr pPtsTmp; - - x1 = x2; - y1 = y2; - nptTmp = npt; - pPtsTmp = pPts + 1; - while (--nptTmp) { - x1 += pPtsTmp->x; - y1 += pPtsTmp->y; - ++pPtsTmp; - } - if (x2 == x1 && y2 == y1) - selfJoin = TRUE; - } else if (x2 == pPts[npt - 1].x && y2 == pPts[npt - 1].y) { - selfJoin = TRUE; - } - projectLeft = pGC->capStyle == CapProjecting && !selfJoin; - projectRight = FALSE; - dashIndex = 0; - dashOffset = 0; - miStepDash ((int) pGC->dashOffset, &dashIndex, - pGC->dash, (int) pGC->numInDashList, &dashOffset); - while (--npt) { - x1 = x2; - y1 = y2; - ++pPts; - x2 = pPts->x; - y2 = pPts->y; - if (mode == CoordModePrevious) { - x2 += x1; - y2 += y1; - } - if (x1 != x2 || y1 != y2) { - somethingDrawn = TRUE; - if (npt == 1 && pGC->capStyle == CapProjecting && (!selfJoin || !firstIsFg)) - projectRight = TRUE; - prevDashIndex = dashIndex; - miWideDashSegment (pGC, spanData, &dashOffset, &dashIndex, - x1, y1, x2, y2, projectLeft, projectRight, &leftFace, &rightFace); - startIsFg = !(prevDashIndex & 1); - endIsFg = (dashIndex & 1) ^ (dashOffset != 0); - if (pGC->lineStyle == LineDoubleDash || startIsFg) { - foreground = startIsFg; - if (first || (pGC->lineStyle == LineOnOffDash && !prevIsFg)) { - if (first && selfJoin) { - firstFace = leftFace; - firstIsFg = startIsFg; - } else if (pGC->capStyle == CapRound) - miLineArc (pGC, foreground, spanData, - &leftFace, (LineFacePtr) NULL, (double) 0.0, (double) 0.0, TRUE); - } else { - miLineJoin (pGC, foreground, spanData, &leftFace, &prevRightFace); - } - } - prevRightFace = rightFace; - prevIsFg = endIsFg; - first = FALSE; - projectLeft = FALSE; - } - if (npt == 1 && somethingDrawn) { - if (pGC->lineStyle == LineDoubleDash || endIsFg) { - foreground = endIsFg; - if (selfJoin && (pGC->lineStyle == LineDoubleDash || firstIsFg)) { - miLineJoin (pGC, foreground, spanData, &firstFace, &rightFace); - } else { - if (pGC->capStyle == CapRound) - miLineArc (pGC, foreground, spanData, - (LineFacePtr) NULL, &rightFace, - (double) 0.0, (double) 0.0, TRUE); - } - } else { - /* glue a cap to the start of the line if - * we're OnOffDash and ended on odd dash - */ - if (selfJoin && firstIsFg) { - foreground = TRUE; - if (pGC->capStyle == CapProjecting) - miLineProjectingCap (pGC, foreground, spanData, - &firstFace, TRUE, (double) 0.0, (double) 0.0, TRUE); - else if (pGC->capStyle == CapRound) - miLineArc (pGC, foreground, spanData, - &firstFace, (LineFacePtr) NULL, - (double) 0.0, (double) 0.0, TRUE); - } - } - } - } - /* handle crock where all points are coincident */ - if (!somethingDrawn && (pGC->lineStyle == LineDoubleDash || !(dashIndex & 1))) { - /* not the same as endIsFg computation above */ - foreground = (dashIndex & 1) == 0; - switch (pGC->capStyle) { - case CapRound: - miLineArc (pGC, foreground, spanData, - (LineFacePtr) NULL, (LineFacePtr) NULL, (double) x2, (double) y2, FALSE); - break; - case CapProjecting: - x1 = pGC->lineWidth; - miFillRectPolyHelper (pGC, foreground, spanData, - x2 - (x1 >> 1), y2 - (x1 >> 1), x1, x1); - break; - } - } - if (spanData) - miCleanupSpanData (pGC, spanData); -} - -#undef ExchangeSpans -#define ExchangeSpans(a, b) \ -{ \ - DDXPointRec tpt; \ - int tw; \ - \ - tpt = spans[a]; spans[a] = spans[b]; spans[b] = tpt; \ - tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ -} - -static void QuickSortSpans( - DDXPointRec spans[], - int widths[], - int numSpans) -{ - int y; - int i, j, m; - DDXPointPtr r; - - /* Always called with numSpans > 1 */ - /* Sorts only by y, doesn't bother to sort by x */ - - do - { - if (numSpans < 9) - { - /* Do insertion sort */ - int yprev; - - yprev = spans[0].y; - i = 1; - do - { /* while i != numSpans */ - y = spans[i].y; - if (yprev > y) - { - /* spans[i] is out of order. Move into proper location. */ - DDXPointRec tpt; - int tw, k; - - for (j = 0; y >= spans[j].y; j++) {} - tpt = spans[i]; - tw = widths[i]; - for (k = i; k != j; k--) - { - spans[k] = spans[k-1]; - widths[k] = widths[k-1]; - } - spans[j] = tpt; - widths[j] = tw; - y = spans[i].y; - } /* if out of order */ - yprev = y; - i++; - } while (i != numSpans); - return; - } - - /* Choose partition element, stick in location 0 */ - m = numSpans / 2; - if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); - if (spans[m].y > spans[numSpans-1].y) ExchangeSpans(m, numSpans-1); - if (spans[m].y > spans[0].y) ExchangeSpans(m, 0); - y = spans[0].y; - - /* Partition array */ - i = 0; - j = numSpans; - do - { - r = &(spans[i]); - do - { - r++; - i++; - } while (i != numSpans && r->y < y); - r = &(spans[j]); - do - { - r--; - j--; - } while (y < r->y); - if (i < j) - ExchangeSpans(i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeSpans(0, j); - - /* Recurse */ - if (numSpans-j-1 > 1) - QuickSortSpans(&spans[j+1], &widths[j+1], numSpans-j-1); - numSpans = j; - } while (numSpans > 1); -} - -#define NextBand() \ -{ \ - clipy1 = pboxBandStart->y1; \ - clipy2 = pboxBandStart->y2; \ - pboxBandEnd = pboxBandStart + 1; \ - while (pboxBandEnd != pboxLast && pboxBandEnd->y1 == clipy1) { \ - pboxBandEnd++; \ - } \ - for (; ppt != pptLast && ppt->y < clipy1; ppt++, pwidth++) {} \ -} - -/* - Clip a list of scanlines to a region. The caller has allocated the - space. FSorted is non-zero if the scanline origins are in ascending - order. - returns the number of new, clipped scanlines. -*/ - -int spice_canvas_clip_spans(pixman_region32_t *prgnDst, - DDXPointPtr ppt, - int *pwidth, - int nspans, - DDXPointPtr pptNew, - int *pwidthNew, - int fSorted) -{ - DDXPointPtr pptLast; - int *pwidthNewStart; /* the vengeance of Xerox! */ - int y, x1, x2; - int numRects; - pixman_box32_t *pboxBandStart; - - pptLast = ppt + nspans; - pwidthNewStart = pwidthNew; - - pboxBandStart = pixman_region32_rectangles (prgnDst, &numRects); - - if (numRects == 1) { - /* Do special fast code with clip boundaries in registers(?) */ - /* It doesn't pay much to make use of fSorted in this case, - so we lump everything together. */ - - int clipx1, clipx2, clipy1, clipy2; - - clipx1 = pboxBandStart->x1; - clipy1 = pboxBandStart->y1; - clipx2 = pboxBandStart->x2; - clipy2 = pboxBandStart->y2; - - for (; ppt != pptLast; ppt++, pwidth++) { - y = ppt->y; - x1 = ppt->x; - if (clipy1 <= y && y < clipy2) { - x2 = x1 + *pwidth; - if (x1 < clipx1) - x1 = clipx1; - if (x2 > clipx2) - x2 = clipx2; - if (x1 < x2) { - /* part of span in clip rectangle */ - pptNew->x = x1; - pptNew->y = y; - *pwidthNew = x2 - x1; - pptNew++; - pwidthNew++; - } - } - } /* end for */ - } else if (numRects != 0) { - /* Have to clip against many boxes */ - pixman_box32_t *pboxBandEnd, *pbox, *pboxLast; - int clipy1, clipy2; - - /* In this case, taking advantage of sorted spans gains more than - the sorting costs. */ - if ((! fSorted) && (nspans > 1)) - QuickSortSpans(ppt, pwidth, nspans); - - pboxLast = pboxBandStart + numRects; - - NextBand(); - - for (; ppt != pptLast; ) { - y = ppt->y; - if (y < clipy2) { - /* span is in the current band */ - pbox = pboxBandStart; - x1 = ppt->x; - x2 = x1 + *pwidth; - do { /* For each box in band */ - int newx1, newx2; - - newx1 = x1; - newx2 = x2; - if (newx1 < pbox->x1) - newx1 = pbox->x1; - if (newx2 > pbox->x2) - newx2 = pbox->x2; - if (newx1 < newx2) { - /* Part of span in clip rectangle */ - pptNew->x = newx1; - pptNew->y = y; - *pwidthNew = newx2 - newx1; - pptNew++; - pwidthNew++; - } - pbox++; - } while (pbox != pboxBandEnd); - ppt++; - pwidth++; - } else { - /* Move to next band, adjust ppt as needed */ - pboxBandStart = pboxBandEnd; - if (pboxBandStart == pboxLast) - break; /* We're completely done */ - NextBand(); - } - } - } - return (pwidthNew - pwidthNewStart); -} diff --git a/common/lines.h b/common/lines.h deleted file mode 100644 index 73eef9bc..00000000 --- a/common/lines.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -******************************************************************/ - -#ifndef LINES_H -#define LINES_H - -#include <pixman_utils.h> -#include <stdlib.h> -#include <string.h> -#include "draw.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct lineGC lineGC; - -typedef struct { - void (*FillSpans)(lineGC * pGC, - int num_spans, SpicePoint * points, int *widths, - int sorted, int foreground); - void (*FillRects)(lineGC * pGC, - int nun_rects, pixman_rectangle32_t * rects, - int foreground); -} lineGCOps; - -struct lineGC { - int width; - int height; - unsigned char alu; - unsigned short lineWidth; - unsigned short dashOffset; - unsigned short numInDashList; - unsigned char *dash; - unsigned int lineStyle:2; - unsigned int capStyle:2; - unsigned int joinStyle:2; - lineGCOps *ops; -}; - -/* CoordinateMode for drawing routines */ - -#define CoordModeOrigin 0 /* relative to the origin */ -#define CoordModePrevious 1 /* relative to previous point */ - -/* LineStyle */ - -#define LineSolid 0 -#define LineOnOffDash 1 -#define LineDoubleDash 2 - -/* capStyle */ - -#define CapNotLast 0 -#define CapButt 1 -#define CapRound 2 -#define CapProjecting 3 - -/* joinStyle */ - -#define JoinMiter 0 -#define JoinRound 1 -#define JoinBevel 2 - -extern void spice_canvas_zero_line(lineGC *pgc, - int mode, - int num_points, - SpicePoint * points); -extern void spice_canvas_zero_dash_line(lineGC * pgc, - int mode, - int n_points, - SpicePoint * points); -extern void spice_canvas_wide_dash_line(lineGC * pGC, - int mode, - int num_points, - SpicePoint * points); -extern void spice_canvas_wide_line(lineGC *pGC, - int mode, - int num_points, - SpicePoint * points); -extern int spice_canvas_clip_spans(pixman_region32_t *clip_region, - SpicePoint *points, - int *widths, - int num_spans, - SpicePoint *new_points, - int *new_widths, - int sorted); - -#ifdef __cplusplus -} -#endif - -#endif /* LINES_H */ diff --git a/common/lz.c b/common/lz.c deleted file mode 100644 index 5f517940..00000000 --- a/common/lz.c +++ /dev/null @@ -1,740 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - - Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. - - This file incorporates work covered by the following copyright and - permission notice: - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, copy, - modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "lz.h" - -#define DEBUG - -#ifdef DEBUG - -#define ASSERT(usr, x) \ - if (!(x)) (usr)->error(usr, "%s: ASSERT %s failed\n", __FUNCTION__, #x); - -#else - -#define ASSERT(usr, x) - -#endif - -#define HASH_LOG 13 -#define HASH_SIZE (1 << HASH_LOG) -#define HASH_MASK (HASH_SIZE - 1) - - -typedef struct LzImageSegment LzImageSegment; -struct LzImageSegment { - uint8_t *lines; - uint8_t *lines_end; - unsigned int size_delta; // total size of the previous segments in units of - // pixels for rgb and bytes for plt. - LzImageSegment *next; -}; - -// TODO: pack? -typedef struct HashEntry { - LzImageSegment *image_seg; - uint8_t *ref; -} HashEntry; - -typedef struct Encoder { - LzUsrContext *usr; - - LzImageType type; - const SpicePalette *palette; // for decoding images with palettes to rgb - int stride; // stride is in bytes. For rgb must be equal to - // width*bytes_per_pix. - // For palettes stride can be bigger than width/pixels_per_byte by 1 only if - // width%pixels_per_byte != 0. - int height; - int width; // the original width (in pixels) - - LzImageSegment *head_image_segs; - LzImageSegment *tail_image_segs; - LzImageSegment *free_image_segs; - - // the dictionary hash table is composed (1) a pointer to the segment the word was found in - // (2) a pointer to the first byte in the segment that matches the word - HashEntry htab[HASH_SIZE]; - - uint8_t *io_start; - uint8_t *io_now; - uint8_t *io_end; - size_t io_bytes_count; - - uint8_t *io_last_copy; // pointer to the last byte in which copy count was written -} Encoder; - -/****************************************************/ -/* functions for managing the pool of image segments*/ -/****************************************************/ -static INLINE LzImageSegment *lz_alloc_image_seg(Encoder *encoder); -static void lz_reset_image_seg(Encoder *encoder); -static int lz_read_image_segments(Encoder *encoder, uint8_t *first_lines, - unsigned int num_first_lines); - - -// return a free image segment if one exists. Make allocation if needed. adds it to the -// tail of the image segments lists -static INLINE LzImageSegment *lz_alloc_image_seg(Encoder *encoder) -{ - LzImageSegment *ret; - - if (encoder->free_image_segs) { - ret = encoder->free_image_segs; - encoder->free_image_segs = ret->next; - } else { - if (!(ret = (LzImageSegment *)encoder->usr->malloc(encoder->usr, sizeof(*ret)))) { - return NULL; - } - } - - ret->next = NULL; - if (encoder->tail_image_segs) { - encoder->tail_image_segs->next = ret; - } - encoder->tail_image_segs = ret; - - if (!encoder->head_image_segs) { - encoder->head_image_segs = ret; - } - - return ret; -} - -// adding seg to the head of free segments (lz_reset_image_seg removes it from used ones) -static INLINE void __lz_free_image_seg(Encoder *encoder, LzImageSegment *seg) -{ - seg->next = encoder->free_image_segs; - encoder->free_image_segs = seg; -} - -// moves all the used image segments to the free pool -static void lz_reset_image_seg(Encoder *encoder) -{ - while (encoder->head_image_segs) { - LzImageSegment *seg = encoder->head_image_segs; - encoder->head_image_segs = seg->next; - __lz_free_image_seg(encoder, seg); - } - encoder->tail_image_segs = NULL; -} - -static void lz_dealloc_free_segments(Encoder *encoder) -{ - while (encoder->free_image_segs) { - LzImageSegment *seg = encoder->free_image_segs; - encoder->free_image_segs = seg->next; - encoder->usr->free(encoder->usr, seg); - } -} - -// return FALSE when operation fails (due to failure in allocation) -static int lz_read_image_segments(Encoder *encoder, uint8_t *first_lines, - unsigned int num_first_lines) -{ - LzImageSegment *image_seg; - uint32_t size_delta = 0; - unsigned int num_lines = num_first_lines; - uint8_t* lines = first_lines; - int row; - - ASSERT(encoder->usr, !encoder->head_image_segs); - - image_seg = lz_alloc_image_seg(encoder); - if (!image_seg) { - goto error_1; - } - - image_seg->lines = lines; - image_seg->lines_end = lines + num_lines * encoder->stride; - image_seg->size_delta = size_delta; - - size_delta += num_lines * encoder->stride / RGB_BYTES_PER_PIXEL[encoder->type]; - - for (row = num_first_lines; row < encoder->height; row += num_lines) { - num_lines = encoder->usr->more_lines(encoder->usr, &lines); - if (num_lines <= 0) { - encoder->usr->error(encoder->usr, "more lines failed\n"); - } - image_seg = lz_alloc_image_seg(encoder); - - if (!image_seg) { - goto error_1; - } - - image_seg->lines = lines; - image_seg->lines_end = lines + num_lines * encoder->stride; - image_seg->size_delta = size_delta; - - size_delta += num_lines * encoder->stride / RGB_BYTES_PER_PIXEL[encoder->type]; - } - - return TRUE; -error_1: - lz_reset_image_seg(encoder); - return FALSE; -} - -/************************************************************************** -* Handling encoding and decoding of a byte -***************************************************************************/ -static INLINE int more_io_bytes(Encoder *encoder) -{ - uint8_t *io_ptr; - int num_io_bytes = encoder->usr->more_space(encoder->usr, &io_ptr); - encoder->io_bytes_count += num_io_bytes; - encoder->io_now = io_ptr; - encoder->io_end = encoder->io_now + num_io_bytes; - return num_io_bytes; -} - -static INLINE void encode(Encoder *encoder, uint8_t byte) -{ - if (encoder->io_now == encoder->io_end) { - if (more_io_bytes(encoder) <= 0) { - encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__); - } - ASSERT(encoder->usr, encoder->io_now); - } - - ASSERT(encoder->usr, encoder->io_now < encoder->io_end); - *(encoder->io_now++) = byte; -} - -static INLINE void encode_32(Encoder *encoder, unsigned int word) -{ - encode(encoder, (uint8_t)(word >> 24)); - encode(encoder, (uint8_t)(word >> 16) & 0x0000ff); - encode(encoder, (uint8_t)(word >> 8) & 0x0000ff); - encode(encoder, (uint8_t)(word & 0x0000ff)); -} - -static INLINE void encode_copy_count(Encoder *encoder, uint8_t copy_count) -{ - encode(encoder, copy_count); - encoder->io_last_copy = encoder->io_now - 1; // io_now cannot be the first byte of the buffer -} - -static INLINE void update_copy_count(Encoder *encoder, uint8_t copy_count) -{ - ASSERT(encoder->usr, encoder->io_last_copy); - *(encoder->io_last_copy) = copy_count; -} - -static INLINE void encode_level(Encoder *encoder, uint8_t level_code) -{ - *(encoder->io_start) |= level_code; -} - -// decrease the io ptr by 1 -static INLINE void compress_output_prev(Encoder *encoder) -{ - // io_now cannot be the first byte of the buffer - encoder->io_now--; - // the function should be called only when copy count is written unnecessarily by lz_compress - ASSERT(encoder->usr, encoder->io_now == encoder->io_last_copy) -} - -static int encoder_reset(Encoder *encoder, uint8_t *io_ptr, uint8_t *io_ptr_end) -{ - ASSERT(encoder->usr, io_ptr <= io_ptr_end); - encoder->io_bytes_count = io_ptr_end - io_ptr; - encoder->io_start = io_ptr; - encoder->io_now = io_ptr; - encoder->io_end = io_ptr_end; - encoder->io_last_copy = NULL; - - return TRUE; -} - -static INLINE uint8_t decode(Encoder *encoder) -{ - if (encoder->io_now == encoder->io_end) { - int num_io_bytes = more_io_bytes(encoder); - if (num_io_bytes <= 0) { - encoder->usr->error(encoder->usr, "%s: no more bytes\n", __FUNCTION__); - } - ASSERT(encoder->usr, encoder->io_now); - } - ASSERT(encoder->usr, encoder->io_now < encoder->io_end); - return *(encoder->io_now++); -} - -static INLINE uint32_t decode_32(Encoder *encoder) -{ - uint32_t word = 0; - word |= decode(encoder); - word <<= 8; - word |= decode(encoder); - word <<= 8; - word |= decode(encoder); - word <<= 8; - word |= decode(encoder); - return word; -} - -static INLINE int is_io_to_decode_end(Encoder *encoder) -{ - if (encoder->io_now != encoder->io_end) { - return FALSE; - } else { - int num_io_bytes = more_io_bytes(encoder); //disable inline optimizations - return (num_io_bytes <= 0); - } -} - -/******************************************************************* -* intialization and finalization of lz -********************************************************************/ -static int init_encoder(Encoder *encoder, LzUsrContext *usr) -{ - encoder->usr = usr; - encoder->free_image_segs = NULL; - encoder->head_image_segs = NULL; - encoder->tail_image_segs = NULL; - return TRUE; -} - -LzContext *lz_create(LzUsrContext *usr) -{ - Encoder *encoder; - - if (!usr || !usr->error || !usr->warn || !usr->info || !usr->malloc || - !usr->free || !usr->more_space || !usr->more_lines) { - return NULL; - } - - if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) { - return NULL; - } - - if (!init_encoder(encoder, usr)) { - usr->free(usr, encoder); - return NULL; - } - return (LzContext *)encoder; -} - -void lz_destroy(LzContext *lz) -{ - Encoder *encoder = (Encoder *)lz; - - if (!lz) { - return; - } - - if (encoder->head_image_segs) { - encoder->usr->error(encoder->usr, "%s: used_image_segments not empty\n", __FUNCTION__); - lz_reset_image_seg(encoder); - } - lz_dealloc_free_segments(encoder); - - encoder->usr->free(encoder->usr, encoder); -} - -/******************************************************************* -* encoding and decoding the image -********************************************************************/ -/* - * Give hints to the compiler for branch prediction optimization. - */ -#if defined(__GNUC__) && (__GNUC__ > 2) -#define LZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) -#define LZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) -#else -#define LZ_EXPECT_CONDITIONAL(c) (c) -#define LZ_UNEXPECT_CONDITIONAL(c) (c) -#endif - - -#ifdef __GNUC__ -#define ATTR_PACKED __attribute__ ((__packed__)) -#else -#define ATTR_PACKED -#pragma pack(push) -#pragma pack(1) -#endif - - -/* the palette images will be treated as one byte pixels. Their width should be transformed - accordingly. -*/ -typedef struct ATTR_PACKED one_byte_pixel_t { - uint8_t a; -} one_byte_pixel_t; - -typedef struct ATTR_PACKED rgb32_pixel_t { - uint8_t b; - uint8_t g; - uint8_t r; - uint8_t pad; -} rgb32_pixel_t; - -typedef struct ATTR_PACKED rgb24_pixel_t { - uint8_t b; - uint8_t g; - uint8_t r; -} rgb24_pixel_t; - -typedef uint16_t rgb16_pixel_t; - -#ifndef __GNUC__ -#pragma pack(pop) -#endif - -#undef ATTR_PACKED - - -#define MAX_COPY 32 -#define MAX_LEN 264 /* 256 + 8 */ -#define BOUND_OFFSET 2 -#define LIMIT_OFFSET 6 -#define MIN_FILE_SIZE 4 -#define COMP_LEVEL_SIZE_LIMIT 65536 - -// TODO: implemented lz2. should lz1 be an option (no RLE + distance limitation of MAX_DISTANCE) -// TODO: I think MAX_FARDISTANCE can be changed easily to 2^29 -// (and maybe even more when pixel > byte). -// i.e. we can support 512M Bytes/Pixels distance instead of only ~68K. -#define MAX_DISTANCE 8191 // 2^13 -#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1) // ~2^16+2^13 - - -#define LZ_PLT -#include "lz_compress_tmpl.c" -#define LZ_PLT -#include "lz_decompress_tmpl.c" - -#define LZ_PLT -#define PLT8 -#define TO_RGB32 -#include "lz_decompress_tmpl.c" - -#define LZ_PLT -#define PLT4_BE -#define TO_RGB32 -#include "lz_decompress_tmpl.c" - -#define LZ_PLT -#define PLT4_LE -#define TO_RGB32 -#include "lz_decompress_tmpl.c" - -#define LZ_PLT -#define PLT1_BE -#define TO_RGB32 -#include "lz_decompress_tmpl.c" - -#define LZ_PLT -#define PLT1_LE -#define TO_RGB32 -#include "lz_decompress_tmpl.c" - - -#define LZ_RGB16 -#include "lz_compress_tmpl.c" -#define LZ_RGB16 -#include "lz_decompress_tmpl.c" -#define LZ_RGB16 -#define TO_RGB32 -#include "lz_decompress_tmpl.c" - -#define LZ_RGB24 -#include "lz_compress_tmpl.c" -#define LZ_RGB24 -#include "lz_decompress_tmpl.c" - - -#define LZ_RGB32 -#include "lz_compress_tmpl.c" -#define LZ_RGB32 -#include "lz_decompress_tmpl.c" - -#define LZ_RGB_ALPHA -#include "lz_compress_tmpl.c" -#define LZ_RGB_ALPHA -#include "lz_decompress_tmpl.c" - -#undef LZ_UNEXPECT_CONDITIONAL -#undef LZ_EXPECT_CONDITIONAL - -int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down, - uint8_t *lines, unsigned int num_lines, int stride, - uint8_t *io_ptr, unsigned int num_io_bytes) -{ - Encoder *encoder = (Encoder *)lz; - uint8_t *io_ptr_end = io_ptr + num_io_bytes; - - encoder->type = type; - encoder->width = width; - encoder->height = height; - encoder->stride = stride; - - if (IS_IMAGE_TYPE_PLT[encoder->type]) { - if (encoder->stride > (width / PLT_PIXELS_PER_BYTE[encoder->type])) { - if (((width % PLT_PIXELS_PER_BYTE[encoder->type]) == 0) || ( - (encoder->stride - (width / PLT_PIXELS_PER_BYTE[encoder->type])) > 1)) { - encoder->usr->error(encoder->usr, "stride overflows (plt)\n"); - } - } - } else { - if (encoder->stride != width * RGB_BYTES_PER_PIXEL[encoder->type]) { - encoder->usr->error(encoder->usr, "stride != width*bytes_per_pixel (rgb)\n"); - } - } - - // assign the output buffer - if (!encoder_reset(encoder, io_ptr, io_ptr_end)) { - encoder->usr->error(encoder->usr, "lz encoder io reset failed\n"); - } - - // first read the list of the image segments - if (!lz_read_image_segments(encoder, lines, num_lines)) { - encoder->usr->error(encoder->usr, "lz encoder reading image segments failed\n"); - } - - encode_32(encoder, LZ_MAGIC); - encode_32(encoder, LZ_VERSION); - encode_32(encoder, type); - encode_32(encoder, width); - encode_32(encoder, height); - encode_32(encoder, stride); - encode_32(encoder, top_down); // TODO: maybe compress type and top_down to one byte - - switch (encoder->type) { - case LZ_IMAGE_TYPE_PLT1_BE: - case LZ_IMAGE_TYPE_PLT1_LE: - case LZ_IMAGE_TYPE_PLT4_BE: - case LZ_IMAGE_TYPE_PLT4_LE: - case LZ_IMAGE_TYPE_PLT8: - lz_plt_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGB16: - lz_rgb16_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGB24: - lz_rgb24_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGB32: - lz_rgb32_compress(encoder); - break; - case LZ_IMAGE_TYPE_RGBA: - lz_rgb32_compress(encoder); - lz_rgb_alpha_compress(encoder); - break; - case LZ_IMAGE_TYPE_XXXA: - lz_rgb_alpha_compress(encoder); - break; - case LZ_IMAGE_TYPE_INVALID: - default: - encoder->usr->error(encoder->usr, "bad image type\n"); - } - - // move all the used segments to the free ones - lz_reset_image_seg(encoder); - - encoder->io_bytes_count -= (encoder->io_end - encoder->io_now); - - return encoder->io_bytes_count; -} - -/* - initialize and read lz magic -*/ -void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes, - LzImageType *out_type, int *out_width, int *out_height, - int *out_n_pixels, int *out_top_down, const SpicePalette *palette) -{ - Encoder *encoder = (Encoder *)lz; - uint8_t *io_ptr_end = io_ptr + num_io_bytes; - uint32_t magic; - uint32_t version; - - if (!encoder_reset(encoder, io_ptr, io_ptr_end)) { - encoder->usr->error(encoder->usr, "io reset failed"); - } - - magic = decode_32(encoder); - if (magic != LZ_MAGIC) { - encoder->usr->error(encoder->usr, "bad magic\n"); - } - - version = decode_32(encoder); - if (version != LZ_VERSION) { - encoder->usr->error(encoder->usr, "bad version\n"); - } - - encoder->type = (LzImageType)decode_32(encoder); - encoder->width = decode_32(encoder); - encoder->height = decode_32(encoder); - encoder->stride = decode_32(encoder); - *out_top_down = decode_32(encoder); - - *out_width = encoder->width; - *out_height = encoder->height; -// *out_stride = encoder->stride; - *out_type = encoder->type; - - // TODO: maybe instead of stride we can encode out_n_pixels - // (if stride is not necessary in decoding). - if (IS_IMAGE_TYPE_PLT[encoder->type]) { - encoder->palette = palette; - *out_n_pixels = encoder->stride * PLT_PIXELS_PER_BYTE[encoder->type] * encoder->height; - } else { - *out_n_pixels = encoder->width * encoder->height; - } -} - -void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf) -{ - Encoder *encoder = (Encoder *)lz; - size_t out_size = 0; - size_t alpha_size = 0; - size_t size = 0; - if (IS_IMAGE_TYPE_PLT[encoder->type]) { - if (to_type == encoder->type) { - size = encoder->height * encoder->stride; - out_size = lz_plt_decompress(encoder, (one_byte_pixel_t *)buf, size); - } else if (to_type == LZ_IMAGE_TYPE_RGB32) { - size = encoder->height * encoder->stride * PLT_PIXELS_PER_BYTE[encoder->type]; - if (!encoder->palette) { - encoder->usr->error(encoder->usr, - "a palette is missing (for bpp to rgb decoding)\n"); - } - switch (encoder->type) { - case LZ_IMAGE_TYPE_PLT1_BE: - out_size = lz_plt1_be_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - break; - case LZ_IMAGE_TYPE_PLT1_LE: - out_size = lz_plt1_le_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - break; - case LZ_IMAGE_TYPE_PLT4_BE: - out_size = lz_plt4_be_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - break; - case LZ_IMAGE_TYPE_PLT4_LE: - out_size = lz_plt4_le_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - break; - case LZ_IMAGE_TYPE_PLT8: - out_size = lz_plt8_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - break; - case LZ_IMAGE_TYPE_RGB16: - case LZ_IMAGE_TYPE_RGB24: - case LZ_IMAGE_TYPE_RGB32: - case LZ_IMAGE_TYPE_RGBA: - case LZ_IMAGE_TYPE_XXXA: - case LZ_IMAGE_TYPE_INVALID: - default: - encoder->usr->error(encoder->usr, "bad image type\n"); - } - } else { - encoder->usr->error(encoder->usr, "unsupported output format\n"); - } - } else { - size = encoder->height * encoder->width; - switch (encoder->type) { - case LZ_IMAGE_TYPE_RGB16: - if (encoder->type == to_type) { - out_size = lz_rgb16_decompress(encoder, (rgb16_pixel_t *)buf, size); - } else if (to_type == LZ_IMAGE_TYPE_RGB32) { - out_size = lz_rgb16_to_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - } else { - encoder->usr->error(encoder->usr, "unsupported output format\n"); - } - break; - case LZ_IMAGE_TYPE_RGB24: - if (encoder->type == to_type) { - out_size = lz_rgb24_decompress(encoder, (rgb24_pixel_t *)buf, size); - } else if (to_type == LZ_IMAGE_TYPE_RGB32) { - out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - } else { - encoder->usr->error(encoder->usr, "unsupported output format\n"); - } - break; - case LZ_IMAGE_TYPE_RGB32: - if (encoder->type == to_type) { - out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - } else { - encoder->usr->error(encoder->usr, "unsupported output format\n"); - } - break; - case LZ_IMAGE_TYPE_RGBA: - if (encoder->type == to_type) { - out_size = lz_rgb32_decompress(encoder, (rgb32_pixel_t *)buf, size); - alpha_size = lz_rgb_alpha_decompress(encoder, (rgb32_pixel_t *)buf, size); - ASSERT(encoder->usr, alpha_size == size); - } else { - encoder->usr->error(encoder->usr, "unsupported output format\n"); - } - break; - case LZ_IMAGE_TYPE_XXXA: - if (encoder->type == to_type) { - alpha_size = lz_rgb_alpha_decompress(encoder, (rgb32_pixel_t *)buf, size); - out_size = alpha_size; - } else { - encoder->usr->error(encoder->usr, "unsupported output format\n"); - } - break; - case LZ_IMAGE_TYPE_PLT1_LE: - case LZ_IMAGE_TYPE_PLT1_BE: - case LZ_IMAGE_TYPE_PLT4_LE: - case LZ_IMAGE_TYPE_PLT4_BE: - case LZ_IMAGE_TYPE_PLT8: - case LZ_IMAGE_TYPE_INVALID: - default: - encoder->usr->error(encoder->usr, "bad image type\n"); - } - } - - ASSERT(encoder->usr, is_io_to_decode_end(encoder)); - ASSERT(encoder->usr, out_size == size); - - if (out_size != size) { - encoder->usr->error(encoder->usr, "bad decode size\n"); - } -} diff --git a/common/lz.h b/common/lz.h deleted file mode 100644 index 472e34dd..00000000 --- a/common/lz.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - dictionary compression for images based on fastlz (http://www.fastlz.org/) - (Distributed under MIT license). -*/ -#ifndef __LZ_H -#define __LZ_H - -#include "lz_common.h" -#include "lz_config.h" -#include "draw.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void *LzContext; - -typedef struct LzUsrContext LzUsrContext; -struct LzUsrContext { - void (*error)(LzUsrContext *usr, const char *fmt, ...); - void (*warn)(LzUsrContext *usr, const char *fmt, ...); - void (*info)(LzUsrContext *usr, const char *fmt, ...); - void *(*malloc)(LzUsrContext *usr, int size); - void (*free)(LzUsrContext *usr, void *ptr); - int (*more_space)(LzUsrContext *usr, uint8_t **io_ptr); // get the next chunk of the - // compressed buffer. return - // number of bytes in the chunk. - int (*more_lines)(LzUsrContext *usr, uint8_t **lines); // get the next chunk of the - // original image. If the image - // is down to top, return it from - // the last line to the first one - // (stride should always be - // positive) -}; - -/* - assumes width is in pixels and stride is in bytes - return: the number of bytes in the compressed data - - TODO : determine size limit for the first segment and each chunk. check validity - of the segment or go to literal copy. - TODO : currently support only rgb images in which width*bytes_per_pixel = stride OR - palette images in which stride equals the min number of bytes to - hold a line. stride is not necessary for now. just for sanity check. - stride should be > 0 -*/ -int lz_encode(LzContext *lz, LzImageType type, int width, int height, int top_down, - uint8_t *lines, unsigned int num_lines, int stride, - uint8_t *io_ptr, unsigned int num_io_bytes); - -/* - prepare encoder and read lz magic. - out_n_pixels number of compressed pixels. May differ from Width*height in plt1/4. - Use it for allocation the decompressed buffer. - -*/ -void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes, - LzImageType *out_type, int *out_width, int *out_height, - int *out_n_pixels, int *out_top_down, const SpicePalette *palette); - -/* - to_type = the image output type. - We assume the buffer is consecutive. i.e. width = stride - - Important: if the image is plt1/4 and to_type is rgb32, the image - will decompressed including the last bits in each line. This means buffer should be - larger than width*height if needed and you should use stride to fix it. - Note: If the image is down to top, set the stride in the sw surface to negative. - use alloc_lz_image_surface create the surface. -*/ -void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf); - -LzContext *lz_create(LzUsrContext *usr); - -void lz_destroy(LzContext *lz); - -#ifdef __cplusplus -} -#endif - -#endif // __LZ_H diff --git a/common/lz_common.h b/common/lz_common.h deleted file mode 100644 index 4156cffc..00000000 --- a/common/lz_common.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -/*common header for encoder and decoder*/ - -#ifndef _LZ_COMMON_H -#define _LZ_COMMON_H - -#ifdef __cplusplus -extern "C" { -#endif - -//#define DEBUG - -/* change the max window size will require change in the encoding format*/ -#define LZ_MAX_WINDOW_SIZE (1 << 25) -#define MAX_COPY 32 - -typedef enum { - LZ_IMAGE_TYPE_INVALID, - LZ_IMAGE_TYPE_PLT1_LE, - LZ_IMAGE_TYPE_PLT1_BE, // PLT stands for palette - LZ_IMAGE_TYPE_PLT4_LE, - LZ_IMAGE_TYPE_PLT4_BE, - LZ_IMAGE_TYPE_PLT8, - LZ_IMAGE_TYPE_RGB16, - LZ_IMAGE_TYPE_RGB24, - LZ_IMAGE_TYPE_RGB32, - LZ_IMAGE_TYPE_RGBA, - LZ_IMAGE_TYPE_XXXA -} LzImageType; - -#define LZ_IMAGE_TYPE_MASK 0x0f -#define LZ_IMAGE_TYPE_LOG 4 // number of bits required for coding the image type - -/* access to the arrays is based on the image types */ -static const int IS_IMAGE_TYPE_PLT[] = {0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; -static const int IS_IMAGE_TYPE_RGB[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; -static const int PLT_PIXELS_PER_BYTE[] = {0, 8, 8, 2, 2, 1}; -static const int RGB_BYTES_PER_PIXEL[] = {0, 1, 1, 1, 1, 1, 2, 3, 4, 4, 4}; - - -#define LZ_MAGIC (*(uint32_t *)"LZ ") -#define LZ_VERSION_MAJOR 1U -#define LZ_VERSION_MINOR 1U -#define LZ_VERSION ((LZ_VERSION_MAJOR << 16) | (LZ_VERSION_MINOR & 0xffff)) - -#ifdef __cplusplus -} -#endif - -#endif // _LZ_COMMON_H diff --git a/common/lz_compress_tmpl.c b/common/lz_compress_tmpl.c deleted file mode 100644 index 6db53872..00000000 --- a/common/lz_compress_tmpl.c +++ /dev/null @@ -1,529 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - - Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - This file incorporates work covered by the following copyright and - permission notice: - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, copy, - modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#define DJB2_START 5381; -#define DJB2_HASH(hash, c) (hash = ((hash << 5) + hash) ^ (c)) //|{hash = ((hash << 5) + hash) + c;} - -/* - For each pixel type the following macros are defined: - PIXEL : input type - FNAME(name) - ENCODE_PIXEL(encoder, pixel) : writing a pixel to the compressed buffer (byte by byte) - SAME_PIXEL(pix1, pix2) : comparing two pixels - HASH_FUNC(value, pix_ptr) : hash func of 3 consecutive pixels -*/ - -#ifdef LZ_PLT -#define PIXEL one_byte_pixel_t -#define FNAME(name) lz_plt_##name -#define ENCODE_PIXEL(e, pix) encode(e, (pix).a) // gets the pixel and write only the needed bytes - // from the pixel -#define SAME_PIXEL(pix1, pix2) ((pix1).a == (pix2).a) -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0].a); \ - DJB2_HASH(v, p[1].a); \ - DJB2_HASH(v, p[2].a); \ - v &= HASH_MASK; \ - } -#endif - -#ifdef LZ_RGB_ALPHA -//#undef LZ_RGB_ALPHA -#define PIXEL rgb32_pixel_t -#define FNAME(name) lz_rgb_alpha_##name -#define ENCODE_PIXEL(e, pix) {encode(e, (pix).pad);} -#define SAME_PIXEL(pix1, pix2) ((pix1).pad == (pix2).pad) -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0].pad); \ - DJB2_HASH(v, p[1].pad); \ - DJB2_HASH(v, p[2].pad); \ - v &= HASH_MASK; \ - } -#endif - - -#ifdef LZ_RGB16 -#define PIXEL rgb16_pixel_t -#define FNAME(name) lz_rgb16_##name -#define GET_r(pix) (((pix) >> 10) & 0x1f) -#define GET_g(pix) (((pix) >> 5) & 0x1f) -#define GET_b(pix) ((pix) & 0x1f) -#define ENCODE_PIXEL(e, pix) {encode(e, (pix) >> 8); encode(e, (pix) & 0xff);} - -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0] & (0x00ff)); \ - DJB2_HASH(v, (p[0] >> 8) & (0x007f)); \ - DJB2_HASH(v, p[1]&(0x00ff)); \ - DJB2_HASH(v, (p[1] >> 8) & (0x007f)); \ - DJB2_HASH(v, p[2] & (0x00ff)); \ - DJB2_HASH(v, (p[2] >> 8) & (0x007f)); \ - v &= HASH_MASK; \ -} -#endif - -#ifdef LZ_RGB24 -#define PIXEL rgb24_pixel_t -#define FNAME(name) lz_rgb24_##name -#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);} -#endif - -#ifdef LZ_RGB32 -#define PIXEL rgb32_pixel_t -#define FNAME(name) lz_rgb32_##name -#define ENCODE_PIXEL(e, pix) {encode(e, (pix).b); encode(e, (pix).g); encode(e, (pix).r);} -#endif - - -#if defined(LZ_RGB24) || defined(LZ_RGB32) -#define GET_r(pix) ((pix).r) -#define GET_g(pix) ((pix).g) -#define GET_b(pix) ((pix).b) -#define HASH_FUNC(v, p) { \ - v = DJB2_START; \ - DJB2_HASH(v, p[0].r); \ - DJB2_HASH(v, p[0].g); \ - DJB2_HASH(v, p[0].b); \ - DJB2_HASH(v, p[1].r); \ - DJB2_HASH(v, p[1].g); \ - DJB2_HASH(v, p[1].b); \ - DJB2_HASH(v, p[2].r); \ - DJB2_HASH(v, p[2].g); \ - DJB2_HASH(v, p[2].b); \ - v &= HASH_MASK; \ - } -#endif - -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) -#define SAME_PIXEL(p1, p2) (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \ - GET_b(p1) == GET_b(p2)) - -#endif - -#define PIXEL_ID(pix_ptr, seg_ptr) (pix_ptr - ((PIXEL *)seg_ptr->lines) + seg_ptr->size_delta) - -// when encoding, the ref can be in previous segment, and we should check that it doesn't -// exceeds its bounds. -// TODO: optimization: when only one chunk exists or when the reference is in the same segment, -// don't make checks if we reach end of segments -// TODO: optimize to continue match between segments? -// TODO: check hash function -// TODO: check times - -/* compresses one segment starting from 'from'.*/ -static void FNAME(compress_seg)(Encoder *encoder, LzImageSegment *seg, PIXEL *from, int copied) -{ - const PIXEL *ip = from; - const PIXEL *ip_bound = (PIXEL *)(seg->lines_end) - BOUND_OFFSET; - const PIXEL *ip_limit = (PIXEL *)(seg->lines_end) - LIMIT_OFFSET; - HashEntry *hslot; - int hval; - int copy = copied; - - if (copy == 0) { - encode_copy_count(encoder, MAX_COPY - 1); - } - - - while (LZ_EXPECT_CONDITIONAL(ip < ip_limit)) { // TODO: maybe change ip_limit and enabling - // moving to the next seg - const PIXEL *ref; - const PIXEL *ref_limit; - size_t distance; - - /* minimum match length */ -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - size_t len = 3; -#elif defined(LZ_RGB16) - size_t len = 2; -#else - size_t len = 1; -#endif - /* comparison starting-point */ - const PIXEL *anchor = ip; - - - - // TODO: RLE without checking if not first byte. - // TODO: optimize comparisons - - /* check for a run */ // TODO for RGB we can use less pixels - if (LZ_EXPECT_CONDITIONAL(ip > (PIXEL *)(seg->lines))) { - if (SAME_PIXEL(ip[-1], ip[0]) && SAME_PIXEL(ip[0], ip[1]) && SAME_PIXEL(ip[1], ip[2])) { - distance = 1; - ip += 3; - ref = anchor + 2; - ref_limit = (PIXEL *)(seg->lines_end); -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) - len = 3; -#endif - goto match; - } - } - - /* find potential match */ - HASH_FUNC(hval, ip); - hslot = encoder->htab + hval; - ref = (PIXEL *)(hslot->ref); - ref_limit = (PIXEL *)(hslot->image_seg->lines_end); - - /* calculate distance to the match */ - distance = PIXEL_ID(anchor, seg) - PIXEL_ID(ref, hslot->image_seg); - - /* update hash table */ - hslot->image_seg = seg; - hslot->ref = (uint8_t *)anchor; - - /* is this a match? check the first 3 pixels */ - if (distance == 0 || (distance >= MAX_FARDISTANCE)) { - goto literal; - } - /* check if the hval key identical*/ - // no need to check ref limit here because the word size in the htab is 3 pixels - if (!SAME_PIXEL(*ref, *ip)) { - ref++; - ip++; - goto literal; - } - ref++; - ip++; - - /* minimum match length for rgb16 is 2 and for plt and alpha is 3 */ -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) || defined(LZ_RGB16) - if (!SAME_PIXEL(*ref, *ip)) { - ref++; - ip++; - goto literal; - } - ref++; - ip++; -#endif - -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - if (!SAME_PIXEL(*ref, *ip)) { - ref++; - ip++; - goto literal; - } - ref++; - ip++; -#endif - /* far, needs at least 5-byte match */ - if (distance >= MAX_DISTANCE) { -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - if (ref >= (ref_limit - 1)) { - goto literal; - } -#else - if (ref > (ref_limit - 1)) { - goto literal; - } -#endif - if (!SAME_PIXEL(*ref, *ip)) { - ref++; - ip++; - goto literal; - } - ref++; - ip++; - len++; -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - if (!SAME_PIXEL(*ref, *ip)) { - ref++; - ip++; - goto literal; - } - ref++; - ip++; - len++; -#endif - } -match: // RLE or dictionary (both are encoded by distance from ref (-1) and length) - - /* distance is biased */ - distance--; - - // ip is located now at the position of the second mismatch. - // later it will be subtracted by 3 - - if (!distance) { - /* zero distance means a run */ - PIXEL x = *ref; - while ((ip < ip_bound) && (ref < ref_limit)) { // TODO: maybe separate a run from - // the same seg or from different - // ones in order to spare - // ref < ref_limit - if (!SAME_PIXEL(*ref, x)) { - ref++; - break; - } else { - ref++; - ip++; - } - } - } else { - // TODO: maybe separate a run from the same seg or from different ones in order - // to spare ref < ref_limit and that way we can also perform 8 calls of - // (ref++ != ip++) outside a loop - for (;;) { - while ((ip < ip_bound) && (ref < ref_limit)) { - if (!SAME_PIXEL(*ref, *ip)) { - ref++; - ip++; - break; - } else { - ref++; - ip++; - } - } - break; - } - } - - /* if we have copied something, adjust the copy count */ - if (copy) { - /* copy is biased, '0' means 1 byte copy */ - update_copy_count(encoder, copy - 1); - } else { - /* back, to overwrite the copy count */ - compress_output_prev(encoder); - } - - /* reset literal counter */ - copy = 0; - - /* length is biased, '1' means a match of 3 pixels for PLT and alpha*/ - /* for RGB 16 1 means 2 */ - /* for RGB24/32 1 means 1...*/ - ip -= 3; - len = ip - anchor; -#if defined(LZ_RGB16) - len++; -#elif defined(LZ_RGB24) || defined(LZ_RGB32) - len += 2; -#endif - /* encode the match (like fastlz level 2)*/ - if (distance < MAX_DISTANCE) { // MAX_DISTANCE is 2^13 - 1 - // when copy is performed, the byte that holds the copy count is smaller than 32. - // When there is a reference, the first byte is always larger then 32 - - // 3 bits = length, 5 bits = 5 MSB of distance, 8 bits = 8 LSB of distance - if (len < 7) { - encode(encoder, (uint8_t)((len << 5) + (distance >> 8))); - encode(encoder, (uint8_t)(distance & 255)); - } else { // more than 3 bits are needed for length - // 3 bits 7, 5 bits = 5 MSB of distance, next bytes are 255 till we - // receive a smaller number, last byte = 8 LSB of distance - encode(encoder, (uint8_t)((7 << 5) + (distance >> 8))); - for (len -= 7; len >= 255; len -= 255) { - encode(encoder, 255); - } - encode(encoder, (uint8_t)len); - encode(encoder, (uint8_t)(distance & 255)); - } - } else { - /* far away */ - if (len < 7) { // the max_far_distance is ~2^16+2^13 so two more bytes are needed - // 3 bits = length, 5 bits = 5 MSB of MAX_DISTANCE, 8 bits = 8 LSB of MAX_DISTANCE, - // 8 bits = 8 MSB distance-MAX_distance (smaller than 2^16),8 bits=8 LSB of - // distance-MAX_distance - distance -= MAX_DISTANCE; - encode(encoder, (uint8_t)((len << 5) + 31)); - encode(encoder, (uint8_t)255); - encode(encoder, (uint8_t)(distance >> 8)); - encode(encoder, (uint8_t)(distance & 255)); - } else { - // same as before, but the first byte is followed by the left overs of len - distance -= MAX_DISTANCE; - encode(encoder, (uint8_t)((7 << 5) + 31)); - for (len -= 7; len >= 255; len -= 255) { - encode(encoder, 255); - } - encode(encoder, (uint8_t)len); - encode(encoder, 255); - encode(encoder, (uint8_t)(distance >> 8)); - encode(encoder, (uint8_t)(distance & 255)); - } - } - - /* update the hash at match boundary */ -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) - if (ip > anchor) { -#endif - HASH_FUNC(hval, ip); - encoder->htab[hval].ref = (uint8_t *)ip; - ip++; - encoder->htab[hval].image_seg = seg; -#if defined(LZ_RGB16) || defined(LZ_RGB24) || defined(LZ_RGB32) - } else {ip++; - } -#endif -#if defined(LZ_RGB24) || defined(LZ_RGB32) - if (ip > anchor) { -#endif - HASH_FUNC(hval, ip); - encoder->htab[hval].ref = (uint8_t *)ip; - ip++; - encoder->htab[hval].image_seg = seg; -#if defined(LZ_RGB24) || defined(LZ_RGB32) - } else {ip++; - } -#endif - /* assuming literal copy */ - encode_copy_count(encoder, MAX_COPY - 1); - continue; - -literal: - ENCODE_PIXEL(encoder, *anchor); - anchor++; - ip = anchor; - copy++; - - if (LZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) { - copy = 0; - encode_copy_count(encoder, MAX_COPY - 1); - } - } // END LOOP (ip < ip_limit) - - - /* left-over as literal copy */ - ip_bound++; - while (ip <= ip_bound) { - ENCODE_PIXEL(encoder, *ip); - ip++; - copy++; - if (copy == MAX_COPY) { - copy = 0; - encode_copy_count(encoder, MAX_COPY - 1); - } - } - - /* if we have copied something, adjust the copy length */ - if (copy) { - update_copy_count(encoder, copy - 1); - } else { - compress_output_prev(encoder); // in case we created a new buffer for copy, check that - // red_worker could handle size that do not contain the - // ne buffer - } -} - - -/* initializes the hash table. if the file is very small, copies it. - copies the first two pixels of the first segment, and sends the segments - one by one to compress_seg. - the number of bytes compressed are stored inside encoder. - */ -static void FNAME(compress)(Encoder *encoder) -{ - LzImageSegment *cur_seg = encoder->head_image_segs; - HashEntry *hslot; - PIXEL *ip; - - // fetch the first image segment that is not too small - while (cur_seg && ((((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) < 4)) { - // coping the segment - if (cur_seg->lines != cur_seg->lines_end) { - ip = (PIXEL *)cur_seg->lines; - // Note: we assume MAX_COPY > 3 - encode_copy_count(encoder, (uint8_t)( - (((PIXEL *)cur_seg->lines_end) - ((PIXEL *)cur_seg->lines)) - 1)); - while (ip < (PIXEL *)cur_seg->lines_end) { - ENCODE_PIXEL(encoder, *ip); - ip++; - } - } - cur_seg = cur_seg->next; - } - - if (!cur_seg) { - return; - } - - ip = (PIXEL *)cur_seg->lines; - - /* initialize hash table */ - for (hslot = encoder->htab; hslot < encoder->htab + HASH_SIZE; hslot++) { - hslot->ref = (uint8_t*)ip; - hslot->image_seg = cur_seg; - } - - encode_copy_count(encoder, MAX_COPY - 1); - ENCODE_PIXEL(encoder, *ip); - ip++; - ENCODE_PIXEL(encoder, *ip); - ip++; - - // compressing the first segment - FNAME(compress_seg)(encoder, cur_seg, ip, 2); - - // compressing the next segments - for (cur_seg = cur_seg->next; cur_seg; cur_seg = cur_seg->next) { - FNAME(compress_seg)(encoder, cur_seg, (PIXEL *)cur_seg->lines, 0); - } -} - -#undef FNAME -#undef PIXEL_ID -#undef PIXEL -#undef ENCODE_PIXEL -#undef SAME_PIXEL -#undef LZ_READU16 -#undef HASH_FUNC -#undef BYTES_TO_16 -#undef HASH_FUNC_16 -#undef GET_r -#undef GET_g -#undef GET_b -#undef GET_CODE -#undef LZ_PLT -#undef LZ_RGB_ALPHA -#undef LZ_RGB16 -#undef LZ_RGB24 -#undef LZ_RGB32 -#undef HASH_FUNC2 diff --git a/common/lz_config.h b/common/lz_config.h deleted file mode 100644 index d8675a88..00000000 --- a/common/lz_config.h +++ /dev/null @@ -1,39 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef __LZ_CONFIG_H -#define __LZ_CONFIG_H - -#include <spice/types.h> -#include <spice/macros.h> - -#ifdef __GNUC__ -#include <string.h> -#else -#ifdef QXLDD -#include <windef.h> -#include "os_dep.h" -#else -#include <stddef.h> -#include <string.h> -#endif // QXLDD -#endif //__GNUC__ - -#endif //__LZ_CONFIG_H diff --git a/common/lz_decompress_tmpl.c b/common/lz_decompress_tmpl.c deleted file mode 100644 index b0cbb2a9..00000000 --- a/common/lz_decompress_tmpl.c +++ /dev/null @@ -1,326 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - - Copyright (C) 2009 Red Hat, Inc. and/or its affiliates. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. - - This file incorporates work covered by the following copyright and - permission notice: - Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) - Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, copy, - modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -*/ - -// External defines: PLT, RGBX/PLTXX/ALPHA, TO_RGB32. -// If PLT4/1 and TO_RGB32 are defined, we need CAST_PLT_DISTANCE (because then the number of -// pixels differ from the units used in the compression) - -/* - For each output pixel type the following macros are defined: - OUT_PIXEL - the output pixel type - COPY_PIXEL(p, out) - assigns the pixel to the place pointed by out and increases - out. Used in RLE. Need special handling because in alpha we - copy only the pad byte. - COPY_REF_PIXEL(ref, out) - copies the pixel pointed by ref to the pixel pointed by out. - Increases ref and out. - COPY_COMP_PIXEL(encoder, out) - copies pixel from the compressed buffer to the decompressed - buffer. Increases out. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if !defined(LZ_RGB_ALPHA) -#define COPY_PIXEL(p, out) (*out++ = p) -#define COPY_REF_PIXEL(ref, out) (*out++ = *ref++) -#endif - - -// decompressing plt to plt -#ifdef LZ_PLT -#ifndef TO_RGB32 -#define OUT_PIXEL one_byte_pixel_t -#define FNAME(name) lz_plt_##name -#define COPY_COMP_PIXEL(encoder, out) {out->a = decode(encoder); out++;} -#else // TO_RGB32 -#define OUT_PIXEL rgb32_pixel_t -#define COPY_PLT_ENTRY(ent, out) { \ - (out)->b = ent; \ - (out)->g = (ent >> 8); \ - (out)->r = (ent >> 16); \ - (out)->pad = 0; \ -} -#ifdef PLT8 -#define FNAME(name) lz_plt8_to_rgb32_##name -#define COPY_COMP_PIXEL(encoder, out) { \ - uint32_t rgb = encoder->palette->ents[decode(encoder)]; \ - COPY_PLT_ENTRY(rgb, out); \ - out++;} -#elif defined(PLT4_BE) -#define FNAME(name) lz_plt4_be_to_rgb32_##name -#define COPY_COMP_PIXEL(encoder, out){ \ - uint8_t byte = decode(encoder); \ - uint32_t rgb = encoder->palette->ents[((byte >> 4) & 0x0f) % (encoder->palette->num_ents)]; \ - COPY_PLT_ENTRY(rgb, out); \ - out++; \ - rgb = encoder->palette->ents[(byte & 0x0f) % (encoder->palette->num_ents)]; \ - COPY_PLT_ENTRY(rgb, out); \ - out++; \ -} -#define CAST_PLT_DISTANCE(dist) (dist*2) -#elif defined(PLT4_LE) -#define FNAME(name) lz_plt4_le_to_rgb32_##name -#define COPY_COMP_PIXEL(encoder, out){ \ - uint8_t byte = decode(encoder); \ - uint32_t rgb = encoder->palette->ents[(byte & 0x0f) % (encoder->palette->num_ents)]; \ - COPY_PLT_ENTRY(rgb, out); \ - out++; \ - rgb = encoder->palette->ents[((byte >> 4) & 0x0f) % (encoder->palette->num_ents)]; \ - COPY_PLT_ENTRY(rgb, out); \ - out++; \ -} -#define CAST_PLT_DISTANCE(dist) (dist*2) -#elif defined(PLT1_BE) // TODO store palette entries for direct access -#define FNAME(name) lz_plt1_be_to_rgb32_##name -#define COPY_COMP_PIXEL(encoder, out){ \ - uint8_t byte = decode(encoder); \ - int i; \ - uint32_t fore = encoder->palette->ents[1]; \ - uint32_t back = encoder->palette->ents[0]; \ - for (i = 7; i >= 0; i--) \ - { \ - if ((byte >> i) & 1) { \ - COPY_PLT_ENTRY(fore, out); \ - } else { \ - COPY_PLT_ENTRY(back, out); \ - } \ - out++; \ - } \ -} -#define CAST_PLT_DISTANCE(dist) (dist*8) -#elif defined(PLT1_LE) -#define FNAME(name) lz_plt1_le_to_rgb32_##name -#define COPY_COMP_PIXEL(encoder, out){ \ - uint8_t byte = decode(encoder); \ - int i; \ - uint32_t fore = encoder->palette->ents[1]; \ - uint32_t back = encoder->palette->ents[0]; \ - for (i = 0; i < 8; i++) \ - { \ - if ((byte >> i) & 1) { \ - COPY_PLT_ENTRY(fore, out); \ - } else { \ - COPY_PLT_ENTRY(back, out); \ - } \ - out++; \ - } \ -} -#define CAST_PLT_DISTANCE(dist) (dist*8) -#endif // PLT Type -#endif // TO_RGB32 -#endif - -#ifdef LZ_RGB16 -#ifndef TO_RGB32 -#define OUT_PIXEL rgb16_pixel_t -#define FNAME(name) lz_rgb16_##name -#define COPY_COMP_PIXEL(e, out) {*out = ((decode(e) << 8) | decode(e)); out++;} -#else -#define OUT_PIXEL rgb32_pixel_t -#define FNAME(name) lz_rgb16_to_rgb32_##name -#define COPY_COMP_PIXEL(e, out) { \ - out->r = decode(e); \ - out->b = decode(e); \ - out->g = (((out->r) << 6) | ((out->b) >> 2)) & ~0x07; \ - out->g |= (out->g >> 5); \ - out->r = ((out->r << 1) & ~0x07)| ((out->r >> 4) & 0x07); \ - out->b = (out->b << 3) | ((out->b >> 2) & 0x07); \ - out->pad = 0; \ - out++; \ -} -#endif -#endif - -#ifdef LZ_RGB24 -#define OUT_PIXEL rgb24_pixel_t -#define FNAME(name) lz_rgb24_##name -#define COPY_COMP_PIXEL(e, out) {out->b = decode(e); out->g = decode(e); out->r = decode(e); out++;} -#endif - -#ifdef LZ_RGB32 -#define OUT_PIXEL rgb32_pixel_t -#define FNAME(name) lz_rgb32_##name -#define COPY_COMP_PIXEL(e, out) { \ - out->b = decode(e); \ - out->g = decode(e); \ - out->r = decode(e); \ - out->pad = 0; \ - out++; \ -} -#endif - -#ifdef LZ_RGB_ALPHA -#define OUT_PIXEL rgb32_pixel_t -#define FNAME(name) lz_rgb_alpha_##name -#define COPY_PIXEL(p, out) {out->pad = p.pad; out++;} -#define COPY_REF_PIXEL(ref, out) {out->pad = ref->pad; out++; ref++;} -#define COPY_COMP_PIXEL(e, out) {out->pad = decode(e); out++;} -#endif - -// return num of bytes in out_buf -static size_t FNAME(decompress)(Encoder *encoder, OUT_PIXEL *out_buf, int size) -{ - OUT_PIXEL *op = out_buf; - OUT_PIXEL *op_limit = out_buf + size; - uint32_t ctrl = decode(encoder); - int loop = TRUE; - - do { - const OUT_PIXEL *ref = op; - uint32_t len = ctrl >> 5; - uint32_t ofs = (ctrl & 31) << 8; // 5 MSb of distance - - if (ctrl >= MAX_COPY) { // reference (dictionary/RLE) - /* retrieving the reference and the match length */ - - uint8_t code; - len--; - //ref -= ofs; - if (len == 7 - 1) { // match length is bigger than 7 - do { - code = decode(encoder); - len += code; - } while (code == 255); // remaining of len - } - code = decode(encoder); - ofs += code; - - /* match from 16-bit distance */ - if (LZ_UNEXPECT_CONDITIONAL(code == 255)) { - if (LZ_EXPECT_CONDITIONAL((ofs - code) == (31 << 8))) { - ofs = decode(encoder) << 8; - ofs += decode(encoder); - ofs += MAX_DISTANCE; - } - } - -#if defined(LZ_PLT) || defined(LZ_RGB_ALPHA) - len += 3; // length is biased by 2 + 1 (fixing bias) -#elif defined(LZ_RGB16) - len += 2; // length is biased by 1 + 1 (fixing bias) -#else - len += 1; -#endif - ofs += 1; // offset is biased by 1 (fixing bias) - -#if defined(TO_RGB32) -#if defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || defined(PLT1_LE) - ofs = CAST_PLT_DISTANCE(ofs); - len = CAST_PLT_DISTANCE(len); -#endif -#endif - ref -= ofs; - - ASSERT(encoder->usr, op + len <= op_limit); - ASSERT(encoder->usr, ref + len <= op_limit); - ASSERT(encoder->usr, ref >= out_buf); - - // TODO: optimize by not calling loop at least 3 times when not PLT_TO_RGB32 (len is - // always >=3). in PLT_TO_RGB32 len >= 3*number_of_pixels_per_byte - - /* copying the match*/ - - if (ref == (op - 1)) { // run // TODO: this will never be called in PLT4/1_TO_RGB - // because the number of pixel copied is larger - // then one... - /* optimize copy for a run */ - OUT_PIXEL b = *ref; - for (; len; --len) { - COPY_PIXEL(b, op); - ASSERT(encoder->usr, op <= op_limit); - } - } else { - for (; len; --len) { - COPY_REF_PIXEL(ref, op); - ASSERT(encoder->usr, op <= op_limit); - } - } - } else { // copy - ctrl++; // copy count is biased by 1 -#if defined(TO_RGB32) && (defined(PLT4_BE) || defined(PLT4_LE) || defined(PLT1_BE) || \ - defined(PLT1_LE)) - ASSERT(encoder->usr, op + CAST_PLT_DISTANCE(ctrl) <= op_limit); -#else - ASSERT(encoder->usr, op + ctrl <= op_limit); -#endif - COPY_COMP_PIXEL(encoder, op); - - ASSERT(encoder->usr, op <= op_limit); - - for (--ctrl; ctrl; ctrl--) { - COPY_COMP_PIXEL(encoder, op); - ASSERT(encoder->usr, op <= op_limit); - } - } - - if (LZ_EXPECT_CONDITIONAL(op < op_limit)) { - ctrl = decode(encoder); - } else { - loop = FALSE; - } - } while (LZ_EXPECT_CONDITIONAL(loop)); - - return (op - out_buf); -} - -#undef LZ_PLT -#undef PLT8 -#undef PLT4_BE -#undef PLT4_LE -#undef PLT1_BE -#undef PLT1_LE -#undef LZ_RGB16 -#undef LZ_RGB24 -#undef LZ_RGB32 -#undef LZ_RGB_ALPHA -#undef TO_RGB32 -#undef OUT_PIXEL -#undef FNAME -#undef COPY_PIXEL -#undef COPY_REF_PIXEL -#undef COPY_COMP_PIXEL -#undef COPY_PLT_ENTRY -#undef CAST_PLT_DISTANCE diff --git a/common/marshaller.c b/common/marshaller.c deleted file mode 100644 index 9023d084..00000000 --- a/common/marshaller.c +++ /dev/null @@ -1,615 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2010 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "marshaller.h" -#include "mem.h" -#include <string.h> -#include <stdlib.h> -#include <assert.h> - -#ifdef WORDS_BIGENDIAN -#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v) -#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v) -#define write_int16(ptr,v) (*((int16_t *)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v))) -#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = SPICE_BYTESWAP16((uint16_t)(v))) -#define write_int32(ptr,v) (*((int32_t *)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v))) -#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = SPICE_BYTESWAP32((uint32_t)(v))) -#define write_int64(ptr,v) (*((int64_t *)(ptr)) = SPICE_BYTESWAP64((uint64_t)(v))) -#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = SPICE_BYTESWAP64((uint64_t)(v))) -#else -#define write_int8(ptr,v) (*((int8_t *)(ptr)) = v) -#define write_uint8(ptr,v) (*((uint8_t *)(ptr)) = v) -#define write_int16(ptr,v) (*((int16_t *)(ptr)) = v) -#define write_uint16(ptr,v) (*((uint16_t *)(ptr)) = v) -#define write_int32(ptr,v) (*((int32_t *)(ptr)) = v) -#define write_uint32(ptr,v) (*((uint32_t *)(ptr)) = v) -#define write_int64(ptr,v) (*((int64_t *)(ptr)) = v) -#define write_uint64(ptr,v) (*((uint64_t *)(ptr)) = v) -#endif - -typedef struct { - uint8_t *data; - size_t len; - spice_marshaller_item_free_func free_data; - void *opaque; -} MarshallerItem; - -/* Try to fit in 4k page with 2*pointer-size overhead (next ptr and malloc size) */ -#define MARSHALLER_BUFFER_SIZE (4096 - sizeof(void *) * 2) - -typedef struct MarshallerBuffer MarshallerBuffer; -struct MarshallerBuffer { - MarshallerBuffer *next; - uint8_t data[MARSHALLER_BUFFER_SIZE]; -}; - -#define N_STATIC_ITEMS 4 - -typedef struct SpiceMarshallerData SpiceMarshallerData; - -typedef struct { - SpiceMarshaller *marshaller; - int item_nr; - int is_64bit; - size_t offset; -} MarshallerRef; - -struct SpiceMarshaller { - size_t total_size; - SpiceMarshallerData *data; - SpiceMarshaller *next; - - MarshallerRef pointer_ref; - - int n_items; - int items_size; /* number of items availible in items */ - MarshallerItem *items; - - MarshallerItem static_items[N_STATIC_ITEMS]; -}; - -struct SpiceMarshallerData { - size_t total_size; - size_t base; - SpiceMarshaller *marshallers; - SpiceMarshaller *last_marshaller; - - size_t current_buffer_position; - MarshallerBuffer *current_buffer; - MarshallerItem *current_buffer_item; - MarshallerBuffer *buffers; - - SpiceMarshaller static_marshaller; - MarshallerBuffer static_buffer; -}; - -static void spice_marshaller_init(SpiceMarshaller *m, - SpiceMarshallerData *data) -{ - m->data = data; - m->next = NULL; - m->total_size = 0; - m->pointer_ref.marshaller = NULL; - m->n_items = 0; - m->items_size = N_STATIC_ITEMS; - m->items = m->static_items; -} - -SpiceMarshaller *spice_marshaller_new(void) -{ - SpiceMarshallerData *d; - SpiceMarshaller *m; - - d = spice_new(SpiceMarshallerData, 1); - - d->last_marshaller = d->marshallers = &d->static_marshaller; - d->total_size = 0; - d->base = 0; - d->buffers = &d->static_buffer; - d->buffers->next = NULL; - d->current_buffer = d->buffers; - d->current_buffer_position = 0; - d->current_buffer_item = NULL; - - m = &d->static_marshaller; - spice_marshaller_init(m, d); - - return m; -} - -static void free_item_data(SpiceMarshaller *m) -{ - MarshallerItem *item; - int i; - - /* Free all user data */ - for (i = 0; i < m->n_items; i++) { - item = &m->items[i]; - if (item->free_data != NULL) { - item->free_data(item->data, item->opaque); - } - } -} - -static void free_items(SpiceMarshaller *m) -{ - if (m->items != m->static_items) { - free(m->items); - } -} - -void spice_marshaller_reset(SpiceMarshaller *m) -{ - SpiceMarshaller *m2, *next; - SpiceMarshallerData *d; - - /* Only supported for root marshaller */ - assert(m->data->marshallers == m); - - for (m2 = m; m2 != NULL; m2 = next) { - next = m2->next; - free_item_data(m2); - - /* Free non-root marshallers */ - if (m2 != m) { - free_items(m2); - free(m2); - } - } - - m->next = NULL; - m->n_items = 0; - m->total_size = 0; - - d = m->data; - d->last_marshaller = d->marshallers; - d->total_size = 0; - d->base = 0; - d->current_buffer_item = NULL; - d->current_buffer = d->buffers; - d->current_buffer_position = 0; -} - -void spice_marshaller_destroy(SpiceMarshaller *m) -{ - MarshallerBuffer *buf, *next; - SpiceMarshallerData *d; - - /* Only supported for root marshaller */ - assert(m->data->marshallers == m); - - spice_marshaller_reset(m); - - free_items(m); - - d = m->data; - - buf = d->buffers->next; - while (buf != NULL) { - next = buf->next; - free(buf); - buf = next; - } - - free(d); -} - -static MarshallerItem *spice_marshaller_add_item(SpiceMarshaller *m) -{ - MarshallerItem *item; - - if (m->n_items == m->items_size) { - int items_size = m->items_size * 2; - - if (m->items == m->static_items) { - m->items = spice_new(MarshallerItem, items_size); - memcpy(m->items, m->static_items, sizeof(MarshallerItem) * m->n_items); - } else { - m->items = spice_renew(MarshallerItem, m->items, items_size); - } - m->items_size = items_size; - } - item = &m->items[m->n_items++]; - item->free_data = NULL; - - return item; -} - -static size_t remaining_buffer_size(SpiceMarshallerData *d) -{ - return MARSHALLER_BUFFER_SIZE - d->current_buffer_position; -} - -uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size) -{ - MarshallerItem *item; - SpiceMarshallerData *d; - uint8_t *res; - - if (size == 0) { - return NULL; - } - - d = m->data; - - /* Check current item */ - item = &m->items[m->n_items - 1]; - if (item == d->current_buffer_item && - remaining_buffer_size(d) >= size) { - assert(m->n_items >= 1); - /* We can piggy back on existing item+buffer */ - res = item->data + item->len; - item->len += size; - d->current_buffer_position += size; - d->total_size += size; - m->total_size += size; - return res; - } - - item = spice_marshaller_add_item(m); - - if (remaining_buffer_size(d) >= size) { - /* Fits in current buffer */ - item->data = d->current_buffer->data + d->current_buffer_position; - item->len = size; - d->current_buffer_position += size; - d->current_buffer_item = item; - } else if (size > MARSHALLER_BUFFER_SIZE / 2) { - /* Large item, allocate by itself */ - item->data = (uint8_t *)spice_malloc(size); - item->len = size; - item->free_data = (spice_marshaller_item_free_func)free; - item->opaque = NULL; - } else { - /* Use next buffer */ - if (d->current_buffer->next == NULL) { - d->current_buffer->next = spice_new(MarshallerBuffer, 1); - d->current_buffer->next->next = NULL; - } - d->current_buffer = d->current_buffer->next; - d->current_buffer_position = size; - d->current_buffer_item = item; - item->data = d->current_buffer->data; - item->len = size; - } - - d->total_size += size; - m->total_size += size; - return item->data; -} - -void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size) -{ - MarshallerItem *item; - - if (size == 0) { - return; - } - - item = &m->items[m->n_items - 1]; - - assert(item->len >= size); - item->len -= size; -} - -uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size, - spice_marshaller_item_free_func free_data, void *opaque) -{ - MarshallerItem *item; - SpiceMarshallerData *d; - - if (data == NULL || size == 0) { - return NULL; - } - - item = spice_marshaller_add_item(m); - item->data = data; - item->len = size; - item->free_data = free_data; - item->opaque = opaque; - - d = m->data; - m->total_size += size; - d->total_size += size; - - return data; -} - -uint8_t *spice_marshaller_add(SpiceMarshaller *m, uint8_t *data, size_t size) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, size); - memcpy(ptr, data, size); - return ptr; -} - -uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, uint8_t *data, size_t size) -{ - return spice_marshaller_add_ref_full(m, data, size, NULL, NULL); -} - -void spice_marshaller_add_ref_chunks(SpiceMarshaller *m, SpiceChunks *chunks) -{ - unsigned int i; - - for (i = 0; i < chunks->num_chunks; i++) { - spice_marshaller_add_ref(m, chunks->chunk[i].data, - chunks->chunk[i].len); - } -} - -SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m) -{ - SpiceMarshallerData *d; - SpiceMarshaller *m2; - - d = m->data; - - m2 = spice_new(SpiceMarshaller, 1); - spice_marshaller_init(m2, d); - - d->last_marshaller->next = m2; - d->last_marshaller = m2; - - return m2; -} - -SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit) -{ - SpiceMarshaller *m2; - uint8_t *p; - int size; - - size = is_64bit ? 8 : 4; - - p = spice_marshaller_reserve_space(m, size); - memset(p, 0, size); - m2 = spice_marshaller_get_submarshaller(m); - m2->pointer_ref.marshaller = m; - m2->pointer_ref.item_nr = m->n_items - 1; - m2->pointer_ref.offset = m->items[m->n_items - 1].len - size; - m2->pointer_ref.is_64bit = is_64bit; - - return m2; -} - -uint8_t *lookup_ref(MarshallerRef *ref) -{ - MarshallerItem *item; - - item = &ref->marshaller->items[ref->item_nr]; - return item->data + ref->offset; -} - - -void spice_marshaller_set_base(SpiceMarshaller *m, size_t base) -{ - /* Only supported for root marshaller */ - assert(m->data->marshallers == m); - - m->data->base = base; -} - -uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip_bytes, - size_t *len, int *free_res) -{ - MarshallerItem *item; - uint8_t *res, *p; - int i; - - /* Only supported for root marshaller */ - assert(m->data->marshallers == m); - - if (m->n_items == 1) { - *free_res = FALSE; - if (m->items[0].len <= skip_bytes) { - *len = 0; - return NULL; - } - *len = m->items[0].len - skip_bytes; - return m->items[0].data + skip_bytes; - } - - *free_res = TRUE; - res = (uint8_t *)spice_malloc(m->data->total_size - skip_bytes); - *len = m->data->total_size - skip_bytes; - p = res; - - do { - for (i = 0; i < m->n_items; i++) { - item = &m->items[i]; - - if (item->len <= skip_bytes) { - skip_bytes -= item->len; - continue; - } - memcpy(p, item->data + skip_bytes, item->len - skip_bytes); - p += item->len - skip_bytes; - skip_bytes = 0; - } - m = m->next; - } while (m != NULL); - - return res; -} - -uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m) -{ - return m->items[0].data; -} - -size_t spice_marshaller_get_offset(SpiceMarshaller *m) -{ - SpiceMarshaller *m2; - size_t offset; - - offset = 0; - m2 = m->data->marshallers; - while (m2 != m) { - offset += m2->total_size; - m2 = m2->next; - } - return offset - m->data->base; -} - -size_t spice_marshaller_get_size(SpiceMarshaller *m) -{ - return m->total_size; -} - -size_t spice_marshaller_get_total_size(SpiceMarshaller *m) -{ - return m->data->total_size; -} - -void spice_marshaller_flush(SpiceMarshaller *m) -{ - SpiceMarshaller *m2; - uint8_t *ptr_pos; - - /* Only supported for root marshaller */ - assert(m->data->marshallers == m); - - for (m2 = m; m2 != NULL; m2 = m2->next) { - if (m2->pointer_ref.marshaller != NULL && m2->total_size > 0) { - ptr_pos = lookup_ref(&m2->pointer_ref); - if (m2->pointer_ref.is_64bit) { - write_uint64(ptr_pos, - spice_marshaller_get_offset(m2)); - } else { - write_uint32(ptr_pos, - spice_marshaller_get_offset(m2)); - } - } - } -} - -#ifndef WIN32 -int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec, - int n_vec, size_t skip_bytes) -{ - MarshallerItem *item; - int v, i; - - /* Only supported for root marshaller */ - assert(m->data->marshallers == m); - - v = 0; - do { - for (i = 0; i < m->n_items; i++) { - item = &m->items[i]; - - if (item->len <= skip_bytes) { - skip_bytes -= item->len; - continue; - } - if (v == n_vec) { - return v; /* Not enough space in vec */ - } - vec[v].iov_base = (void *)item->data + skip_bytes; - vec[v].iov_len = item->len - skip_bytes; - skip_bytes = 0; - v++; - } - m = m->next; - } while (m != NULL); - - return v; -} -#endif - -void *spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(uint64_t)); - write_uint64(ptr, v); - return (void *)ptr; -} - -void *spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(int64_t)); - write_int64(ptr, v); - return (void *)ptr; -} - -void *spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(uint32_t)); - write_uint32(ptr, v); - return (void *)ptr; -} - -void spice_marshaller_set_uint32(SpiceMarshaller *m, void *ref, uint32_t v) -{ - write_uint32((uint8_t *)ref, v); -} - -void *spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(int32_t)); - write_int32(ptr, v); - return (void *)ptr; -} - -void *spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(uint16_t)); - write_uint16(ptr, v); - return (void *)ptr; -} - -void *spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(int16_t)); - write_int16(ptr, v); - return (void *)ptr; -} - -void *spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(uint8_t)); - write_uint8(ptr, v); - return (void *)ptr; -} - -void *spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v) -{ - uint8_t *ptr; - - ptr = spice_marshaller_reserve_space(m, sizeof(int8_t)); - write_int8(ptr, v); - return (void *)ptr; -} diff --git a/common/marshaller.h b/common/marshaller.h deleted file mode 100644 index 0a61fefd..00000000 --- a/common/marshaller.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2010 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_MARSHALLER -#define _H_MARSHALLER - -#include <spice/types.h> -#include "mem.h" -#ifndef WIN32 -#include <sys/uio.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct SpiceMarshaller SpiceMarshaller; -typedef void (*spice_marshaller_item_free_func)(uint8_t *data, void *opaque); - -SpiceMarshaller *spice_marshaller_new(void); -void spice_marshaller_reset(SpiceMarshaller *m); -void spice_marshaller_destroy(SpiceMarshaller *m); -uint8_t *spice_marshaller_reserve_space(SpiceMarshaller *m, size_t size); -void spice_marshaller_unreserve_space(SpiceMarshaller *m, size_t size); -uint8_t *spice_marshaller_add(SpiceMarshaller *m, uint8_t *data, size_t size); -uint8_t *spice_marshaller_add_ref(SpiceMarshaller *m, uint8_t *data, size_t size); -uint8_t *spice_marshaller_add_ref_full(SpiceMarshaller *m, uint8_t *data, size_t size, - spice_marshaller_item_free_func free_data, void *opaque); -void spice_marshaller_add_ref_chunks(SpiceMarshaller *m, SpiceChunks *chunks); -void spice_marshaller_flush(SpiceMarshaller *m); -void spice_marshaller_set_base(SpiceMarshaller *m, size_t base); -uint8_t *spice_marshaller_linearize(SpiceMarshaller *m, size_t skip, - size_t *len, int *free_res); -uint8_t *spice_marshaller_get_ptr(SpiceMarshaller *m); -size_t spice_marshaller_get_offset(SpiceMarshaller *m); -size_t spice_marshaller_get_size(SpiceMarshaller *m); -size_t spice_marshaller_get_total_size(SpiceMarshaller *m); -SpiceMarshaller *spice_marshaller_get_submarshaller(SpiceMarshaller *m); -SpiceMarshaller *spice_marshaller_get_ptr_submarshaller(SpiceMarshaller *m, int is_64bit); -#ifndef WIN32 -int spice_marshaller_fill_iovec(SpiceMarshaller *m, struct iovec *vec, - int n_vec, size_t skip_bytes); -#endif -void *spice_marshaller_add_uint64(SpiceMarshaller *m, uint64_t v); -void *spice_marshaller_add_int64(SpiceMarshaller *m, int64_t v); -void *spice_marshaller_add_uint32(SpiceMarshaller *m, uint32_t v); -void *spice_marshaller_add_int32(SpiceMarshaller *m, int32_t v); -void *spice_marshaller_add_uint16(SpiceMarshaller *m, uint16_t v); -void *spice_marshaller_add_int16(SpiceMarshaller *m, int16_t v); -void *spice_marshaller_add_uint8(SpiceMarshaller *m, uint8_t v); -void *spice_marshaller_add_int8(SpiceMarshaller *m, int8_t v); - -void spice_marshaller_set_uint32(SpiceMarshaller *m, void *ref, uint32_t v); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/mem.c b/common/mem.c deleted file mode 100644 index 5298e37d..00000000 --- a/common/mem.c +++ /dev/null @@ -1,297 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2010 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "mem.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#ifndef MALLOC_ERROR -#define MALLOC_ERROR(format, ...) { \ - printf(format "\n", ## __VA_ARGS__); \ - abort(); \ -} -#endif - -size_t spice_strnlen(const char *str, size_t max_len) -{ - size_t len = 0; - - while (len < max_len && *str != 0) { - len++; - str++; - } - - return len; -} - -char *spice_strdup(const char *str) -{ - char *copy; - - if (str == NULL) { - return NULL; - } - - copy = (char *)spice_malloc(strlen(str) + 1); - strcpy(copy, str); - return copy; -} - -char *spice_strndup(const char *str, size_t n_bytes) -{ - char *copy; - - if (str == NULL) { - return NULL; - } - - copy = (char *)spice_malloc(n_bytes + 1); - strncpy(copy, str, n_bytes); - copy[n_bytes] = 0; - return copy; -} - -void *spice_memdup(const void *mem, size_t n_bytes) -{ - void *copy; - - if (mem == NULL) { - return NULL; - } - - copy = spice_malloc(n_bytes); - memcpy(copy, mem, n_bytes); - return copy; -} - -void *spice_malloc(size_t n_bytes) -{ - void *mem; - - if (SPICE_LIKELY(n_bytes)) { - mem = malloc(n_bytes); - - if (SPICE_LIKELY(mem != NULL)) { - return mem; - } - - MALLOC_ERROR("spice_malloc: panic: unable to allocate %lu bytes\n", - (unsigned long)n_bytes); - } - return NULL; -} - -void *spice_malloc0(size_t n_bytes) -{ - void *mem; - - if (SPICE_LIKELY(n_bytes)) { - mem = calloc(1, n_bytes); - - if (SPICE_LIKELY(mem != NULL)) { - return mem; - } - - MALLOC_ERROR("spice_malloc0: panic: unable to allocate %lu bytes\n", - (unsigned long)n_bytes); - } - return NULL; -} - -void *spice_realloc(void *mem, size_t n_bytes) -{ - if (SPICE_LIKELY(n_bytes)) { - mem = realloc(mem, n_bytes); - - if (SPICE_LIKELY(mem != NULL)) { - return mem; - } - - MALLOC_ERROR("spice_realloc: panic: unable to allocate %lu bytes\n", - (unsigned long)n_bytes); - } - - free(mem); - - return NULL; -} - -#define SIZE_OVERFLOWS(a,b) (SPICE_UNLIKELY ((a) > SIZE_MAX / (b))) - -void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes) -{ - if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { - MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu bytes", - (unsigned long)n_blocks, (unsigned long)n_block_bytes); - } - - return spice_malloc(n_blocks * n_block_bytes); -} - -void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size) -{ - size_t size1, size2; - if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { - MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes", - (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size); - } - size1 = n_blocks * n_block_bytes; - size2 = size1 + extra_size; - if (size2 < size1) { - MALLOC_ERROR("spice_malloc_n: overflow allocating %lu*%lu + %lubytes", - (unsigned long)n_blocks, (unsigned long)n_block_bytes, (unsigned long)extra_size); - } - return spice_malloc(size2); -} - - -void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) -{ - if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { - MALLOC_ERROR("spice_malloc0_n: overflow allocating %lu*%lu bytes", - (unsigned long)n_blocks, (unsigned long)n_block_bytes); - } - - return spice_malloc0 (n_blocks * n_block_bytes); -} - -void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) -{ - if (SIZE_OVERFLOWS (n_blocks, n_block_bytes)) { - MALLOC_ERROR("spice_realloc_n: overflow allocating %lu*%lu bytes", - (unsigned long)n_blocks, (unsigned long)n_block_bytes); - } - - return spice_realloc(mem, n_blocks * n_block_bytes); -} - -SpiceChunks *spice_chunks_new(uint32_t count) -{ - SpiceChunks *chunks; - - chunks = (SpiceChunks *)spice_malloc_n_m(count, sizeof(SpiceChunk), sizeof(SpiceChunks)); - chunks->flags = 0; - chunks->num_chunks = count; - - return chunks; -} - -SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len) -{ - SpiceChunks *chunks; - - chunks = spice_chunks_new(1); - chunks->data_size = chunks->chunk[0].len = len; - chunks->chunk[0].data = data; - return chunks; -} - -void spice_chunks_destroy(SpiceChunks *chunks) -{ - unsigned int i; - - if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) { - for (i = 0; i < chunks->num_chunks; i++) { - free(chunks->chunk[i].data); - } - } - - free(chunks); -} - -void spice_chunks_linearize(SpiceChunks *chunks) -{ - uint8_t *data, *p; - unsigned int i; - - if (chunks->num_chunks > 1) { - data = (uint8_t*)spice_malloc(chunks->data_size); - for (p = data, i = 0; i < chunks->num_chunks; i++) { - memcpy(p, chunks->chunk[i].data, - chunks->chunk[i].len); - p += chunks->chunk[i].len; - } - if (chunks->flags & SPICE_CHUNKS_FLAGS_FREE) { - for (i = 0; i < chunks->num_chunks; i++) { - free(chunks->chunk[i].data); - } - } - chunks->num_chunks = 1; - chunks->flags |= SPICE_CHUNKS_FLAGS_FREE; - chunks->flags &= ~SPICE_CHUNKS_FLAGS_UNSTABLE; - chunks->chunk[0].data = data; - chunks->chunk[0].len = chunks->data_size; - } -} - -void spice_buffer_reserve(SpiceBuffer *buffer, size_t len) -{ - if ((buffer->capacity - buffer->offset) < len) { - buffer->capacity += (len + 1024); - buffer->buffer = (uint8_t*)spice_realloc(buffer->buffer, buffer->capacity); - } -} - -int spice_buffer_empty(SpiceBuffer *buffer) -{ - return buffer->offset == 0; -} - -uint8_t *spice_buffer_end(SpiceBuffer *buffer) -{ - return buffer->buffer + buffer->offset; -} - -void spice_buffer_reset(SpiceBuffer *buffer) -{ - buffer->offset = 0; -} - -void spice_buffer_free(SpiceBuffer *buffer) -{ - free(buffer->buffer); - buffer->offset = 0; - buffer->capacity = 0; - buffer->buffer = NULL; -} - -void spice_buffer_append(SpiceBuffer *buffer, const void *data, size_t len) -{ - spice_buffer_reserve(buffer, len); - memcpy(buffer->buffer + buffer->offset, data, len); - buffer->offset += len; -} - -size_t spice_buffer_copy(SpiceBuffer *buffer, void *dest, size_t len) -{ - len = MIN(buffer->offset, len); - memcpy(dest, buffer->buffer, len); - return len; -} - -size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len) -{ - len = MIN(buffer->offset, len); - memmove(buffer->buffer, buffer->buffer + len, buffer->offset - len); - buffer->offset -= len; - return len; -} diff --git a/common/mem.h b/common/mem.h deleted file mode 100644 index af89ba6f..00000000 --- a/common/mem.h +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2010 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_MEM -#define _H_MEM - -#include <stdlib.h> -#include <spice/macros.h> - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef STDC_HEADERS -# include <stdlib.h> -# include <stddef.h> -#else -# ifdef HAVE_STDLIB_H -# include <stdlib.h> -# endif -#endif -#ifdef HAVE_ALLOCA_H -# include <alloca.h> -#elif defined __GNUC__ -#if !defined alloca -# define alloca __builtin_alloca -#endif -#elif defined _AIX -# define alloca __alloca -#elif defined _MSC_VER -# include <malloc.h> -# define alloca _alloca -#else -# ifndef HAVE_ALLOCA -# ifdef __cplusplus -extern "C" -# endif -void *alloca (size_t); -# endif -#endif - -typedef struct SpiceChunk { - uint8_t *data; - uint32_t len; -} SpiceChunk; - -enum { - SPICE_CHUNKS_FLAGS_UNSTABLE = (1<<0), - SPICE_CHUNKS_FLAGS_FREE = (1<<1) -}; - -typedef struct SpiceChunks { - uint32_t data_size; - uint32_t num_chunks; - uint32_t flags; - SpiceChunk chunk[0]; -} SpiceChunks; - -typedef struct SpiceBuffer -{ - size_t capacity; - size_t offset; - uint8_t *buffer; -} SpiceBuffer; - -char *spice_strdup(const char *str) SPICE_GNUC_MALLOC; -char *spice_strndup(const char *str, size_t n_bytes) SPICE_GNUC_MALLOC; -void *spice_memdup(const void *mem, size_t n_bytes) SPICE_GNUC_MALLOC; -void *spice_malloc(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1); -void *spice_malloc0(size_t n_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE(1); -void *spice_realloc(void *mem, size_t n_bytes) SPICE_GNUC_WARN_UNUSED_RESULT; -void *spice_malloc_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2); -void *spice_malloc_n_m(size_t n_blocks, size_t n_block_bytes, size_t extra_size) SPICE_GNUC_MALLOC; -void *spice_malloc0_n(size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_MALLOC SPICE_GNUC_ALLOC_SIZE2(1,2); -void *spice_realloc_n(void *mem, size_t n_blocks, size_t n_block_bytes) SPICE_GNUC_WARN_UNUSED_RESULT; -SpiceChunks *spice_chunks_new(uint32_t count) SPICE_GNUC_MALLOC; -SpiceChunks *spice_chunks_new_linear(uint8_t *data, uint32_t len) SPICE_GNUC_MALLOC; -void spice_chunks_destroy(SpiceChunks *chunks); -void spice_chunks_linearize(SpiceChunks *chunks); - -size_t spice_strnlen(const char *str, size_t max_len); - -/* Optimize: avoid the call to the (slower) _n function if we can - * determine at compile-time that no overflow happens. - */ -#if defined (__GNUC__) && (__GNUC__ >= 2) && defined (__OPTIMIZE__) -# define _SPICE_NEW(struct_type, n_structs, func) \ - (struct_type *) (__extension__ ({ \ - size_t __n = (size_t) (n_structs); \ - size_t __s = sizeof (struct_type); \ - void *__p; \ - if (__s == 1) \ - __p = spice_##func (__n); \ - else if (__builtin_constant_p (__n) && \ - __n <= SIZE_MAX / __s) \ - __p = spice_##func (__n * __s); \ - else \ - __p = spice_##func##_n (__n, __s); \ - __p; \ - })) -# define _SPICE_RENEW(struct_type, mem, n_structs, func) \ - (struct_type *) (__extension__ ({ \ - size_t __n = (size_t) (n_structs); \ - size_t __s = sizeof (struct_type); \ - void *__p = (void *) (mem); \ - if (__s == 1) \ - __p = spice_##func (__p, __n); \ - else if (__builtin_constant_p (__n) && \ - __n <= SIZE_MAX / __s) \ - __p = spice_##func (__p, __n * __s); \ - else \ - __p = spice_##func##_n (__p, __n, __s); \ - __p; \ - })) -#else - -/* Unoptimized version: always call the _n() function. */ - -#define _SPICE_NEW(struct_type, n_structs, func) \ - ((struct_type *) spice_##func##_n ((n_structs), sizeof (struct_type))) -#define _SPICE_RENEW(struct_type, mem, n_structs, func) \ - ((struct_type *) spice_##func##_n (mem, (n_structs), sizeof (struct_type))) - -#endif - -#define spice_new(struct_type, n_structs) _SPICE_NEW(struct_type, n_structs, malloc) -#define spice_new0(struct_type, n_structs) _SPICE_NEW(struct_type, n_structs, malloc0) -#define spice_renew(struct_type, mem, n_structs) _SPICE_RENEW(struct_type, mem, n_structs, realloc) - -/* Buffer management */ -void spice_buffer_reserve(SpiceBuffer *buffer, size_t len); -int spice_buffer_empty(SpiceBuffer *buffer); -uint8_t *spice_buffer_end(SpiceBuffer *buffer); -void spice_buffer_reset(SpiceBuffer *buffer); -void spice_buffer_free(SpiceBuffer *buffer); -void spice_buffer_append(SpiceBuffer *buffer, const void *data, size_t len); -size_t spice_buffer_copy(SpiceBuffer *buffer, void *dest, size_t len); -size_t spice_buffer_remove(SpiceBuffer *buffer, size_t len); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/common/messages.h b/common/messages.h deleted file mode 100644 index ec58da55..00000000 --- a/common/messages.h +++ /dev/null @@ -1,525 +0,0 @@ -/* - Copyright (C) 2009-2010 Red Hat, Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef _H_MESSAGES -#define _H_MESSAGES - -#include <spice/protocol.h> -#include "draw.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct SpiceMsgData { - uint32_t data_size; - uint8_t data[0]; -} SpiceMsgData; - -typedef struct SpiceMsgEmpty { -} SpiceMsgEmpty; - -typedef struct SpiceMsgInputsInit { - uint32_t keyboard_modifiers; -} SpiceMsgInputsInit; - -typedef struct SpiceMsgInputsKeyModifiers { - uint32_t modifiers; -} SpiceMsgInputsKeyModifiers; - -typedef struct SpiceMsgMainMultiMediaTime { - uint32_t time; -} SpiceMsgMainMultiMediaTime; - -typedef struct SpiceMsgMainMigrationBegin { - uint16_t port; - uint16_t sport; - uint32_t host_size; - uint8_t *host_data; - uint16_t pub_key_type; - uint32_t pub_key_size; - uint8_t *pub_key_data; - uint32_t cert_subject_size; - uint8_t *cert_subject_data; -} SpiceMsgMainMigrationBegin; - -typedef struct SpiceMsgMainMigrationSwitchHost { - uint16_t port; - uint16_t sport; - uint32_t host_size; - uint8_t *host_data; - uint32_t cert_subject_size; - uint8_t *cert_subject_data; -} SpiceMsgMainMigrationSwitchHost; - - -typedef struct SpiceMsgMigrate { - uint32_t flags; -} SpiceMsgMigrate; - -typedef struct SpiceResourceID { - uint8_t type; - uint64_t id; -} SpiceResourceID; - -typedef struct SpiceResourceList { - uint16_t count; - SpiceResourceID resources[0]; -} SpiceResourceList; - -typedef struct SpiceMsgSetAck { - uint32_t generation; - uint32_t window; -} SpiceMsgSetAck; - -typedef struct SpiceMsgcAckSync { - uint32_t generation; -} SpiceMsgcAckSync; - -typedef struct SpiceWaitForChannel { - uint8_t channel_type; - uint8_t channel_id; - uint64_t message_serial; -} SpiceWaitForChannel; - -typedef struct SpiceMsgWaitForChannels { - uint8_t wait_count; - SpiceWaitForChannel wait_list[0]; -} SpiceMsgWaitForChannels; - -typedef struct SpiceChannelId { - uint8_t type; - uint8_t id; -} SpiceChannelId; - -typedef struct SpiceMsgMainInit { - uint32_t session_id; - uint32_t display_channels_hint; - uint32_t supported_mouse_modes; - uint32_t current_mouse_mode; - uint32_t agent_connected; - uint32_t agent_tokens; - uint32_t multi_media_time; - uint32_t ram_hint; -} SpiceMsgMainInit; - -typedef struct SpiceMsgDisconnect { - uint64_t time_stamp; - uint32_t reason; // SPICE_ERR_? -} SpiceMsgDisconnect; - -typedef struct SpiceMsgNotify { - uint64_t time_stamp; - uint32_t severity; - uint32_t visibilty; - uint32_t what; - uint32_t message_len; - uint8_t message[0]; -} SpiceMsgNotify; - -typedef struct SpiceMsgChannels { - uint32_t num_of_channels; - SpiceChannelId channels[0]; -} SpiceMsgChannels; - -typedef struct SpiceMsgMainName { - uint32_t name_len; - uint8_t name[0]; -} SpiceMsgMainName; - -typedef struct SpiceMsgMainUuid { - uint8_t uuid[16]; -} SpiceMsgMainUuid; - -typedef struct SpiceMsgMainMouseMode { - uint32_t supported_modes; - uint32_t current_mode; -} SpiceMsgMainMouseMode; - -typedef struct SpiceMsgPing { - uint32_t id; - uint64_t timestamp; - void *data; - uint32_t data_len; -} SpiceMsgPing; - -typedef struct SpiceMsgMainAgentDisconnect { - uint32_t error_code; // SPICE_ERR_? -} SpiceMsgMainAgentDisconnect; - -#define SPICE_AGENT_MAX_DATA_SIZE 2048 - -typedef struct SpiceMsgMainAgentTokens { - uint32_t num_tokens; -} SpiceMsgMainAgentTokens, SpiceMsgcMainAgentTokens, SpiceMsgcMainAgentStart; - -typedef struct SpiceMsgcClientInfo { - uint64_t cache_size; -} SpiceMsgcClientInfo; - -typedef struct SpiceMsgcMainMouseModeRequest { - uint32_t mode; -} SpiceMsgcMainMouseModeRequest; - -typedef struct SpiceCursor { - uint32_t flags; - SpiceCursorHeader header; - uint32_t data_size; - uint8_t *data; -} SpiceCursor; - -typedef struct SpiceMsgDisplayMode { - uint32_t x_res; - uint32_t y_res; - uint32_t bits; -} SpiceMsgDisplayMode; - -typedef struct SpiceMsgSurfaceCreate { - uint32_t surface_id; - uint32_t width; - uint32_t height; - uint32_t format; - uint32_t flags; -} SpiceMsgSurfaceCreate; - -typedef struct SpiceMsgSurfaceDestroy { - uint32_t surface_id; -} SpiceMsgSurfaceDestroy; - -typedef struct SpiceMsgDisplayBase { - uint32_t surface_id; - SpiceRect box; - SpiceClip clip; -} SpiceMsgDisplayBase; - -typedef struct SpiceMsgDisplayDrawFill { - SpiceMsgDisplayBase base; - SpiceFill data; -} SpiceMsgDisplayDrawFill; - -typedef struct SpiceMsgDisplayDrawOpaque { - SpiceMsgDisplayBase base; - SpiceOpaque data; -} SpiceMsgDisplayDrawOpaque; - -typedef struct SpiceMsgDisplayDrawCopy { - SpiceMsgDisplayBase base; - SpiceCopy data; -} SpiceMsgDisplayDrawCopy; - -typedef struct SpiceMsgDisplayDrawTransparent { - SpiceMsgDisplayBase base; - SpiceTransparent data; -} SpiceMsgDisplayDrawTransparent; - -typedef struct SpiceMsgDisplayDrawAlphaBlend { - SpiceMsgDisplayBase base; - SpiceAlphaBlend data; -} SpiceMsgDisplayDrawAlphaBlend; - -typedef struct SpiceMsgDisplayCopyBits { - SpiceMsgDisplayBase base; - SpicePoint src_pos; -} SpiceMsgDisplayCopyBits; - -typedef SpiceMsgDisplayDrawCopy SpiceMsgDisplayDrawBlend; - -typedef struct SpiceMsgDisplayDrawRop3 { - SpiceMsgDisplayBase base; - SpiceRop3 data; -} SpiceMsgDisplayDrawRop3; - -typedef struct SpiceMsgDisplayDrawBlackness { - SpiceMsgDisplayBase base; - SpiceBlackness data; -} SpiceMsgDisplayDrawBlackness; - -typedef struct SpiceMsgDisplayDrawWhiteness { - SpiceMsgDisplayBase base; - SpiceWhiteness data; -} SpiceMsgDisplayDrawWhiteness; - -typedef struct SpiceMsgDisplayDrawInvers { - SpiceMsgDisplayBase base; - SpiceInvers data; -} SpiceMsgDisplayDrawInvers; - -typedef struct SpiceMsgDisplayDrawStroke { - SpiceMsgDisplayBase base; - SpiceStroke data; -} SpiceMsgDisplayDrawStroke; - -typedef struct SpiceMsgDisplayDrawText { - SpiceMsgDisplayBase base; - SpiceText data; -} SpiceMsgDisplayDrawText; - -typedef struct SpiceMsgDisplayInvalOne { - uint64_t id; -} SpiceMsgDisplayInvalOne; - -typedef struct SpiceMsgDisplayStreamCreate { - uint32_t surface_id; - uint32_t id; - uint32_t flags; - uint32_t codec_type; - uint64_t stamp; - uint32_t stream_width; - uint32_t stream_height; - uint32_t src_width; - uint32_t src_height; - SpiceRect dest; - SpiceClip clip; -} SpiceMsgDisplayStreamCreate; - -typedef struct SpiceMsgDisplayStreamData { - uint32_t id; - uint32_t multi_media_time; - uint32_t data_size; - uint8_t data[0]; -} SpiceMsgDisplayStreamData; - -typedef struct SpiceMsgDisplayStreamClip { - uint32_t id; - SpiceClip clip; -} SpiceMsgDisplayStreamClip; - -typedef struct SpiceMsgDisplayStreamDestroy { - uint32_t id; -} SpiceMsgDisplayStreamDestroy; - -typedef struct SpiceMsgCursorInit { - SpicePoint16 position; - uint16_t trail_length; - uint16_t trail_frequency; - uint8_t visible; - SpiceCursor cursor; -} SpiceMsgCursorInit; - -typedef struct SpiceMsgCursorSet { - SpicePoint16 position; - uint8_t visible; - SpiceCursor cursor; -} SpiceMsgCursorSet; - -typedef struct SpiceMsgCursorMove { - SpicePoint16 position; -} SpiceMsgCursorMove; - -typedef struct SpiceMsgCursorTrail { - uint16_t length; - uint16_t frequency; -} SpiceMsgCursorTrail; - -typedef struct SpiceMsgcDisplayInit { - uint8_t pixmap_cache_id; - int64_t pixmap_cache_size; //in pixels - uint8_t glz_dictionary_id; - int32_t glz_dictionary_window_size; // in pixels -} SpiceMsgcDisplayInit; - -typedef struct SpiceMsgcKeyDown { - uint32_t code; -} SpiceMsgcKeyDown; - -typedef struct SpiceMsgcKeyUp { - uint32_t code; -} SpiceMsgcKeyUp; - -typedef struct SpiceMsgcKeyModifiers { - uint32_t modifiers; -} SpiceMsgcKeyModifiers; - -typedef struct SpiceMsgcMouseMotion { - int32_t dx; - int32_t dy; - uint32_t buttons_state; -} SpiceMsgcMouseMotion; - -typedef struct SpiceMsgcMousePosition { - uint32_t x; - uint32_t y; - uint32_t buttons_state; - uint8_t display_id; -} SpiceMsgcMousePosition; - -typedef struct SpiceMsgcMousePress { - int32_t button; - int32_t buttons_state; -} SpiceMsgcMousePress; - -typedef struct SpiceMsgcMouseRelease { - int32_t button; - int32_t buttons_state; -} SpiceMsgcMouseRelease; - -typedef struct SpiceMsgAudioVolume { - uint8_t nchannels; - uint16_t volume[0]; -} SpiceMsgAudioVolume; - -typedef struct SpiceMsgAudioMute { - uint8_t mute; -} SpiceMsgAudioMute; - -typedef struct SpiceMsgPlaybackMode { - uint32_t time; - uint32_t mode; //SPICE_AUDIO_DATA_MODE_? - uint8_t *data; - uint32_t data_size; -} SpiceMsgPlaybackMode, SpiceMsgcRecordMode; - -typedef struct SpiceMsgPlaybackStart { - uint32_t channels; - uint32_t format; //SPICE_AUDIO_FMT_? - uint32_t frequency; - uint32_t time; -} SpiceMsgPlaybackStart; - -typedef struct SpiceMsgPlaybackPacket { - uint32_t time; - uint8_t *data; - uint32_t data_size; -} SpiceMsgPlaybackPacket, SpiceMsgcRecordPacket; - -typedef struct SpiceMsgRecordStart { - uint32_t channels; - uint32_t format; //SPICE_AUDIO_FMT_? - uint32_t frequency; -} SpiceMsgRecordStart; - -typedef struct SpiceMsgcRecordStartMark { - uint32_t time; -} SpiceMsgcRecordStartMark; - -typedef struct SpiceMsgTunnelInit { - uint16_t max_num_of_sockets; - uint32_t max_socket_data_size; -} SpiceMsgTunnelInit; - -typedef uint8_t SpiceTunnelIPv4[4]; - -typedef struct SpiceMsgTunnelIpInfo { - uint16_t type; - union { - SpiceTunnelIPv4 ipv4; - } u; - uint8_t data[0]; -} SpiceMsgTunnelIpInfo; - -typedef struct SpiceMsgTunnelServiceIpMap { - uint32_t service_id; - SpiceMsgTunnelIpInfo virtual_ip; -} SpiceMsgTunnelServiceIpMap; - -typedef struct SpiceMsgTunnelSocketOpen { - uint16_t connection_id; - uint32_t service_id; - uint32_t tokens; -} SpiceMsgTunnelSocketOpen; - -/* connection id must be the first field in msgs directed to a specific connection */ - -typedef struct SpiceMsgTunnelSocketFin { - uint16_t connection_id; -} SpiceMsgTunnelSocketFin; - -typedef struct SpiceMsgTunnelSocketClose { - uint16_t connection_id; -} SpiceMsgTunnelSocketClose; - -typedef struct SpiceMsgTunnelSocketData { - uint16_t connection_id; - uint8_t data[0]; -} SpiceMsgTunnelSocketData; - -typedef struct SpiceMsgTunnelSocketTokens { - uint16_t connection_id; - uint32_t num_tokens; -} SpiceMsgTunnelSocketTokens; - -typedef struct SpiceMsgTunnelSocketClosedAck { - uint16_t connection_id; -} SpiceMsgTunnelSocketClosedAck; - -typedef struct SpiceMsgcTunnelAddGenericService { - uint32_t type; - uint32_t id; - uint32_t group; - uint32_t port; - uint64_t name; - uint64_t description; - union { - SpiceMsgTunnelIpInfo ip; - } u; -} SpiceMsgcTunnelAddGenericService; - -typedef struct SpiceMsgcTunnelRemoveService { - uint32_t id; -} SpiceMsgcTunnelRemoveService; - -/* connection id must be the first field in msgs directed to a specific connection */ - -typedef struct SpiceMsgcTunnelSocketOpenAck { - uint16_t connection_id; - uint32_t tokens; -} SpiceMsgcTunnelSocketOpenAck; - -typedef struct SpiceMsgcTunnelSocketOpenNack { - uint16_t connection_id; -} SpiceMsgcTunnelSocketOpenNack; - -typedef struct SpiceMsgcTunnelSocketData { - uint16_t connection_id; - uint8_t data[0]; -} SpiceMsgcTunnelSocketData; - -typedef struct SpiceMsgcTunnelSocketFin { - uint16_t connection_id; -} SpiceMsgcTunnelSocketFin; - -typedef struct SpiceMsgcTunnelSocketClosed { - uint16_t connection_id; -} SpiceMsgcTunnelSocketClosed; - -typedef struct SpiceMsgcTunnelSocketClosedAck { - uint16_t connection_id; -} SpiceMsgcTunnelSocketClosedAck; - -typedef struct SpiceMsgcTunnelSocketTokens { - uint16_t connection_id; - uint32_t num_tokens; -} SpiceMsgcTunnelSocketTokens; - -#ifdef __cplusplus -} -#endif - -#endif /* _H_SPICE_PROTOCOL */ diff --git a/common/mutex.h b/common/mutex.h deleted file mode 100644 index 6789b8f4..00000000 --- a/common/mutex.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_MUTEX -#define _H_MUTEX - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#include <windows.h> -typedef CRITICAL_SECTION mutex_t; -#define MUTEX_INIT(mutex) InitializeCriticalSection(&mutex) -#define MUTEX_LOCK(mutex) EnterCriticalSection(&mutex) -#define MUTEX_UNLOCK(mutex) LeaveCriticalSection(&mutex) -#else -#include <pthread.h> -typedef pthread_mutex_t mutex_t; -#define MUTEX_INIT(mutex) pthread_mutex_init(&mutex, NULL); -#define MUTEX_LOCK(mutex) pthread_mutex_lock(&mutex) -#define MUTEX_UNLOCK(mutex) pthread_mutex_unlock(&mutex) -#endif - -#ifdef __cplusplus -} -#endif - -#endif // _H_MUTEX diff --git a/common/ogl_ctx.c b/common/ogl_ctx.c deleted file mode 100644 index 41c05915..00000000 --- a/common/ogl_ctx.c +++ /dev/null @@ -1,251 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <X11/Xlib.h> -#include <GL/glx.h> - -#include "ogl_ctx.h" -#include "spice_common.h" - -enum { - OGLCTX_TYPE_PBUF, - OGLCTX_TYPE_PIXMAP, -}; - -struct OGLCtx { - int type; - Display *x_display; - GLXContext glx_context; - GLXDrawable drawable; -}; - -typedef struct OGLPixmapCtx { - OGLCtx base; - Pixmap pixmap; -} OGLPixmapCtx; - - - -const char *oglctx_type_str(OGLCtx *ctx) -{ - static const char *pbuf_str = "pbuf"; - static const char *pixmap_str = "pixmap"; - static const char *invalid_str = "invalid"; - - switch (ctx->type) { - case OGLCTX_TYPE_PBUF: - return pbuf_str; - case OGLCTX_TYPE_PIXMAP: - return pixmap_str; - default: - return invalid_str; - } -} - -void oglctx_make_current(OGLCtx *ctx) -{ - if (!glXMakeCurrent(ctx->x_display, ctx->drawable, ctx->glx_context)) { - printf("%s: failed\n", __FUNCTION__); - } -} - -OGLCtx *pbuf_create(int width, int heigth) -{ - OGLCtx *ctx; - Display *x_display; - int num_configs; - GLXFBConfig *fb_config; - GLXPbuffer glx_pbuf; - GLXContext glx_context; - - const int glx_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_STENCIL_SIZE, 4, - 0 }; - - int pbuf_attrib[] = { GLX_PRESERVED_CONTENTS, True, - GLX_PBUFFER_WIDTH, width, - GLX_PBUFFER_HEIGHT, heigth, - GLX_LARGEST_PBUFFER, False, - 0, 0 }; - - if (!(ctx = calloc(1, sizeof(*ctx)))) { - printf("%s: alloc pbuf failed\n", __FUNCTION__); - return NULL; - } - - if (!(x_display = XOpenDisplay(NULL))) { - printf("%s: open display failed\n", __FUNCTION__); - goto error_1; - } - - if (!(fb_config = glXChooseFBConfig(x_display, 0, glx_attributes, &num_configs)) || - !num_configs) { - printf("%s: choose fb config failed\n", __FUNCTION__); - goto error_2; - } - - if (!(glx_pbuf = glXCreatePbuffer(x_display, fb_config[0], pbuf_attrib))) { - goto error_3; - } - - if (!(glx_context = glXCreateNewContext(x_display, fb_config[0], GLX_RGBA_TYPE, NULL, True))) { - printf("%s: create context failed\n", __FUNCTION__); - goto error_4; - } - - XFree(fb_config); - - ctx->type = OGLCTX_TYPE_PBUF; - ctx->drawable = glx_pbuf; - ctx->glx_context = glx_context; - ctx->x_display = x_display; - - return ctx; - -error_4: - glXDestroyPbuffer(x_display, glx_pbuf); - -error_3: - XFree(fb_config); - -error_2: - XCloseDisplay(x_display); - -error_1: - free(ctx); - - return NULL; -} - -OGLCtx *pixmap_create(int width, int heigth) -{ - Display *x_display; - int num_configs; - GLXFBConfig *fb_config; - GLXPixmap glx_pixmap; - GLXContext glx_context; - Pixmap pixmap; - int screen; - Window root_window; - OGLPixmapCtx *pix; - - const int glx_attributes[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_STENCIL_SIZE, 4, - 0 }; - - if (!(pix = calloc(1, sizeof(*pix)))) { - printf("%s: alloc pix failed\n", __FUNCTION__); - return NULL; - } - - if (!(x_display = XOpenDisplay(NULL))) { - printf("%s: open display failed\n", __FUNCTION__); - goto error_1; - } - - screen = DefaultScreen(x_display); - root_window = RootWindow(x_display, screen); - - if (!(fb_config = glXChooseFBConfig(x_display, 0, glx_attributes, &num_configs)) || - !num_configs) { - printf("%s: choose fb config failed\n", __FUNCTION__); - goto error_2; - } - - if (!(pixmap = XCreatePixmap(x_display, root_window, width, heigth, 32 /*use fb config*/))) { - printf("%s: create x pixmap failed\n", __FUNCTION__); - goto error_3; - } - - if (!(glx_pixmap = glXCreatePixmap(x_display, fb_config[0], pixmap, NULL))) { - printf("%s: create glx pixmap failed\n", __FUNCTION__); - goto error_4; - } - - - if (!(glx_context = glXCreateNewContext(x_display, fb_config[0], GLX_RGBA_TYPE, NULL, True))) { - printf("%s: create context failed\n", __FUNCTION__); - goto error_5; - } - - XFree(fb_config); - - pix->base.type = OGLCTX_TYPE_PIXMAP; - pix->base.x_display = x_display; - pix->base.drawable = glx_pixmap; - pix->base.glx_context = glx_context; - pix->pixmap = pixmap; - - return &pix->base; - -error_5: - glXDestroyPixmap(x_display, glx_pixmap); - -error_4: - XFreePixmap(x_display, pixmap); - -error_3: - XFree(fb_config); - -error_2: - XCloseDisplay(x_display); - -error_1: - free(pix); - - return NULL; -} - -void oglctx_destroy(OGLCtx *ctx) -{ - if (!ctx) { - return; - } - // test is current ? - - glXDestroyContext(ctx->x_display, ctx->glx_context); - switch (ctx->type) { - case OGLCTX_TYPE_PBUF: - glXDestroyPbuffer(ctx->x_display, ctx->drawable); - break; - case OGLCTX_TYPE_PIXMAP: - glXDestroyPixmap(ctx->x_display, ctx->drawable); - XFreePixmap(ctx->x_display, ((OGLPixmapCtx *)ctx)->pixmap); - break; - default: - PANIC("invalid ogl ctx type"); - } - - XCloseDisplay(ctx->x_display); - free(ctx); -} diff --git a/common/ogl_ctx.h b/common/ogl_ctx.h deleted file mode 100644 index e7f677ac..00000000 --- a/common/ogl_ctx.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_GLCTX -#define _H_GLCTX - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct OGLCtx OGLCtx; - -const char *oglctx_type_str(OGLCtx *ctx); -void oglctx_make_current(OGLCtx *ctx); -OGLCtx *pbuf_create(int width, int heigth); -OGLCtx *pixmap_create(int width, int heigth); -void oglctx_destroy(OGLCtx *ctx); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/pixman_utils.c b/common/pixman_utils.c deleted file mode 100644 index 1136aa72..00000000 --- a/common/pixman_utils.c +++ /dev/null @@ -1,1594 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "pixman_utils.h" -#include "spice_common.h" -#include <spice/macros.h> - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include "mem.h" - -#define SOLID_RASTER_OP(_name, _size, _type, _equation) \ -static void \ -solid_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type src) \ -{ \ - while (len--) { \ - _type dst = *ptr; \ - if (dst) /* avoid unused warning */{}; \ - *ptr = (_type)(_equation); \ - ptr++; \ - } \ -} \ - -#define TILED_RASTER_OP(_name, _size, _type, _equation) \ -static void \ -tiled_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) \ -{ \ - while (len--) { \ - _type src = *tile; \ - _type dst = *ptr; \ - if (src) /* avoid unused warning */{}; \ - if (dst) /* avoid unused warning */{}; \ - *ptr = (_type)(_equation); \ - ptr++; \ - tile++; \ - if (tile == tile_end) \ - tile -= tile_width; \ - } \ -} \ - -#define COPY_RASTER_OP(_name, _size, _type, _equation) \ -static void \ - copy_rop_ ## _name ## _ ## _size (_type *ptr, _type *src_line, int len) \ -{ \ - while (len--) { \ - _type src = *src_line; \ - _type dst = *ptr; \ - if (src) /* avoid unused warning */ {}; \ - if (dst) /* avoid unused warning */{}; \ - *ptr = (_type)(_equation); \ - ptr++; \ - src_line++; \ - } \ -} \ - -#define RASTER_OP(name, equation) \ - SOLID_RASTER_OP(name, 8, uint8_t, equation) \ - SOLID_RASTER_OP(name, 16, uint16_t, equation) \ - SOLID_RASTER_OP(name, 32, uint32_t, equation) \ - TILED_RASTER_OP(name, 8, uint8_t, equation) \ - TILED_RASTER_OP(name, 16, uint16_t, equation) \ - TILED_RASTER_OP(name, 32, uint32_t, equation) \ - COPY_RASTER_OP(name, 8, uint8_t, equation) \ - COPY_RASTER_OP(name, 16, uint16_t, equation) \ - COPY_RASTER_OP(name, 32, uint32_t, equation) - -RASTER_OP(clear, 0x0) -RASTER_OP(and, src & dst) -RASTER_OP(and_reverse, src & ~dst) -RASTER_OP(copy, src) -RASTER_OP(and_inverted, ~src & dst) -RASTER_OP(noop, dst) -RASTER_OP(xor, src ^ dst) -RASTER_OP(or, src | dst) -RASTER_OP(nor, ~src & ~dst) -RASTER_OP(equiv, ~src ^ dst) -RASTER_OP(invert, ~dst) -RASTER_OP(or_reverse, src | ~dst) -RASTER_OP(copy_inverted, ~src) -RASTER_OP(or_inverted, ~src | dst) -RASTER_OP(nand, ~src | ~dst) -RASTER_OP(set, 0xffffffff) - -typedef void (*solid_rop_8_func_t)(uint8_t *ptr, int len, uint8_t src); -typedef void (*solid_rop_16_func_t)(uint16_t *ptr, int len, uint16_t src); -typedef void (*solid_rop_32_func_t)(uint32_t *ptr, int len, uint32_t src); -typedef void (*tiled_rop_8_func_t)(uint8_t *ptr, int len, - uint8_t *tile, uint8_t *tile_end, int tile_width); -typedef void (*tiled_rop_16_func_t)(uint16_t *ptr, int len, - uint16_t *tile, uint16_t *tile_end, int tile_width); -typedef void (*tiled_rop_32_func_t)(uint32_t *ptr, int len, - uint32_t *tile, uint32_t *tile_end, int tile_width); -typedef void (*copy_rop_8_func_t)(uint8_t *ptr, uint8_t *src, int len); -typedef void (*copy_rop_16_func_t)(uint16_t *ptr, uint16_t *src, int len); -typedef void (*copy_rop_32_func_t)(uint32_t *ptr, uint32_t *src, int len); - -#define ROP_TABLE(_type, _size) \ -static void (*solid_rops_ ## _size[16]) (_type *ptr, int len, _type src) = { \ - solid_rop_clear_ ## _size, \ - solid_rop_and_ ## _size, \ - solid_rop_and_reverse_ ## _size, \ - solid_rop_copy_ ## _size, \ - solid_rop_and_inverted_ ## _size, \ - solid_rop_noop_ ## _size, \ - solid_rop_xor_ ## _size, \ - solid_rop_or_ ## _size, \ - solid_rop_nor_ ## _size, \ - solid_rop_equiv_ ## _size, \ - solid_rop_invert_ ## _size, \ - solid_rop_or_reverse_ ## _size, \ - solid_rop_copy_inverted_ ## _size, \ - solid_rop_or_inverted_ ## _size, \ - solid_rop_nand_ ## _size, \ - solid_rop_set_ ## _size \ -}; \ -static void (*tiled_rops_ ## _size[16]) (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) = { \ - tiled_rop_clear_ ## _size, \ - tiled_rop_and_ ## _size, \ - tiled_rop_and_reverse_ ## _size, \ - tiled_rop_copy_ ## _size, \ - tiled_rop_and_inverted_ ## _size, \ - tiled_rop_noop_ ## _size, \ - tiled_rop_xor_ ## _size, \ - tiled_rop_or_ ## _size, \ - tiled_rop_nor_ ## _size, \ - tiled_rop_equiv_ ## _size, \ - tiled_rop_invert_ ## _size, \ - tiled_rop_or_reverse_ ## _size, \ - tiled_rop_copy_inverted_ ## _size, \ - tiled_rop_or_inverted_ ## _size, \ - tiled_rop_nand_ ## _size, \ - tiled_rop_set_ ## _size \ -}; \ -static void (*copy_rops_ ## _size[16]) (_type *ptr, _type *tile, int len) = { \ - copy_rop_clear_ ## _size, \ - copy_rop_and_ ## _size, \ - copy_rop_and_reverse_ ## _size, \ - copy_rop_copy_ ## _size, \ - copy_rop_and_inverted_ ## _size, \ - copy_rop_noop_ ## _size, \ - copy_rop_xor_ ## _size, \ - copy_rop_or_ ## _size, \ - copy_rop_nor_ ## _size, \ - copy_rop_equiv_ ## _size, \ - copy_rop_invert_ ## _size, \ - copy_rop_or_reverse_ ## _size, \ - copy_rop_copy_inverted_ ## _size, \ - copy_rop_or_inverted_ ## _size, \ - copy_rop_nand_ ## _size, \ - copy_rop_set_ ## _size \ -}; - -ROP_TABLE(uint8_t, 8) -ROP_TABLE(uint16_t, 16) -ROP_TABLE(uint32_t, 32) - -/* We can't get the real bits per pixel info from pixman_image_t, - only the DEPTH which is the sum of all a+r+g+b bits, which - is e.g. 24 for 32bit xRGB. We really want the bpp, so - we have this ugly conversion thing */ -int spice_pixman_image_get_bpp(pixman_image_t *image) -{ - int depth; - - depth = pixman_image_get_depth(image); - if (depth == 24) { - return 32; - } - if (depth == 15) { - return 16; - } - return depth; -} - -void spice_pixman_fill_rect(pixman_image_t *dest, - int x, int y, - int width, int height, - uint32_t value) -{ - uint32_t *bits; - int stride, depth; - uint32_t byte_width; - uint8_t *byte_line; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - ASSERT(x >= 0); - ASSERT(y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(x + width <= pixman_image_get_width(dest)); - ASSERT(y + height <= pixman_image_get_height(dest)); - - if (pixman_fill(bits, - stride / 4, - depth, - x, y, - width, height, - value)) { - return; - } - - if (depth == 8) { - byte_line = ((uint8_t *)bits) + stride * y + x; - byte_width = width; - value = (value & 0xff) * 0x01010101; - } else if (depth == 16) { - byte_line = ((uint8_t *)bits) + stride * y + x * 2; - byte_width = 2 * width; - value = (value & 0xffff) * 0x00010001; - } else { - ASSERT (depth == 32) - byte_line = ((uint8_t *)bits) + stride * y + x * 4; - byte_width = 4 * width; - } - - while (height--) { - int w; - uint8_t *d = byte_line; - - byte_line += stride; - w = byte_width; - - while (w >= 1 && ((uintptr_t)d & 1)) { - *(uint8_t *)d = (value & 0xff); - w--; - d++; - } - - while (w >= 2 && ((uintptr_t)d & 3)) { - *(uint16_t *)d = value; - w -= 2; - d += 2; - } - - while (w >= 4 && ((uintptr_t)d & 7)) { - *(uint32_t *)d = value; - - w -= 4; - d += 4; - } - - while (w >= 4) { - *(uint32_t *)d = value; - - w -= 4; - d += 4; - } - - while (w >= 2) { - *(uint16_t *)d = value; - w -= 2; - d += 2; - } - - while (w >= 1) { - *(uint8_t *)d = (value & 0xff); - w--; - d++; - } - } -} - -void spice_pixman_fill_rect_rop(pixman_image_t *dest, - int x, int y, - int width, int height, - uint32_t value, - SpiceROP rop) -{ - uint32_t *bits; - int stride, depth; - uint8_t *byte_line; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - ASSERT(x >= 0); - ASSERT(y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(x + width <= pixman_image_get_width(dest)); - ASSERT(y + height <= pixman_image_get_height(dest)); - ASSERT(rop >= 0 && rop < 16); - - if (depth == 8) { - solid_rop_8_func_t rop_func = solid_rops_8[rop]; - - byte_line = ((uint8_t *)bits) + stride * y + x; - while (height--) { - rop_func((uint8_t *)byte_line, width, (uint8_t)value); - byte_line += stride; - } - - } else if (depth == 16) { - solid_rop_16_func_t rop_func = solid_rops_16[rop]; - - byte_line = ((uint8_t *)bits) + stride * y + x * 2; - while (height--) { - rop_func((uint16_t *)byte_line, width, (uint16_t)value); - byte_line += stride; - } - } else { - solid_rop_32_func_t rop_func = solid_rops_32[rop]; - - byte_line = ((uint8_t *)bits) + stride * y + x * 4; - while (height--) { - rop_func((uint32_t *)byte_line, width, (uint32_t)value); - byte_line += stride; - } - } -} - -void spice_pixman_tile_rect(pixman_image_t *dest, - int x, int y, - int width, int height, - pixman_image_t *tile, - int offset_x, - int offset_y) -{ - uint32_t *bits, *tile_bits; - int stride, depth; - int tile_width, tile_height, tile_stride; - uint8_t *byte_line; - uint8_t *tile_line; - int tile_start_x, tile_start_y, tile_end_dx; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - tile_bits = pixman_image_get_data(tile); - tile_stride = pixman_image_get_stride(tile); - tile_width = pixman_image_get_width(tile); - tile_height = pixman_image_get_height(tile); - - ASSERT(x >= 0); - ASSERT(y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(x + width <= pixman_image_get_width(dest)); - ASSERT(y + height <= pixman_image_get_height(dest)); - ASSERT(depth == spice_pixman_image_get_bpp(tile)); - - tile_start_x = (x - offset_x) % tile_width; - if (tile_start_x < 0) { - tile_start_x += tile_width; - } - tile_start_y = (y - offset_y) % tile_height; - if (tile_start_y < 0) { - tile_start_y += tile_height; - } - tile_end_dx = tile_width - tile_start_x; - - if (depth == 8) { - byte_line = ((uint8_t *)bits) + stride * y + x; - tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x; - while (height--) { - tiled_rop_copy_8((uint8_t *)byte_line, width, - (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx, - tile_width); - byte_line += stride; - tile_line += tile_stride; - if (++tile_start_y == tile_height) { - tile_line -= tile_height * tile_stride; - tile_start_y = 0; - } - } - - } else if (depth == 16) { - byte_line = ((uint8_t *)bits) + stride * y + x * 2; - tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2; - while (height--) { - tiled_rop_copy_16((uint16_t *)byte_line, width, - (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx, - tile_width); - byte_line += stride; - tile_line += tile_stride; - if (++tile_start_y == tile_height) { - tile_line -= tile_height * tile_stride; - tile_start_y = 0; - } - } - } else { - ASSERT (depth == 32); - - byte_line = ((uint8_t *)bits) + stride * y + x * 4; - tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4; - while (height--) { - tiled_rop_copy_32((uint32_t *)byte_line, width, - (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx, - tile_width); - byte_line += stride; - tile_line += tile_stride; - if (++tile_start_y == tile_height) { - tile_line -= tile_height * tile_stride; - tile_start_y = 0; - } - } - } -} - -void spice_pixman_tile_rect_rop(pixman_image_t *dest, - int x, int y, - int width, int height, - pixman_image_t *tile, - int offset_x, - int offset_y, - SpiceROP rop) -{ - uint32_t *bits, *tile_bits; - int stride, depth; - int tile_width, tile_height, tile_stride; - uint8_t *byte_line; - uint8_t *tile_line; - int tile_start_x, tile_start_y, tile_end_dx; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - tile_bits = pixman_image_get_data(tile); - tile_stride = pixman_image_get_stride(tile); - tile_width = pixman_image_get_width(tile); - tile_height = pixman_image_get_height(tile); - - ASSERT(x >= 0); - ASSERT(y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(x + width <= pixman_image_get_width(dest)); - ASSERT(y + height <= pixman_image_get_height(dest)); - ASSERT(rop >= 0 && rop < 16); - ASSERT(depth == spice_pixman_image_get_bpp(tile)); - - tile_start_x = (x - offset_x) % tile_width; - if (tile_start_x < 0) { - tile_start_x += tile_width; - } - tile_start_y = (y - offset_y) % tile_height; - if (tile_start_y < 0) { - tile_start_y += tile_height; - } - tile_end_dx = tile_width - tile_start_x; - - if (depth == 8) { - tiled_rop_8_func_t rop_func = tiled_rops_8[rop]; - - byte_line = ((uint8_t *)bits) + stride * y + x; - tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x; - while (height--) { - rop_func((uint8_t *)byte_line, width, - (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx, - tile_width); - byte_line += stride; - tile_line += tile_stride; - if (++tile_start_y == tile_height) { - tile_line -= tile_height * tile_stride; - tile_start_y = 0; - } - } - - } else if (depth == 16) { - tiled_rop_16_func_t rop_func = tiled_rops_16[rop]; - - byte_line = ((uint8_t *)bits) + stride * y + x * 2; - tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2; - while (height--) { - rop_func((uint16_t *)byte_line, width, - (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx, - tile_width); - byte_line += stride; - tile_line += tile_stride; - if (++tile_start_y == tile_height) { - tile_line -= tile_height * tile_stride; - tile_start_y = 0; - } - } - } else { - tiled_rop_32_func_t rop_func = tiled_rops_32[rop]; - - ASSERT (depth == 32); - - byte_line = ((uint8_t *)bits) + stride * y + x * 4; - tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4; - while (height--) { - rop_func((uint32_t *)byte_line, width, - (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx, - tile_width); - byte_line += stride; - tile_line += tile_stride; - if (++tile_start_y == tile_height) { - tile_line -= tile_height * tile_stride; - tile_start_y = 0; - } - } - } -} - - -void spice_pixman_blit(pixman_image_t *dest, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height) -{ - uint32_t *bits, *src_bits; - int stride, depth, src_depth; - int src_width, src_height, src_stride; - uint8_t *byte_line; - uint8_t *src_line; - int byte_width; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - src_bits = pixman_image_get_data(src); - src_stride = pixman_image_get_stride(src); - src_width = pixman_image_get_width(src); - src_height = pixman_image_get_height(src); - src_depth = spice_pixman_image_get_bpp(src); - - /* Clip source */ - if (src_x < 0) { - width += src_x; - dest_x -= src_x; - src_x = 0; - } - if (src_y < 0) { - height += src_y; - dest_y -= src_y; - src_y = 0; - } - if (src_x + width > src_width) { - width = src_width - src_x; - } - if (src_y + height > src_height) { - height = src_height - src_y; - } - - if (width <= 0 || height <= 0) { - return; - } - - ASSERT(src_x >= 0); - ASSERT(src_y >= 0); - ASSERT(dest_x >= 0); - ASSERT(dest_y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(dest_x + width <= pixman_image_get_width(dest)); - ASSERT(dest_y + height <= pixman_image_get_height(dest)); - ASSERT(src_x + width <= pixman_image_get_width(src)); - ASSERT(src_y + height <= pixman_image_get_height(src)); - ASSERT(depth == src_depth); - - if (pixman_blt(src_bits, - bits, - src_stride / 4, - stride / 4, - depth, depth, - src_x, src_y, - dest_x, dest_y, - width, height)) { - return; - } - - if (depth == 8) { - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x; - byte_width = width; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x; - } else if (depth == 16) { - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2; - byte_width = width * 2; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2; - } else { - ASSERT (depth == 32); - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4; - byte_width = width * 4; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4; - } - - while (height--) { - memcpy(byte_line, src_line, byte_width); - byte_line += stride; - src_line += src_stride; - } -} - -void spice_pixman_blit_rop (pixman_image_t *dest, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - SpiceROP rop) -{ - uint32_t *bits, *src_bits; - int stride, depth, src_depth; - int src_width, src_height, src_stride; - uint8_t *byte_line; - uint8_t *src_line; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - src_bits = pixman_image_get_data(src); - src_stride = pixman_image_get_stride(src); - src_width = pixman_image_get_width(src); - src_height = pixman_image_get_height(src); - src_depth = spice_pixman_image_get_bpp(src); - - /* Clip source */ - if (src_x < 0) { - width += src_x; - dest_x -= src_x; - src_x = 0; - } - if (src_y < 0) { - height += src_y; - dest_y -= src_y; - src_y = 0; - } - if (src_x + width > src_width) { - width = src_width - src_x; - } - if (src_y + height > src_height) { - height = src_height - src_y; - } - - if (width <= 0 || height <= 0) { - return; - } - - ASSERT(src_x >= 0); - ASSERT(src_y >= 0); - ASSERT(dest_x >= 0); - ASSERT(dest_y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(dest_x + width <= pixman_image_get_width(dest)); - ASSERT(dest_y + height <= pixman_image_get_height(dest)); - ASSERT(src_x + width <= pixman_image_get_width(src)); - ASSERT(src_y + height <= pixman_image_get_height(src)); - ASSERT(depth == src_depth); - - if (depth == 8) { - copy_rop_8_func_t rop_func = copy_rops_8[rop]; - - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x; - - while (height--) { - rop_func((uint8_t *)byte_line, (uint8_t *)src_line, width); - byte_line += stride; - src_line += src_stride; - } - } else if (depth == 16) { - copy_rop_16_func_t rop_func = copy_rops_16[rop]; - - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2; - - while (height--) { - rop_func((uint16_t *)byte_line, (uint16_t *)src_line, width); - byte_line += stride; - src_line += src_stride; - } - } else { - copy_rop_32_func_t rop_func = copy_rops_32[rop]; - - ASSERT (depth == 32); - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4; - - while (height--) { - rop_func((uint32_t *)byte_line, (uint32_t *)src_line, width); - byte_line += stride; - src_line += src_stride; - } - } - -} - -void spice_pixman_blit_colorkey (pixman_image_t *dest, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - uint32_t transparent_color) -{ - uint32_t *bits, *src_bits; - int stride, depth; - int src_width, src_height, src_stride; - uint8_t *byte_line; - uint8_t *src_line; - int x; - - bits = pixman_image_get_data(dest); - stride = pixman_image_get_stride(dest); - depth = spice_pixman_image_get_bpp(dest); - /* stride is in bytes, depth in bits */ - - src_bits = pixman_image_get_data(src); - src_stride = pixman_image_get_stride(src); - src_width = pixman_image_get_width(src); - src_height = pixman_image_get_height(src); - - /* Clip source */ - if (src_x < 0) { - width += src_x; - dest_x -= src_x; - src_x = 0; - } - if (src_y < 0) { - height += src_y; - dest_y -= src_y; - src_y = 0; - } - if (src_x + width > src_width) { - width = src_width - src_x; - } - if (src_y + height > src_height) { - height = src_height - src_y; - } - - if (width <= 0 || height <= 0) { - return; - } - - ASSERT(src_x >= 0); - ASSERT(src_y >= 0); - ASSERT(dest_x >= 0); - ASSERT(dest_y >= 0); - ASSERT(width > 0); - ASSERT(height > 0); - ASSERT(dest_x + width <= pixman_image_get_width(dest)); - ASSERT(dest_y + height <= pixman_image_get_height(dest)); - ASSERT(src_x + width <= pixman_image_get_width(src)); - ASSERT(src_y + height <= pixman_image_get_height(src)); - ASSERT(depth == spice_pixman_image_get_bpp(src)); - - if (depth == 8) { - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x; - - while (height--) { - uint8_t *d = (uint8_t *)byte_line; - uint8_t *s = (uint8_t *)src_line; - for (x = 0; x < width; x++) { - uint8_t val = *s; - if (val != (uint8_t)transparent_color) { - *d = val; - } - s++; d++; - } - - byte_line += stride; - src_line += src_stride; - } - } else if (depth == 16) { - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2; - - while (height--) { - uint16_t *d = (uint16_t *)byte_line; - uint16_t *s = (uint16_t *)src_line; - - for (x = 0; x < width; x++) { - uint16_t val = *s; - if (val != (uint16_t)transparent_color) { - *d = val; - } - s++; d++; - } - - byte_line += stride; - src_line += src_stride; - } - } else { - ASSERT (depth == 32); - byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4; - src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4; - - while (height--) { - uint32_t *d = (uint32_t *)byte_line; - uint32_t *s = (uint32_t *)src_line; - - transparent_color &= 0xffffff; - for (x = 0; x < width; x++) { - uint32_t val = *s; - if ((0xffffff & val) != transparent_color) { - *d = val; - } - s++; d++; - } - - byte_line += stride; - src_line += src_stride; - } - } -} - -static void copy_bits_up(uint8_t *data, const int stride, int bpp, - const int src_x, const int src_y, - const int width, const int height, - const int dest_x, const int dest_y) -{ - uint8_t *src = data + src_y * stride + src_x * bpp; - uint8_t *dest = data + dest_y * stride + dest_x * bpp; - uint8_t *end = dest + height * stride; - for (; dest != end; dest += stride, src += stride) { - memcpy(dest, src, width * bpp); - } -} - -static void copy_bits_down(uint8_t *data, const int stride, int bpp, - const int src_x, const int src_y, - const int width, const int height, - const int dest_x, const int dest_y) -{ - uint8_t *src = data + (src_y + height - 1) * stride + src_x * bpp; - uint8_t *end = data + (dest_y - 1) * stride + dest_x * bpp; - uint8_t *dest = end + height * stride; - - for (; dest != end; dest -= stride, src -= stride) { - memcpy(dest, src, width * bpp); - } -} - -static void copy_bits_same_line(uint8_t *data, const int stride, int bpp, - const int src_x, const int src_y, - const int width, const int height, - const int dest_x, const int dest_y) -{ - uint8_t *src = data + src_y * stride + src_x * bpp; - uint8_t *dest = data + dest_y * stride + dest_x * bpp; - uint8_t *end = dest + height * stride; - for (; dest != end; dest += stride, src += stride) { - memmove(dest, src, width * bpp); - } -} - -void spice_pixman_copy_rect (pixman_image_t *image, - int src_x, int src_y, - int width, int height, - int dest_x, int dest_y) -{ - uint8_t *data; - int stride; - int bpp; - - data = (uint8_t *)pixman_image_get_data(image); - stride = pixman_image_get_stride(image); - bpp = spice_pixman_image_get_bpp(image) / 8; - - if (dest_y > src_y) { - copy_bits_down(data, stride, bpp, - src_x, src_y, - width, height, - dest_x, dest_y); - } else if (dest_y < src_y) { - copy_bits_up(data, stride, bpp, - src_x, src_y, - width, height, - dest_x, dest_y); - } else { - copy_bits_same_line(data, stride, bpp, - src_x, src_y, - width, height, - dest_x, dest_y); - } -} - -pixman_bool_t spice_pixman_region32_init_rects (pixman_region32_t *region, - const SpiceRect *rects, - int count) -{ - /* These types are compatible, so just cast */ - return pixman_region32_init_rects(region, (pixman_box32_t *)rects, count); -} - -pixman_format_code_t spice_surface_format_to_pixman(uint32_t surface_format) -{ - switch (surface_format) { - case SPICE_SURFACE_FMT_1_A: - return PIXMAN_a1; - case SPICE_SURFACE_FMT_8_A: - return PIXMAN_a8; - case SPICE_SURFACE_FMT_16_555: - return PIXMAN_x1r5g5b5; - case SPICE_SURFACE_FMT_16_565: - return PIXMAN_r5g6b5; - case SPICE_SURFACE_FMT_32_xRGB: - return PIXMAN_x8r8g8b8; - case SPICE_SURFACE_FMT_32_ARGB: - return PIXMAN_a8r8g8b8; - default: - printf("Unknown surface format %d\n", surface_format); - abort(); - break; - } - return (pixman_format_code_t)0; /* Not reached */ -} - -/* Returns the "spice native" pixman version of a specific bitmap format. - * This isn't bitwise the same as the bitmap format, for instance we - * typically convert indexed to real color modes and use the standard - * surface modes rather than weird things like 24bit - */ -pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format, - uint32_t palette_surface_format) -{ - switch (bitmap_format) { - case SPICE_BITMAP_FMT_1BIT_LE: - case SPICE_BITMAP_FMT_1BIT_BE: - case SPICE_BITMAP_FMT_4BIT_LE: - case SPICE_BITMAP_FMT_4BIT_BE: - case SPICE_BITMAP_FMT_8BIT: - /* Indexed mode palettes are the same as their destination canvas format */ - return spice_surface_format_to_pixman(palette_surface_format); - - case SPICE_BITMAP_FMT_16BIT: - return PIXMAN_x1r5g5b5; - - case SPICE_BITMAP_FMT_24BIT: - case SPICE_BITMAP_FMT_32BIT: - return PIXMAN_x8r8g8b8; - - case SPICE_BITMAP_FMT_RGBA: - return PIXMAN_a8r8g8b8; - - case SPICE_BITMAP_FMT_INVALID: - default: - printf("Unknown bitmap format %d\n", bitmap_format); - abort(); - return PIXMAN_a8r8g8b8; - } -} - -/* Tries to view a spice bitmap as a pixman_image_t without copying, - * will often fail due to unhandled formats or strides. - */ -pixman_image_t *spice_bitmap_try_as_pixman(int src_format, - int flags, - int width, - int height, - uint8_t *data, - int stride) -{ - pixman_format_code_t pixman_format; - - /* Pixman stride must be multiple of 4 */ - if (stride % 4 != 0) { - return NULL; - } - - switch (src_format) { - case SPICE_BITMAP_FMT_32BIT: -#ifdef WORDS_BIGENDIAN - pixman_format = PIXMAN_b8g8r8x8; -#else - pixman_format = PIXMAN_x8r8g8b8; -#endif - break; - case SPICE_BITMAP_FMT_RGBA: -#ifdef WORDS_BIGENDIAN - pixman_format = PIXMAN_b8g8r8a8; -#else - pixman_format = PIXMAN_a8r8g8b8; -#endif - break; - case SPICE_BITMAP_FMT_24BIT: -#ifdef WORDS_BIGENDIAN - pixman_format = PIXMAN_b8g8r8; -#else - pixman_format = PIXMAN_r8g8b8; -#endif - break; - case SPICE_BITMAP_FMT_16BIT: -#ifdef WORDS_BIGENDIAN - return NULL; -#else - pixman_format = PIXMAN_x1r5g5b5; -#endif - break; - - default: - return NULL; - } - - if (!(flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { - data += stride * (height - 1); - stride = -stride; - } - - return pixman_image_create_bits (pixman_format, - width, - height, - (uint32_t *)data, - stride); -} - -#ifdef WORDS_BIGENDIAN -#define UINT16_FROM_LE(x) SPICE_BYTESWAP16(x) -#define UINT32_FROM_LE(x) SPICE_BYTESWAP32(x) -#else -#define UINT16_FROM_LE(x) (x) -#define UINT32_FROM_LE(x) (x) -#endif - -static INLINE uint32_t rgb_16_555_to_32(uint16_t color) -{ - uint32_t ret; - - ret = ((color & 0x001f) << 3) | ((color & 0x001c) >> 2); - ret |= ((color & 0x03e0) << 6) | ((color & 0x0380) << 1); - ret |= ((color & 0x7c00) << 9) | ((color & 0x7000) << 4); - - return ret; -} - -static INLINE uint16_t rgb_32_to_16_555(uint32_t color) -{ - return - (((color) >> 3) & 0x001f) | - (((color) >> 6) & 0x03e0) | - (((color) >> 9) & 0x7c00); -} - - -static void bitmap_32_to_32(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end) -{ -#ifdef WORDS_BIGENDIAN - for (; src != end; src += src_stride, dest += dest_stride) { - uint32_t* src_line = (uint32_t *)src; - uint32_t* src_line_end = src_line + width; - uint32_t* dest_line = (uint32_t *)dest; - - for (; src_line < src_line_end; ++dest_line, ++src_line) { - *dest_line = UINT32_FROM_LE(*src_line); - } - } -#else - for (; src != end; src += src_stride, dest += dest_stride) { - memcpy(dest, src, width * 4); - } -#endif -} - -static void bitmap_24_to_32(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end) -{ - for (; src != end; src += src_stride, dest += dest_stride) { - uint8_t* src_line = src; - uint8_t* src_line_end = src_line + width * 3; - uint32_t* dest_line = (uint32_t *)dest; - - for (; src_line < src_line_end; ++dest_line) { - uint32_t r, g, b; - b = *(src_line++); - g = *(src_line++); - r = *(src_line++); - *dest_line = (r << 16) | (g << 8) | (b); - } - } -} - -static void bitmap_16_to_16_555(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end) -{ -#ifdef WORDS_BIGENDIAN - for (; src != end; src += src_stride, dest += dest_stride) { - uint16_t* src_line = (uint16_t *)src; - uint16_t* src_line_end = src_line + width; - uint16_t* dest_line = (uint16_t *)dest; - - for (; src_line < src_line_end; ++dest_line, ++src_line) { - *dest_line = UINT16_FROM_LE(*src_line); - } - } -#else - for (; src != end; src += src_stride, dest += dest_stride) { - memcpy(dest, src, width * 2); - } -#endif -} - -static void bitmap_8_32_to_32(uint8_t *dest, int dest_stride, - uint8_t *src, int src_stride, - int width, uint8_t *end, - SpicePalette *palette) -{ - uint32_t local_ents[256]; - uint32_t *ents; - int n_ents; -#ifdef WORDS_BIGENDIAN - int i; -#endif - - if (!palette) { - PANIC("No palette"); - return; - } - - n_ents = MIN(palette->num_ents, 256); - ents = palette->ents; - - if (n_ents < 255 -#ifdef WORDS_BIGENDIAN - || TRUE -#endif - ) { - memcpy(local_ents, ents, n_ents*4); - ents = local_ents; - -#ifdef WORDS_BIGENDIAN - for (i = 0; i < n_ents; i++) { - ents[i] = UINT32_FROM_LE(ents[i]); - } -#endif - } - - for (; src != end; src += src_stride, dest += dest_stride) { - uint32_t *dest_line = (uint32_t*)dest; - uint8_t *src_line = src; - uint8_t *src_line_end = src_line + width; - - while (src_line < src_line_end) { - *(dest_line++) = ents[*(src_line++)]; - } - } -} - -static void bitmap_8_16_to_16_555(uint8_t *dest, int dest_stride, - uint8_t *src, int src_stride, - int width, uint8_t *end, - SpicePalette *palette) -{ - uint32_t local_ents[256]; - uint32_t *ents; - int n_ents; -#ifdef WORDS_BIGENDIAN - int i; -#endif - - if (!palette) { - PANIC("No palette"); - return; - } - - n_ents = MIN(palette->num_ents, 256); - ents = palette->ents; - - if (n_ents < 255 -#ifdef WORDS_BIGENDIAN - || TRUE -#endif - ) { - memcpy(local_ents, ents, n_ents*4); - ents = local_ents; - -#ifdef WORDS_BIGENDIAN - for (i = 0; i < n_ents; i++) { - ents[i] = UINT32_FROM_LE(ents[i]); - } -#endif - } - - for (; src != end; src += src_stride, dest += dest_stride) { - uint16_t *dest_line = (uint16_t*)dest; - uint8_t *src_line = src; - uint8_t *src_line_end = src_line + width; - - while (src_line < src_line_end) { - *(dest_line++) = ents[*(src_line++)]; - } - } -} - -static void bitmap_4be_32_to_32(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end, - SpicePalette *palette) -{ - uint32_t local_ents[16]; - uint32_t *ents; - int n_ents; -#ifdef WORDS_BIGENDIAN - int i; -#endif - - if (!palette) { - PANIC("No palette"); - return; - } - - n_ents = MIN(palette->num_ents, 16); - ents = palette->ents; - - if (n_ents < 16 -#ifdef WORDS_BIGENDIAN - || TRUE -#endif - ) { - memcpy(local_ents, ents, n_ents*4); - ents = local_ents; - -#ifdef WORDS_BIGENDIAN - for (i = 0; i < n_ents; i++) { - ents[i] = UINT32_FROM_LE(ents[i]); - } -#endif - } - - for (; src != end; src += src_stride, dest += dest_stride) { - uint32_t *dest_line = (uint32_t *)dest; - uint8_t *row = src; - int i; - - for (i = 0; i < (width >> 1); i++) { - *(dest_line++) = ents[(*row >> 4) & 0x0f]; - *(dest_line++) = ents[*(row++) & 0x0f]; - } - if (width & 1) { - *(dest_line) = ents[(*row >> 4) & 0x0f]; - } - } -} - -static void bitmap_4be_16_to_16_555(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end, - SpicePalette *palette) -{ - uint32_t local_ents[16]; - uint32_t *ents; - int n_ents; -#ifdef WORDS_BIGENDIAN - int i; -#endif - - if (!palette) { - PANIC("No palette"); - return; - } - - n_ents = MIN(palette->num_ents, 16); - ents = palette->ents; - - if (n_ents < 16 -#ifdef WORDS_BIGENDIAN - || TRUE -#endif - ) { - memcpy(local_ents, ents, n_ents*4); - ents = local_ents; - -#ifdef WORDS_BIGENDIAN - for (i = 0; i < n_ents; i++) { - ents[i] = UINT32_FROM_LE(ents[i]); - } -#endif - } - - for (; src != end; src += src_stride, dest += dest_stride) { - uint16_t *dest_line = (uint16_t *)dest; - uint8_t *row = src; - int i; - - for (i = 0; i < (width >> 1); i++) { - *(dest_line++) = ents[(*row >> 4) & 0x0f]; - *(dest_line++) = ents[*(row++) & 0x0f]; - } - if (width & 1) { - *(dest_line) = ents[(*row >> 4) & 0x0f]; - } - } -} - -static INLINE int test_bit_be(void* addr, int bit) -{ - return !!(((uint8_t*)addr)[bit >> 3] & (0x80 >> (bit & 0x07))); -} - -static void bitmap_1be_32_to_32(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end, - SpicePalette *palette) -{ - uint32_t fore_color; - uint32_t back_color; - - ASSERT(palette != NULL); - - if (!palette) { - return; - } - - fore_color = UINT32_FROM_LE(palette->ents[1]); - back_color = UINT32_FROM_LE(palette->ents[0]); - - for (; src != end; src += src_stride, dest += dest_stride) { - uint32_t* dest_line = (uint32_t*)dest; - int i; - - for (i = 0; i < width; i++) { - if (test_bit_be(src, i)) { - *(dest_line++) = fore_color; - } else { - *(dest_line++) = back_color; - } - } - } -} - - -static void bitmap_1be_16_to_16_555(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end, - SpicePalette *palette) -{ - uint16_t fore_color; - uint16_t back_color; - - ASSERT(palette != NULL); - - if (!palette) { - return; - } - - fore_color = (uint16_t) UINT32_FROM_LE(palette->ents[1]); - back_color = (uint16_t) UINT32_FROM_LE(palette->ents[0]); - - for (; src != end; src += src_stride, dest += dest_stride) { - uint16_t* dest_line = (uint16_t*)dest; - int i; - - for (i = 0; i < width; i++) { - if (test_bit_be(src, i)) { - *(dest_line++) = fore_color; - } else { - *(dest_line++) = back_color; - } - } - } -} - -#ifdef NOT_USED_ATM - -static void bitmap_16_to_32(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end) -{ - for (; src != end; src += src_stride, dest += dest_stride) { - uint16_t* src_line = (uint16_t*)src; - uint16_t* src_line_end = src_line + width; - uint32_t* dest_line = (uint32_t*)dest; - - for (; src_line < src_line_end; ++dest_line, src_line++) { - *dest_line = rgb_16_555_to_32(UINT16_FROM_LE(*src_line)); - } - } -} - -static void bitmap_32_to_16_555(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end) -{ - for (; src != end; src += src_stride, dest += dest_stride) { - uint32_t* src_line = (uint32_t *)src; - uint32_t* src_line_end = src_line + width; - uint16_t* dest_line = (uint16_t *)dest; - - for (; src_line < src_line_end; ++dest_line, ++src_line) { - *dest_line = rgb_32_to_16_555(UINT16_FROM_LE(*src_line)); - } - } -} - - -static void bitmap_24_to_16_555(uint8_t* dest, int dest_stride, - uint8_t* src, int src_stride, - int width, uint8_t* end) -{ - for (; src != end; src += src_stride, dest += dest_stride) { - uint8_t* src_line = src; - uint8_t* src_line_end = src_line + width * 3; - uint16_t* dest_line = (uint16_t *)dest; - - for (; src_line < src_line_end; ++dest_line) { - uint8_t r, g, b; - b = *(src_line++); - g = *(src_line++); - r = *(src_line++); - *dest_line = rgb_32_to_16_555(r << 24 | g << 16 | b); - } - } -} - -#endif - -/* This assumes that the dest, if set is the same format as - spice_bitmap_format_to_pixman would have picked */ -pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image, - int src_format, - int flags, - int width, - int height, - uint8_t *src, - int src_stride, - uint32_t palette_surface_format, - SpicePalette *palette) -{ - uint8_t* dest; - int dest_stride; - uint8_t* end; - - if (dest_image == NULL) { - pixman_format_code_t dest_format; - - dest_format = spice_bitmap_format_to_pixman(src_format, - palette_surface_format); - dest_image = pixman_image_create_bits (dest_format, - width, height, - NULL, 0); - } - - dest = (uint8_t *)pixman_image_get_data(dest_image); - dest_stride = pixman_image_get_stride(dest_image); - if (!(flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) { - ASSERT(height > 0); - dest += dest_stride * (height - 1); - dest_stride = -dest_stride; - } - end = src + (height * src_stride); - - switch (src_format) { - case SPICE_BITMAP_FMT_32BIT: - case SPICE_BITMAP_FMT_RGBA: - bitmap_32_to_32(dest, dest_stride, src, src_stride, width, end); - break; - case SPICE_BITMAP_FMT_24BIT: - bitmap_24_to_32(dest, dest_stride, src, src_stride, width, end); - break; - case SPICE_BITMAP_FMT_16BIT: - bitmap_16_to_16_555(dest, dest_stride, src, src_stride, width, end); - break; - case SPICE_BITMAP_FMT_8BIT: - if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB || - palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) { - bitmap_8_32_to_32(dest, dest_stride, src, src_stride, width, end, palette); - } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) { - bitmap_8_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette); - } else { - PANIC("Unsupported palette format"); - } - break; - case SPICE_BITMAP_FMT_4BIT_BE: - if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB || - palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) { - bitmap_4be_32_to_32(dest, dest_stride, src, src_stride, width, end, palette); - } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) { - bitmap_4be_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette); - } else { - PANIC("Unsupported palette format"); - } - break; - case SPICE_BITMAP_FMT_1BIT_BE: - if (palette_surface_format == SPICE_SURFACE_FMT_32_ARGB || - palette_surface_format == SPICE_SURFACE_FMT_32_xRGB) { - bitmap_1be_32_to_32(dest, dest_stride, src, src_stride, width, end, palette); - } else if (palette_surface_format == SPICE_SURFACE_FMT_16_555) { - bitmap_1be_16_to_16_555(dest, dest_stride, src, src_stride, width, end, palette); - } else { - PANIC("Unsupported palette format"); - } - break; - default: - PANIC("Unsupported bitmap format"); - break; - } - - return dest_image; -} - -static int pixman_format_compatible (pixman_format_code_t dest_format, - pixman_format_code_t src_format) -{ - if (dest_format == src_format) { - return TRUE; - } - - if (src_format == PIXMAN_a8r8g8b8 && - dest_format == PIXMAN_x8r8g8b8) { - /* This is the same, we just ignore the alphas */ - return TRUE; - } - - return FALSE; -} - -pixman_image_t *spice_bitmap_convert_to_pixman(pixman_format_code_t dest_format, - pixman_image_t *dest_image, - int src_format, - int flags, - int width, - int height, - uint8_t *src, - int src_stride, - uint32_t palette_surface_format, - SpicePalette *palette) -{ - pixman_image_t *src_image; - pixman_format_code_t native_format; - - if (dest_image == NULL) { - dest_image = pixman_image_create_bits (dest_format, - width, height, - NULL, 0); - } - - native_format = - spice_bitmap_format_to_pixman(src_format, palette_surface_format); - - if (pixman_format_compatible (dest_format, native_format)) { - return spice_bitmap_to_pixman(dest_image, - src_format, - flags, width,height, - src, src_stride, - palette_surface_format, palette); - } - - src_image = spice_bitmap_try_as_pixman(src_format, - flags, width,height, - src, src_stride); - - /* Can't convert directly, need a temporary copy - * Hopefully most bitmap reads should not need conversion (i.e. - * hit the spice_bitmap_to_pixmap case above) or work with the - * try_as_pixmap case, but in case some specific combination - * shows up here commonly we might want to add non-temporary - * conversion special casing here */ - if (src_image == NULL) { - src_image = spice_bitmap_to_pixman(NULL, - src_format, - flags, width,height, - src, src_stride, - palette_surface_format, palette); - } - - pixman_image_composite32 (PIXMAN_OP_SRC, - src_image, NULL, dest_image, - 0, 0, - 0, 0, - 0, 0, - width, height); - - pixman_image_unref (src_image); - - return dest_image; -} diff --git a/common/pixman_utils.h b/common/pixman_utils.h deleted file mode 100644 index 61eaddd9..00000000 --- a/common/pixman_utils.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H__PIXMAN_UTILS -#define _H__PIXMAN_UTILS - -#include <spice/types.h> -#include <stdlib.h> -#define PIXMAN_DONT_DEFINE_STDINT -#include <pixman.h> - -#include "draw.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* This lists all possible 2 argument binary raster ops. - * This enum has the same values as the X11 GXcopy type - * and same as the GL constants (GL_AND etc) if you - * or it with 0x1500. However it is not exactly the - * same as the win32 ROP2 type (they use another order). - */ -typedef enum { - SPICE_ROP_CLEAR, /* 0x0 0 */ - SPICE_ROP_AND, /* 0x1 src AND dst */ - SPICE_ROP_AND_REVERSE, /* 0x2 src AND NOT dst */ - SPICE_ROP_COPY, /* 0x3 src */ - SPICE_ROP_AND_INVERTED, /* 0x4 (NOT src) AND dst */ - SPICE_ROP_NOOP, /* 0x5 dst */ - SPICE_ROP_XOR, /* 0x6 src XOR dst */ - SPICE_ROP_OR, /* 0x7 src OR dst */ - SPICE_ROP_NOR, /* 0x8 (NOT src) AND (NOT dst) */ - SPICE_ROP_EQUIV, /* 0x9 (NOT src) XOR dst */ - SPICE_ROP_INVERT, /* 0xa NOT dst */ - SPICE_ROP_OR_REVERSE, /* 0xb src OR (NOT dst) */ - SPICE_ROP_COPY_INVERTED, /* 0xc NOT src */ - SPICE_ROP_OR_INVERTED, /* 0xd (NOT src) OR dst */ - SPICE_ROP_NAND, /* 0xe (NOT src) OR (NOT dst) */ - SPICE_ROP_SET /* 0xf 1 */ -} SpiceROP; - - -int spice_pixman_image_get_bpp(pixman_image_t *image); - -pixman_format_code_t spice_surface_format_to_pixman(uint32_t surface_format); -pixman_format_code_t spice_bitmap_format_to_pixman(int bitmap_format, - uint32_t palette_surface_format); -pixman_image_t *spice_bitmap_try_as_pixman(int src_format, int flags, - int width, int height, - uint8_t *data, int stride); -pixman_image_t *spice_bitmap_to_pixman(pixman_image_t *dest_image, - int src_format, int flags, - int width, int height, - uint8_t *src, int src_stride, - uint32_t palette_surface_format, - SpicePalette *palette); -pixman_image_t *spice_bitmap_convert_to_pixman(pixman_format_code_t dest_format, - pixman_image_t *dest_image, - int src_format, int flags, - int width, int height, - uint8_t *src, int src_stride, - uint32_t palette_surface_format, - SpicePalette *palette); - -void spice_pixman_region32_init_from_bitmap(pixman_region32_t *region, - uint32_t *data, - int width, int height, - int stride); -pixman_bool_t spice_pixman_region32_init_rects(pixman_region32_t *region, - const SpiceRect *rects, - int count); -void spice_pixman_fill_rect(pixman_image_t *dest, - int x, int y, - int w, int h, - uint32_t value); -void spice_pixman_fill_rect_rop(pixman_image_t *dest, - int x, int y, - int w, int h, - uint32_t value, - SpiceROP rop); -void spice_pixman_tile_rect(pixman_image_t *dest, - int x, int y, - int w, int h, - pixman_image_t *tile, - int offset_x, - int offset_y); -void spice_pixman_tile_rect_rop(pixman_image_t *dest, - int x, int y, - int w, int h, - pixman_image_t *tile, - int offset_x, - int offset_y, - SpiceROP rop); -void spice_pixman_blit(pixman_image_t *dest, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int w, int h); -void spice_pixman_blit_rop(pixman_image_t *dest, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int w, int h, - SpiceROP rop); -void spice_pixman_blit_colorkey(pixman_image_t *dest, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - uint32_t transparent_color); -void spice_pixman_copy_rect(pixman_image_t *image, - int src_x, int src_y, - int w, int h, - int dest_x, int dest_y); - -#ifdef __cplusplus -} -#endif - -#endif /* _H__PIXMAN_UTILS */ diff --git a/common/quic.c b/common/quic.c deleted file mode 100644 index 707724a2..00000000 --- a/common/quic.c +++ /dev/null @@ -1,1699 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -// Red Hat image compression based on SFALIC by Roman Starosolski -// http://sun.iinf.polsl.gliwice.pl/~rstaros/sfalic/index.html - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "quic.h" -#include <spice/macros.h> -#include "bitops.h" - -//#define DEBUG - -#define RLE -#define RLE_STAT -#define PRED_1 -//#define RLE_PRED_1 -#define RLE_PRED_2 -//#define RLE_PRED_3 -#define QUIC_RGB - -#define QUIC_MAGIC (*(uint32_t *)"QUIC") -#define QUIC_VERSION_MAJOR 0U -#define QUIC_VERSION_MINOR 1U -#define QUIC_VERSION ((QUIC_VERSION_MAJOR << 16) | (QUIC_VERSION_MAJOR & 0xffff)) - -#ifdef DEBUG - -#define ASSERT(usr, x) \ - if (!(x)) (usr)->error(usr, "%s: ASSERT %s failed\n", __FUNCTION__, #x); - -#else - -#define ASSERT(usr, x) - -#endif - -typedef uint8_t BYTE; - -/* maximum number of codes in family */ -#define MAXNUMCODES 8 - -/* model evolution, warning: only 1,3 and 5 allowed */ -#define DEFevol 3 -#define MINevol 0 -#define MAXevol 5 - -/* starting wait mask index */ -#define DEFwmistart 0 -#define MINwmistart 0 - -/* codeword length limit */ -#define DEFmaxclen 26 - -/* target wait mask index */ -#define DEFwmimax 6 - -/* number of symbols to encode before increasing wait mask index */ -#define DEFwminext 2048 -#define MINwminext 1 -#define MAXwminext 100000000 - -typedef struct QuicFamily { - unsigned int nGRcodewords[MAXNUMCODES]; /* indexed by code number, contains number of - unmodified GR codewords in the code */ - unsigned int notGRcwlen[MAXNUMCODES]; /* indexed by code number, contains codeword - length of the not-GR codeword */ - unsigned int notGRprefixmask[MAXNUMCODES]; /* indexed by code number, contains mask to - determine if the codeword is GR or not-GR */ - unsigned int notGRsuffixlen[MAXNUMCODES]; /* indexed by code number, contains suffix - length of the not-GR codeword */ - - /* array for translating distribution U to L for depths up to 8 bpp, - initialized by decorelateinit() */ - BYTE xlatU2L[256]; - - /* array for translating distribution L to U for depths up to 8 bpp, - initialized by corelateinit() */ - unsigned int xlatL2U[256]; -} QuicFamily; - -static QuicFamily family_8bpc; -static QuicFamily family_5bpc; - -typedef unsigned COUNTER; /* counter in the array of counters in bucket of the data model */ - -typedef struct s_bucket { - COUNTER *pcounters; /* pointer to array of counters */ - unsigned int bestcode; /* best code so far */ -} s_bucket; - -typedef struct Encoder Encoder; - -typedef struct CommonState { - Encoder *encoder; - - unsigned int waitcnt; - unsigned int tabrand_seed; - unsigned int wm_trigger; - unsigned int wmidx; - unsigned int wmileft; - -#ifdef RLE_STAT - int melcstate; /* index to the state array */ - - int melclen; /* contents of the state array location - indexed by melcstate: the "expected" - run length is 2^melclen, shorter runs are - encoded by a 1 followed by the run length - in binary representation, wit a fixed length - of melclen bits */ - - unsigned long melcorder; /* 2^ melclen */ -#endif -} CommonState; - - -#define MAX_CHANNELS 4 - -typedef struct FamilyStat { - s_bucket **buckets_ptrs; - s_bucket *buckets_buf; - COUNTER *counters; -} FamilyStat; - -typedef struct Channel { - Encoder *encoder; - - int correlate_row_width; - BYTE *correlate_row; - - s_bucket **_buckets_ptrs; - - FamilyStat family_stat_8bpc; - FamilyStat family_stat_5bpc; - - CommonState state; -} Channel; - -struct Encoder { - QuicUsrContext *usr; - QuicImageType type; - unsigned int width; - unsigned int height; - unsigned int num_channels; - - unsigned int n_buckets_8bpc; - unsigned int n_buckets_5bpc; - - unsigned int io_available_bits; - uint32_t io_word; - uint32_t io_next_word; - uint32_t *io_now; - uint32_t *io_end; - uint32_t io_words_count; - - int rows_completed; - - Channel channels[MAX_CHANNELS]; - - CommonState rgb_state; -}; - -/* target wait mask index */ -static int wmimax = DEFwmimax; - -/* number of symbols to encode before increasing wait mask index */ -static int wminext = DEFwminext; - -/* model evolution mode */ -static int evol = DEFevol; - -/* bppmask[i] contains i ones as lsb-s */ -static const unsigned long int bppmask[33] = { - 0x00000000, /* [0] */ - 0x00000001, 0x00000003, 0x00000007, 0x0000000f, - 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, - 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff, - 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff, - 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff, - 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff, - 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff, - 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff /* [32] */ -}; - -static const unsigned int bitat[32] = { - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x00000100, 0x00000200, 0x00000400, 0x00000800, - 0x00001000, 0x00002000, 0x00004000, 0x00008000, - 0x00010000, 0x00020000, 0x00040000, 0x00080000, - 0x00100000, 0x00200000, 0x00400000, 0x00800000, - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000 /* [31]*/ -}; - - -#define TABRAND_TABSIZE 256 -#define TABRAND_SEEDMASK 0x0ff - -static const unsigned int tabrand_chaos[TABRAND_TABSIZE] = { - 0x02c57542, 0x35427717, 0x2f5a2153, 0x9244f155, 0x7bd26d07, 0x354c6052, 0x57329b28, 0x2993868e, - 0x6cd8808c, 0x147b46e0, 0x99db66af, 0xe32b4cac, 0x1b671264, 0x9d433486, 0x62a4c192, 0x06089a4b, - 0x9e3dce44, 0xdaabee13, 0x222425ea, 0xa46f331d, 0xcd589250, 0x8bb81d7f, 0xc8b736b9, 0x35948d33, - 0xd7ac7fd0, 0x5fbe2803, 0x2cfbc105, 0x013dbc4e, 0x7a37820f, 0x39f88e9e, 0xedd58794, 0xc5076689, - 0xfcada5a4, 0x64c2f46d, 0xb3ba3243, 0x8974b4f9, 0x5a05aebd, 0x20afcd00, 0x39e2b008, 0x88a18a45, - 0x600bde29, 0xf3971ace, 0xf37b0a6b, 0x7041495b, 0x70b707ab, 0x06beffbb, 0x4206051f, 0xe13c4ee3, - 0xc1a78327, 0x91aa067c, 0x8295f72a, 0x732917a6, 0x1d871b4d, 0x4048f136, 0xf1840e7e, 0x6a6048c1, - 0x696cb71a, 0x7ff501c3, 0x0fc6310b, 0x57e0f83d, 0x8cc26e74, 0x11a525a2, 0x946934c7, 0x7cd888f0, - 0x8f9d8604, 0x4f86e73b, 0x04520316, 0xdeeea20c, 0xf1def496, 0x67687288, 0xf540c5b2, 0x22401484, - 0x3478658a, 0xc2385746, 0x01979c2c, 0x5dad73c8, 0x0321f58b, 0xf0fedbee, 0x92826ddf, 0x284bec73, - 0x5b1a1975, 0x03df1e11, 0x20963e01, 0xa17cf12b, 0x740d776e, 0xa7a6bf3c, 0x01b5cce4, 0x1118aa76, - 0xfc6fac0a, 0xce927e9b, 0x00bf2567, 0x806f216c, 0xbca69056, 0x795bd3e9, 0xc9dc4557, 0x8929b6c2, - 0x789d52ec, 0x3f3fbf40, 0xb9197368, 0xa38c15b5, 0xc3b44fa8, 0xca8333b0, 0xb7e8d590, 0xbe807feb, - 0xbf5f8360, 0xd99e2f5c, 0x372928e1, 0x7c757c4c, 0x0db5b154, 0xc01ede02, 0x1fc86e78, 0x1f3985be, - 0xb4805c77, 0x00c880fa, 0x974c1b12, 0x35ab0214, 0xb2dc840d, 0x5b00ae37, 0xd313b026, 0xb260969d, - 0x7f4c8879, 0x1734c4d3, 0x49068631, 0xb9f6a021, 0x6b863e6f, 0xcee5debf, 0x29f8c9fb, 0x53dd6880, - 0x72b61223, 0x1f67a9fd, 0x0a0f6993, 0x13e59119, 0x11cca12e, 0xfe6b6766, 0x16b6effc, 0x97918fc4, - 0xc2b8a563, 0x94f2f741, 0x0bfa8c9a, 0xd1537ae8, 0xc1da349c, 0x873c60ca, 0x95005b85, 0x9b5c080e, - 0xbc8abbd9, 0xe1eab1d2, 0x6dac9070, 0x4ea9ebf1, 0xe0cf30d4, 0x1ef5bd7b, 0xd161043e, 0x5d2fa2e2, - 0xff5d3cae, 0x86ed9f87, 0x2aa1daa1, 0xbd731a34, 0x9e8f4b22, 0xb1c2c67a, 0xc21758c9, 0xa182215d, - 0xccb01948, 0x8d168df7, 0x04238cfe, 0x368c3dbc, 0x0aeadca5, 0xbad21c24, 0x0a71fee5, 0x9fc5d872, - 0x54c152c6, 0xfc329483, 0x6783384a, 0xeddb3e1c, 0x65f90e30, 0x884ad098, 0xce81675a, 0x4b372f7d, - 0x68bf9a39, 0x43445f1e, 0x40f8d8cb, 0x90d5acb6, 0x4cd07282, 0x349eeb06, 0x0c9d5332, 0x520b24ef, - 0x80020447, 0x67976491, 0x2f931ca3, 0xfe9b0535, 0xfcd30220, 0x61a9e6cc, 0xa487d8d7, 0x3f7c5dd1, - 0x7d0127c5, 0x48f51d15, 0x60dea871, 0xc9a91cb7, 0x58b53bb3, 0x9d5e0b2d, 0x624a78b4, 0x30dbee1b, - 0x9bdf22e7, 0x1df5c299, 0x2d5643a7, 0xf4dd35ff, 0x03ca8fd6, 0x53b47ed8, 0x6f2c19aa, 0xfeb0c1f4, - 0x49e54438, 0x2f2577e6, 0xbf876969, 0x72440ea9, 0xfa0bafb8, 0x74f5b3a0, 0x7dd357cd, 0x89ce1358, - 0x6ef2cdda, 0x1e7767f3, 0xa6be9fdb, 0x4f5f88f8, 0xba994a3a, 0x08ca6b65, 0xe0893818, 0x9e00a16a, - 0xf42bfc8f, 0x9972eedc, 0x749c8b51, 0x32c05f5e, 0xd706805f, 0x6bfbb7cf, 0xd9210a10, 0x31a1db97, - 0x923a9559, 0x37a7a1f6, 0x059f8861, 0xca493e62, 0x65157e81, 0x8f6467dd, 0xab85ff9f, 0x9331aff2, - 0x8616b9f5, 0xedbd5695, 0xee7e29b1, 0x313ac44f, 0xb903112f, 0x432ef649, 0xdc0a36c0, 0x61cf2bba, - 0x81474925, 0xa8b6c7ad, 0xee5931de, 0xb2f8158d, 0x59fb7409, 0x2e3dfaed, 0x9af25a3f, 0xe1fed4d5, -}; - -static unsigned int stabrand(void) -{ - //ASSERT( !(TABRAND_SEEDMASK & TABRAND_TABSIZE)); - //ASSERT( TABRAND_SEEDMASK + 1 == TABRAND_TABSIZE ); - - return TABRAND_SEEDMASK; -} - -static unsigned int tabrand(unsigned int *tabrand_seed) -{ - return tabrand_chaos[++*tabrand_seed & TABRAND_SEEDMASK]; -} - -static const unsigned short besttrigtab[3][11] = { /* array of wm_trigger for waitmask and evol, - used by set_wm_trigger() */ - /* 1 */ { 550, 900, 800, 700, 500, 350, 300, 200, 180, 180, 160}, - /* 3 */ { 110, 550, 900, 800, 550, 400, 350, 250, 140, 160, 140}, - /* 5 */ { 100, 120, 550, 900, 700, 500, 400, 300, 220, 250, 160} -}; - -/* set wm_trigger knowing waitmask (param) and evol (glob)*/ -static void set_wm_trigger(CommonState *state) -{ - unsigned int wm = state->wmidx; - if (wm > 10) { - wm = 10; - } - - ASSERT(state->encoder->usr, evol < 6); - - state->wm_trigger = besttrigtab[evol / 2][wm]; - - ASSERT(state->encoder->usr, state->wm_trigger <= 2000); - ASSERT(state->encoder->usr, state->wm_trigger >= 1); -} - -static int ceil_log_2(int val) /* ceil(log_2(val)) */ -{ - int result; - - //ASSERT(val>0); - - if (val == 1) { - return 0; - } - - result = 1; - val -= 1; - while (val >>= 1) { - result++; - } - - return result; -} - -/* number of leading zeroes in the byte, used by cntlzeroes(uint)*/ -static const BYTE lzeroes[256] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -/* count leading zeroes */ -static unsigned int cnt_l_zeroes(const unsigned int bits) -{ - if (bits & 0xff800000) { - return lzeroes[bits >> 24]; - } else if (bits & 0xffff8000) { - return 8 + lzeroes[(bits >> 16) & 0x000000ff]; - } else if (bits & 0xffffff80) { - return 16 + lzeroes[(bits >> 8) & 0x000000ff]; - } else { - return 24 + lzeroes[bits & 0x000000ff]; - } -} - -#define QUIC_FAMILY_8BPC -#include "quic_family_tmpl.c" - -#ifdef QUIC_RGB -#define QUIC_FAMILY_5BPC -#include "quic_family_tmpl.c" -#endif - -static void decorelate_init(QuicFamily *family, int bpc) -{ - const unsigned int pixelbitmask = bppmask[bpc]; - const unsigned int pixelbitmaskshr = pixelbitmask >> 1; - unsigned int s; - - //ASSERT(bpc <= 8); - - for (s = 0; s <= pixelbitmask; s++) { - if (s <= pixelbitmaskshr) { - family->xlatU2L[s] = s << 1; - } else { - family->xlatU2L[s] = ((pixelbitmask - s) << 1) + 1; - } - } -} - -static void corelate_init(QuicFamily *family, int bpc) -{ - const unsigned long int pixelbitmask = bppmask[bpc]; - unsigned long int s; - - //ASSERT(bpc <= 8); - - for (s = 0; s <= pixelbitmask; s++) { - if (s & 0x01) { - family->xlatL2U[s] = pixelbitmask - (s >> 1); - } else { - family->xlatL2U[s] = (s >> 1); - } - } -} - -static void family_init(QuicFamily *family, int bpc, int limit) -{ - int l; - - for (l = 0; l < bpc; l++) { /* fill arrays indexed by code number */ - int altprefixlen, altcodewords; - - altprefixlen = limit - bpc; - if (altprefixlen > (int)(bppmask[bpc - l])) { - altprefixlen = bppmask[bpc - l]; - } - - altcodewords = bppmask[bpc] + 1 - (altprefixlen << l); - - family->nGRcodewords[l] = (altprefixlen << l); - family->notGRcwlen[l] = altprefixlen + ceil_log_2(altcodewords); - family->notGRprefixmask[l] = bppmask[32 - altprefixlen]; /* needed for decoding only */ - family->notGRsuffixlen[l] = ceil_log_2(altcodewords); /* needed for decoding only */ - } - - decorelate_init(family, bpc); - corelate_init(family, bpc); -} - -static void more_io_words(Encoder *encoder) -{ - uint32_t *io_ptr; - int num_io_words = encoder->usr->more_space(encoder->usr, &io_ptr, encoder->rows_completed); - if (num_io_words <= 0) { - encoder->usr->error(encoder->usr, "%s: no more words\n", __FUNCTION__); - } - ASSERT(encoder->usr, io_ptr); - encoder->io_words_count += num_io_words; - encoder->io_now = io_ptr; - encoder->io_end = encoder->io_now + num_io_words; -} - -static void __write_io_word(Encoder *encoder) -{ - more_io_words(encoder); - *(encoder->io_now++) = encoder->io_word; -} - -static void (*__write_io_word_ptr)(Encoder *encoder) = __write_io_word; - -static INLINE void write_io_word(Encoder *encoder) -{ - if (encoder->io_now == encoder->io_end) { - __write_io_word_ptr(encoder); //disable inline optimizations - return; - } - *(encoder->io_now++) = encoder->io_word; -} - -static INLINE void encode(Encoder *encoder, unsigned int word, unsigned int len) -{ - int delta; - - ASSERT(encoder->usr, len > 0 && len < 32); - ASSERT(encoder->usr, !(word & ~bppmask[len])); - if ((delta = ((int)encoder->io_available_bits - len)) >= 0) { - encoder->io_available_bits = delta; - encoder->io_word |= word << encoder->io_available_bits; - return; - } - delta = -delta; - encoder->io_word |= word >> delta; - write_io_word(encoder); - encoder->io_available_bits = 32 - delta; - encoder->io_word = word << encoder->io_available_bits; - - ASSERT(encoder->usr, encoder->io_available_bits < 32); - ASSERT(encoder->usr, (encoder->io_word & bppmask[encoder->io_available_bits]) == 0); -} - -static INLINE void encode_32(Encoder *encoder, unsigned int word) -{ - encode(encoder, word >> 16, 16); - encode(encoder, word & 0x0000ffff, 16); -} - -static INLINE void flush(Encoder *encoder) -{ - if (encoder->io_available_bits > 0 && encoder->io_available_bits != 32) { - encode(encoder, 0, encoder->io_available_bits); - } - encode_32(encoder, 0); - encode(encoder, 0, 1); -} - -static void __read_io_word(Encoder *encoder) -{ - more_io_words(encoder); - encoder->io_next_word = *(encoder->io_now++); -} - -static void (*__read_io_word_ptr)(Encoder *encoder) = __read_io_word; - - -static INLINE void read_io_word(Encoder *encoder) -{ - if (encoder->io_now == encoder->io_end) { - __read_io_word_ptr(encoder); //disable inline optimizations - return; - } - ASSERT(encoder->usr, encoder->io_now < encoder->io_end); - encoder->io_next_word = *(encoder->io_now++); -} - -static INLINE void decode_eatbits(Encoder *encoder, int len) -{ - int delta; - - ASSERT(encoder->usr, len > 0 && len < 32); - encoder->io_word <<= len; - - if ((delta = ((int)encoder->io_available_bits - len)) >= 0) { - encoder->io_available_bits = delta; - encoder->io_word |= encoder->io_next_word >> encoder->io_available_bits; - return; - } - - delta = -delta; - encoder->io_word |= encoder->io_next_word << delta; - read_io_word(encoder); - encoder->io_available_bits = 32 - delta; - encoder->io_word |= (encoder->io_next_word >> encoder->io_available_bits); -} - -static INLINE void decode_eat32bits(Encoder *encoder) -{ - decode_eatbits(encoder, 16); - decode_eatbits(encoder, 16); -} - -#ifdef RLE - -#ifdef RLE_STAT - -static INLINE void encode_ones(Encoder *encoder, unsigned int n) -{ - unsigned int count; - - for (count = n >> 5; count; count--) { - encode(encoder, ~0U, 32); - } - - if ((n &= 0x1f)) { - encode(encoder, (1U << n) - 1, n); - } -} - -#define MELCSTATES 32 /* number of melcode states */ - -static int zeroLUT[256]; /* table to find out number of leading zeros */ - -static int J[MELCSTATES] = { - 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, - 7, 8, 9, 10, 11, 12, 13, 14, 15 -}; - -/* creates the bit counting look-up table. */ -static void init_zeroLUT(void) -{ - int i, j, k, l; - - j = k = 1; - l = 8; - for (i = 0; i < 256; ++i) { - zeroLUT[i] = l; - --k; - if (k == 0) { - k = j; - --l; - j *= 2; - } - } -} - -static void encoder_init_rle(CommonState *state) -{ - state->melcstate = 0; - state->melclen = J[0]; - state->melcorder = 1 << state->melclen; -} - -#ifdef QUIC_RGB - -static void encode_run(Encoder *encoder, unsigned int runlen) //todo: try use end of line -{ - int hits = 0; - - while (runlen >= encoder->rgb_state.melcorder) { - hits++; - runlen -= encoder->rgb_state.melcorder; - if (encoder->rgb_state.melcstate < MELCSTATES) { - encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate]; - encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen); - } - } - - /* send the required number of "hit" bits (one per occurrence - of a run of length melcorder). This number is never too big: - after 31 such "hit" bits, each "hit" would represent a run of 32K - pixels. - */ - encode_ones(encoder, hits); - - encode(encoder, runlen, encoder->rgb_state.melclen + 1); - - /* adjust melcoder parameters */ - if (encoder->rgb_state.melcstate) { - encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate]; - encoder->rgb_state.melcorder = (1L << encoder->rgb_state.melclen); - } -} - -#endif - -static void encode_channel_run(Encoder *encoder, Channel *channel, unsigned int runlen) -{ - //todo: try use end of line - int hits = 0; - - while (runlen >= channel->state.melcorder) { - hits++; - runlen -= channel->state.melcorder; - if (channel->state.melcstate < MELCSTATES) { - channel->state.melclen = J[++channel->state.melcstate]; - channel->state.melcorder = (1L << channel->state.melclen); - } - } - - /* send the required number of "hit" bits (one per occurrence - of a run of length melcorder). This number is never too big: - after 31 such "hit" bits, each "hit" would represent a run of 32K - pixels. - */ - encode_ones(encoder, hits); - - encode(encoder, runlen, channel->state.melclen + 1); - - /* adjust melcoder parameters */ - if (channel->state.melcstate) { - channel->state.melclen = J[--channel->state.melcstate]; - channel->state.melcorder = (1L << channel->state.melclen); - } -} - -/* decoding routine: reads bits from the input and returns a run length. */ -/* argument is the number of pixels left to end-of-line (bound on run length) */ - -#ifdef QUIC_RGB -static int decode_run(Encoder *encoder) -{ - int runlen = 0; - - do { - register int temp, hits; - temp = zeroLUT[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the - input stream, up to 8 */ - for (hits = 1; hits <= temp; hits++) { - runlen += encoder->rgb_state.melcorder; - - if (encoder->rgb_state.melcstate < MELCSTATES) { - encoder->rgb_state.melclen = J[++encoder->rgb_state.melcstate]; - encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen); - } - } - if (temp != 8) { - decode_eatbits(encoder, temp + 1); /* consume the leading - 0 of the remainder encoding */ - break; - } - decode_eatbits(encoder, 8); - } while (1); - - /* read the length of the remainder */ - if (encoder->rgb_state.melclen) { - runlen += encoder->io_word >> (32 - encoder->rgb_state.melclen); - decode_eatbits(encoder, encoder->rgb_state.melclen); - } - - /* adjust melcoder parameters */ - if (encoder->rgb_state.melcstate) { - encoder->rgb_state.melclen = J[--encoder->rgb_state.melcstate]; - encoder->rgb_state.melcorder = (1U << encoder->rgb_state.melclen); - } - - return runlen; -} - -#endif - -static int decode_channel_run(Encoder *encoder, Channel *channel) -{ - int runlen = 0; - - do { - register int temp, hits; - temp = zeroLUT[(BYTE)(~(encoder->io_word >> 24))];/* number of leading ones in the - input stream, up to 8 */ - for (hits = 1; hits <= temp; hits++) { - runlen += channel->state.melcorder; - - if (channel->state.melcstate < MELCSTATES) { - channel->state.melclen = J[++channel->state.melcstate]; - channel->state.melcorder = (1U << channel->state.melclen); - } - } - if (temp != 8) { - decode_eatbits(encoder, temp + 1); /* consume the leading - 0 of the remainder encoding */ - break; - } - decode_eatbits(encoder, 8); - } while (1); - - /* read the length of the remainder */ - if (channel->state.melclen) { - runlen += encoder->io_word >> (32 - channel->state.melclen); - decode_eatbits(encoder, channel->state.melclen); - } - - /* adjust melcoder parameters */ - if (channel->state.melcstate) { - channel->state.melclen = J[--channel->state.melcstate]; - channel->state.melcorder = (1U << channel->state.melclen); - } - - return runlen; -} - -#else - -static INLINE void encode_run(Encoder *encoder, unsigned int len) -{ - int odd = len & 1U; - int msb; - - len &= ~1U; - - while ((msb = spice_bit_find_msb(len))) { - len &= ~(1 << (msb - 1)); - ASSERT(encoder->usr, msb < 32); - encode(encoder, (1 << (msb)) - 1, msb); - encode(encoder, 0, 1); - } - - if (odd) { - encode(encoder, 2, 2); - } else { - encode(encoder, 0, 1); - } -} - -static INLINE unsigned int decode_run(Encoder *encoder) -{ - unsigned int len = 0; - int count; - - do { - count = 0; - while (encoder->io_word & (1U << 31)) { - decode_eatbits(encoder, 1); - count++; - ASSERT(encoder->usr, count < 32); - } - decode_eatbits(encoder, 1); - len += (1U << count) >> 1; - } while (count > 1); - - return len; -} - -#endif -#endif - -static INLINE void init_decode_io(Encoder *encoder) -{ - encoder->io_next_word = encoder->io_word = *(encoder->io_now++); - encoder->io_available_bits = 0; -} - -#ifdef __GNUC__ -#define ATTR_PACKED __attribute__ ((__packed__)) -#else -#define ATTR_PACKED -#pragma pack(push) -#pragma pack(1) -#endif - -typedef struct ATTR_PACKED one_byte_pixel_t { - BYTE a; -} one_byte_t; - -typedef struct ATTR_PACKED three_bytes_pixel_t { - BYTE a; - BYTE b; - BYTE c; -} three_bytes_t; - -typedef struct ATTR_PACKED four_bytes_pixel_t { - BYTE a; - BYTE b; - BYTE c; - BYTE d; -} four_bytes_t; - -typedef struct ATTR_PACKED rgb32_pixel_t { - BYTE b; - BYTE g; - BYTE r; - BYTE pad; -} rgb32_pixel_t; - -typedef struct ATTR_PACKED rgb24_pixel_t { - BYTE b; - BYTE g; - BYTE r; -} rgb24_pixel_t; - -typedef uint16_t rgb16_pixel_t; - -#ifndef __GNUC__ -#pragma pack(pop) -#endif - -#undef ATTR_PACKED - -#define ONE_BYTE -#include "quic_tmpl.c" - -#define FOUR_BYTE -#include "quic_tmpl.c" - -#ifdef QUIC_RGB - -#define QUIC_RGB32 -#include "quic_rgb_tmpl.c" - -#define QUIC_RGB24 -#include "quic_rgb_tmpl.c" - -#define QUIC_RGB16 -#include "quic_rgb_tmpl.c" - -#define QUIC_RGB16_TO_32 -#include "quic_rgb_tmpl.c" - -#else - -#define THREE_BYTE -#include "quic_tmpl.c" - -#endif - -static void fill_model_structures(Encoder *encoder, FamilyStat *family_stat, - unsigned int rep_first, unsigned int first_size, - unsigned int rep_next, unsigned int mul_size, - unsigned int levels, unsigned int ncounters, - unsigned int nbuckets, unsigned int n_buckets_ptrs) -{ - unsigned int - bsize, - bstart, - bend = 0, - repcntr, - bnumber; - - COUNTER * free_counter = family_stat->counters;/* first free location in the array of - counters */ - - bnumber = 0; - - repcntr = rep_first + 1; /* first bucket */ - bsize = first_size; - - do { /* others */ - if (bnumber) { - bstart = bend + 1; - } else { - bstart = 0; - } - - if (!--repcntr) { - repcntr = rep_next; - bsize *= mul_size; - } - - bend = bstart + bsize - 1; - if (bend + bsize >= levels) { - bend = levels - 1; - } - - family_stat->buckets_buf[bnumber].pcounters = free_counter; - free_counter += ncounters; - - ASSERT(encoder->usr, bstart < n_buckets_ptrs); - { - unsigned int i; - ASSERT(encoder->usr, bend < n_buckets_ptrs); - for (i = bstart; i <= bend; i++) { - family_stat->buckets_ptrs[i] = family_stat->buckets_buf + bnumber; - } - } - - bnumber++; - } while (bend < levels - 1); - - ASSERT(encoder->usr, free_counter - family_stat->counters == nbuckets * ncounters); -} - -static void find_model_params(Encoder *encoder, - const int bpc, - unsigned int *ncounters, - unsigned int *levels, - unsigned int *n_buckets_ptrs, - unsigned int *repfirst, - unsigned int *firstsize, - unsigned int *repnext, - unsigned int *mulsize, - unsigned int *nbuckets) -{ - unsigned int bsize; /* bucket size */ - unsigned int bstart, bend = 0; /* bucket start and end, range : 0 to levels-1*/ - unsigned int repcntr; /* helper */ - - ASSERT(encoder->usr, bpc <= 8 && bpc > 0); - - - *ncounters = 8; - - *levels = 0x1 << bpc; - - *n_buckets_ptrs = 0; /* ==0 means: not set yet */ - - switch (evol) { /* set repfirst firstsize repnext mulsize */ - case 1: /* buckets contain following numbers of contexts: 1 1 1 2 2 4 4 8 8 ... */ - *repfirst = 3; - *firstsize = 1; - *repnext = 2; - *mulsize = 2; - break; - case 3: /* 1 2 4 8 16 32 64 ... */ - *repfirst = 1; - *firstsize = 1; - *repnext = 1; - *mulsize = 2; - break; - case 5: /* 1 4 16 64 256 1024 4096 16384 65536 */ - *repfirst = 1; - *firstsize = 1; - *repnext = 1; - *mulsize = 4; - break; - case 0: /* obsolete */ - case 2: /* obsolete */ - case 4: /* obsolete */ - encoder->usr->error(encoder->usr, "findmodelparams(): evol value obsolete!!!\n"); - default: - encoder->usr->error(encoder->usr, "findmodelparams(): evol out of range!!!\n"); - } - - *nbuckets = 0; - repcntr = *repfirst + 1; /* first bucket */ - bsize = *firstsize; - - do { /* other buckets */ - if (nbuckets) { /* bucket start */ - bstart = bend + 1; - } else { - bstart = 0; - } - - if (!--repcntr) { /* bucket size */ - repcntr = *repnext; - bsize *= *mulsize; - } - - bend = bstart + bsize - 1; /* bucket end */ - if (bend + bsize >= *levels) { /* if following bucked was bigger than current one */ - bend = *levels - 1; /* concatenate them */ - } - - if (!*n_buckets_ptrs) { /* array size not set yet? */ - *n_buckets_ptrs = *levels; - #if 0 - if (bend == *levels - 1) { /* this bucket is last - all in the first array */ - *n_buckets_ptrs = *levels; - } else if (bsize >= 256) { /* this bucket is allowed to reside in the 2nd table */ - b_lo_ptrs = bstart; - assert(bstart); /* previous bucket exists */ - } - #endif - } - - (*nbuckets)++; - } while (bend < *levels - 1); -} - -static int init_model_structures(Encoder *encoder, FamilyStat *family_stat, - unsigned int rep_first, unsigned int first_size, - unsigned int rep_next, unsigned int mul_size, - unsigned int levels, unsigned int ncounters, - unsigned int n_buckets_ptrs, unsigned int n_buckets) -{ - family_stat->buckets_ptrs = (s_bucket **)encoder->usr->malloc(encoder->usr, - n_buckets_ptrs * - sizeof(s_bucket *)); - if (!family_stat->buckets_ptrs) { - return FALSE; - } - - family_stat->counters = (COUNTER *)encoder->usr->malloc(encoder->usr, - n_buckets * sizeof(COUNTER) * - MAXNUMCODES); - if (!family_stat->counters) { - goto error_1; - } - - family_stat->buckets_buf = (s_bucket *)encoder->usr->malloc(encoder->usr, - n_buckets * sizeof(s_bucket)); - if (!family_stat->buckets_buf) { - goto error_2; - } - - fill_model_structures(encoder, family_stat, rep_first, first_size, rep_next, mul_size, levels, - ncounters, n_buckets, n_buckets_ptrs); - - return TRUE; - -error_2: - encoder->usr->free(encoder->usr, family_stat->counters); - -error_1: - encoder->usr->free(encoder->usr, family_stat->buckets_ptrs); - - return FALSE; -} - -static void free_family_stat(QuicUsrContext *usr, FamilyStat *family_stat) -{ - usr->free(usr, family_stat->buckets_ptrs); - usr->free(usr, family_stat->counters); - usr->free(usr, family_stat->buckets_buf); -} - -static int init_channel(Encoder *encoder, Channel *channel) -{ - unsigned int ncounters; - unsigned int levels; - unsigned int rep_first; - unsigned int first_size; - unsigned int rep_next; - unsigned int mul_size; - unsigned int n_buckets; - unsigned int n_buckets_ptrs; - - channel->encoder = encoder; - channel->state.encoder = encoder; - channel->correlate_row_width = 0; - channel->correlate_row = NULL; - - find_model_params(encoder, 8, &ncounters, &levels, &n_buckets_ptrs, &rep_first, - &first_size, &rep_next, &mul_size, &n_buckets); - encoder->n_buckets_8bpc = n_buckets; - if (!init_model_structures(encoder, &channel->family_stat_8bpc, rep_first, first_size, - rep_next, mul_size, levels, ncounters, n_buckets_ptrs, - n_buckets)) { - return FALSE; - } - - find_model_params(encoder, 5, &ncounters, &levels, &n_buckets_ptrs, &rep_first, - &first_size, &rep_next, &mul_size, &n_buckets); - encoder->n_buckets_5bpc = n_buckets; - if (!init_model_structures(encoder, &channel->family_stat_5bpc, rep_first, first_size, - rep_next, mul_size, levels, ncounters, n_buckets_ptrs, - n_buckets)) { - free_family_stat(encoder->usr, &channel->family_stat_8bpc); - return FALSE; - } - - return TRUE; -} - -static void destroy_channel(Channel *channel) -{ - QuicUsrContext *usr = channel->encoder->usr; - if (channel->correlate_row) { - usr->free(usr, channel->correlate_row - 1); - } - free_family_stat(usr, &channel->family_stat_8bpc); - free_family_stat(usr, &channel->family_stat_5bpc); -} - -static int init_encoder(Encoder *encoder, QuicUsrContext *usr) -{ - int i; - - encoder->usr = usr; - encoder->rgb_state.encoder = encoder; - - for (i = 0; i < MAX_CHANNELS; i++) { - if (!init_channel(encoder, &encoder->channels[i])) { - for (--i; i >= 0; i--) { - destroy_channel(&encoder->channels[i]); - } - return FALSE; - } - } - return TRUE; -} - -static int encoder_reste(Encoder *encoder, uint32_t *io_ptr, uint32_t *io_ptr_end) -{ - ASSERT(encoder->usr, ((unsigned long)io_ptr % 4) == ((unsigned long)io_ptr_end % 4)); - ASSERT(encoder->usr, io_ptr <= io_ptr_end); - - encoder->rgb_state.waitcnt = 0; - encoder->rgb_state.tabrand_seed = stabrand(); - encoder->rgb_state.wmidx = DEFwmistart; - encoder->rgb_state.wmileft = wminext; - set_wm_trigger(&encoder->rgb_state); - -#if defined(RLE) && defined(RLE_STAT) - encoder_init_rle(&encoder->rgb_state); -#endif - - encoder->io_words_count = io_ptr_end - io_ptr; - encoder->io_now = io_ptr; - encoder->io_end = io_ptr_end; - encoder->rows_completed = 0; - - return TRUE; -} - -static int encoder_reste_channels(Encoder *encoder, int channels, int width, int bpc) -{ - int i; - - encoder->num_channels = channels; - - for (i = 0; i < channels; i++) { - s_bucket *bucket; - s_bucket *end_bucket; - - if (encoder->channels[i].correlate_row_width < width) { - encoder->channels[i].correlate_row_width = 0; - if (encoder->channels[i].correlate_row) { - encoder->usr->free(encoder->usr, encoder->channels[i].correlate_row - 1); - } - if (!(encoder->channels[i].correlate_row = (BYTE *)encoder->usr->malloc(encoder->usr, - width + 1))) { - return FALSE; - } - encoder->channels[i].correlate_row++; - encoder->channels[i].correlate_row_width = width; - } - - if (bpc == 8) { - MEMCLEAR(encoder->channels[i].family_stat_8bpc.counters, - encoder->n_buckets_8bpc * sizeof(COUNTER) * MAXNUMCODES); - bucket = encoder->channels[i].family_stat_8bpc.buckets_buf; - end_bucket = bucket + encoder->n_buckets_8bpc; - for (; bucket < end_bucket; bucket++) { - bucket->bestcode = /*BPC*/ 8 - 1; - } - encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_8bpc.buckets_ptrs; - } else if (bpc == 5) { - MEMCLEAR(encoder->channels[i].family_stat_5bpc.counters, - encoder->n_buckets_5bpc * sizeof(COUNTER) * MAXNUMCODES); - bucket = encoder->channels[i].family_stat_5bpc.buckets_buf; - end_bucket = bucket + encoder->n_buckets_5bpc; - for (; bucket < end_bucket; bucket++) { - bucket->bestcode = /*BPC*/ 5 - 1; - } - encoder->channels[i]._buckets_ptrs = encoder->channels[i].family_stat_5bpc.buckets_ptrs; - } else { - encoder->usr->warn(encoder->usr, "%s: bad bpc %d\n", __FUNCTION__, bpc); - return FALSE; - } - - encoder->channels[i].state.waitcnt = 0; - encoder->channels[i].state.tabrand_seed = stabrand(); - encoder->channels[i].state.wmidx = DEFwmistart; - encoder->channels[i].state.wmileft = wminext; - set_wm_trigger(&encoder->channels[i].state); - -#if defined(RLE) && defined(RLE_STAT) - encoder_init_rle(&encoder->channels[i].state); -#endif - } - return TRUE; -} - -static void quic_image_params(Encoder *encoder, QuicImageType type, int *channels, int *bpc) -{ - ASSERT(encoder->usr, channels && bpc); - switch (type) { - case QUIC_IMAGE_TYPE_GRAY: - *channels = 1; - *bpc = 8; - break; - case QUIC_IMAGE_TYPE_RGB16: - *channels = 3; - *bpc = 5; -#ifndef QUIC_RGB - encoder->usr->error(encoder->usr, "not implemented\n"); -#endif - break; - case QUIC_IMAGE_TYPE_RGB24: - *channels = 3; - *bpc = 8; - break; - case QUIC_IMAGE_TYPE_RGB32: - *channels = 3; - *bpc = 8; - break; - case QUIC_IMAGE_TYPE_RGBA: - *channels = 4; - *bpc = 8; - break; - case QUIC_IMAGE_TYPE_INVALID: - default: - *channels = 0; - *bpc = 0; - encoder->usr->error(encoder->usr, "bad image type\n"); - } -} - -#define FILL_LINES() { \ - if (line == lines_end) { \ - int n = encoder->usr->more_lines(encoder->usr, &line); \ - if (n <= 0) { \ - encoder->usr->error(encoder->usr, "more lines failed\n"); \ - } \ - lines_end = line + n * stride; \ - } \ -} - -#define NEXT_LINE() { \ - line += stride; \ - FILL_LINES(); \ -} - -#define QUIC_COMPRESS_RGB(bits) \ - encoder->channels[0].correlate_row[-1] = 0; \ - encoder->channels[1].correlate_row[-1] = 0; \ - encoder->channels[2].correlate_row[-1] = 0; \ - quic_rgb##bits##_compress_row0(encoder, (rgb##bits##_pixel_t *)(line), width); \ - encoder->rows_completed++; \ - for (row = 1; row < height; row++) { \ - prev = line; \ - NEXT_LINE(); \ - encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; \ - encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; \ - encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; \ - quic_rgb##bits##_compress_row(encoder, (rgb##bits##_pixel_t *)prev, \ - (rgb##bits##_pixel_t *)line, width); \ - encoder->rows_completed++; \ - } - -int quic_encode(QuicContext *quic, QuicImageType type, int width, int height, - uint8_t *line, unsigned int num_lines, int stride, - uint32_t *io_ptr, unsigned int num_io_words) -{ - Encoder *encoder = (Encoder *)quic; - uint32_t *io_ptr_end = io_ptr + num_io_words; - uint8_t *lines_end; - int row; - uint8_t *prev; - int channels; - int bpc; -#ifndef QUIC_RGB - int i; -#endif - - ASSERT(encoder->usr, line); - lines_end = line + num_lines * stride; - - quic_image_params(encoder, type, &channels, &bpc); - - if (!encoder_reste(encoder, io_ptr, io_ptr_end) || - !encoder_reste_channels(encoder, channels, width, bpc)) { - return QUIC_ERROR; - } - - encoder->io_word = 0; - encoder->io_available_bits = 32; - - encode_32(encoder, QUIC_MAGIC); - encode_32(encoder, QUIC_VERSION); - encode_32(encoder, type); - encode_32(encoder, width); - encode_32(encoder, height); - - FILL_LINES(); - - switch (type) { -#ifdef QUIC_RGB - case QUIC_IMAGE_TYPE_RGB32: - ASSERT(encoder->usr, ABS(stride) >= width * 4); - QUIC_COMPRESS_RGB(32); - break; - case QUIC_IMAGE_TYPE_RGB24: - ASSERT(encoder->usr, ABS(stride) >= width * 3); - QUIC_COMPRESS_RGB(24); - break; - case QUIC_IMAGE_TYPE_RGB16: - ASSERT(encoder->usr, ABS(stride) >= width * 2); - QUIC_COMPRESS_RGB(16); - break; - case QUIC_IMAGE_TYPE_RGBA: - ASSERT(encoder->usr, ABS(stride) >= width * 4); - - encoder->channels[0].correlate_row[-1] = 0; - encoder->channels[1].correlate_row[-1] = 0; - encoder->channels[2].correlate_row[-1] = 0; - quic_rgb32_compress_row0(encoder, (rgb32_pixel_t *)(line), width); - - encoder->channels[3].correlate_row[-1] = 0; - quic_four_compress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(line + 3), width); - - encoder->rows_completed++; - - for (row = 1; row < height; row++) { - prev = line; - NEXT_LINE(); - encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; - encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; - encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; - quic_rgb32_compress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)line, width); - - encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0]; - quic_four_compress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3), - (four_bytes_t *)(line + 3), width); - encoder->rows_completed++; - } - break; -#else - case QUIC_IMAGE_TYPE_RGB24: - ASSERT(encoder->usr, ABS(stride) >= width * 3); - for (i = 0; i < 3; i++) { - encoder->channels[i].correlate_row[-1] = 0; - quic_three_compress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(line + i), - width); - } - encoder->rows_completed++; - for (row = 1; row < height; row++) { - prev = line; - NEXT_LINE(); - for (i = 0; i < 3; i++) { - encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; - quic_three_compress_row(encoder, &encoder->channels[i], (three_bytes_t *)(prev + i), - (three_bytes_t *)(line + i), width); - } - encoder->rows_completed++; - } - break; - case QUIC_IMAGE_TYPE_RGB32: - case QUIC_IMAGE_TYPE_RGBA: - ASSERT(encoder->usr, ABS(stride) >= width * 4); - for (i = 0; i < channels; i++) { - encoder->channels[i].correlate_row[-1] = 0; - quic_four_compress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(line + i), - width); - } - encoder->rows_completed++; - for (row = 1; row < height; row++) { - prev = line; - NEXT_LINE(); - for (i = 0; i < channels; i++) { - encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; - quic_four_compress_row(encoder, &encoder->channels[i], (four_bytes_t *)(prev + i), - (four_bytes_t *)(line + i), width); - } - encoder->rows_completed++; - } - break; -#endif - case QUIC_IMAGE_TYPE_GRAY: - ASSERT(encoder->usr, ABS(stride) >= width); - encoder->channels[0].correlate_row[-1] = 0; - quic_one_compress_row0(encoder, &encoder->channels[0], (one_byte_t *)line, width); - encoder->rows_completed++; - for (row = 1; row < height; row++) { - prev = line; - NEXT_LINE(); - encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; - quic_one_compress_row(encoder, &encoder->channels[0], (one_byte_t *)prev, - (one_byte_t *)line, width); - encoder->rows_completed++; - } - break; - case QUIC_IMAGE_TYPE_INVALID: - default: - encoder->usr->error(encoder->usr, "bad image type\n"); - } - - flush(encoder); - encoder->io_words_count -= (encoder->io_end - encoder->io_now); - - return encoder->io_words_count; -} - -int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words, - QuicImageType *out_type, int *out_width, int *out_height) -{ - Encoder *encoder = (Encoder *)quic; - uint32_t *io_ptr_end = io_ptr + num_io_words; - QuicImageType type; - int width; - int height; - uint32_t magic; - uint32_t version; - int channels; - int bpc; - - if (!encoder_reste(encoder, io_ptr, io_ptr_end)) { - return QUIC_ERROR; - } - - init_decode_io(encoder); - - magic = encoder->io_word; - decode_eat32bits(encoder); - if (magic != QUIC_MAGIC) { - encoder->usr->warn(encoder->usr, "bad magic\n"); - return QUIC_ERROR; - } - - version = encoder->io_word; - decode_eat32bits(encoder); - if (version != QUIC_VERSION) { - encoder->usr->warn(encoder->usr, "bad version\n"); - return QUIC_ERROR; - } - - type = (QuicImageType)encoder->io_word; - decode_eat32bits(encoder); - - width = encoder->io_word; - decode_eat32bits(encoder); - - height = encoder->io_word; - decode_eat32bits(encoder); - - quic_image_params(encoder, type, &channels, &bpc); - - if (!encoder_reste_channels(encoder, channels, width, bpc)) { - return QUIC_ERROR; - } - - *out_width = encoder->width = width; - *out_height = encoder->height = height; - *out_type = encoder->type = type; - return QUIC_OK; -} - -#ifndef QUIC_RGB -static void clear_row(four_bytes_t *row, int width) -{ - four_bytes_t *end; - for (end = row + width; row < end; row++) { - row->a = 0; - } -} - -#endif - -#ifdef QUIC_RGB - -static void uncompress_rgba(Encoder *encoder, uint8_t *buf, int stride) -{ - unsigned int row; - uint8_t *prev; - - encoder->channels[0].correlate_row[-1] = 0; - encoder->channels[1].correlate_row[-1] = 0; - encoder->channels[2].correlate_row[-1] = 0; - quic_rgb32_uncompress_row0(encoder, (rgb32_pixel_t *)buf, encoder->width); - - encoder->channels[3].correlate_row[-1] = 0; - quic_four_uncompress_row0(encoder, &encoder->channels[3], (four_bytes_t *)(buf + 3), - encoder->width); - - encoder->rows_completed++; - for (row = 1; row < encoder->height; row++) { - prev = buf; - buf += stride; - - encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; - encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; - encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; - quic_rgb32_uncompress_row(encoder, (rgb32_pixel_t *)prev, (rgb32_pixel_t *)buf, - encoder->width); - - encoder->channels[3].correlate_row[-1] = encoder->channels[3].correlate_row[0]; - quic_four_uncompress_row(encoder, &encoder->channels[3], (four_bytes_t *)(prev + 3), - (four_bytes_t *)(buf + 3), encoder->width); - - encoder->rows_completed++; - } -} - -#endif - -static void uncompress_gray(Encoder *encoder, uint8_t *buf, int stride) -{ - unsigned int row; - uint8_t *prev; - - encoder->channels[0].correlate_row[-1] = 0; - quic_one_uncompress_row0(encoder, &encoder->channels[0], (one_byte_t *)buf, encoder->width); - encoder->rows_completed++; - for (row = 1; row < encoder->height; row++) { - prev = buf; - buf += stride; - encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; - quic_one_uncompress_row(encoder, &encoder->channels[0], (one_byte_t *)prev, - (one_byte_t *)buf, encoder->width); - encoder->rows_completed++; - } -} - -#define QUIC_UNCOMPRESS_RGB(prefix, type) \ - encoder->channels[0].correlate_row[-1] = 0; \ - encoder->channels[1].correlate_row[-1] = 0; \ - encoder->channels[2].correlate_row[-1] = 0; \ - quic_rgb##prefix##_uncompress_row0(encoder, (type *)buf, encoder->width); \ - encoder->rows_completed++; \ - for (row = 1; row < encoder->height; row++) { \ - prev = buf; \ - buf += stride; \ - encoder->channels[0].correlate_row[-1] = encoder->channels[0].correlate_row[0]; \ - encoder->channels[1].correlate_row[-1] = encoder->channels[1].correlate_row[0]; \ - encoder->channels[2].correlate_row[-1] = encoder->channels[2].correlate_row[0]; \ - quic_rgb##prefix##_uncompress_row(encoder, (type *)prev, (type *)buf, \ - encoder->width); \ - encoder->rows_completed++; \ - } - -int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride) -{ - Encoder *encoder = (Encoder *)quic; - unsigned int row; - uint8_t *prev; -#ifndef QUIC_RGB - int i; -#endif - - ASSERT(encoder->usr, buf); - - switch (encoder->type) { -#ifdef QUIC_RGB - case QUIC_IMAGE_TYPE_RGB32: - case QUIC_IMAGE_TYPE_RGB24: - if (type == QUIC_IMAGE_TYPE_RGB32) { - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4); - QUIC_UNCOMPRESS_RGB(32, rgb32_pixel_t); - break; - } else if (type == QUIC_IMAGE_TYPE_RGB24) { - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 3); - QUIC_UNCOMPRESS_RGB(24, rgb24_pixel_t); - break; - } - encoder->usr->warn(encoder->usr, "unsupported output format\n"); - return QUIC_ERROR; - case QUIC_IMAGE_TYPE_RGB16: - if (type == QUIC_IMAGE_TYPE_RGB16) { - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 2); - QUIC_UNCOMPRESS_RGB(16, rgb16_pixel_t); - } else if (type == QUIC_IMAGE_TYPE_RGB32) { - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4); - QUIC_UNCOMPRESS_RGB(16_to_32, rgb32_pixel_t); - } else { - encoder->usr->warn(encoder->usr, "unsupported output format\n"); - return QUIC_ERROR; - } - - break; - case QUIC_IMAGE_TYPE_RGBA: - - if (type != QUIC_IMAGE_TYPE_RGBA) { - encoder->usr->warn(encoder->usr, "unsupported output format\n"); - return QUIC_ERROR; - } - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 4); - uncompress_rgba(encoder, buf, stride); - break; -#else - case QUIC_IMAGE_TYPE_RGB24: - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width * 3); - for (i = 0; i < 3; i++) { - encoder->channels[i].correlate_row[-1] = 0; - quic_three_uncompress_row0(encoder, &encoder->channels[i], (three_bytes_t *)(buf + i), - encoder->width); - } - encoder->rows_completed++; - for (row = 1; row < encoder->height; row++) { - prev = buf; - buf += stride; - for (i = 0; i < 3; i++) { - encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; - quic_three_uncompress_row(encoder, &encoder->channels[i], - (three_bytes_t *)(prev + i), - (three_bytes_t *)(buf + i), - encoder->width); - } - encoder->rows_completed++; - } - break; - case QUIC_IMAGE_TYPE_RGB32: - ASSERT(encoder->usr, ABS(stride) >= encoder->width * 4); - for (i = 0; i < 3; i++) { - encoder->channels[i].correlate_row[-1] = 0; - quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i), - encoder->width); - } - clear_row((four_bytes_t *)(buf + 3), encoder->width); - encoder->rows_completed++; - for (row = 1; row < encoder->height; row++) { - prev = buf; - buf += stride; - for (i = 0; i < 3; i++) { - encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; - quic_four_uncompress_row(encoder, &encoder->channels[i], - (four_bytes_t *)(prev + i), - (four_bytes_t *)(buf + i), - encoder->width); - } - clear_row((four_bytes_t *)(buf + 3), encoder->width); - encoder->rows_completed++; - } - break; - case QUIC_IMAGE_TYPE_RGBA: - ASSERT(encoder->usr, ABS(stride) >= encoder->width * 4); - for (i = 0; i < 4; i++) { - encoder->channels[i].correlate_row[-1] = 0; - quic_four_uncompress_row0(encoder, &encoder->channels[i], (four_bytes_t *)(buf + i), - encoder->width); - } - encoder->rows_completed++; - for (row = 1; row < encoder->height; row++) { - prev = buf; - buf += stride; - for (i = 0; i < 4; i++) { - encoder->channels[i].correlate_row[-1] = encoder->channels[i].correlate_row[0]; - quic_four_uncompress_row(encoder, &encoder->channels[i], - (four_bytes_t *)(prev + i), - (four_bytes_t *)(buf + i), - encoder->width); - } - encoder->rows_completed++; - } - break; -#endif - case QUIC_IMAGE_TYPE_GRAY: - - if (type != QUIC_IMAGE_TYPE_GRAY) { - encoder->usr->warn(encoder->usr, "unsupported output format\n"); - return QUIC_ERROR; - } - ASSERT(encoder->usr, ABS(stride) >= (int)encoder->width); - uncompress_gray(encoder, buf, stride); - break; - case QUIC_IMAGE_TYPE_INVALID: - default: - encoder->usr->error(encoder->usr, "bad image type\n"); - } - return QUIC_OK; -} - -static int need_init = TRUE; - -QuicContext *quic_create(QuicUsrContext *usr) -{ - Encoder *encoder; - - if (!usr || need_init || !usr->error || !usr->warn || !usr->info || !usr->malloc || - !usr->free || !usr->more_space || !usr->more_lines) { - return NULL; - } - - if (!(encoder = (Encoder *)usr->malloc(usr, sizeof(Encoder)))) { - return NULL; - } - - if (!init_encoder(encoder, usr)) { - usr->free(usr, encoder); - return NULL; - } - return (QuicContext *)encoder; -} - -void quic_destroy(QuicContext *quic) -{ - Encoder *encoder = (Encoder *)quic; - int i; - - if (!quic) { - return; - } - - for (i = 0; i < MAX_CHANNELS; i++) { - destroy_channel(&encoder->channels[i]); - } - encoder->usr->free(encoder->usr, encoder); -} - -void quic_init(void) -{ - if (!need_init) { - return; - } - need_init = FALSE; - - family_init(&family_8bpc, 8, DEFmaxclen); - family_init(&family_5bpc, 5, DEFmaxclen); -#if defined(RLE) && defined(RLE_STAT) - init_zeroLUT(); -#endif -} diff --git a/common/quic.h b/common/quic.h deleted file mode 100644 index 7ec94f56..00000000 --- a/common/quic.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __QUIC_H -#define __QUIC_H - -#include "quic_config.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - QUIC_IMAGE_TYPE_INVALID, - QUIC_IMAGE_TYPE_GRAY, - QUIC_IMAGE_TYPE_RGB16, - QUIC_IMAGE_TYPE_RGB24, - QUIC_IMAGE_TYPE_RGB32, - QUIC_IMAGE_TYPE_RGBA -} QuicImageType; - -#define QUIC_ERROR -1 -#define QUIC_OK 0 - -typedef void *QuicContext; - -typedef struct QuicUsrContext QuicUsrContext; -struct QuicUsrContext { - void (*error)(QuicUsrContext *usr, const char *fmt, ...); - void (*warn)(QuicUsrContext *usr, const char *fmt, ...); - void (*info)(QuicUsrContext *usr, const char *fmt, ...); - void *(*malloc)(QuicUsrContext *usr, int size); - void (*free)(QuicUsrContext *usr, void *ptr); - int (*more_space)(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed); - int (*more_lines)(QuicUsrContext *usr, uint8_t **lines); // on return the last line of previous - // lines bunch must still be valid -}; - -int quic_encode(QuicContext *quic, QuicImageType type, int width, int height, - uint8_t *lines, unsigned int num_lines, int stride, - uint32_t *io_ptr, unsigned int num_io_words); - -int quic_decode_begin(QuicContext *quic, uint32_t *io_ptr, unsigned int num_io_words, - QuicImageType *type, int *width, int *height); -int quic_decode(QuicContext *quic, QuicImageType type, uint8_t *buf, int stride); - - -QuicContext *quic_create(QuicUsrContext *usr); -void quic_destroy(QuicContext *quic); - -void quic_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/quic_config.h b/common/quic_config.h deleted file mode 100644 index 13c71f1d..00000000 --- a/common/quic_config.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __QUIC_CONFIG_H -#define __QUIC_CONFIG_H - -#include <spice/types.h> -#include <spice/macros.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __GNUC__ -#include <string.h> -#define MEMCLEAR(ptr, size) memset(ptr, 0, size) -#else -#ifdef QXLDD -#include <windef.h> -#include "os_dep.h" -#define MEMCLEAR(ptr, size) RtlZeroMemory(ptr, size) -#else -#include <stddef.h> -#include <string.h> -#define MEMCLEAR(ptr, size) memset(ptr, 0, size) -#endif // QXLDD -#endif //__GNUC__ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/quic_family_tmpl.c b/common/quic_family_tmpl.c deleted file mode 100644 index bfba0ccf..00000000 --- a/common/quic_family_tmpl.c +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef QUIC_FAMILY_8BPC -#undef QUIC_FAMILY_8BPC -#define FNAME(name) name##_8bpc -#define VNAME(name) name##_8bpc -#define BPC 8 -#endif - - -#ifdef QUIC_FAMILY_5BPC -#undef QUIC_FAMILY_5BPC -#define FNAME(name) name##_5bpc -#define VNAME(name) name##_5bpc -#define BPC 5 -#endif - - -static unsigned int FNAME(golomb_code_len)(const BYTE n, const unsigned int l) -{ - if (n < VNAME(family).nGRcodewords[l]) { - return (n >> l) + 1 + l; - } else { - return VNAME(family).notGRcwlen[l]; - } -} - -static void FNAME(golomb_coding)(const BYTE n, const unsigned int l, unsigned int * const codeword, - unsigned int * const codewordlen) -{ - if (n < VNAME(family).nGRcodewords[l]) { - (*codeword) = bitat[l] | (n & bppmask[l]); - (*codewordlen) = (n >> l) + l + 1; - } else { - (*codeword) = n - VNAME(family).nGRcodewords[l]; - (*codewordlen) = VNAME(family).notGRcwlen[l]; - } -} - -static unsigned int FNAME(golomb_decoding)(const unsigned int l, const unsigned int bits, - unsigned int * const codewordlen) -{ - if (bits > VNAME(family).notGRprefixmask[l]) { /*GR*/ - const unsigned int zeroprefix = cnt_l_zeroes(bits); /* leading zeroes in codeword */ - const unsigned int cwlen = zeroprefix + 1 + l; /* codeword length */ - (*codewordlen) = cwlen; - return (zeroprefix << l) | ((bits >> (32 - cwlen)) & bppmask[l]); - } else { /* not-GR */ - const unsigned int cwlen = VNAME(family).notGRcwlen[l]; - (*codewordlen) = cwlen; - return VNAME(family).nGRcodewords[l] + ((bits) >> (32 - cwlen) & - bppmask[VNAME(family).notGRsuffixlen[l]]); - } -} - -/* update the bucket using just encoded curval */ -static void FNAME(update_model)(CommonState *state, s_bucket * const bucket, - const BYTE curval, unsigned int bpp) -{ - COUNTER * const pcounters = bucket->pcounters; - unsigned int i; - unsigned int bestcode; - unsigned int bestcodelen; - //unsigned int bpp = encoder->bpp; - - /* update counters, find minimum */ - - bestcode = bpp - 1; - bestcodelen = (pcounters[bestcode] += FNAME(golomb_code_len)(curval, bestcode)); - - for (i = bpp - 2; i < bpp; i--) { /* NOTE: expression i<bpp for signed int i would be: i>=0 */ - const unsigned int ithcodelen = (pcounters[i] += FNAME(golomb_code_len)(curval, i)); - - if (ithcodelen < bestcodelen) { - bestcode = i; - bestcodelen = ithcodelen; - } - } - - bucket->bestcode = bestcode; /* store the found minimum */ - - if (bestcodelen > state->wm_trigger) { /* halving counters? */ - for (i = 0; i < bpp; i++) { - pcounters[i] >>= 1; - } - } -} - -static s_bucket *FNAME(find_bucket)(Channel *channel, const unsigned int val) -{ - ASSERT(channel->encoder->usr, val < (0x1U << BPC)); - - return channel->_buckets_ptrs[val]; -} - -#undef FNAME -#undef VNAME -#undef BPC diff --git a/common/quic_rgb_tmpl.c b/common/quic_rgb_tmpl.c deleted file mode 100644 index 8f356792..00000000 --- a/common/quic_rgb_tmpl.c +++ /dev/null @@ -1,765 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef QUIC_RGB32 -#undef QUIC_RGB32 -#define PIXEL rgb32_pixel_t -#define FNAME(name) quic_rgb32_##name -#define golomb_coding golomb_coding_8bpc -#define golomb_decoding golomb_decoding_8bpc -#define update_model update_model_8bpc -#define find_bucket find_bucket_8bpc -#define family family_8bpc -#define BPC 8 -#define BPC_MASK 0xffU -#define COMPRESS_IMP -#define SET_r(pix, val) ((pix)->r = val) -#define GET_r(pix) ((pix)->r) -#define SET_g(pix, val) ((pix)->g = val) -#define GET_g(pix) ((pix)->g) -#define SET_b(pix, val) ((pix)->b = val) -#define GET_b(pix) ((pix)->b) -#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0) -#endif - -#ifdef QUIC_RGB24 -#undef QUIC_RGB24 -#define PIXEL rgb24_pixel_t -#define FNAME(name) quic_rgb24_##name -#define golomb_coding golomb_coding_8bpc -#define golomb_decoding golomb_decoding_8bpc -#define update_model update_model_8bpc -#define find_bucket find_bucket_8bpc -#define family family_8bpc -#define BPC 8 -#define BPC_MASK 0xffU -#define COMPRESS_IMP -#define SET_r(pix, val) ((pix)->r = val) -#define GET_r(pix) ((pix)->r) -#define SET_g(pix, val) ((pix)->g = val) -#define GET_g(pix) ((pix)->g) -#define SET_b(pix, val) ((pix)->b = val) -#define GET_b(pix) ((pix)->b) -#define UNCOMPRESS_PIX_START(pix) -#endif - -#ifdef QUIC_RGB16 -#undef QUIC_RGB16 -#define PIXEL rgb16_pixel_t -#define FNAME(name) quic_rgb16_##name -#define golomb_coding golomb_coding_5bpc -#define golomb_decoding golomb_decoding_5bpc -#define update_model update_model_5bpc -#define find_bucket find_bucket_5bpc -#define family family_5bpc -#define BPC 5 -#define BPC_MASK 0x1fU -#define COMPRESS_IMP -#define SET_r(pix, val) (*(pix) = (*(pix) & ~(0x1f << 10)) | ((val) << 10)) -#define GET_r(pix) ((*(pix) >> 10) & 0x1f) -#define SET_g(pix, val) (*(pix) = (*(pix) & ~(0x1f << 5)) | ((val) << 5)) -#define GET_g(pix) ((*(pix) >> 5) & 0x1f) -#define SET_b(pix, val) (*(pix) = (*(pix) & ~0x1f) | (val)) -#define GET_b(pix) (*(pix) & 0x1f) -#define UNCOMPRESS_PIX_START(pix) (*(pix) = 0) -#endif - -#ifdef QUIC_RGB16_TO_32 -#undef QUIC_RGB16_TO_32 -#define PIXEL rgb32_pixel_t -#define FNAME(name) quic_rgb16_to_32_##name -#define golomb_coding golomb_coding_5bpc -#define golomb_decoding golomb_decoding_5bpc -#define update_model update_model_5bpc -#define find_bucket find_bucket_5bpc -#define family family_5bpc -#define BPC 5 -#define BPC_MASK 0x1fU - -#define SET_r(pix, val) ((pix)->r = ((val) << 3) | (((val) & 0x1f) >> 2)) -#define GET_r(pix) ((pix)->r >> 3) -#define SET_g(pix, val) ((pix)->g = ((val) << 3) | (((val) & 0x1f) >> 2)) -#define GET_g(pix) ((pix)->g >> 3) -#define SET_b(pix, val) ((pix)->b = ((val) << 3) | (((val) & 0x1f) >> 2)) -#define GET_b(pix) ((pix)->b >> 3) -#define UNCOMPRESS_PIX_START(pix) ((pix)->pad = 0) -#endif - -#define SAME_PIXEL(p1, p2) \ - (GET_r(p1) == GET_r(p2) && GET_g(p1) == GET_g(p2) && \ - GET_b(p1) == GET_b(p2)) - - -#define _PIXEL_A(channel, curr) ((unsigned int)GET_##channel((curr) - 1)) -#define _PIXEL_B(channel, prev) ((unsigned int)GET_##channel(prev)) -#define _PIXEL_C(channel, prev) ((unsigned int)GET_##channel((prev) - 1)) - -/* a */ - -#define DECORELATE_0(channel, curr, bpc_mask)\ - family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)_PIXEL_A(channel, curr)) & bpc_mask] - -#define CORELATE_0(channel, curr, correlate, bpc_mask)\ - ((family.xlatL2U[correlate] + _PIXEL_A(channel, curr)) & bpc_mask) - -#ifdef PRED_1 - -/* (a+b)/2 */ -#define DECORELATE(channel, prev, curr, bpc_mask, r) \ - r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - (int)((_PIXEL_A(channel, curr) + \ - _PIXEL_B(channel, prev)) >> 1)) & bpc_mask] - -#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) \ - SET_##channel(r, ((family.xlatL2U[correlate] + \ - (int)((_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev)) >> 1)) & bpc_mask)) -#endif - -#ifdef PRED_2 - -/* .75a+.75b-.5c */ -#define DECORELATE(channel, prev, curr, bpc_mask, r) { \ - int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) - \ - (int)(_PIXEL_C(channel, prev) << 1)) >> 2; \ - if (p < 0) { \ - p = 0; \ - } else if ((unsigned)p > bpc_mask) { \ - p = bpc_mask; \ - } \ - r = family.xlatU2L[(unsigned)((int)GET_##channel(curr) - p) & bpc_mask]; \ -} - -#define CORELATE(channel, prev, curr, correlate, bpc_mask, r) { \ - const int p = ((int)(3 * (_PIXEL_A(channel, curr) + _PIXEL_B(channel, prev))) - \ - (int)(_PIXEL_C(channel, prev) << 1) ) >> 2; \ - const unsigned int s = family.xlatL2U[correlate]; \ - if (!(p & ~bpc_mask)) { \ - SET_##channel(r, (s + (unsigned)p) & bpc_mask); \ - } else if (p < 0) { \ - SET_##channel(r, s); \ - } else { \ - SET_##channel(r, (s + bpc_mask) & bpc_mask); \ - } \ -} - -#endif - - -#define COMPRESS_ONE_ROW0_0(channel) \ - correlate_row_##channel[0] = family.xlatU2L[GET_##channel(cur_row)]; \ - golomb_coding(correlate_row_##channel[0], find_bucket(channel_##channel, \ - correlate_row_##channel[-1])->bestcode, \ - &codeword, &codewordlen); \ - encode(encoder, codeword, codewordlen); - -#define COMPRESS_ONE_ROW0(channel, index) \ - correlate_row_##channel[index] = DECORELATE_0(channel, &cur_row[index], bpc_mask); \ - golomb_coding(correlate_row_##channel[index], find_bucket(channel_##channel, \ - correlate_row_##channel[index -1])->bestcode, \ - &codeword, &codewordlen); \ - encode(encoder, codeword, codewordlen); - -#define UPDATE_MODEL(index) \ - update_model(&encoder->rgb_state, find_bucket(channel_r, correlate_row_r[index - 1]), \ - correlate_row_r[index], bpc); \ - update_model(&encoder->rgb_state, find_bucket(channel_g, correlate_row_g[index - 1]), \ - correlate_row_g[index], bpc); \ - update_model(&encoder->rgb_state, find_bucket(channel_b, correlate_row_b[index - 1]), \ - correlate_row_b[index], bpc); - - -#ifdef RLE_PRED_1 -#define RLE_PRED_1_IMP \ -if (SAME_PIXEL(&cur_row[i - 1], &prev_row[i])) { \ - if (run_index != i && SAME_PIXEL(&prev_row[i - 1], &prev_row[i]) && \ - i + 1 < end && SAME_PIXEL(&prev_row[i], &prev_row[i + 1])) { \ - goto do_run; \ - } \ -} -#else -#define RLE_PRED_1_IMP -#endif - -#ifdef RLE_PRED_2 -#define RLE_PRED_2_IMP \ -if (SAME_PIXEL(&prev_row[i - 1], &prev_row[i])) { \ - if (run_index != i && i > 2 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2])) { \ - goto do_run; \ - } \ -} -#else -#define RLE_PRED_2_IMP -#endif - -#ifdef RLE_PRED_3 -#define RLE_PRED_3_IMP \ -if (i > 1 && SAME_PIXEL(&cur_row[i - 1], &cur_row[i - 2]) && i != run_index) { \ - goto do_run; \ -} -#else -#define RLE_PRED_3_IMP -#endif - -#ifdef COMPRESS_IMP - -static void FNAME(compress_row0_seg)(Encoder *encoder, int i, - const PIXEL * const cur_row, - const int end, - const unsigned int waitmask, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - Channel * const channel_r = encoder->channels; - Channel * const channel_g = channel_r + 1; - Channel * const channel_b = channel_g + 1; - - BYTE * const correlate_row_r = channel_r->correlate_row; - BYTE * const correlate_row_g = channel_g->correlate_row; - BYTE * const correlate_row_b = channel_b->correlate_row; - int stopidx; - - ASSERT(encoder->usr, end - i > 0); - - if (!i) { - unsigned int codeword, codewordlen; - - COMPRESS_ONE_ROW0_0(r); - COMPRESS_ONE_ROW0_0(g); - COMPRESS_ONE_ROW0_0(b); - - if (encoder->rgb_state.waitcnt) { - encoder->rgb_state.waitcnt--; - } else { - encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - UPDATE_MODEL(0); - } - stopidx = ++i + encoder->rgb_state.waitcnt; - } else { - stopidx = i + encoder->rgb_state.waitcnt; - } - - while (stopidx < end) { - for (; i <= stopidx; i++) { - unsigned int codeword, codewordlen; - COMPRESS_ONE_ROW0(r, i); - COMPRESS_ONE_ROW0(g, i); - COMPRESS_ONE_ROW0(b, i); - } - - UPDATE_MODEL(stopidx); - stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codeword, codewordlen; - - COMPRESS_ONE_ROW0(r, i); - COMPRESS_ONE_ROW0(g, i); - COMPRESS_ONE_ROW0(b, i); - } - encoder->rgb_state.waitcnt = stopidx - end; -} - -static void FNAME(compress_row0)(Encoder *encoder, const PIXEL *cur_row, - unsigned int width) -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - int pos = 0; - - while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { - if (encoder->rgb_state.wmileft) { - FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + encoder->rgb_state.wmileft, - bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); - width -= encoder->rgb_state.wmileft; - pos += encoder->rgb_state.wmileft; - } - - encoder->rgb_state.wmidx++; - set_wm_trigger(&encoder->rgb_state); - encoder->rgb_state.wmileft = wminext; - } - - if (width) { - FNAME(compress_row0_seg)(encoder, pos, cur_row, pos + width, - bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); - if (wmimax > (int)encoder->rgb_state.wmidx) { - encoder->rgb_state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax); - ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -#define COMPRESS_ONE_0(channel) \ - correlate_row_##channel[0] = family.xlatU2L[(unsigned)((int)GET_##channel(cur_row) - \ - (int)GET_##channel(prev_row) ) & bpc_mask]; \ - golomb_coding(correlate_row_##channel[0], \ - find_bucket(channel_##channel, correlate_row_##channel[-1])->bestcode, \ - &codeword, &codewordlen); \ - encode(encoder, codeword, codewordlen); - -#define COMPRESS_ONE(channel, index) \ - DECORELATE(channel, &prev_row[index], &cur_row[index],bpc_mask, \ - correlate_row_##channel[index]); \ - golomb_coding(correlate_row_##channel[index], \ - find_bucket(channel_##channel, correlate_row_##channel[index - 1])->bestcode, \ - &codeword, &codewordlen); \ - encode(encoder, codeword, codewordlen); - -static void FNAME(compress_row_seg)(Encoder *encoder, int i, - const PIXEL * const prev_row, - const PIXEL * const cur_row, - const int end, - const unsigned int waitmask, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - Channel * const channel_r = encoder->channels; - Channel * const channel_g = channel_r + 1; - Channel * const channel_b = channel_g + 1; - - BYTE * const correlate_row_r = channel_r->correlate_row; - BYTE * const correlate_row_g = channel_g->correlate_row; - BYTE * const correlate_row_b = channel_b->correlate_row; - int stopidx; -#ifdef RLE - int run_index = 0; - int run_size; -#endif - - ASSERT(encoder->usr, end - i > 0); - - if (!i) { - unsigned int codeword, codewordlen; - - COMPRESS_ONE_0(r); - COMPRESS_ONE_0(g); - COMPRESS_ONE_0(b); - - if (encoder->rgb_state.waitcnt) { - encoder->rgb_state.waitcnt--; - } else { - encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - UPDATE_MODEL(0); - } - stopidx = ++i + encoder->rgb_state.waitcnt; - } else { - stopidx = i + encoder->rgb_state.waitcnt; - } - for (;;) { - while (stopidx < end) { - for (; i <= stopidx; i++) { - unsigned int codeword, codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - COMPRESS_ONE(r, i); - COMPRESS_ONE(g, i); - COMPRESS_ONE(b, i); - } - - UPDATE_MODEL(stopidx); - stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codeword, codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - COMPRESS_ONE(r, i); - COMPRESS_ONE(g, i); - COMPRESS_ONE(b, i); - } - encoder->rgb_state.waitcnt = stopidx - end; - - return; - -#ifdef RLE -do_run: - run_index = i; - encoder->rgb_state.waitcnt = stopidx - i; - run_size = 0; - - while (SAME_PIXEL(&cur_row[i], &cur_row[i - 1])) { - run_size++; - if (++i == end) { - encode_run(encoder, run_size); - return; - } - } - encode_run(encoder, run_size); - stopidx = i + encoder->rgb_state.waitcnt; -#endif - } -} - -static void FNAME(compress_row)(Encoder *encoder, - const PIXEL * const prev_row, - const PIXEL * const cur_row, - unsigned int width) - -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - unsigned int pos = 0; - - while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { - if (encoder->rgb_state.wmileft) { - FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row, - pos + encoder->rgb_state.wmileft, - bppmask[encoder->rgb_state.wmidx], - bpc, bpc_mask); - width -= encoder->rgb_state.wmileft; - pos += encoder->rgb_state.wmileft; - } - - encoder->rgb_state.wmidx++; - set_wm_trigger(&encoder->rgb_state); - encoder->rgb_state.wmileft = wminext; - } - - if (width) { - FNAME(compress_row_seg)(encoder, pos, prev_row, cur_row, pos + width, - bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); - if (wmimax > (int)encoder->rgb_state.wmidx) { - encoder->rgb_state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax); - ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -#endif - -#define UNCOMPRESS_ONE_ROW0_0(channel) \ - correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ - correlate_row_##channel[-1])->bestcode, \ - encoder->io_word, &codewordlen); \ - SET_##channel(&cur_row[0], (BYTE)family.xlatL2U[correlate_row_##channel[0]]); \ - decode_eatbits(encoder, codewordlen); - -#define UNCOMPRESS_ONE_ROW0(channel) \ - correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ - correlate_row_##channel[i - 1])->bestcode, \ - encoder->io_word, \ - &codewordlen); \ - SET_##channel(&cur_row[i], CORELATE_0(channel, &cur_row[i], correlate_row_##channel[i], \ - bpc_mask)); \ - decode_eatbits(encoder, codewordlen); - -static void FNAME(uncompress_row0_seg)(Encoder *encoder, int i, - PIXEL * const cur_row, - const int end, - const unsigned int waitmask, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - Channel * const channel_r = encoder->channels; - Channel * const channel_g = channel_r + 1; - Channel * const channel_b = channel_g + 1; - - BYTE * const correlate_row_r = channel_r->correlate_row; - BYTE * const correlate_row_g = channel_g->correlate_row; - BYTE * const correlate_row_b = channel_b->correlate_row; - int stopidx; - - ASSERT(encoder->usr, end - i > 0); - - if (!i) { - unsigned int codewordlen; - - UNCOMPRESS_PIX_START(&cur_row[i]); - UNCOMPRESS_ONE_ROW0_0(r); - UNCOMPRESS_ONE_ROW0_0(g); - UNCOMPRESS_ONE_ROW0_0(b); - - if (encoder->rgb_state.waitcnt) { - --encoder->rgb_state.waitcnt; - } else { - encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - UPDATE_MODEL(0); - } - stopidx = ++i + encoder->rgb_state.waitcnt; - } else { - stopidx = i + encoder->rgb_state.waitcnt; - } - - while (stopidx < end) { - for (; i <= stopidx; i++) { - unsigned int codewordlen; - - UNCOMPRESS_PIX_START(&cur_row[i]); - UNCOMPRESS_ONE_ROW0(r); - UNCOMPRESS_ONE_ROW0(g); - UNCOMPRESS_ONE_ROW0(b); - } - UPDATE_MODEL(stopidx); - stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codewordlen; - - UNCOMPRESS_PIX_START(&cur_row[i]); - UNCOMPRESS_ONE_ROW0(r); - UNCOMPRESS_ONE_ROW0(g); - UNCOMPRESS_ONE_ROW0(b); - } - encoder->rgb_state.waitcnt = stopidx - end; -} - -static void FNAME(uncompress_row0)(Encoder *encoder, - PIXEL * const cur_row, - unsigned int width) - -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - unsigned int pos = 0; - - while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { - if (encoder->rgb_state.wmileft) { - FNAME(uncompress_row0_seg)(encoder, pos, cur_row, - pos + encoder->rgb_state.wmileft, - bppmask[encoder->rgb_state.wmidx], - bpc, bpc_mask); - pos += encoder->rgb_state.wmileft; - width -= encoder->rgb_state.wmileft; - } - - encoder->rgb_state.wmidx++; - set_wm_trigger(&encoder->rgb_state); - encoder->rgb_state.wmileft = wminext; - } - - if (width) { - FNAME(uncompress_row0_seg)(encoder, pos, cur_row, pos + width, - bppmask[encoder->rgb_state.wmidx], bpc, bpc_mask); - if (wmimax > (int)encoder->rgb_state.wmidx) { - encoder->rgb_state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax); - ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -#define UNCOMPRESS_ONE_0(channel) \ - correlate_row_##channel[0] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ - correlate_row_##channel[-1])->bestcode, \ - encoder->io_word, &codewordlen); \ - SET_##channel(&cur_row[0], (family.xlatL2U[correlate_row_##channel[0]] + \ - GET_##channel(prev_row)) & bpc_mask); \ - decode_eatbits(encoder, codewordlen); - -#define UNCOMPRESS_ONE(channel) \ - correlate_row_##channel[i] = (BYTE)golomb_decoding(find_bucket(channel_##channel, \ - correlate_row_##channel[i - 1])->bestcode, \ - encoder->io_word, \ - &codewordlen); \ - CORELATE(channel, &prev_row[i], &cur_row[i], correlate_row_##channel[i], bpc_mask, \ - &cur_row[i]); \ - decode_eatbits(encoder, codewordlen); - -static void FNAME(uncompress_row_seg)(Encoder *encoder, - const PIXEL * const prev_row, - PIXEL * const cur_row, - int i, - const int end, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - Channel * const channel_r = encoder->channels; - Channel * const channel_g = channel_r + 1; - Channel * const channel_b = channel_g + 1; - - BYTE * const correlate_row_r = channel_r->correlate_row; - BYTE * const correlate_row_g = channel_g->correlate_row; - BYTE * const correlate_row_b = channel_b->correlate_row; - const unsigned int waitmask = bppmask[encoder->rgb_state.wmidx]; - int stopidx; -#ifdef RLE - int run_index = 0; - int run_end; -#endif - - ASSERT(encoder->usr, end - i > 0); - - if (!i) { - unsigned int codewordlen; - - UNCOMPRESS_PIX_START(&cur_row[i]); - UNCOMPRESS_ONE_0(r); - UNCOMPRESS_ONE_0(g); - UNCOMPRESS_ONE_0(b); - - if (encoder->rgb_state.waitcnt) { - --encoder->rgb_state.waitcnt; - } else { - encoder->rgb_state.waitcnt = (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - UPDATE_MODEL(0); - } - stopidx = ++i + encoder->rgb_state.waitcnt; - } else { - stopidx = i + encoder->rgb_state.waitcnt; - } - for (;;) { - while (stopidx < end) { - for (; i <= stopidx; i++) { - unsigned int codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - UNCOMPRESS_PIX_START(&cur_row[i]); - UNCOMPRESS_ONE(r); - UNCOMPRESS_ONE(g); - UNCOMPRESS_ONE(b); - } - - UPDATE_MODEL(stopidx); - - stopidx = i + (tabrand(&encoder->rgb_state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - UNCOMPRESS_PIX_START(&cur_row[i]); - UNCOMPRESS_ONE(r); - UNCOMPRESS_ONE(g); - UNCOMPRESS_ONE(b); - } - - encoder->rgb_state.waitcnt = stopidx - end; - - return; - -#ifdef RLE -do_run: - encoder->rgb_state.waitcnt = stopidx - i; - run_index = i; - run_end = i + decode_run(encoder); - - for (; i < run_end; i++) { - UNCOMPRESS_PIX_START(&cur_row[i]); - SET_r(&cur_row[i], GET_r(&cur_row[i - 1])); - SET_g(&cur_row[i], GET_g(&cur_row[i - 1])); - SET_b(&cur_row[i], GET_b(&cur_row[i - 1])); - } - - if (i == end) { - return; - } - - stopidx = i + encoder->rgb_state.waitcnt; -#endif - } -} - -static void FNAME(uncompress_row)(Encoder *encoder, - const PIXEL * const prev_row, - PIXEL * const cur_row, - unsigned int width) - -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - unsigned int pos = 0; - - while ((wmimax > (int)encoder->rgb_state.wmidx) && (encoder->rgb_state.wmileft <= width)) { - if (encoder->rgb_state.wmileft) { - FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos, - pos + encoder->rgb_state.wmileft, bpc, bpc_mask); - pos += encoder->rgb_state.wmileft; - width -= encoder->rgb_state.wmileft; - } - - encoder->rgb_state.wmidx++; - set_wm_trigger(&encoder->rgb_state); - encoder->rgb_state.wmileft = wminext; - } - - if (width) { - FNAME(uncompress_row_seg)(encoder, prev_row, cur_row, pos, - pos + width, bpc, bpc_mask); - if (wmimax > (int)encoder->rgb_state.wmidx) { - encoder->rgb_state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)encoder->rgb_state.wmidx <= wmimax); - ASSERT(encoder->usr, encoder->rgb_state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -#undef PIXEL -#undef FNAME -#undef _PIXEL_A -#undef _PIXEL_B -#undef _PIXEL_C -#undef SAME_PIXEL -#undef RLE_PRED_1_IMP -#undef RLE_PRED_2_IMP -#undef RLE_PRED_3_IMP -#undef UPDATE_MODEL -#undef DECORELATE_0 -#undef DECORELATE -#undef COMPRESS_ONE_ROW0_0 -#undef COMPRESS_ONE_ROW0 -#undef COMPRESS_ONE_0 -#undef COMPRESS_ONE -#undef CORELATE_0 -#undef CORELATE -#undef UNCOMPRESS_ONE_ROW0_0 -#undef UNCOMPRESS_ONE_ROW0 -#undef UNCOMPRESS_ONE_0 -#undef UNCOMPRESS_ONE -#undef golomb_coding -#undef golomb_decoding -#undef update_model -#undef find_bucket -#undef family -#undef BPC -#undef BPC_MASK -#undef COMPRESS_IMP -#undef SET_r -#undef GET_r -#undef SET_g -#undef GET_g -#undef SET_b -#undef GET_b -#undef UNCOMPRESS_PIX_START diff --git a/common/quic_tmpl.c b/common/quic_tmpl.c deleted file mode 100644 index 6acd5042..00000000 --- a/common/quic_tmpl.c +++ /dev/null @@ -1,635 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef ONE_BYTE -#undef ONE_BYTE -#define FNAME(name) quic_one_##name -#define PIXEL one_byte_t -#endif - -#ifdef THREE_BYTE -#undef THREE_BYTE -#define FNAME(name) quic_three_##name -#define PIXEL three_bytes_t -#endif - -#ifdef FOUR_BYTE -#undef FOUR_BYTE -#define FNAME(name) quic_four_##name -#define PIXEL four_bytes_t -#endif - -#define golomb_coding golomb_coding_8bpc -#define golomb_decoding golomb_decoding_8bpc -#define update_model update_model_8bpc -#define find_bucket find_bucket_8bpc -#define family family_8bpc - -#define BPC 8 -#define BPC_MASK 0xffU - -#define _PIXEL_A ((unsigned int)curr[-1].a) -#define _PIXEL_B ((unsigned int)prev[0].a) -#define _PIXEL_C ((unsigned int)prev[-1].a) - -#ifdef RLE_PRED_1 -#define RLE_PRED_1_IMP \ -if (cur_row[i - 1].a == prev_row[i].a) { \ - if (run_index != i && prev_row[i - 1].a == prev_row[i].a && \ - i + 1 < end && prev_row[i].a == prev_row[i + 1].a) { \ - goto do_run; \ - } \ -} -#else -#define RLE_PRED_1_IMP -#endif - -#ifdef RLE_PRED_2 -#define RLE_PRED_2_IMP \ -if (prev_row[i - 1].a == prev_row[i].a) { \ - if (run_index != i && i > 2 && cur_row[i - 1].a == cur_row[i - 2].a) { \ - goto do_run; \ - } \ -} -#else -#define RLE_PRED_2_IMP -#endif - -#ifdef RLE_PRED_3 -#define RLE_PRED_3_IMP \ -if (i > 1 && cur_row[i - 1].a == cur_row[i - 2].a && i != run_index) { \ - goto do_run; \ -} -#else -#define RLE_PRED_3_IMP -#endif - -/* a */ -static INLINE BYTE FNAME(decorelate_0)(const PIXEL * const curr, const unsigned int bpc_mask) -{ - return family.xlatU2L[(unsigned)((int)curr[0].a - (int)_PIXEL_A) & bpc_mask]; -} - -static INLINE void FNAME(corelate_0)(PIXEL *curr, const BYTE corelate, - const unsigned int bpc_mask) -{ - curr->a = (family.xlatL2U[corelate] + _PIXEL_A) & bpc_mask; -} - -#ifdef PRED_1 - -/* (a+b)/2 */ -static INLINE BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr, - const unsigned int bpc_mask) -{ - return family.xlatU2L[(unsigned)((int)curr->a - (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask]; -} - - -static INLINE void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate, - const unsigned int bpc_mask) -{ - curr->a = (family.xlatL2U[corelate] + (int)((_PIXEL_A + _PIXEL_B) >> 1)) & bpc_mask; -} - -#endif - -#ifdef PRED_2 - -/* .75a+.75b-.5c */ -static INLINE BYTE FNAME(decorelate)(const PIXEL *const prev, const PIXEL * const curr, - const unsigned int bpc_mask) -{ - int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2; - - if (p < 0) { - p = 0; - } else if ((unsigned)p > bpc_mask) { - p = bpc_mask; - } - - { - return family.xlatU2L[(unsigned)((int)curr->a - p) & bpc_mask]; - } -} - -static INLINE void FNAME(corelate)(const PIXEL *prev, PIXEL *curr, const BYTE corelate, - const unsigned int bpc_mask) -{ - const int p = ((int)(3 * (_PIXEL_A + _PIXEL_B)) - (int)(_PIXEL_C << 1)) >> 2; - const unsigned int s = family.xlatL2U[corelate]; - - if (!(p & ~bpc_mask)) { - curr->a = (s + (unsigned)p) & bpc_mask; - } else if (p < 0) { - curr->a = s; - } else { - curr->a = (s + bpc_mask) & bpc_mask; - } -} - -#endif - -static void FNAME(compress_row0_seg)(Encoder *encoder, Channel *channel, int i, - const PIXEL * const cur_row, - const int end, - const unsigned int waitmask, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - BYTE * const decorelate_drow = channel->correlate_row; - int stopidx; - - ASSERT(encoder->usr, end - i > 0); - - if (i == 0) { - unsigned int codeword, codewordlen; - - decorelate_drow[0] = family.xlatU2L[cur_row->a]; - golomb_coding(decorelate_drow[0], find_bucket(channel, decorelate_drow[-1])->bestcode, - &codeword, &codewordlen); - encode(encoder, codeword, codewordlen); - - if (channel->state.waitcnt) { - channel->state.waitcnt--; - } else { - channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); - update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]), - decorelate_drow[i], bpc); - } - stopidx = ++i + channel->state.waitcnt; - } else { - stopidx = i + channel->state.waitcnt; - } - - while (stopidx < end) { - for (; i <= stopidx; i++) { - unsigned int codeword, codewordlen; - decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask); - golomb_coding(decorelate_drow[i], - find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword, - &codewordlen); - encode(encoder, codeword, codewordlen); - } - - update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]), - decorelate_drow[stopidx], bpc); - stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codeword, codewordlen; - decorelate_drow[i] = FNAME(decorelate_0)(&cur_row[i], bpc_mask); - golomb_coding(decorelate_drow[i], find_bucket(channel, decorelate_drow[i - 1])->bestcode, - &codeword, &codewordlen); - encode(encoder, codeword, codewordlen); - } - channel->state.waitcnt = stopidx - end; -} - -static void FNAME(compress_row0)(Encoder *encoder, Channel *channel, const PIXEL *cur_row, - unsigned int width) -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - int pos = 0; - - while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { - if (channel->state.wmileft) { - FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + channel->state.wmileft, - bppmask[channel->state.wmidx], bpc, bpc_mask); - width -= channel->state.wmileft; - pos += channel->state.wmileft; - } - - channel->state.wmidx++; - set_wm_trigger(&channel->state); - channel->state.wmileft = wminext; - } - - if (width) { - FNAME(compress_row0_seg)(encoder, channel, pos, cur_row, pos + width, - bppmask[channel->state.wmidx], bpc, bpc_mask); - if (wmimax > (int)channel->state.wmidx) { - channel->state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax); - ASSERT(encoder->usr, channel->state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -static void FNAME(compress_row_seg)(Encoder *encoder, Channel *channel, int i, - const PIXEL * const prev_row, - const PIXEL * const cur_row, - const int end, - const unsigned int waitmask, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - BYTE * const decorelate_drow = channel->correlate_row; - int stopidx; -#ifdef RLE - int run_index = 0; - int run_size; -#endif - - ASSERT(encoder->usr, end - i > 0); - - if (!i) { - unsigned int codeword, codewordlen; - - decorelate_drow[0] = family.xlatU2L[(unsigned)((int)cur_row->a - - (int)prev_row->a) & bpc_mask]; - - golomb_coding(decorelate_drow[0], - find_bucket(channel, decorelate_drow[-1])->bestcode, - &codeword, - &codewordlen); - encode(encoder, codeword, codewordlen); - - if (channel->state.waitcnt) { - channel->state.waitcnt--; - } else { - channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); - update_model(&channel->state, find_bucket(channel, decorelate_drow[-1]), - decorelate_drow[0], bpc); - } - stopidx = ++i + channel->state.waitcnt; - } else { - stopidx = i + channel->state.waitcnt; - } - for (;;) { - while (stopidx < end) { - for (; i <= stopidx; i++) { - unsigned int codeword, codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask); - golomb_coding(decorelate_drow[i], - find_bucket(channel, decorelate_drow[i - 1])->bestcode, &codeword, - &codewordlen); - encode(encoder, codeword, codewordlen); - } - - update_model(&channel->state, find_bucket(channel, decorelate_drow[stopidx - 1]), - decorelate_drow[stopidx], bpc); - stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codeword, codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - decorelate_drow[i] = FNAME(decorelate)(&prev_row[i], &cur_row[i], bpc_mask); - golomb_coding(decorelate_drow[i], find_bucket(channel, - decorelate_drow[i - 1])->bestcode, - &codeword, &codewordlen); - encode(encoder, codeword, codewordlen); - } - channel->state.waitcnt = stopidx - end; - - return; - -#ifdef RLE -do_run: - run_index = i; - channel->state.waitcnt = stopidx - i; - run_size = 0; - - while (cur_row[i].a == cur_row[i - 1].a) { - run_size++; - if (++i == end) { -#ifdef RLE_STAT - encode_channel_run(encoder, channel, run_size); -#else - encode_run(encoder, run_size); -#endif - return; - } - } -#ifdef RLE_STAT - encode_channel_run(encoder, channel, run_size); -#else - encode_run(encoder, run_size); -#endif - stopidx = i + channel->state.waitcnt; -#endif - } -} - -static void FNAME(compress_row)(Encoder *encoder, Channel *channel, - const PIXEL * const prev_row, - const PIXEL * const cur_row, - unsigned int width) - -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - unsigned int pos = 0; - - while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { - if (channel->state.wmileft) { - FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row, - pos + channel->state.wmileft, bppmask[channel->state.wmidx], - bpc, bpc_mask); - width -= channel->state.wmileft; - pos += channel->state.wmileft; - } - - channel->state.wmidx++; - set_wm_trigger(&channel->state); - channel->state.wmileft = wminext; - } - - if (width) { - FNAME(compress_row_seg)(encoder, channel, pos, prev_row, cur_row, pos + width, - bppmask[channel->state.wmidx], bpc, bpc_mask); - if (wmimax > (int)channel->state.wmidx) { - channel->state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax); - ASSERT(encoder->usr, channel->state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -static void FNAME(uncompress_row0_seg)(Encoder *encoder, Channel *channel, int i, - BYTE * const correlate_row, - PIXEL * const cur_row, - const int end, - const unsigned int waitmask, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - int stopidx; - - ASSERT(encoder->usr, end - i > 0); - - if (i == 0) { - unsigned int codewordlen; - - correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel, - correlate_row[-1])->bestcode, - encoder->io_word, &codewordlen); - cur_row[0].a = (BYTE)family.xlatL2U[correlate_row[0]]; - decode_eatbits(encoder, codewordlen); - - if (channel->state.waitcnt) { - --channel->state.waitcnt; - } else { - channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); - update_model(&channel->state, find_bucket(channel, correlate_row[-1]), - correlate_row[0], bpc); - } - stopidx = ++i + channel->state.waitcnt; - } else { - stopidx = i + channel->state.waitcnt; - } - - while (stopidx < end) { - struct s_bucket * pbucket = NULL; - - for (; i <= stopidx; i++) { - unsigned int codewordlen; - - pbucket = find_bucket(channel, correlate_row[i - 1]); - correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word, - &codewordlen); - FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask); - decode_eatbits(encoder, codewordlen); - } - - update_model(&channel->state, pbucket, correlate_row[stopidx], bpc); - - stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codewordlen; - - correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel, - correlate_row[i - 1])->bestcode, - encoder->io_word, &codewordlen); - FNAME(corelate_0)(&cur_row[i], correlate_row[i], bpc_mask); - decode_eatbits(encoder, codewordlen); - } - channel->state.waitcnt = stopidx - end; -} - -static void FNAME(uncompress_row0)(Encoder *encoder, Channel *channel, - PIXEL * const cur_row, - unsigned int width) - -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - BYTE * const correlate_row = channel->correlate_row; - unsigned int pos = 0; - - while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { - if (channel->state.wmileft) { - FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row, - pos + channel->state.wmileft, bppmask[channel->state.wmidx], - bpc, bpc_mask); - pos += channel->state.wmileft; - width -= channel->state.wmileft; - } - - channel->state.wmidx++; - set_wm_trigger(&channel->state); - channel->state.wmileft = wminext; - } - - if (width) { - FNAME(uncompress_row0_seg)(encoder, channel, pos, correlate_row, cur_row, pos + width, - bppmask[channel->state.wmidx], bpc, bpc_mask); - if (wmimax > (int)channel->state.wmidx) { - channel->state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax); - ASSERT(encoder->usr, channel->state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -static void FNAME(uncompress_row_seg)(Encoder *encoder, Channel *channel, - BYTE *correlate_row, - const PIXEL * const prev_row, - PIXEL * const cur_row, - int i, - const int end, - const unsigned int bpc, - const unsigned int bpc_mask) -{ - const unsigned int waitmask = bppmask[channel->state.wmidx]; - int stopidx; -#ifdef RLE - int run_index = 0; - int run_end; -#endif - - ASSERT(encoder->usr, end - i > 0); - - if (i == 0) { - unsigned int codewordlen; - - correlate_row[0] = (BYTE)golomb_decoding(find_bucket(channel, correlate_row[-1])->bestcode, - encoder->io_word, &codewordlen); - cur_row[0].a = (family.xlatL2U[correlate_row[0]] + prev_row[0].a) & bpc_mask; - decode_eatbits(encoder, codewordlen); - - if (channel->state.waitcnt) { - --channel->state.waitcnt; - } else { - channel->state.waitcnt = (tabrand(&channel->state.tabrand_seed) & waitmask); - update_model(&channel->state, find_bucket(channel, correlate_row[-1]), - correlate_row[0], bpc); - } - stopidx = ++i + channel->state.waitcnt; - } else { - stopidx = i + channel->state.waitcnt; - } - for (;;) { - while (stopidx < end) { - struct s_bucket * pbucket = NULL; - - for (; i <= stopidx; i++) { - unsigned int codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - pbucket = find_bucket(channel, correlate_row[i - 1]); - correlate_row[i] = (BYTE)golomb_decoding(pbucket->bestcode, encoder->io_word, - &codewordlen); - FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask); - decode_eatbits(encoder, codewordlen); - } - - update_model(&channel->state, pbucket, correlate_row[stopidx], bpc); - - stopidx = i + (tabrand(&channel->state.tabrand_seed) & waitmask); - } - - for (; i < end; i++) { - unsigned int codewordlen; -#ifdef RLE - RLE_PRED_1_IMP; - RLE_PRED_2_IMP; - RLE_PRED_3_IMP; -#endif - correlate_row[i] = (BYTE)golomb_decoding(find_bucket(channel, - correlate_row[i - 1])->bestcode, - encoder->io_word, &codewordlen); - FNAME(corelate)(&prev_row[i], &cur_row[i], correlate_row[i], bpc_mask); - decode_eatbits(encoder, codewordlen); - } - - channel->state.waitcnt = stopidx - end; - - return; - -#ifdef RLE -do_run: - channel->state.waitcnt = stopidx - i; - run_index = i; -#ifdef RLE_STAT - run_end = i + decode_channel_run(encoder, channel); -#else - run_end = i + decode_run(encoder); -#endif - - for (; i < run_end; i++) { - cur_row[i].a = cur_row[i - 1].a; - } - - if (i == end) { - return; - } - - stopidx = i + channel->state.waitcnt; -#endif - } -} - -static void FNAME(uncompress_row)(Encoder *encoder, Channel *channel, - const PIXEL * const prev_row, - PIXEL * const cur_row, - unsigned int width) - -{ - const unsigned int bpc = BPC; - const unsigned int bpc_mask = BPC_MASK; - BYTE * const correlate_row = channel->correlate_row; - unsigned int pos = 0; - - while ((wmimax > (int)channel->state.wmidx) && (channel->state.wmileft <= width)) { - if (channel->state.wmileft) { - FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos, - pos + channel->state.wmileft, bpc, bpc_mask); - pos += channel->state.wmileft; - width -= channel->state.wmileft; - } - - channel->state.wmidx++; - set_wm_trigger(&channel->state); - channel->state.wmileft = wminext; - } - - if (width) { - FNAME(uncompress_row_seg)(encoder, channel, correlate_row, prev_row, cur_row, pos, - pos + width, bpc, bpc_mask); - if (wmimax > (int)channel->state.wmidx) { - channel->state.wmileft -= width; - } - } - - ASSERT(encoder->usr, (int)channel->state.wmidx <= wmimax); - ASSERT(encoder->usr, channel->state.wmidx <= 32); - ASSERT(encoder->usr, wminext > 0); -} - -#undef PIXEL -#undef FNAME -#undef _PIXEL_A -#undef _PIXEL_B -#undef _PIXEL_C -#undef RLE_PRED_1_IMP -#undef RLE_PRED_2_IMP -#undef RLE_PRED_3_IMP -#undef golomb_coding -#undef golomb_deoding -#undef update_model -#undef find_bucket -#undef family -#undef BPC -#undef BPC_MASK diff --git a/common/rect.h b/common/rect.h deleted file mode 100644 index ef265cd9..00000000 --- a/common/rect.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_RECT -#define _H_RECT - -#include "draw.h" -#include <spice/macros.h> - -#ifdef __cplusplus -extern "C" { -#endif - -static INLINE void rect_sect(SpiceRect* r, const SpiceRect* bounds) -{ - r->left = MAX(r->left, bounds->left); - r->right = MIN(r->right, bounds->right); - r->right = MAX(r->left, r->right); - - r->top = MAX(r->top, bounds->top); - r->bottom = MIN(r->bottom, bounds->bottom); - r->bottom = MAX(r->top, r->bottom); -} - -static INLINE void rect_offset(SpiceRect* r, int dx, int dy) -{ - r->left += dx; - r->right += dx; - r->top += dy; - r->bottom += dy; -} - -static INLINE int rect_is_empty(const SpiceRect* r) -{ - return r->top == r->bottom || r->left == r->right; -} - -static INLINE int rect_intersects(const SpiceRect* r1, const SpiceRect* r2) -{ - return r1->left < r2->right && r1->right > r2->left && - r1->top < r2->bottom && r1->bottom > r2->top; -} - -static INLINE int rect_is_equal(const SpiceRect *r1, const SpiceRect *r2) -{ - return r1->top == r2->top && r1->left == r2->left && - r1->bottom == r2->bottom && r1->right == r2->right; -} - -static INLINE void rect_union(SpiceRect *dest, const SpiceRect *r) -{ - dest->top = MIN(dest->top, r->top); - dest->left = MIN(dest->left, r->left); - dest->bottom = MAX(dest->bottom, r->bottom); - dest->right = MAX(dest->right, r->right); -} - -static INLINE int rect_is_same_size(const SpiceRect *r1, const SpiceRect *r2) -{ - return r1->right - r1->left == r2->right - r2->left && - r1->bottom - r1->top == r2->bottom - r2->top; -} - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus - -static inline void rect_sect(SpiceRect& r, const SpiceRect& bounds) -{ - rect_sect(&r, &bounds); -} - -static inline void rect_offset(SpiceRect& r, int dx, int dy) -{ - rect_offset(&r, dx, dy); -} - -static inline int rect_is_empty(const SpiceRect& r) -{ - return rect_is_empty(&r); -} - -static inline int rect_intersects(const SpiceRect& r1, const SpiceRect& r2) -{ - return rect_intersects(&r1, &r2); -} - -static inline int rect_is_equal(const SpiceRect& r1, const SpiceRect& r2) -{ - return rect_is_equal(&r1, &r2); -} - -static inline void rect_union(SpiceRect& dest, const SpiceRect& r) -{ - rect_union(&dest, &r); -} - -static inline int rect_is_same_size(const SpiceRect& r1, const SpiceRect& r2) -{ - return rect_is_same_size(&r1, &r2); -} - -#endif - -#endif diff --git a/common/region.c b/common/region.c deleted file mode 100644 index 35935eac..00000000 --- a/common/region.c +++ /dev/null @@ -1,890 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <spice/macros.h> - -#include "region.h" -#include "rect.h" -#include "mem.h" - -/* true iff two Boxes overlap */ -#define EXTENTCHECK(r1, r2) \ - (!( ((r1)->x2 <= (r2)->x1) || \ - ((r1)->x1 >= (r2)->x2) || \ - ((r1)->y2 <= (r2)->y1) || \ - ((r1)->y1 >= (r2)->y2) ) ) - -/* true iff Box r1 contains Box r2 */ -#define SUBSUMES(r1, r2) \ - ( ((r1)->x1 <= (r2)->x1) && \ - ((r1)->x2 >= (r2)->x2) && \ - ((r1)->y1 <= (r2)->y1) && \ - ((r1)->y2 >= (r2)->y2) ) - - -void region_init(QRegion *rgn) -{ - pixman_region32_init(rgn); -} - -void region_clear(QRegion *rgn) -{ - pixman_region32_fini(rgn); - pixman_region32_init(rgn); -} - -void region_destroy(QRegion *rgn) -{ - pixman_region32_fini(rgn); -} - -void region_clone(QRegion *dest, const QRegion *src) -{ - pixman_region32_init(dest); - pixman_region32_copy(dest, (pixman_region32_t *)src); -} - -#define FIND_BAND(r, r_band_end, r_end, ry1) \ - do { \ - ry1 = r->y1; \ - r_band_end = r + 1; \ - while ((r_band_end != r_end) && (r_band_end->y1 == ry1)) { \ - r_band_end++; \ - } \ - } while (0) - -static int test_band(int query, - int res, - pixman_box32_t *r1, - pixman_box32_t *r1_end, - pixman_box32_t *r2, - pixman_box32_t *r2_end) -{ - int x1; - int x2; - - do { - x1 = MAX(r1->x1, r2->x1); - x2 = MIN(r1->x2, r2->x2); - - /* - * Is there any overlap between the two rectangles? - */ - if (x1 < x2) { - res |= REGION_TEST_SHARED; - - if (r1->x1 < r2->x1 || r1->x2 > r2->x2) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } - - if (r2->x1 < r1->x1 || r2->x2 > r1->x2) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - } else { - /* No overlap at all, the leftmost is exclusive */ - if (r1->x1 < r2->x1) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } else { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - } - - if ((res & query) == query) { - return res; - } - - /* - * Advance the pointer(s) with the leftmost right side, since the next - * rectangle on that list may still overlap the other region's - * current rectangle. - */ - if (r1->x2 == x2) { - r1++; - } - if (r2->x2 == x2) { - r2++; - } - } while ((r1 != r1_end) && (r2 != r2_end)); - - /* - * Deal with whichever band (if any) still has rectangles left. - */ - if (r1 != r1_end) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } else if (r2 != r2_end) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - - return res; -} - -static int test_generic (pixman_region32_t *reg1, - pixman_region32_t *reg2, - int query) -{ - pixman_box32_t *r1; /* Pointer into first region */ - pixman_box32_t *r2; /* Pointer into 2d region */ - pixman_box32_t *r1_end; /* End of 1st region */ - pixman_box32_t *r2_end; /* End of 2d region */ - int ybot; /* Bottom of intersection */ - int ytop; /* Top of intersection */ - pixman_box32_t * r1_band_end; /* End of current band in r1 */ - pixman_box32_t * r2_band_end; /* End of current band in r2 */ - int top; /* Top of non-overlapping band */ - int bot; /* Bottom of non-overlapping band*/ - int r1y1; /* Temps for r1->y1 and r2->y1 */ - int r2y1; - int r1_num_rects; - int r2_num_rects; - int res; - - r1 = pixman_region32_rectangles(reg1, &r1_num_rects); - r1_end = r1 + r1_num_rects; - - r2 = pixman_region32_rectangles(reg2, &r2_num_rects); - r2_end = r2 + r2_num_rects; - - res = 0; - - /* - * Initialize ybot. - * In the upcoming loop, ybot and ytop serve different functions depending - * on whether the band being handled is an overlapping or non-overlapping - * band. - * In the case of a non-overlapping band (only one of the regions - * has points in the band), ybot is the bottom of the most recent - * intersection and thus clips the top of the rectangles in that band. - * ytop is the top of the next intersection between the two regions and - * serves to clip the bottom of the rectangles in the current band. - * For an overlapping band (where the two regions intersect), ytop clips - * the top of the rectangles of both regions and ybot clips the bottoms. - */ - - ybot = MIN(r1->y1, r2->y1); - - do { - /* - * This algorithm proceeds one source-band (as opposed to a - * destination band, which is determined by where the two regions - * intersect) at a time. r1_band_end and r2_band_end serve to mark the - * rectangle after the last one in the current band for their - * respective regions. - */ - FIND_BAND(r1, r1_band_end, r1_end, r1y1); - FIND_BAND(r2, r2_band_end, r2_end, r2y1); - - /* - * First handle the band that doesn't intersect, if any. - * - * Note that attention is restricted to one band in the - * non-intersecting region at once, so if a region has n - * bands between the current position and the next place it overlaps - * the other, this entire loop will be passed through n times. - */ - if (r1y1 < r2y1) { - top = MAX (r1y1, ybot); - bot = MIN (r1->y2, r2y1); - if (top != bot) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - - if ((res & query) == query) { - return res & query; - } - } - - ytop = r2y1; - } else if (r2y1 < r1y1) { - top = MAX (r2y1, ybot); - bot = MIN (r2->y2, r1y1); - - if (top != bot) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - - if ((res & query) == query) { - return res & query; - } - } - ytop = r1y1; - } else { - ytop = r1y1; - } - - /* - * Now see if we've hit an intersecting band. The two bands only - * intersect if ybot > ytop - */ - ybot = MIN (r1->y2, r2->y2); - if (ybot > ytop) { - res = test_band(query, res, - r1, r1_band_end, - r2, r2_band_end); - if ((res & query) == query) { - return res & query; - } - } - - /* - * If we've finished with a band (y2 == ybot) we skip forward - * in the region to the next band. - */ - if (r1->y2 == ybot) { - r1 = r1_band_end; - } - - if (r2->y2 == ybot) { - r2 = r2_band_end; - } - - } - while (r1 != r1_end && r2 != r2_end); - - /* - * Deal with whichever region (if any) still has rectangles left. - */ - - if (r1 != r1_end) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } else if (r2 != r2_end) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - - return res & query; -} - -int region_test(const QRegion *_reg1, const QRegion *_reg2, int query) -{ - int res; - pixman_region32_t *reg1 = (pixman_region32_t *)_reg1; - pixman_region32_t *reg2 = (pixman_region32_t *)_reg2; - - query = (query) ? query & REGION_TEST_ALL : REGION_TEST_ALL; - - res = 0; - - if (!pixman_region32_not_empty(reg1) || !pixman_region32_not_empty(reg2) || - !EXTENTCHECK (®1->extents, ®2->extents)) { - /* One or more regions are empty or they are disjoint */ - - if (pixman_region32_not_empty(reg1)) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } - - if (pixman_region32_not_empty(reg2)) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - - return res & query; - } else if (!reg1->data && !reg2->data) { - /* Just two rectangles that intersect */ - res |= REGION_TEST_SHARED; - - if (!SUBSUMES(®1->extents, ®2->extents)) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - - if (!SUBSUMES(®2->extents, ®1->extents)) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } - - return res & query; - } else if (!reg2->data && SUBSUMES (®2->extents, ®1->extents)) { - /* reg2 is just a rect that contains all of reg1 */ - - res |= REGION_TEST_SHARED; /* some piece must be shared, because reg is not empty */ - res |= REGION_TEST_RIGHT_EXCLUSIVE; /* reg2 contains all of reg1 and then some */ - - return res & query; - } else if (!reg1->data && SUBSUMES (®1->extents, ®2->extents)) { - /* reg1 is just a rect that contains all of reg2 */ - - res |= REGION_TEST_SHARED; /* some piece must be shared, because reg is not empty */ - res |= REGION_TEST_LEFT_EXCLUSIVE; /* reg1 contains all of reg2 and then some */ - - return res & query; - } else if (reg1 == reg2) { - res |= REGION_TEST_SHARED; - return res & query; - } else { - /* General purpose intersection */ - return test_generic (reg1, reg2, query); - } -} - -int region_is_valid(const QRegion *rgn) -{ - return pixman_region32_selfcheck((pixman_region32_t *)rgn); -} - -int region_is_empty(const QRegion *rgn) -{ - return !pixman_region32_not_empty((pixman_region32_t *)rgn); -} - -SpiceRect *region_dup_rects(const QRegion *rgn, uint32_t *num_rects) -{ - pixman_box32_t *boxes; - SpiceRect *rects; - int n, i; - - boxes = pixman_region32_rectangles((pixman_region32_t *)rgn, &n); - if (num_rects) { - *num_rects = n; - } - rects = spice_new(SpiceRect, n); - for (i = 0; i < n; i++) { - rects[i].left = boxes[i].x1; - rects[i].top = boxes[i].y1; - rects[i].right = boxes[i].x2; - rects[i].bottom = boxes[i].y2; - } - return rects; -} - -void region_ret_rects(const QRegion *rgn, SpiceRect *rects, uint32_t num_rects) -{ - pixman_box32_t *boxes; - unsigned int n, i; - - boxes = pixman_region32_rectangles((pixman_region32_t *)rgn, (int *)&n); - for (i = 0; i < n && i < num_rects; i++) { - rects[i].left = boxes[i].x1; - rects[i].top = boxes[i].y1; - rects[i].right = boxes[i].x2; - rects[i].bottom = boxes[i].y2; - } - - if (i && i != n) { - unsigned int x; - - for (x = 0; x < (n - num_rects); ++x) { - rects[i - 1].left = MIN(rects[i - 1].left, boxes[i + x].x1); - rects[i - 1].top = MIN(rects[i - 1].top, boxes[i + x].y1); - rects[i - 1].right = MAX(rects[i - 1].right, boxes[i + x].x2); - rects[i - 1].bottom = MAX(rects[i - 1].bottom, boxes[i + x].y2); - } - } -} - - -int region_is_equal(const QRegion *rgn1, const QRegion *rgn2) -{ - return pixman_region32_equal((pixman_region32_t *)rgn1, (pixman_region32_t *)rgn2); -} - -int region_intersects(const QRegion *rgn1, const QRegion *rgn2) -{ - int test_res; - - if (!region_bounds_intersects(rgn1, rgn2)) { - return FALSE; - } - - test_res = region_test(rgn1, rgn2, REGION_TEST_SHARED); - return !!test_res; -} - -int region_bounds_intersects(const QRegion *rgn1, const QRegion *rgn2) -{ - pixman_box32_t *extents1, *extents2; - - extents1 = pixman_region32_extents((pixman_region32_t *)rgn1); - extents2 = pixman_region32_extents((pixman_region32_t *)rgn1); - - return EXTENTCHECK(extents1, extents2); -} - -int region_contains(const QRegion *rgn, const QRegion *other) -{ - int test_res; - - test_res = region_test(rgn, other, REGION_TEST_RIGHT_EXCLUSIVE); - return !test_res; -} - -int region_contains_point(const QRegion *rgn, int32_t x, int32_t y) -{ - return pixman_region32_contains_point((pixman_region32_t *)rgn, x, y, NULL); -} - -void region_or(QRegion *rgn, const QRegion *other_rgn) -{ - pixman_region32_union(rgn, rgn, (pixman_region32_t *)other_rgn); -} - -void region_and(QRegion *rgn, const QRegion *other_rgn) -{ - pixman_region32_intersect(rgn, rgn, (pixman_region32_t *)other_rgn); -} - -void region_xor(QRegion *rgn, const QRegion *other_rgn) -{ - pixman_region32_t intersection; - - pixman_region32_copy(&intersection, rgn); - pixman_region32_intersect(&intersection, - &intersection, - (pixman_region32_t *)other_rgn); - pixman_region32_union(rgn, rgn, (pixman_region32_t *)other_rgn); - pixman_region32_subtract(rgn, rgn, &intersection); - pixman_region32_fini(&intersection); -} - -void region_exclude(QRegion *rgn, const QRegion *other_rgn) -{ - pixman_region32_subtract(rgn, rgn, (pixman_region32_t *)other_rgn); -} - -void region_add(QRegion *rgn, const SpiceRect *r) -{ - pixman_region32_union_rect(rgn, rgn, r->left, r->top, - r->right - r->left, - r->bottom - r->top); -} - -void region_remove(QRegion *rgn, const SpiceRect *r) -{ - pixman_region32_t rg; - - pixman_region32_init_rect(&rg, r->left, r->top, - r->right - r->left, - r->bottom - r->top); - pixman_region32_subtract(rgn, rgn, &rg); - pixman_region32_fini(&rg); -} - - -void region_offset(QRegion *rgn, int32_t dx, int32_t dy) -{ - pixman_region32_translate(rgn, dx, dy); -} - -void region_dump(const QRegion *rgn, const char *prefix) -{ - pixman_box32_t *rects, *extents; - int n_rects, i; - - printf("%sREGION: %p, ", prefix, rgn); - - if (!pixman_region32_not_empty((pixman_region32_t *)rgn)) { - printf("EMPTY\n"); - return; - } - - extents = pixman_region32_extents((pixman_region32_t *)rgn); - rects = pixman_region32_rectangles((pixman_region32_t *)rgn, &n_rects); - printf("num %u bounds (%d, %d, %d, %d)\n", - n_rects, - extents->x1, - extents->y1, - extents->x2, - extents->y2); - - - for (i = 0; i < n_rects; i++) { - printf("%*s %12d %12d %12d %12d\n", - (int)strlen(prefix), "", - rects[i].x1, - rects[i].y1, - rects[i].x2, - rects[i].y2); - } -} - -#ifdef REGION_TEST - -static int slow_region_test(const QRegion *rgn, const QRegion *other_rgn, int query) -{ - pixman_region32_t intersection; - int res; - - pixman_region32_init(&intersection); - pixman_region32_intersect(&intersection, - (pixman_region32_t *)rgn, - (pixman_region32_t *)other_rgn); - - res = 0; - - if (query & REGION_TEST_SHARED && - pixman_region32_not_empty(&intersection)) { - res |= REGION_TEST_SHARED; - } - - if (query & REGION_TEST_LEFT_EXCLUSIVE && - !pixman_region32_equal(&intersection, (pixman_region32_t *)rgn)) { - res |= REGION_TEST_LEFT_EXCLUSIVE; - } - - if (query & REGION_TEST_RIGHT_EXCLUSIVE && - !pixman_region32_equal(&intersection, (pixman_region32_t *)other_rgn)) { - res |= REGION_TEST_RIGHT_EXCLUSIVE; - } - - pixman_region32_fini(&intersection); - - return res; -} - - -static int rect_is_valid(const SpiceRect *r) -{ - if (r->top > r->bottom || r->left > r->right) { - printf("%s: invalid rect\n", __FUNCTION__); - return FALSE; - } - return TRUE; -} - -static void rect_set(SpiceRect *r, int32_t top, int32_t left, int32_t bottom, int32_t right) -{ - r->top = top; - r->left = left; - r->bottom = bottom; - r->right = right; - ASSERT(rect_is_valid(r)); -} - -static void random_region(QRegion *reg) -{ - int i; - int num_rects; - int x, y, w, h; - SpiceRect _r; - SpiceRect *r = &_r; - - region_clear(reg); - - num_rects = rand() % 20; - for (i = 0; i < num_rects; i++) { - x = rand()%100; - y = rand()%100; - w = rand()%100; - h = rand()%100; - rect_set(r, - x, y, - x+w, y+h); - region_add(reg, r); - } -} - -static void test(const QRegion *r1, const QRegion *r2, int *expected) -{ - printf("r1 is_empty %s [%s]\n", - region_is_empty(r1) ? "TRUE" : "FALSE", - (region_is_empty(r1) == *(expected++)) ? "OK" : "ERR"); - printf("r2 is_empty %s [%s]\n", - region_is_empty(r2) ? "TRUE" : "FALSE", - (region_is_empty(r2) == *(expected++)) ? "OK" : "ERR"); - printf("is_equal %s [%s]\n", - region_is_equal(r1, r2) ? "TRUE" : "FALSE", - (region_is_equal(r1, r2) == *(expected++)) ? "OK" : "ERR"); - printf("intersects %s [%s]\n", - region_intersects(r1, r2) ? "TRUE" : "FALSE", - (region_intersects(r1, r2) == *(expected++)) ? "OK" : "ERR"); - printf("contains %s [%s]\n", - region_contains(r1, r2) ? "TRUE" : "FALSE", - (region_contains(r1, r2) == *(expected++)) ? "OK" : "ERR"); -} - -enum { - EXPECT_R1_EMPTY, - EXPECT_R2_EMPTY, - EXPECT_EQUAL, - EXPECT_SECT, - EXPECT_CONT, -}; - -int main(void) -{ - QRegion _r1, _r2, _r3; - QRegion *r1 = &_r1; - QRegion *r2 = &_r2; - QRegion *r3 = &_r3; - SpiceRect _r; - SpiceRect *r = &_r; - int expected[5]; - int i, j; - - region_init(r1); - region_init(r2); - - printf("dump r1 empty rgn [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = TRUE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = TRUE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - region_clone(r3, r1); - printf("dump r3 clone rgn [%s]\n", region_is_valid(r3) ? "VALID" : "INVALID"); - region_dump(r3, ""); - expected[EXPECT_R1_EMPTY] = TRUE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = TRUE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r3, expected); - region_destroy(r3); - printf("\n"); - - rect_set(r, 0, 0, 100, 100); - region_add(r1, r); - printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r1); - rect_set(r, 0, 0, 0, 0); - region_add(r1, r); - printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = TRUE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = TRUE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - rect_set(r, -100, -100, 0, 0); - region_add(r1, r); - printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r1); - rect_set(r, -100, -100, 100, 100); - region_add(r1, r); - printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - - region_clear(r1); - region_clear(r2); - - rect_set(r, 100, 100, 200, 200); - region_add(r1, r); - printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - rect_set(r, 300, 300, 400, 400); - region_add(r1, r); - printf("dump r1 [%s]\n", region_is_valid(r1) ? "VALID" : "INVALID"); - region_dump(r1, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = TRUE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - rect_set(r, 500, 500, 600, 600); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = FALSE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r2); - - rect_set(r, 100, 100, 200, 200); - region_add(r2, r); - rect_set(r, 300, 300, 400, 400); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = TRUE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r2); - - rect_set(r, 100, 100, 200, 200); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r2); - - rect_set(r, -2000, -2000, -1000, -1000); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = FALSE; - expected[EXPECT_CONT] = FALSE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r2); - - rect_set(r, -2000, -2000, 1000, 1000); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = FALSE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r2); - - rect_set(r, 150, 150, 175, 175); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = TRUE; - test(r1, r2, expected); - printf("\n"); - - region_clear(r2); - - rect_set(r, 150, 150, 350, 350); - region_add(r2, r); - printf("dump r2 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = FALSE; - test(r1, r2, expected); - printf("\n"); - - region_and(r2, r1); - printf("dump r2 and r1 [%s]\n", region_is_valid(r2) ? "VALID" : "INVALID"); - region_dump(r2, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = FALSE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = FALSE; - test(r2, r1, expected); - printf("\n"); - - - region_clone(r3, r1); - printf("dump r3 clone rgn [%s]\n", region_is_valid(r3) ? "VALID" : "INVALID"); - region_dump(r3, ""); - expected[EXPECT_R1_EMPTY] = FALSE; - expected[EXPECT_R2_EMPTY] = FALSE; - expected[EXPECT_EQUAL] = TRUE; - expected[EXPECT_SECT] = TRUE; - expected[EXPECT_CONT] = TRUE; - test(r1, r3, expected); - printf("\n"); - - j = 0; - for (i = 0; i < 1000000; i++) { - int res1, res2, test; - int tests[] = { - REGION_TEST_LEFT_EXCLUSIVE, - REGION_TEST_RIGHT_EXCLUSIVE, - REGION_TEST_SHARED, - REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE, - REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_SHARED, - REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED, - REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED - }; - - random_region(r1); - random_region(r2); - - for (test = 0; test < 7; test++) { - res1 = region_test(r1, r2, tests[test]); - res2 = slow_region_test(r1, r2, tests[test]); - if (res1 != res2) { - printf ("Error in region_test %d, got %d, expected %d, query=%d\n", - j, res1, res2, tests[test]); - printf ("r1:\n"); - region_dump(r1, ""); - printf ("r2:\n"); - region_dump(r2, ""); - } - j++; - } - } - - region_destroy(r3); - region_destroy(r1); - region_destroy(r2); - - return 0; -} - -#endif diff --git a/common/region.h b/common/region.h deleted file mode 100644 index 954e06fa..00000000 --- a/common/region.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_REGION -#define _H_REGION - -#include <stdint.h> -#include "draw.h" -#include <pixman_utils.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef pixman_region32_t QRegion; - -#define REGION_TEST_LEFT_EXCLUSIVE (1 << 0) -#define REGION_TEST_RIGHT_EXCLUSIVE (1 << 1) -#define REGION_TEST_SHARED (1 << 2) -#define REGION_TEST_ALL \ - (REGION_TEST_LEFT_EXCLUSIVE | REGION_TEST_RIGHT_EXCLUSIVE | REGION_TEST_SHARED) - -void region_init(QRegion *rgn); -void region_clear(QRegion *rgn); -void region_destroy(QRegion *rgn); -void region_clone(QRegion *dest, const QRegion *src); -SpiceRect *region_dup_rects(const QRegion *rgn, uint32_t *num_rects); -void region_ret_rects(const QRegion *rgn, SpiceRect *rects, uint32_t num_rects); - -int region_test(const QRegion *rgn, const QRegion *other_rgn, int query); -int region_is_valid(const QRegion *rgn); -int region_is_empty(const QRegion *rgn); -int region_is_equal(const QRegion *rgn1, const QRegion *rgn2); -int region_intersects(const QRegion *rgn1, const QRegion *rgn2); -int region_bounds_intersects(const QRegion *rgn1, const QRegion *rgn2); -int region_contains(const QRegion *rgn, const QRegion *other); -int region_contains_point(const QRegion *rgn, int32_t x, int32_t y); - -void region_or(QRegion *rgn, const QRegion *other_rgn); -void region_and(QRegion *rgn, const QRegion *other_rgn); -void region_xor(QRegion *rgn, const QRegion *other_rgn); -void region_exclude(QRegion *rgn, const QRegion *other_rgn); - -void region_add(QRegion *rgn, const SpiceRect *r); -void region_remove(QRegion *rgn, const SpiceRect *r); - -void region_offset(QRegion *rgn, int32_t dx, int32_t dy); - -void region_dump(const QRegion *rgn, const char *prefix); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/ring.h b/common/ring.h deleted file mode 100644 index cb70696a..00000000 --- a/common/ring.h +++ /dev/null @@ -1,172 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_RING2 -#define _H_RING2 - -#include "spice_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct Ring RingItem; -typedef struct Ring { - RingItem *prev; - RingItem *next; -} Ring; - -static inline void ring_init(Ring *ring) -{ - ring->next = ring->prev = ring; -} - -static inline void ring_item_init(RingItem *item) -{ - item->next = item->prev = NULL; -} - -static inline int ring_item_is_linked(RingItem *item) -{ - return !!item->next; -} - -static inline int ring_is_empty(Ring *ring) -{ - ASSERT(ring->next != NULL && ring->prev != NULL); - return ring == ring->next; -} - -static inline void ring_add(Ring *ring, RingItem *item) -{ - ASSERT(ring->next != NULL && ring->prev != NULL); - ASSERT(item->next == NULL && item->prev == NULL); - - item->next = ring->next; - item->prev = ring; - ring->next = item->next->prev = item; -} - -static inline void ring_add_after(RingItem *item, RingItem *pos) -{ - ring_add(pos, item); -} - -static inline void ring_add_before(RingItem *item, RingItem *pos) -{ - ring_add(pos->prev, item); -} - -static inline void __ring_remove(RingItem *item) -{ - item->next->prev = item->prev; - item->prev->next = item->next; - item->prev = item->next = 0; -} - -static inline void ring_remove(RingItem *item) -{ - ASSERT(item->next != NULL && item->prev != NULL); - ASSERT(item->next != item); - - __ring_remove(item); -} - -static inline RingItem *ring_get_head(Ring *ring) -{ - RingItem *ret; - - ASSERT(ring->next != NULL && ring->prev != NULL); - - if (ring_is_empty(ring)) { - return NULL; - } - ret = ring->next; - return ret; -} - -static inline RingItem *ring_get_tail(Ring *ring) -{ - RingItem *ret; - - ASSERT(ring->next != NULL && ring->prev != NULL); - - if (ring_is_empty(ring)) { - return NULL; - } - ret = ring->prev; - return ret; -} - -static inline RingItem *ring_next(Ring *ring, RingItem *pos) -{ - RingItem *ret; - - ASSERT(ring->next != NULL && ring->prev != NULL); - ASSERT(pos); - ASSERT(pos->next != NULL && pos->prev != NULL); - ret = pos->next; - return (ret == ring) ? NULL : ret; -} - -static inline RingItem *ring_prev(Ring *ring, RingItem *pos) -{ - RingItem *ret; - - ASSERT(ring->next != NULL && ring->prev != NULL); - ASSERT(pos); - ASSERT(pos->next != NULL && pos->prev != NULL); - ret = pos->prev; - return (ret == ring) ? NULL : ret; -} - -#define RING_FOREACH_SAFE(var, next, ring) \ - for ((var) = ring_get_head(ring); \ - (var) && ((next) = ring_next(ring, (var)), 1); \ - (var) = (next)) - - -#define RING_FOREACH(var, ring) \ - for ((var) = ring_get_head(ring); \ - (var); \ - (var) = ring_next(ring, var)) - -#define RING_FOREACH_REVERSED(var, ring) \ - for ((var) = ring_get_tail(ring); \ - (var); \ - (var) = ring_prev(ring, var)) - - -static inline unsigned int ring_get_length(Ring *ring) -{ - RingItem *i; - unsigned int ret = 0; - - for (i = ring_get_head(ring); - i != NULL; - i = ring_next(ring, i)) - ret++; - - return ret; -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/rop3.c b/common/rop3.c deleted file mode 100644 index 12d9f111..00000000 --- a/common/rop3.c +++ /dev/null @@ -1,650 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> - -#include "rop3.h" -#include "spice_common.h" - -typedef void (*rop3_with_pattern_handler_t)(pixman_image_t *d, pixman_image_t *s, - SpicePoint *src_pos, pixman_image_t *p, - SpicePoint *pat_pos); - -typedef void (*rop3_with_color_handler_t)(pixman_image_t *d, pixman_image_t *s, - SpicePoint *src_pos, uint32_t rgb); - -typedef void (*rop3_test_handler_t)(void); - -#define ROP3_NUM_OPS 256 - -static rop3_with_pattern_handler_t rop3_with_pattern_handlers_32[ROP3_NUM_OPS]; -static rop3_with_pattern_handler_t rop3_with_pattern_handlers_16[ROP3_NUM_OPS]; -static rop3_with_color_handler_t rop3_with_color_handlers_32[ROP3_NUM_OPS]; -static rop3_with_color_handler_t rop3_with_color_handlers_16[ROP3_NUM_OPS]; -static rop3_test_handler_t rop3_test_handlers_32[ROP3_NUM_OPS]; -static rop3_test_handler_t rop3_test_handlers_16[ROP3_NUM_OPS]; - - -static void default_rop3_with_pattern_handler(pixman_image_t *d, pixman_image_t *s, - SpicePoint *src_pos, pixman_image_t *p, - SpicePoint *pat_pos) -{ - WARN("not implemented"); -} - -static void default_rop3_withe_color_handler(pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, - uint32_t rgb) -{ - WARN("not implemented"); -} - -static void default_rop3_test_handler(void) -{ -} - -#define ROP3_HANDLERS_DEPTH(name, formula, index, depth) \ -static void rop3_handle_p##depth##_##name(pixman_image_t *d, pixman_image_t *s, \ - SpicePoint *src_pos, \ - pixman_image_t *p, SpicePoint *pat_pos) \ -{ \ - int width = pixman_image_get_width(d); \ - int height = pixman_image_get_height(d); \ - uint8_t *dest_line = (uint8_t *)pixman_image_get_data(d); \ - int dest_stride = pixman_image_get_stride(d); \ - uint8_t *end_line = dest_line + height * dest_stride; \ - \ - int pat_width = pixman_image_get_width(p); \ - int pat_height = pixman_image_get_height(p); \ - uint8_t *pat_base = (uint8_t *)pixman_image_get_data(p); \ - int pat_stride = pixman_image_get_stride(p); \ - int pat_v_offset = pat_pos->y; \ - \ - int src_stride = pixman_image_get_stride(s); \ - uint8_t *src_line; \ - src_line = (uint8_t *)pixman_image_get_data(s) + src_pos->y * src_stride + (src_pos->x * depth / 8); \ - \ - for (; dest_line < end_line; dest_line += dest_stride, src_line += src_stride) { \ - uint##depth##_t *dest = (uint##depth##_t *)dest_line; \ - uint##depth##_t *end = dest + width; \ - uint##depth##_t *src = (uint##depth##_t *)src_line; \ - \ - int pat_h_offset = pat_pos->x; \ - \ - for (; dest < end; dest++, src++) { \ - uint##depth##_t *pat; \ - pat = (uint##depth##_t *) \ - (pat_base + pat_v_offset * pat_stride + (pat_h_offset * depth / 8)); \ - *dest = formula; \ - pat_h_offset = (pat_h_offset + 1) % pat_width; \ - } \ - \ - pat_v_offset = (pat_v_offset + 1) % pat_height; \ - } \ -} \ - \ -static void rop3_handle_c##depth##_##name(pixman_image_t *d, pixman_image_t *s, \ - SpicePoint *src_pos, \ - uint32_t rgb) \ -{ \ - int width = pixman_image_get_width(d); \ - int height = pixman_image_get_height(d); \ - uint8_t *dest_line = (uint8_t *)pixman_image_get_data(d); \ - int dest_stride = pixman_image_get_stride(d); \ - uint8_t *end_line = dest_line + height * dest_stride; \ - uint##depth##_t _pat = rgb; \ - uint##depth##_t *pat = &_pat; \ - \ - int src_stride = pixman_image_get_stride(s); \ - uint8_t *src_line; \ - src_line = (uint8_t *) \ - pixman_image_get_data(s) + src_pos->y * src_stride + (src_pos->x * depth / 8); \ - \ - for (; dest_line < end_line; dest_line += dest_stride, src_line += src_stride) { \ - uint##depth##_t *dest = (uint##depth##_t *)dest_line; \ - uint##depth##_t *end = dest + width; \ - uint##depth##_t *src = (uint##depth##_t *)src_line; \ - for (; dest < end; dest++, src++) { \ - *dest = formula; \ - } \ - } \ -} \ - \ -static void rop3_test##depth##_##name(void) \ -{ \ - uint8_t d = 0xaa; \ - uint8_t s = 0xcc; \ - uint8_t p = 0xf0; \ - uint8_t *pat = &p; \ - uint8_t *src = &s; \ - uint8_t *dest = &d; \ - \ - d = formula; \ - if (d != index) { \ - printf("%s: failed, result is 0x%x expect 0x%x\n", __FUNCTION__, d, index); \ - } \ -} - -#define ROP3_HANDLERS(name, formula, index) \ - ROP3_HANDLERS_DEPTH(name, formula, index, 32) \ - ROP3_HANDLERS_DEPTH(name, formula, index, 16) - -ROP3_HANDLERS(DPSoon, ~(*pat | *src | *dest), 0x01); -ROP3_HANDLERS(DPSona, ~(*pat | *src) & *dest, 0x02); -ROP3_HANDLERS(SDPona, ~(*pat | *dest) & *src, 0x04); -ROP3_HANDLERS(PDSxnon, ~(~(*src ^ *dest) | *pat), 0x06); -ROP3_HANDLERS(PDSaon, ~((*src & *dest) | *pat), 0x07); -ROP3_HANDLERS(SDPnaa, ~*pat & *dest & *src, 0x08); -ROP3_HANDLERS(PDSxon, ~((*src ^ *dest) | *pat), 0x09); -ROP3_HANDLERS(PSDnaon, ~((~*dest & *src) | *pat), 0x0b); -ROP3_HANDLERS(PDSnaon, ~((~*src & *dest) | *pat), 0x0d); -ROP3_HANDLERS(PDSonon, ~(~(*src | *dest) | *pat), 0x0e); -ROP3_HANDLERS(PDSona, ~(*src | *dest) & *pat, 0x10); -ROP3_HANDLERS(SDPxnon, ~(~(*pat ^ *dest) | *src), 0x12); -ROP3_HANDLERS(SDPaon, ~((*pat & *dest) | *src), 0x13); -ROP3_HANDLERS(DPSxnon, ~(~(*pat ^ *src) | *dest), 0x14); -ROP3_HANDLERS(DPSaon, ~((*pat & *src) | *dest), 0x15); -ROP3_HANDLERS(PSDPSanaxx, (~(*pat & *src) & *dest) ^ *src ^ *pat, 0x16); -ROP3_HANDLERS(SSPxDSxaxn, ~(((*src ^ *dest) & (*src ^ *pat)) ^ *src), 0x17); -ROP3_HANDLERS(SPxPDxa, (*src ^ *pat) & (*pat ^ *dest), 0x18); -ROP3_HANDLERS(SDPSanaxn, ~((~(*pat & *src) & *dest) ^ *src), 0x19); -ROP3_HANDLERS(PDSPaox, ((*pat & *src) | *dest) ^ *pat, 0x1a); -ROP3_HANDLERS(SDPSxaxn, ~(((*pat ^ *src) & *dest) ^ *src), 0x1b); -ROP3_HANDLERS(PSDPaox, ((*pat & *dest) | *src) ^ *pat, 0x1c); -ROP3_HANDLERS(DSPDxaxn, ~(((*pat ^ *dest) & *src) ^ *dest), 0x1d); -ROP3_HANDLERS(PDSox, (*dest | *src) ^ *pat, 0x1e); -ROP3_HANDLERS(PDSoan, ~((*src | *dest) & *pat), 0x1f); -ROP3_HANDLERS(DPSnaa, ~*src & *pat & *dest, 0x20); -ROP3_HANDLERS(SDPxon, ~((*pat ^ *dest) | *src), 0x21); -ROP3_HANDLERS(SPDnaon, ~((~*dest & *pat) | *src), 0x23); -ROP3_HANDLERS(SPxDSxa, (*src ^ *pat) & (*dest ^ *src), 0x24); -ROP3_HANDLERS(PDSPanaxn, ~((~(*src & *pat) & *dest) ^ *pat), 0x25); -ROP3_HANDLERS(SDPSaox, ((*src & *pat) | *dest) ^ *src, 0x26); -ROP3_HANDLERS(SDPSxnox, (~(*src ^ *pat) | *dest) ^ *src, 0x27); -ROP3_HANDLERS(DPSxa, (*pat ^ *src) & *dest, 0x28); -ROP3_HANDLERS(PSDPSaoxxn, ~(((*src & *pat) | *dest) ^ *src ^ *pat), 0x29); -ROP3_HANDLERS(DPSana, ~(*src & *pat) & *dest, 0x2a); -ROP3_HANDLERS(SSPxPDxaxn, ~(((*pat ^ *dest) & (*src ^ *pat)) ^ *src), 0x2b); -ROP3_HANDLERS(SPDSoax, ((*src | *dest) & *pat) ^ *src, 0x2c); -ROP3_HANDLERS(PSDnox, (~*dest | *src) ^ *pat, 0x2d); -ROP3_HANDLERS(PSDPxox, ((*pat ^ *dest) | *src) ^ *pat, 0x2e); -ROP3_HANDLERS(PSDnoan, ~((~*dest | *src) & *pat), 0x2f); -ROP3_HANDLERS(SDPnaon, ~((~*pat & *dest) | *src), 0x31); -ROP3_HANDLERS(SDPSoox, (*src | *pat | *dest) ^ *src, 0x32); -ROP3_HANDLERS(SPDSaox, ((*src & *dest) | *pat) ^ *src, 0x34); -ROP3_HANDLERS(SPDSxnox, (~(*src ^ *dest) | *pat) ^ *src, 0x35); -ROP3_HANDLERS(SDPox, (*pat | *dest) ^ *src, 0x36); -ROP3_HANDLERS(SDPoan, ~((*pat | *dest) & *src), 0x37); -ROP3_HANDLERS(PSDPoax, ((*pat | *dest) & *src) ^ *pat, 0x38); -ROP3_HANDLERS(SPDnox, (~*dest | *pat) ^ *src, 0x39); -ROP3_HANDLERS(SPDSxox, ((*src ^ *dest) | *pat) ^ *src, 0x3a); -ROP3_HANDLERS(SPDnoan, ~((~*dest | *pat) & *src), 0x3b); -ROP3_HANDLERS(SPDSonox, (~(*src | *dest) | *pat) ^ *src, 0x3d); -ROP3_HANDLERS(SPDSnaox, ((~*src & *dest) | *pat) ^ *src, 0x3e); -ROP3_HANDLERS(PSDnaa, ~*dest & *src & *pat, 0x40); -ROP3_HANDLERS(DPSxon, ~((*src ^ *pat) | *dest), 0x41); -ROP3_HANDLERS(SDxPDxa, (*src ^ *dest) & (*pat ^ *dest), 0x42); -ROP3_HANDLERS(SPDSanaxn, ~((~(*src & *dest) & *pat) ^ *src), 0x43); -ROP3_HANDLERS(DPSnaon, ~((~*src & *pat) | *dest), 0x45); -ROP3_HANDLERS(DSPDaox, ((*dest & *pat) | *src) ^ *dest, 0x46); -ROP3_HANDLERS(PSDPxaxn, ~(((*pat ^ *dest) & *src) ^ *pat), 0x47); -ROP3_HANDLERS(SDPxa, (*pat ^ *dest) & *src, 0x48); -ROP3_HANDLERS(PDSPDaoxxn, ~(((*dest & *pat) | *src) ^ *dest ^ *pat), 0x49); -ROP3_HANDLERS(DPSDoax, ((*dest | *src) & *pat) ^ *dest, 0x4a); -ROP3_HANDLERS(PDSnox, (~*src | *dest) ^ *pat, 0x4b); -ROP3_HANDLERS(SDPana, ~(*pat & *dest) & *src, 0x4c); -ROP3_HANDLERS(SSPxDSxoxn, ~(((*src ^ *dest) | (*src ^ *pat)) ^ *src), 0x4d); -ROP3_HANDLERS(PDSPxox, ((*pat ^ *src) | *dest) ^ *pat, 0x4e); -ROP3_HANDLERS(PDSnoan, ~((~*src | *dest) & *pat), 0x4f); -ROP3_HANDLERS(DSPnaon, ~((~*pat & *src) | *dest), 0x51); -ROP3_HANDLERS(DPSDaox, ((*dest & *src) | *pat) ^ *dest, 0x52); -ROP3_HANDLERS(SPDSxaxn, ~(((*src ^ *dest) & *pat) ^ *src), 0x53); -ROP3_HANDLERS(DPSonon, ~(~(*src | *pat) | *dest), 0x54); -ROP3_HANDLERS(DPSox, (*src | *pat) ^ *dest, 0x56); -ROP3_HANDLERS(DPSoan, ~((*src | *pat) & *dest), 0x57); -ROP3_HANDLERS(PDSPoax, ((*pat | *src) & *dest) ^ *pat, 0x58); -ROP3_HANDLERS(DPSnox, (~*src | *pat) ^ *dest, 0x59); -ROP3_HANDLERS(DPSDonox, (~(*dest | *src) | *pat) ^ *dest, 0x5b); -ROP3_HANDLERS(DPSDxox, ((*dest ^ *src) | *pat) ^ *dest, 0x5c); -ROP3_HANDLERS(DPSnoan, ~((~*src | *pat) & *dest), 0x5d); -ROP3_HANDLERS(DPSDnaox, ((~*dest & *src) | *pat) ^ *dest, 0x5e); -ROP3_HANDLERS(PDSxa, (*src ^ *dest) & *pat, 0x60); -ROP3_HANDLERS(DSPDSaoxxn, ~(((*src & *dest) | *pat) ^ *src ^ *dest), 0x61); -ROP3_HANDLERS(DSPDoax, ((*dest | *pat) & *src) ^ *dest, 0x62); -ROP3_HANDLERS(SDPnox, (~*pat | *dest) ^ *src, 0x63); -ROP3_HANDLERS(SDPSoax, ((*src | *pat) & *dest) ^ *src, 0x64); -ROP3_HANDLERS(DSPnox, (~*pat | *src) ^ *dest, 0x65); -ROP3_HANDLERS(SDPSonox, (~(*src | *pat) | *dest) ^ *src, 0x67); -ROP3_HANDLERS(DSPDSonoxxn, ~((~(*src | *dest) | *pat) ^ *src ^ *dest), 0x68); -ROP3_HANDLERS(PDSxxn, ~(*src ^ *dest ^ *pat), 0x69); -ROP3_HANDLERS(DPSax, (*src & *pat) ^ *dest, 0x6a); -ROP3_HANDLERS(PSDPSoaxxn, ~(((*src | *pat) & *dest) ^ *src ^ *pat), 0x6b); -ROP3_HANDLERS(SDPax, (*pat & *dest) ^ *src, 0x6c); -ROP3_HANDLERS(PDSPDoaxxn, ~(((*dest | *pat) & *src) ^ *dest ^ *pat), 0x6d); -ROP3_HANDLERS(SDPSnoax, ((~*src | *pat) & *dest) ^ *src, 0x6e); -ROP3_HANDLERS(PDSxnan, ~(~(*src ^ *dest) & *pat), 0x6f); -ROP3_HANDLERS(PDSana, ~(*src & *dest) & *pat, 0x70); -ROP3_HANDLERS(SSDxPDxaxn, ~(((*dest ^ *pat) & (*src ^ *dest)) ^ *src), 0x71); -ROP3_HANDLERS(SDPSxox, ((*src ^ *pat) | *dest) ^ *src, 0x72); -ROP3_HANDLERS(SDPnoan, ~((~*pat | *dest) & *src), 0x73); -ROP3_HANDLERS(DSPDxox, ((*dest ^ *pat) | *src) ^ *dest, 0x74); -ROP3_HANDLERS(DSPnoan, ~((~*pat | *src) & *dest), 0x75); -ROP3_HANDLERS(SDPSnaox, ((~*src & *pat) | *dest) ^ *src, 0x76); -ROP3_HANDLERS(PDSax, (*src & *dest) ^ *pat, 0x78); -ROP3_HANDLERS(DSPDSoaxxn, ~(((*src | *dest) & *pat) ^ *src ^ *dest), 0x79); -ROP3_HANDLERS(DPSDnoax, ((~*dest | *src) & *pat) ^ *dest, 0x7a); -ROP3_HANDLERS(SDPxnan, ~(~(*pat ^ *dest) & *src), 0x7b); -ROP3_HANDLERS(SPDSnoax, ((~*src | *dest) & *pat) ^ *src, 0x7c); -ROP3_HANDLERS(DPSxnan, ~(~(*src ^ *pat) & *dest), 0x7d); -ROP3_HANDLERS(SPxDSxo, (*src ^ *dest) | (*pat ^ *src), 0x7e); -ROP3_HANDLERS(DPSaan, ~(*src & *pat & *dest), 0x7f); -ROP3_HANDLERS(DPSaa, *src & *pat & *dest, 0x80); -ROP3_HANDLERS(SPxDSxon, ~((*src ^ *dest) | (*pat ^ *src)), 0x81); -ROP3_HANDLERS(DPSxna, ~(*src ^ *pat) & *dest, 0x82); -ROP3_HANDLERS(SPDSnoaxn, ~(((~*src | *dest) & *pat) ^ *src), 0x83); -ROP3_HANDLERS(SDPxna, ~(*pat ^ *dest) & *src, 0x84); -ROP3_HANDLERS(PDSPnoaxn, ~(((~*pat | *src) & *dest) ^ *pat), 0x85); -ROP3_HANDLERS(DSPDSoaxx, ((*src | *dest) & *pat) ^ *src ^ *dest, 0x86); -ROP3_HANDLERS(PDSaxn, ~((*src & *dest) ^ *pat), 0x87); -ROP3_HANDLERS(SDPSnaoxn, ~(((~*src & *pat) | *dest) ^ *src), 0x89); -ROP3_HANDLERS(DSPnoa, (~*pat | *src) & *dest, 0x8a); -ROP3_HANDLERS(DSPDxoxn, ~(((*dest ^ *pat) | *src) ^ *dest), 0x8b); -ROP3_HANDLERS(SDPnoa, (~*pat | *dest) & *src, 0x8c); -ROP3_HANDLERS(SDPSxoxn, ~(((*src ^ *pat) | *dest) ^ *src), 0x8d); -ROP3_HANDLERS(SSDxPDxax, ((*dest ^ *pat) & (*dest ^ *src)) ^ *src, 0x8e); -ROP3_HANDLERS(PDSanan, ~(~(*src & *dest) & *pat), 0x8f); -ROP3_HANDLERS(PDSxna, ~(*src ^ *dest) & *pat, 0x90); -ROP3_HANDLERS(SDPSnoaxn, ~(((~*src | *pat) & *dest) ^ *src), 0x91); -ROP3_HANDLERS(DPSDPoaxx, ((*pat | *dest) & *src) ^ *pat ^ *dest, 0x92); -ROP3_HANDLERS(SPDaxn, ~((*dest & *pat) ^ *src), 0x93); -ROP3_HANDLERS(PSDPSoaxx, ((*src | *pat) & *dest) ^ *src ^ *pat, 0x94); -ROP3_HANDLERS(DPSaxn, ~((*src & *pat) ^ *dest), 0x95); -ROP3_HANDLERS(DPSxx, *src ^ *pat ^ *dest, 0x96); -ROP3_HANDLERS(PSDPSonoxx, (~(*src | *pat) | *dest) ^ *src ^ *pat, 0x97); -ROP3_HANDLERS(SDPSonoxn, ~((~(*src | *pat) | *dest) ^ *src), 0x98); -ROP3_HANDLERS(DPSnax, (~*src & *pat) ^ *dest, 0x9a); -ROP3_HANDLERS(SDPSoaxn, ~(((*src | *pat) & *dest) ^ *src), 0x9b); -ROP3_HANDLERS(SPDnax, (~*dest & *pat) ^ *src, 0x9c); -ROP3_HANDLERS(DSPDoaxn, ~(((*dest | *pat) & *src) ^ *dest), 0x9d); -ROP3_HANDLERS(DSPDSaoxx, ((*src & *dest) | *pat) ^ *src ^ *dest, 0x9e); -ROP3_HANDLERS(PDSxan, ~((*src ^ *dest) & *pat), 0x9f); -ROP3_HANDLERS(PDSPnaoxn, ~(((~*pat & *src) | *dest) ^ *pat), 0xa1); -ROP3_HANDLERS(DPSnoa, (~*src | *pat) & *dest, 0xa2); -ROP3_HANDLERS(DPSDxoxn, ~(((*dest ^ *src) | *pat) ^ *dest), 0xa3); -ROP3_HANDLERS(PDSPonoxn, ~((~(*pat | *src) | *dest) ^ *pat), 0xa4); -ROP3_HANDLERS(DSPnax, (~*pat & *src) ^ *dest, 0xa6); -ROP3_HANDLERS(PDSPoaxn, ~(((*pat | *src) & *dest) ^ *pat), 0xa7); -ROP3_HANDLERS(DPSoa, (*src | *pat) & *dest, 0xa8); -ROP3_HANDLERS(DPSoxn, ~((*src | *pat) ^ *dest), 0xa9); -ROP3_HANDLERS(DPSono, ~(*src | *pat) | *dest, 0xab); -ROP3_HANDLERS(SPDSxax, ((*src ^ *dest) & *pat) ^ *src, 0xac); -ROP3_HANDLERS(DPSDaoxn, ~(((*dest & *src) | *pat) ^ *dest), 0xad); -ROP3_HANDLERS(DSPnao, (~*pat & *src) | *dest, 0xae); -ROP3_HANDLERS(PDSnoa, (~*src | *dest) & *pat, 0xb0); -ROP3_HANDLERS(PDSPxoxn, ~(((*pat ^ *src) | *dest) ^ *pat), 0xb1); -ROP3_HANDLERS(SSPxDSxox, ((*src ^ *dest) | (*pat ^ *src)) ^ *src, 0xb2); -ROP3_HANDLERS(SDPanan, ~(~(*pat & *dest) & *src), 0xb3); -ROP3_HANDLERS(PSDnax, (~*dest & *src) ^ *pat, 0xb4); -ROP3_HANDLERS(DPSDoaxn, ~(((*dest | *src) & *pat) ^ *dest), 0xb5); -ROP3_HANDLERS(DPSDPaoxx, ((*pat & *dest) | *src) ^ *pat ^ *dest, 0xb6); -ROP3_HANDLERS(SDPxan, ~((*pat ^ *dest) & *src), 0xb7); -ROP3_HANDLERS(PSDPxax, ((*dest ^ *pat) & *src) ^ *pat, 0xb8); -ROP3_HANDLERS(DSPDaoxn, ~(((*dest & *pat) | *src) ^ *dest), 0xb9); -ROP3_HANDLERS(DPSnao, (~*src & *pat) | *dest, 0xba); -ROP3_HANDLERS(SPDSanax, (~(*src & *dest) & *pat) ^ *src, 0xbc); -ROP3_HANDLERS(SDxPDxan, ~((*dest ^ *pat) & (*dest ^ *src)), 0xbd); -ROP3_HANDLERS(DPSxo, (*src ^ *pat) | *dest, 0xbe); -ROP3_HANDLERS(DPSano, ~(*src & *pat) | *dest, 0xbf); -ROP3_HANDLERS(SPDSnaoxn, ~(((~*src & *dest) | *pat) ^ *src), 0xc1); -ROP3_HANDLERS(SPDSonoxn, ~((~(*src | *dest) | *pat) ^ *src), 0xc2); -ROP3_HANDLERS(SPDnoa, (~*dest | *pat) & *src, 0xc4); -ROP3_HANDLERS(SPDSxoxn, ~(((*src ^ *dest) | *pat) ^ *src), 0xc5); -ROP3_HANDLERS(SDPnax, (~*pat & *dest) ^ *src, 0xc6); -ROP3_HANDLERS(PSDPoaxn, ~(((*pat | *dest) & *src) ^ *pat), 0xc7); -ROP3_HANDLERS(SDPoa, (*pat | *dest) & *src, 0xc8); -ROP3_HANDLERS(SPDoxn, ~((*dest | *pat) ^ *src), 0xc9); -ROP3_HANDLERS(DPSDxax, ((*dest ^ *src) & *pat) ^ *dest, 0xca); -ROP3_HANDLERS(SPDSaoxn, ~(((*src & *dest) | *pat) ^ *src), 0xcb); -ROP3_HANDLERS(SDPono, ~(*pat | *dest) | *src, 0xcd); -ROP3_HANDLERS(SDPnao, (~*pat & *dest) | *src, 0xce); -ROP3_HANDLERS(PSDnoa, (~*dest | *src) & *pat, 0xd0); -ROP3_HANDLERS(PSDPxoxn, ~(((*pat ^ *dest) | *src) ^ *pat), 0xd1); -ROP3_HANDLERS(PDSnax, (~*src & *dest) ^ *pat, 0xd2); -ROP3_HANDLERS(SPDSoaxn, ~(((*src | *dest) & *pat) ^ *src), 0xd3); -ROP3_HANDLERS(SSPxPDxax, ((*dest ^ *pat) & (*pat ^ *src)) ^ *src, 0xd4); -ROP3_HANDLERS(DPSanan, ~(~(*src & *pat) & *dest), 0xd5); -ROP3_HANDLERS(PSDPSaoxx, ((*src & *pat) | *dest) ^ *src ^ *pat, 0xd6); -ROP3_HANDLERS(DPSxan, ~((*src ^ *pat) & *dest), 0xd7); -ROP3_HANDLERS(PDSPxax, ((*pat ^ *src) & *dest) ^ *pat, 0xd8); -ROP3_HANDLERS(SDPSaoxn, ~(((*src & *pat) | *dest) ^ *src), 0xd9); -ROP3_HANDLERS(DPSDanax, (~(*dest & *src) & *pat) ^ *dest, 0xda); -ROP3_HANDLERS(SPxDSxan, ~((*src ^ *dest) & (*pat ^ *src)), 0xdb); -ROP3_HANDLERS(SPDnao, (~*dest & *pat) | *src, 0xdc); -ROP3_HANDLERS(SDPxo, (*pat ^ *dest) | *src, 0xde); -ROP3_HANDLERS(SDPano, ~(*pat & *dest) | *src, 0xdf); -ROP3_HANDLERS(PDSoa, (*src | *dest) & *pat, 0xe0); -ROP3_HANDLERS(PDSoxn, ~((*src | *dest) ^ *pat), 0xe1); -ROP3_HANDLERS(DSPDxax, ((*dest ^ *pat) & *src) ^ *dest, 0xe2); -ROP3_HANDLERS(PSDPaoxn, ~(((*pat & *dest) | *src) ^ *pat), 0xe3); -ROP3_HANDLERS(SDPSxax, ((*src ^ *pat) & *dest) ^ *src, 0xe4); -ROP3_HANDLERS(PDSPaoxn, ~(((*pat & *src) | *dest) ^ *pat), 0xe5); -ROP3_HANDLERS(SDPSanax, (~(*src & *pat) & *dest) ^ *src, 0xe6); -ROP3_HANDLERS(SPxPDxan, ~((*dest ^ *pat) & (*pat ^ *src)), 0xe7); -ROP3_HANDLERS(SSPxDSxax, ((*src ^ *dest) & (*pat ^ *src)) ^ *src, 0xe8); -ROP3_HANDLERS(DSPDSanaxxn, ~((~(*src & *dest) & *pat) ^ *src ^ *dest), 0xe9); -ROP3_HANDLERS(DPSao, (*src & *pat) | *dest, 0xea); -ROP3_HANDLERS(DPSxno, ~(*src ^ *pat) | *dest, 0xeb); -ROP3_HANDLERS(SDPao, (*pat & *dest) | *src, 0xec); -ROP3_HANDLERS(SDPxno, ~(*pat ^ *dest) | *src, 0xed); -ROP3_HANDLERS(SDPnoo, ~*pat | *dest | *src, 0xef); -ROP3_HANDLERS(PDSono, ~(*src | *dest) | *pat, 0xf1); -ROP3_HANDLERS(PDSnao, (~*src & *dest) | *pat, 0xf2); -ROP3_HANDLERS(PSDnao, (~*dest & *src) | *pat, 0xf4); -ROP3_HANDLERS(PDSxo, (*src ^ *dest) | *pat, 0xf6); -ROP3_HANDLERS(PDSano, ~(*src & *dest) | *pat, 0xf7); -ROP3_HANDLERS(PDSao, (*src & *dest) | *pat, 0xf8); -ROP3_HANDLERS(PDSxno, ~(*src ^ *dest) | *pat, 0xf9); -ROP3_HANDLERS(DPSnoo, ~*src | *pat | *dest, 0xfb); -ROP3_HANDLERS(PSDnoo, ~*dest | *src | *pat, 0xfd); -ROP3_HANDLERS(DPSoo, *src | *pat | *dest, 0xfe); - - -#define ROP3_FILL_HANDLERS(op, index) \ - rop3_with_pattern_handlers_32[index] = rop3_handle_p32_##op; \ - rop3_with_pattern_handlers_16[index] = rop3_handle_p16_##op; \ - rop3_with_color_handlers_32[index] = rop3_handle_c32_##op; \ - rop3_with_color_handlers_16[index] = rop3_handle_c16_##op; \ - rop3_test_handlers_32[index] = rop3_test32_##op; \ - rop3_test_handlers_16[index] = rop3_test16_##op; - -void rop3_init(void) -{ - static int need_init = 1; - int i; - - if (!need_init) { - return; - } - need_init = 0; - - for (i = 0; i < ROP3_NUM_OPS; i++) { - rop3_with_pattern_handlers_32[i] = default_rop3_with_pattern_handler; - rop3_with_pattern_handlers_16[i] = default_rop3_with_pattern_handler; - rop3_with_color_handlers_32[i] = default_rop3_withe_color_handler; - rop3_with_color_handlers_16[i] = default_rop3_withe_color_handler; - rop3_test_handlers_32[i] = default_rop3_test_handler; - rop3_test_handlers_16[i] = default_rop3_test_handler; - } - - ROP3_FILL_HANDLERS(DPSoon, 0x01); - ROP3_FILL_HANDLERS(DPSona, 0x02); - ROP3_FILL_HANDLERS(SDPona, 0x04); - ROP3_FILL_HANDLERS(PDSxnon, 0x06); - ROP3_FILL_HANDLERS(PDSaon, 0x07); - ROP3_FILL_HANDLERS(SDPnaa, 0x08); - ROP3_FILL_HANDLERS(PDSxon, 0x09); - ROP3_FILL_HANDLERS(PSDnaon, 0x0b); - ROP3_FILL_HANDLERS(PDSnaon, 0x0d); - ROP3_FILL_HANDLERS(PDSonon, 0x0e); - ROP3_FILL_HANDLERS(PDSona, 0x10); - ROP3_FILL_HANDLERS(SDPxnon, 0x12); - ROP3_FILL_HANDLERS(SDPaon, 0x13); - ROP3_FILL_HANDLERS(DPSxnon, 0x14); - ROP3_FILL_HANDLERS(DPSaon, 0x15); - ROP3_FILL_HANDLERS(PSDPSanaxx, 0x16); - ROP3_FILL_HANDLERS(SSPxDSxaxn, 0x17); - ROP3_FILL_HANDLERS(SPxPDxa, 0x18); - ROP3_FILL_HANDLERS(SDPSanaxn, 0x19); - ROP3_FILL_HANDLERS(PDSPaox, 0x1a); - ROP3_FILL_HANDLERS(SDPSxaxn, 0x1b); - ROP3_FILL_HANDLERS(PSDPaox, 0x1c); - ROP3_FILL_HANDLERS(DSPDxaxn, 0x1d); - ROP3_FILL_HANDLERS(PDSox, 0x1e); - ROP3_FILL_HANDLERS(PDSoan, 0x1f); - ROP3_FILL_HANDLERS(DPSnaa, 0x20); - ROP3_FILL_HANDLERS(SDPxon, 0x21); - ROP3_FILL_HANDLERS(SPDnaon, 0x23); - ROP3_FILL_HANDLERS(SPxDSxa, 0x24); - ROP3_FILL_HANDLERS(PDSPanaxn, 0x25); - ROP3_FILL_HANDLERS(SDPSaox, 0x26); - ROP3_FILL_HANDLERS(SDPSxnox, 0x27); - ROP3_FILL_HANDLERS(DPSxa, 0x28); - ROP3_FILL_HANDLERS(PSDPSaoxxn, 0x29); - ROP3_FILL_HANDLERS(DPSana, 0x2a); - ROP3_FILL_HANDLERS(SSPxPDxaxn, 0x2b); - ROP3_FILL_HANDLERS(SPDSoax, 0x2c); - ROP3_FILL_HANDLERS(PSDnox, 0x2d); - ROP3_FILL_HANDLERS(PSDPxox, 0x2e); - ROP3_FILL_HANDLERS(PSDnoan, 0x2f); - ROP3_FILL_HANDLERS(SDPnaon, 0x31); - ROP3_FILL_HANDLERS(SDPSoox, 0x32); - ROP3_FILL_HANDLERS(SPDSaox, 0x34); - ROP3_FILL_HANDLERS(SPDSxnox, 0x35); - ROP3_FILL_HANDLERS(SDPox, 0x36); - ROP3_FILL_HANDLERS(SDPoan, 0x37); - ROP3_FILL_HANDLERS(PSDPoax, 0x38); - ROP3_FILL_HANDLERS(SPDnox, 0x39); - ROP3_FILL_HANDLERS(SPDSxox, 0x3a); - ROP3_FILL_HANDLERS(SPDnoan, 0x3b); - ROP3_FILL_HANDLERS(SPDSonox, 0x3d); - ROP3_FILL_HANDLERS(SPDSnaox, 0x3e); - ROP3_FILL_HANDLERS(PSDnaa, 0x40); - ROP3_FILL_HANDLERS(DPSxon, 0x41); - ROP3_FILL_HANDLERS(SDxPDxa, 0x42); - ROP3_FILL_HANDLERS(SPDSanaxn, 0x43); - ROP3_FILL_HANDLERS(DPSnaon, 0x45); - ROP3_FILL_HANDLERS(DSPDaox, 0x46); - ROP3_FILL_HANDLERS(PSDPxaxn, 0x47); - ROP3_FILL_HANDLERS(SDPxa, 0x48); - ROP3_FILL_HANDLERS(PDSPDaoxxn, 0x49); - ROP3_FILL_HANDLERS(DPSDoax, 0x4a); - ROP3_FILL_HANDLERS(PDSnox, 0x4b); - ROP3_FILL_HANDLERS(SDPana, 0x4c); - ROP3_FILL_HANDLERS(SSPxDSxoxn, 0x4d); - ROP3_FILL_HANDLERS(PDSPxox, 0x4e); - ROP3_FILL_HANDLERS(PDSnoan, 0x4f); - ROP3_FILL_HANDLERS(DSPnaon, 0x51); - ROP3_FILL_HANDLERS(DPSDaox, 0x52); - ROP3_FILL_HANDLERS(SPDSxaxn, 0x53); - ROP3_FILL_HANDLERS(DPSonon, 0x54); - ROP3_FILL_HANDLERS(DPSox, 0x56); - ROP3_FILL_HANDLERS(DPSoan, 0x57); - ROP3_FILL_HANDLERS(PDSPoax, 0x58); - ROP3_FILL_HANDLERS(DPSnox, 0x59); - ROP3_FILL_HANDLERS(DPSDonox, 0x5b); - ROP3_FILL_HANDLERS(DPSDxox, 0x5c); - ROP3_FILL_HANDLERS(DPSnoan, 0x5d); - ROP3_FILL_HANDLERS(DPSDnaox, 0x5e); - ROP3_FILL_HANDLERS(PDSxa, 0x60); - ROP3_FILL_HANDLERS(DSPDSaoxxn, 0x61); - ROP3_FILL_HANDLERS(DSPDoax, 0x62); - ROP3_FILL_HANDLERS(SDPnox, 0x63); - ROP3_FILL_HANDLERS(SDPSoax, 0x64); - ROP3_FILL_HANDLERS(DSPnox, 0x65); - ROP3_FILL_HANDLERS(SDPSonox, 0x67); - ROP3_FILL_HANDLERS(DSPDSonoxxn, 0x68); - ROP3_FILL_HANDLERS(PDSxxn, 0x69); - ROP3_FILL_HANDLERS(DPSax, 0x6a); - ROP3_FILL_HANDLERS(PSDPSoaxxn, 0x6b); - ROP3_FILL_HANDLERS(SDPax, 0x6c); - ROP3_FILL_HANDLERS(PDSPDoaxxn, 0x6d); - ROP3_FILL_HANDLERS(SDPSnoax, 0x6e); - ROP3_FILL_HANDLERS(PDSxnan, 0x6f); - ROP3_FILL_HANDLERS(PDSana, 0x70); - ROP3_FILL_HANDLERS(SSDxPDxaxn, 0x71); - ROP3_FILL_HANDLERS(SDPSxox, 0x72); - ROP3_FILL_HANDLERS(SDPnoan, 0x73); - ROP3_FILL_HANDLERS(DSPDxox, 0x74); - ROP3_FILL_HANDLERS(DSPnoan, 0x75); - ROP3_FILL_HANDLERS(SDPSnaox, 0x76); - ROP3_FILL_HANDLERS(PDSax, 0x78); - ROP3_FILL_HANDLERS(DSPDSoaxxn, 0x79); - ROP3_FILL_HANDLERS(DPSDnoax, 0x7a); - ROP3_FILL_HANDLERS(SDPxnan, 0x7b); - ROP3_FILL_HANDLERS(SPDSnoax, 0x7c); - ROP3_FILL_HANDLERS(DPSxnan, 0x7d); - ROP3_FILL_HANDLERS(SPxDSxo, 0x7e); - ROP3_FILL_HANDLERS(DPSaan, 0x7f); - ROP3_FILL_HANDLERS(DPSaa, 0x80); - ROP3_FILL_HANDLERS(SPxDSxon, 0x81); - ROP3_FILL_HANDLERS(DPSxna, 0x82); - ROP3_FILL_HANDLERS(SPDSnoaxn, 0x83); - ROP3_FILL_HANDLERS(SDPxna, 0x84); - ROP3_FILL_HANDLERS(PDSPnoaxn, 0x85); - ROP3_FILL_HANDLERS(DSPDSoaxx, 0x86); - ROP3_FILL_HANDLERS(PDSaxn, 0x87); - ROP3_FILL_HANDLERS(SDPSnaoxn, 0x89); - ROP3_FILL_HANDLERS(DSPnoa, 0x8a); - ROP3_FILL_HANDLERS(DSPDxoxn, 0x8b); - ROP3_FILL_HANDLERS(SDPnoa, 0x8c); - ROP3_FILL_HANDLERS(SDPSxoxn, 0x8d); - ROP3_FILL_HANDLERS(SSDxPDxax, 0x8e); - ROP3_FILL_HANDLERS(PDSanan, 0x8f); - ROP3_FILL_HANDLERS(PDSxna, 0x90); - ROP3_FILL_HANDLERS(SDPSnoaxn, 0x91); - ROP3_FILL_HANDLERS(DPSDPoaxx, 0x92); - ROP3_FILL_HANDLERS(SPDaxn, 0x93); - ROP3_FILL_HANDLERS(PSDPSoaxx, 0x94); - ROP3_FILL_HANDLERS(DPSaxn, 0x95); - ROP3_FILL_HANDLERS(DPSxx, 0x96); - ROP3_FILL_HANDLERS(PSDPSonoxx, 0x97); - ROP3_FILL_HANDLERS(SDPSonoxn, 0x98); - ROP3_FILL_HANDLERS(DPSnax, 0x9a); - ROP3_FILL_HANDLERS(SDPSoaxn, 0x9b); - ROP3_FILL_HANDLERS(SPDnax, 0x9c); - ROP3_FILL_HANDLERS(DSPDoaxn, 0x9d); - ROP3_FILL_HANDLERS(DSPDSaoxx, 0x9e); - ROP3_FILL_HANDLERS(PDSxan, 0x9f); - ROP3_FILL_HANDLERS(PDSPnaoxn, 0xa1); - ROP3_FILL_HANDLERS(DPSnoa, 0xa2); - ROP3_FILL_HANDLERS(DPSDxoxn, 0xa3); - ROP3_FILL_HANDLERS(PDSPonoxn, 0xa4); - ROP3_FILL_HANDLERS(DSPnax, 0xa6); - ROP3_FILL_HANDLERS(PDSPoaxn, 0xa7); - ROP3_FILL_HANDLERS(DPSoa, 0xa8); - ROP3_FILL_HANDLERS(DPSoxn, 0xa9); - ROP3_FILL_HANDLERS(DPSono, 0xab); - ROP3_FILL_HANDLERS(SPDSxax, 0xac); - ROP3_FILL_HANDLERS(DPSDaoxn, 0xad); - ROP3_FILL_HANDLERS(DSPnao, 0xae); - ROP3_FILL_HANDLERS(PDSnoa, 0xb0); - ROP3_FILL_HANDLERS(PDSPxoxn, 0xb1); - ROP3_FILL_HANDLERS(SSPxDSxox, 0xb2); - ROP3_FILL_HANDLERS(SDPanan, 0xb3); - ROP3_FILL_HANDLERS(PSDnax, 0xb4); - ROP3_FILL_HANDLERS(DPSDoaxn, 0xb5); - ROP3_FILL_HANDLERS(DPSDPaoxx, 0xb6); - ROP3_FILL_HANDLERS(SDPxan, 0xb7); - ROP3_FILL_HANDLERS(PSDPxax, 0xb8); - ROP3_FILL_HANDLERS(DSPDaoxn, 0xb9); - ROP3_FILL_HANDLERS(DPSnao, 0xba); - ROP3_FILL_HANDLERS(SPDSanax, 0xbc); - ROP3_FILL_HANDLERS(SDxPDxan, 0xbd); - ROP3_FILL_HANDLERS(DPSxo, 0xbe); - ROP3_FILL_HANDLERS(DPSano, 0xbf); - ROP3_FILL_HANDLERS(SPDSnaoxn, 0xc1); - ROP3_FILL_HANDLERS(SPDSonoxn, 0xc2); - ROP3_FILL_HANDLERS(SPDnoa, 0xc4); - ROP3_FILL_HANDLERS(SPDSxoxn, 0xc5); - ROP3_FILL_HANDLERS(SDPnax, 0xc6); - ROP3_FILL_HANDLERS(PSDPoaxn, 0xc7); - ROP3_FILL_HANDLERS(SDPoa, 0xc8); - ROP3_FILL_HANDLERS(SPDoxn, 0xc9); - ROP3_FILL_HANDLERS(DPSDxax, 0xca); - ROP3_FILL_HANDLERS(SPDSaoxn, 0xcb); - ROP3_FILL_HANDLERS(SDPono, 0xcd); - ROP3_FILL_HANDLERS(SDPnao, 0xce); - ROP3_FILL_HANDLERS(PSDnoa, 0xd0); - ROP3_FILL_HANDLERS(PSDPxoxn, 0xd1); - ROP3_FILL_HANDLERS(PDSnax, 0xd2); - ROP3_FILL_HANDLERS(SPDSoaxn, 0xd3); - ROP3_FILL_HANDLERS(SSPxPDxax, 0xd4); - ROP3_FILL_HANDLERS(DPSanan, 0xd5); - ROP3_FILL_HANDLERS(PSDPSaoxx, 0xd6); - ROP3_FILL_HANDLERS(DPSxan, 0xd7); - ROP3_FILL_HANDLERS(PDSPxax, 0xd8); - ROP3_FILL_HANDLERS(SDPSaoxn, 0xd9); - ROP3_FILL_HANDLERS(DPSDanax, 0xda); - ROP3_FILL_HANDLERS(SPxDSxan, 0xdb); - ROP3_FILL_HANDLERS(SPDnao, 0xdc); - ROP3_FILL_HANDLERS(SDPxo, 0xde); - ROP3_FILL_HANDLERS(SDPano, 0xdf); - ROP3_FILL_HANDLERS(PDSoa, 0xe0); - ROP3_FILL_HANDLERS(PDSoxn, 0xe1); - ROP3_FILL_HANDLERS(DSPDxax, 0xe2); - ROP3_FILL_HANDLERS(PSDPaoxn, 0xe3); - ROP3_FILL_HANDLERS(SDPSxax, 0xe4); - ROP3_FILL_HANDLERS(PDSPaoxn, 0xe5); - ROP3_FILL_HANDLERS(SDPSanax, 0xe6); - ROP3_FILL_HANDLERS(SPxPDxan, 0xe7); - ROP3_FILL_HANDLERS(SSPxDSxax, 0xe8); - ROP3_FILL_HANDLERS(DSPDSanaxxn, 0xe9); - ROP3_FILL_HANDLERS(DPSao, 0xea); - ROP3_FILL_HANDLERS(DPSxno, 0xeb); - ROP3_FILL_HANDLERS(SDPao, 0xec); - ROP3_FILL_HANDLERS(SDPxno, 0xed); - ROP3_FILL_HANDLERS(SDPnoo, 0xef); - ROP3_FILL_HANDLERS(PDSono, 0xf1); - ROP3_FILL_HANDLERS(PDSnao, 0xf2); - ROP3_FILL_HANDLERS(PSDnao, 0xf4); - ROP3_FILL_HANDLERS(PDSxo, 0xf6); - ROP3_FILL_HANDLERS(PDSano, 0xf7); - ROP3_FILL_HANDLERS(PDSao, 0xf8); - ROP3_FILL_HANDLERS(PDSxno, 0xf9); - ROP3_FILL_HANDLERS(DPSnoo, 0xfb); - ROP3_FILL_HANDLERS(PSDnoo, 0xfd); - ROP3_FILL_HANDLERS(DPSoo, 0xfe); - - for (i = 0; i < ROP3_NUM_OPS; i++) { - rop3_test_handlers_32[i](); - rop3_test_handlers_16[i](); - } -} - -void do_rop3_with_pattern(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, - pixman_image_t *p, SpicePoint *pat_pos) -{ - int bpp; - - bpp = spice_pixman_image_get_bpp(d); - ASSERT (bpp == spice_pixman_image_get_bpp(s)); - ASSERT (bpp == spice_pixman_image_get_bpp(p)); - - if (bpp == 32) { - rop3_with_pattern_handlers_32[rop3](d, s, src_pos, p, pat_pos); - } else { - rop3_with_pattern_handlers_16[rop3](d, s, src_pos, p, pat_pos); - } -} - -void do_rop3_with_color(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, - uint32_t rgb) -{ - int bpp; - - bpp = spice_pixman_image_get_bpp(d); - ASSERT (bpp == spice_pixman_image_get_bpp(s)); - - if (bpp == 32) { - rop3_with_color_handlers_32[rop3](d, s, src_pos, rgb); - } else { - rop3_with_color_handlers_16[rop3](d, s, src_pos, rgb); - } -} diff --git a/common/rop3.h b/common/rop3.h deleted file mode 100644 index 91c9207e..00000000 --- a/common/rop3.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H_ROP3 -#define _H_ROP3 - -#include <stdint.h> - -#include "draw.h" -#include "pixman_utils.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void do_rop3_with_pattern(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, - pixman_image_t *p, SpicePoint *pat_pos); -void do_rop3_with_color(uint8_t rop3, pixman_image_t *d, pixman_image_t *s, SpicePoint *src_pos, - uint32_t rgb); - -void rop3_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/spice_common.h b/common/spice_common.h deleted file mode 100644 index 434b179a..00000000 --- a/common/spice_common.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef H_SPICE_COMMON -#define H_SPICE_COMMON - -#include <stdio.h> -#include <stdint.h> -#include <time.h> -#include <stdlib.h> -#include "backtrace.h" - -#define ASSERT(x) if (!(x)) { \ - printf("%s: ASSERT %s failed\n", __FUNCTION__, #x); \ - spice_backtrace(); \ - abort(); \ -} - -#define PANIC(format, ...) do { \ - printf("%s: panic: " format "\n", __FUNCTION__, ## __VA_ARGS__ ); \ - abort(); \ -} while (0) - -#define PANIC_ON(x) if ((x)) { \ - printf("%s: panic %s\n", __FUNCTION__, #x); \ - abort(); \ -} - -#define red_error(format, ...) do { \ - printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__ ); \ - abort(); \ -} while (0) -#define red_printf(format, ...) \ - printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__ ) - -#define red_printf_once(format, ...) do { \ - static int do_print = TRUE; \ - if (do_print) { \ - do_print = FALSE; \ - printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__ ); \ - } \ -} while (0) - -#define WARN(format, ...) red_printf("warning: "format, ##__VA_ARGS__ ); -#define WARN_ONCE red_printf_once - -#define red_printf_some(every, format, ...) do { \ - static int count = 0; \ - if (count++ % (every) == 0) { \ - printf("%s: " format "\n", __FUNCTION__, ## __VA_ARGS__ ); \ - } \ -} while (0) - -#define red_printf_debug(debug, prefix, format, ...) do { \ - static int debug_level = -1; \ - if (debug_level == -1) { \ - debug_level = getenv("SPICE_DEBUG_LEVEL") != NULL ? atoi(getenv("SPICE_DEBUG_LEVEL")) : 0; \ - } \ - if (debug <= debug_level) { \ - printf("%s: %s: " format "\n", prefix, __FUNCTION__, ## __VA_ARGS__ ); \ - } \ -} while(0) - -#endif diff --git a/common/ssl_verify.c b/common/ssl_verify.c deleted file mode 100644 index 603d0f39..00000000 --- a/common/ssl_verify.c +++ /dev/null @@ -1,482 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2011 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "mem.h" -#include "ssl_verify.h" - -#ifndef WIN32 -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#endif -#include <ctype.h> - -#ifndef SPICE_DEBUG -# define SPICE_DEBUG(format, ...) -#endif - -#ifdef WIN32 -static int inet_aton(const char* ip, struct in_addr* in_addr) -{ - unsigned long addr = inet_addr(ip); - - if (addr == INADDR_NONE) { - return 0; - } - in_addr->S_un.S_addr = addr; - return 1; -} -#endif - -static int verify_pubkey(X509* cert, const char *key, size_t key_size) -{ - EVP_PKEY* cert_pubkey = NULL; - EVP_PKEY* orig_pubkey = NULL; - BIO* bio = NULL; - int ret = 0; - - if (!key || key_size == 0) - return 0; - - if (!cert) { - SPICE_DEBUG("warning: no cert!"); - return 0; - } - - cert_pubkey = X509_get_pubkey(cert); - if (!cert_pubkey) { - SPICE_DEBUG("warning: reading public key from certificate failed"); - goto finish; - } - - bio = BIO_new_mem_buf((void*)key, key_size); - if (!bio) { - SPICE_DEBUG("creating BIO failed"); - goto finish; - } - - orig_pubkey = d2i_PUBKEY_bio(bio, NULL); - if (!orig_pubkey) { - SPICE_DEBUG("reading pubkey from bio failed"); - goto finish; - } - - ret = EVP_PKEY_cmp(orig_pubkey, cert_pubkey); - - if (ret == 1) - SPICE_DEBUG("public keys match"); - else if (ret == 0) - SPICE_DEBUG("public keys mismatch"); - else - SPICE_DEBUG("public keys types mismatch"); - -finish: - if (bio) - BIO_free(bio); - - if (orig_pubkey) - EVP_PKEY_free(orig_pubkey); - - if (cert_pubkey) - EVP_PKEY_free(cert_pubkey); - - return ret; -} - -/* from gnutls - * compare hostname against certificate, taking account of wildcards - * return 1 on success or 0 on error - * - * note: certnamesize is required as X509 certs can contain embedded NULs in - * the strings such as CN or subjectAltName - */ -static int _gnutls_hostname_compare(const char *certname, - size_t certnamesize, const char *hostname) -{ - /* find the first different character */ - for (; *certname && *hostname && toupper (*certname) == toupper (*hostname); - certname++, hostname++, certnamesize--) - ; - - /* the strings are the same */ - if (certnamesize == 0 && *hostname == '\0') - return 1; - - if (*certname == '*') - { - /* a wildcard certificate */ - - certname++; - certnamesize--; - - while (1) - { - /* Use a recursive call to allow multiple wildcards */ - if (_gnutls_hostname_compare (certname, certnamesize, hostname)) - return 1; - - /* wildcards are only allowed to match a single domain - component or component fragment */ - if (*hostname == '\0' || *hostname == '.') - break; - hostname++; - } - - return 0; - } - - return 0; -} - -/** - * From gnutls and spice red_peer.c - * TODO: switch to gnutls and get rid of this - * - * This function will check if the given certificate's subject matches - * the given hostname. This is a basic implementation of the matching - * described in RFC2818 (HTTPS), which takes into account wildcards, - * and the DNSName/IPAddress subject alternative name PKIX extension. - * - * Returns: 1 for a successful match, and 0 on failure. - **/ -static int verify_hostname(X509* cert, const char *hostname) -{ - GENERAL_NAMES* subject_alt_names; - int found_dns_name = 0; - struct in_addr addr; - int addr_len = 0; - int cn_match = 0; - X509_NAME* subject; - - if (!cert) { - SPICE_DEBUG("warning: no cert!"); - return 0; - } - - // only IpV4 supported - if (inet_aton(hostname, &addr)) { - addr_len = sizeof(struct in_addr); - } - - /* try matching against: - * 1) a DNS name as an alternative name (subjectAltName) extension - * in the certificate - * 2) the common name (CN) in the certificate - * - * either of these may be of the form: *.domain.tld - * - * only try (2) if there is no subjectAltName extension of - * type dNSName - */ - - /* Check through all included subjectAltName extensions, comparing - * against all those of type dNSName. - */ - subject_alt_names = (GENERAL_NAMES*)X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); - - if (subject_alt_names) { - int num_alts = sk_GENERAL_NAME_num(subject_alt_names); - int i; - for (i = 0; i < num_alts; i++) { - const GENERAL_NAME* name = sk_GENERAL_NAME_value(subject_alt_names, i); - if (name->type == GEN_DNS) { - found_dns_name = 1; - if (_gnutls_hostname_compare((char *)ASN1_STRING_data(name->d.dNSName), - ASN1_STRING_length(name->d.dNSName), - hostname)) { - SPICE_DEBUG("alt name match=%s", ASN1_STRING_data(name->d.dNSName)); - GENERAL_NAMES_free(subject_alt_names); - return 1; - } - } else if (name->type == GEN_IPADD) { - int alt_ip_len = ASN1_STRING_length(name->d.iPAddress); - found_dns_name = 1; - if ((addr_len == alt_ip_len)&& - !memcmp(ASN1_STRING_data(name->d.iPAddress), &addr, addr_len)) { - SPICE_DEBUG("alt name IP match=%s", - inet_ntoa(*((struct in_addr*)ASN1_STRING_data(name->d.dNSName)))); - GENERAL_NAMES_free(subject_alt_names); - return 1; - } - } - } - GENERAL_NAMES_free(subject_alt_names); - } - - if (found_dns_name) { - SPICE_DEBUG("warning: SubjectAltName mismatch"); - return 0; - } - - /* extracting commonNames */ - subject = X509_get_subject_name(cert); - if (subject) { - int pos = -1; - X509_NAME_ENTRY* cn_entry; - ASN1_STRING* cn_asn1; - - while ((pos = X509_NAME_get_index_by_NID(subject, NID_commonName, pos)) != -1) { - cn_entry = X509_NAME_get_entry(subject, pos); - if (!cn_entry) { - continue; - } - cn_asn1 = X509_NAME_ENTRY_get_data(cn_entry); - if (!cn_asn1) { - continue; - } - - if (_gnutls_hostname_compare((char*)ASN1_STRING_data(cn_asn1), - ASN1_STRING_length(cn_asn1), - hostname)) { - SPICE_DEBUG("common name match=%s", (char*)ASN1_STRING_data(cn_asn1)); - cn_match = 1; - break; - } - } - } - - if (!cn_match) - SPICE_DEBUG("warning: common name mismatch"); - - return cn_match; -} - -X509_NAME* subject_to_x509_name(const char *subject, int *nentries) -{ - X509_NAME* in_subject; - const char *p; - char *key, *val, *k, *v = NULL; - enum { - KEY, - VALUE - } state; - - key = (char*)alloca(strlen(subject)); - val = (char*)alloca(strlen(subject)); - in_subject = X509_NAME_new(); - - if (!in_subject || !key || !val) { - SPICE_DEBUG("failed to allocate"); - return NULL; - } - - *nentries = 0; - - k = key; - state = KEY; - for (p = subject;; ++p) { - int escape = 0; - if (*p == '\\') { - ++p; - if (*p != '\\' && *p != ',') { - SPICE_DEBUG("Invalid character after \\"); - goto fail; - } - escape = 1; - } - - switch (state) { - case KEY: - if (*p == ' ' && k == key) { - continue; /* skip spaces before key */ - } if (*p == 0) { - if (k == key) /* empty key, ending */ - goto success; - goto fail; - } else if (*p == ',' && !escape) { - goto fail; /* assignment is missing */ - } else if (*p == '=' && !escape) { - state = VALUE; - *k = 0; - v = val; - } else - *k++ = *p; - break; - case VALUE: - if (*p == 0 || (*p == ',' && !escape)) { - if (v == val) /* empty value */ - goto fail; - - *v = 0; - - if (!X509_NAME_add_entry_by_txt(in_subject, key, - MBSTRING_UTF8, - (const unsigned char*)val, - -1, -1, 0)) { - SPICE_DEBUG("warning: failed to add entry %s=%s to X509_NAME", - key, val); - goto fail; - } - *nentries += 1; - - if (*p == 0) - goto success; - - state = KEY; - k = key; - } else - *v++ = *p; - break; - } - } - -success: - return in_subject; - -fail: - if (in_subject) - X509_NAME_free(in_subject); - - return NULL; -} - -int verify_subject(X509* cert, SpiceOpenSSLVerify* verify) -{ - X509_NAME *cert_subject = NULL; - int ret; - int in_entries; - - if (!cert) { - SPICE_DEBUG("warning: no cert!"); - return 0; - } - - cert_subject = X509_get_subject_name(cert); - if (!cert_subject) { - SPICE_DEBUG("warning: reading certificate subject failed"); - return 0; - } - - if (!verify->in_subject) { - verify->in_subject = subject_to_x509_name(verify->subject, &in_entries); - if (!verify->in_subject) { - SPICE_DEBUG("warning: no in_subject!"); - return 0; - } - } - - /* Note: this check is redundant with the pre-condition in X509_NAME_cmp */ - if (X509_NAME_entry_count(cert_subject) != in_entries) { - SPICE_DEBUG("subject mismatch: #entries cert=%d, input=%d", - X509_NAME_entry_count(cert_subject), in_entries); - return 0; - } - - ret = X509_NAME_cmp(cert_subject, verify->in_subject); - - if (ret == 0) - SPICE_DEBUG("subjects match"); - else - SPICE_DEBUG("subjects mismatch"); - - return !ret; -} - -static int openssl_verify(int preverify_ok, X509_STORE_CTX *ctx) -{ - int depth; - SpiceOpenSSLVerify *v; - SSL *ssl; - X509* cert; - - ssl = (SSL*)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - v = (SpiceOpenSSLVerify*)SSL_get_app_data(ssl); - - depth = X509_STORE_CTX_get_error_depth(ctx); - if (depth > 0) { - if (!preverify_ok) { - SPICE_DEBUG("openssl verify failed at depth=%d", depth); - v->all_preverify_ok = 0; - return 0; - } else - return 1; - } - - /* depth == 0 */ - cert = X509_STORE_CTX_get_current_cert(ctx); - if (!cert) { - SPICE_DEBUG("failed to get server certificate"); - return 0; - } - - if (v->verifyop & SPICE_SSL_VERIFY_OP_PUBKEY && - verify_pubkey(cert, v->pubkey, v->pubkey_size)) - return 1; - - if (!v->all_preverify_ok || !preverify_ok) - return 0; - - if (v->verifyop & SPICE_SSL_VERIFY_OP_HOSTNAME && - verify_hostname(cert, v->hostname)) - return 1; - - if (v->verifyop & SPICE_SSL_VERIFY_OP_SUBJECT && - verify_subject(cert, v)) - return 1; - - return 0; -} - -SpiceOpenSSLVerify* spice_openssl_verify_new(SSL *ssl, SPICE_SSL_VERIFY_OP verifyop, - const char *hostname, - const char *pubkey, size_t pubkey_size, - const char *subject) -{ - SpiceOpenSSLVerify *v; - - if (!verifyop) - return NULL; - - v = spice_new0(SpiceOpenSSLVerify, 1); - - v->ssl = ssl; - v->verifyop = verifyop; - v->hostname = spice_strdup(hostname); - v->pubkey = (char*)spice_memdup(pubkey, pubkey_size); - v->pubkey_size = pubkey_size; - v->subject = spice_strdup(subject); - - v->all_preverify_ok = 1; - - SSL_set_app_data(ssl, v); - SSL_set_verify(ssl, - SSL_VERIFY_PEER, openssl_verify); - - return v; -} - -void spice_openssl_verify_free(SpiceOpenSSLVerify* verify) -{ - if (!verify) - return; - - free(verify->pubkey); - free(verify->subject); - free(verify->hostname); - - if (verify->in_subject) - X509_NAME_free(verify->in_subject); - - if (verify->ssl) - SSL_set_app_data(verify->ssl, NULL); - free(verify); -} diff --git a/common/ssl_verify.h b/common/ssl_verify.h deleted file mode 100644 index 067762b4..00000000 --- a/common/ssl_verify.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2011 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef SSL_VERIFY_H -#define SSL_VERIFY_H - -#if defined(WIN32) && !defined(__MINGW32__) -#include <windows.h> -#include <wincrypt.h> -#endif - -#include <openssl/rsa.h> -#include <openssl/evp.h> -#include <openssl/x509.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#undef X509_NAME -#include <openssl/x509v3.h> - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - SPICE_SSL_VERIFY_OP_NONE = 0, - SPICE_SSL_VERIFY_OP_PUBKEY = (1 << 0), - SPICE_SSL_VERIFY_OP_HOSTNAME = (1 << 1), - SPICE_SSL_VERIFY_OP_SUBJECT = (1 << 2), -} SPICE_SSL_VERIFY_OP; - -typedef struct { - SSL *ssl; - SPICE_SSL_VERIFY_OP verifyop; - int all_preverify_ok; - char *hostname; - char *pubkey; - size_t pubkey_size; - char *subject; - X509_NAME *in_subject; -} SpiceOpenSSLVerify; - -SpiceOpenSSLVerify* spice_openssl_verify_new(SSL *ssl, SPICE_SSL_VERIFY_OP verifyop, - const char *hostname, - const char *pubkey, size_t pubkey_size, - const char *subject); -void spice_openssl_verify_free(SpiceOpenSSLVerify* verify); - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // SSL_VERIFY_H diff --git a/common/sw_canvas.c b/common/sw_canvas.c deleted file mode 100644 index 8eabc896..00000000 --- a/common/sw_canvas.c +++ /dev/null @@ -1,1327 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ -#ifdef HAVE_CONFIG_H -#ifdef __MINGW32__ -#undef HAVE_STDLIB_H -#endif -#include <config.h> -#endif - -#ifndef SPICE_CANVAS_INTERNAL -#error "This file shouldn't be compiled directly" -#endif - -#include <math.h> -#include "sw_canvas.h" -#define CANVAS_USE_PIXMAN -#define CANVAS_SINGLE_INSTANCE -#include "canvas_base.c" -#include "rect.h" -#include "region.h" -#include "pixman_utils.h" - -typedef struct SwCanvas SwCanvas; - -struct SwCanvas { - CanvasBase base; - uint32_t *private_data; - int private_data_size; - pixman_image_t *image; -}; - -static pixman_image_t *canvas_get_pixman_brush(SwCanvas *canvas, - SpiceBrush *brush) -{ - switch (brush->type) { - case SPICE_BRUSH_TYPE_SOLID: { - uint32_t color = brush->u.color; - pixman_color_t c; - - c.blue = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask; - color >>= canvas->base.color_shift; - c.green = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask; - color >>= canvas->base.color_shift; - c.red = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask; - c.alpha = 0xffff; - - return pixman_image_create_solid_fill(&c); - } - case SPICE_BRUSH_TYPE_PATTERN: { - SwCanvas *surface_canvas; - pixman_image_t* surface; - pixman_transform_t t; - - surface_canvas = (SwCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat); - if (surface_canvas) { - surface = surface_canvas->image; - surface = pixman_image_ref(surface); - } else { - surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE); - } - pixman_transform_init_translate(&t, - pixman_int_to_fixed(-brush->u.pattern.pos.x), - pixman_int_to_fixed(-brush->u.pattern.pos.y)); - pixman_image_set_transform(surface, &t); - pixman_image_set_repeat(surface, PIXMAN_REPEAT_NORMAL); - return surface; - } - case SPICE_BRUSH_TYPE_NONE: - return NULL; - default: - CANVAS_ERROR("invalid brush type"); - } -} - -static pixman_image_t *get_image(SpiceCanvas *canvas) -{ - SwCanvas *sw_canvas = (SwCanvas *)canvas; - - pixman_image_ref(sw_canvas->image); - - return sw_canvas->image; -} - -static void copy_region(SpiceCanvas *spice_canvas, - pixman_region32_t *dest_region, - int dx, int dy) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_box32_t *dest_rects; - int n_rects; - int i, j, end_line; - - dest_rects = pixman_region32_rectangles(dest_region, &n_rects); - - if (dy > 0) { - if (dx >= 0) { - /* south-east: copy x and y in reverse order */ - for (i = n_rects - 1; i >= 0; i--) { - spice_pixman_copy_rect(canvas->image, - dest_rects[i].x1 - dx, dest_rects[i].y1 - dy, - dest_rects[i].x2 - dest_rects[i].x1, - dest_rects[i].y2 - dest_rects[i].y1, - dest_rects[i].x1, dest_rects[i].y1); - } - } else { - /* south-west: Copy y in reverse order, but x in forward order */ - i = n_rects - 1; - - while (i >= 0) { - /* Copy all rects with same y in forward order */ - for (end_line = i - 1; - end_line >= 0 && dest_rects[end_line].y1 == dest_rects[i].y1; - end_line--) { - } - for (j = end_line + 1; j <= i; j++) { - spice_pixman_copy_rect(canvas->image, - dest_rects[j].x1 - dx, dest_rects[j].y1 - dy, - dest_rects[j].x2 - dest_rects[j].x1, - dest_rects[j].y2 - dest_rects[j].y1, - dest_rects[j].x1, dest_rects[j].y1); - } - i = end_line; - } - } - } else { - if (dx > 0) { - /* north-east: copy y in forward order, but x in reverse order */ - i = 0; - - while (i < n_rects) { - /* Copy all rects with same y in reverse order */ - for (end_line = i; - end_line < n_rects && dest_rects[end_line].y1 == dest_rects[i].y1; - end_line++) { - } - for (j = end_line - 1; j >= i; j--) { - spice_pixman_copy_rect(canvas->image, - dest_rects[j].x1 - dx, dest_rects[j].y1 - dy, - dest_rects[j].x2 - dest_rects[j].x1, - dest_rects[j].y2 - dest_rects[j].y1, - dest_rects[j].x1, dest_rects[j].y1); - } - i = end_line; - } - } else { - /* north-west: Copy x and y in forward order */ - for (i = 0; i < n_rects; i++) { - spice_pixman_copy_rect(canvas->image, - dest_rects[i].x1 - dx, dest_rects[i].y1 - dy, - dest_rects[i].x2 - dest_rects[i].x1, - dest_rects[i].y2 - dest_rects[i].y1, - dest_rects[i].x1, dest_rects[i].y1); - } - } - } -} - -static void fill_solid_spans(SpiceCanvas *spice_canvas, - SpicePoint *points, - int *widths, - int n_spans, - uint32_t color) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - int i; - - for (i = 0; i < n_spans; i++) { - spice_pixman_fill_rect(canvas->image, - points[i].x, points[i].y, - widths[i], - 1, - color); - } -} - -static void fill_solid_rects(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - uint32_t color) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - int i; - - for (i = 0; i < n_rects; i++) { - spice_pixman_fill_rect(canvas->image, - rects[i].x1, rects[i].y1, - rects[i].x2 - rects[i].x1, - rects[i].y2 - rects[i].y1, - color); - } -} - -static void fill_solid_rects_rop(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - uint32_t color, - SpiceROP rop) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - int i; - - for (i = 0; i < n_rects; i++) { - spice_pixman_fill_rect_rop(canvas->image, - rects[i].x1, rects[i].y1, - rects[i].x2 - rects[i].x1, - rects[i].y2 - rects[i].y1, - color, rop); - } -} - -static void __fill_tiled_rects(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - pixman_image_t *tile, - int offset_x, int offset_y) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - int i; - - for (i = 0; i < n_rects; i++) { - spice_pixman_tile_rect(canvas->image, - rects[i].x1, rects[i].y1, - rects[i].x2 - rects[i].x1, - rects[i].y2 - rects[i].y1, - tile, offset_x, offset_y); - } -} - -static void fill_tiled_rects(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - pixman_image_t *tile, - int offset_x, int offset_y) -{ - __fill_tiled_rects(spice_canvas, rects, n_rects, tile, offset_x, offset_y); -} - -static void fill_tiled_rects_from_surface(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - SpiceCanvas *surface_canvas, - int offset_x, int offset_y) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __fill_tiled_rects(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x, - offset_y); -} - -static void __fill_tiled_rects_rop(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - pixman_image_t *tile, - int offset_x, int offset_y, - SpiceROP rop) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - int i; - - for (i = 0; i < n_rects; i++) { - spice_pixman_tile_rect_rop(canvas->image, - rects[i].x1, rects[i].y1, - rects[i].x2 - rects[i].x1, - rects[i].y2 - rects[i].y1, - tile, offset_x, offset_y, - rop); - } -} -static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - pixman_image_t *tile, - int offset_x, int offset_y, - SpiceROP rop) -{ - __fill_tiled_rects_rop(spice_canvas, rects, n_rects, tile, offset_x, offset_y, rop); -} - -static void fill_tiled_rects_rop_from_surface(SpiceCanvas *spice_canvas, - pixman_box32_t *rects, - int n_rects, - SpiceCanvas *surface_canvas, - int offset_x, int offset_y, - SpiceROP rop) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __fill_tiled_rects_rop(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x, - offset_y, rop); -} - -/* Some pixman implementations of OP_OVER on xRGB32 sets - the high bit to 0xff (which is the right value if the - destination was ARGB32, and it should be ignored for - xRGB32. However, this fills our alpha bits with - data that is not wanted or expected by windows, and its - causing us to send rgba images rather than rgb images to - the client. So, we manually clear these bytes. */ -static void clear_dest_alpha(pixman_image_t *dest, - int x, int y, - int width, int height) -{ - uint32_t *data; - int stride; - int w, h; - - w = pixman_image_get_width(dest); - h = pixman_image_get_height(dest); - - if (x + width <= 0 || x >= w || - y + height <= 0 || y >= h || - width == 0 || height == 0) { - return; - } - - if (x < 0) { - width += x; - x = 0; - } - if (x + width > w) { - width = w - x; - } - - if (y < 0) { - height += y; - y = 0; - } - if (y + height > h) { - height = h - y; - } - - stride = pixman_image_get_stride(dest); - data = (uint32_t *) ( - (uint8_t *)pixman_image_get_data(dest) + y * stride + 4 * x); - - if ((*data & 0xff000000U) == 0xff000000U) { - spice_pixman_fill_rect_rop(dest, - x, y, width, height, - 0x00ffffff, SPICE_ROP_AND); - } -} - -static void __blit_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_box32_t *rects; - int n_rects, i; - - rects = pixman_region32_rectangles(region, &n_rects); - - for (i = 0; i < n_rects; i++) { - int src_x, src_y, dest_x, dest_y, width, height; - - dest_x = rects[i].x1; - dest_y = rects[i].y1; - width = rects[i].x2 - rects[i].x1; - height = rects[i].y2 - rects[i].y1; - - src_x = rects[i].x1 - offset_x; - src_y = rects[i].y1 - offset_y; - - spice_pixman_blit(canvas->image, - src_image, - src_x, src_y, - dest_x, dest_y, - width, height); - } -} - -static void blit_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y) -{ - __blit_image(spice_canvas, region, src_image, offset_x, offset_y); -} - -static void blit_image_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - SpiceCanvas *surface_canvas, - int offset_x, int offset_y) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __blit_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y); -} - -static void __blit_image_rop(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y, - SpiceROP rop) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_box32_t *rects; - int n_rects, i; - - rects = pixman_region32_rectangles(region, &n_rects); - - for (i = 0; i < n_rects; i++) { - int src_x, src_y, dest_x, dest_y, width, height; - - dest_x = rects[i].x1; - dest_y = rects[i].y1; - width = rects[i].x2 - rects[i].x1; - height = rects[i].y2 - rects[i].y1; - - src_x = rects[i].x1 - offset_x; - src_y = rects[i].y1 - offset_y; - - spice_pixman_blit_rop(canvas->image, - src_image, - src_x, src_y, - dest_x, dest_y, - width, height, rop); - } -} - -static void blit_image_rop(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y, - SpiceROP rop) -{ - __blit_image_rop(spice_canvas, region, src_image, offset_x, offset_y, rop); -} - -static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - SpiceCanvas *surface_canvas, - int offset_x, int offset_y, - SpiceROP rop) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __blit_image_rop(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, rop); -} - - - -static void __scale_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_transform_t transform; - pixman_fixed_t fsx, fsy; - - fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; - fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; - - pixman_image_set_clip_region32(canvas->image, region); - - pixman_transform_init_scale(&transform, fsx, fsy); - pixman_transform_translate(&transform, NULL, - pixman_int_to_fixed (src_x), - pixman_int_to_fixed (src_y)); - - pixman_image_set_transform(src, &transform); - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || - scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); - pixman_image_set_filter(src, - (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ? - PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, - NULL, 0); - - pixman_image_composite32(PIXMAN_OP_SRC, - src, NULL, canvas->image, - 0, 0, /* src */ - 0, 0, /* mask */ - dest_x, dest_y, /* dst */ - dest_width, dest_height); - - pixman_transform_init_identity(&transform); - pixman_image_set_transform(src, &transform); - - pixman_image_set_clip_region32(canvas->image, NULL); -} - -static void scale_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode) -{ - __scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, dest_y, - dest_width,dest_height,scale_mode); -} - -static void scale_image_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - SpiceCanvas *surface_canvas, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width, - src_height, dest_x, dest_y, dest_width,dest_height,scale_mode); -} - -static void __scale_image_rop(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, SpiceROP rop) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_transform_t transform; - pixman_image_t *scaled; - pixman_box32_t *rects; - int n_rects, i; - pixman_fixed_t fsx, fsy; - - fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; - fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; - - scaled = pixman_image_create_bits(spice_pixman_image_get_format(src), - dest_width, - dest_height, - NULL, 0); - - pixman_region32_translate(region, -dest_x, -dest_y); - pixman_image_set_clip_region32(scaled, region); - - pixman_transform_init_scale(&transform, fsx, fsy); - pixman_transform_translate(&transform, NULL, - pixman_int_to_fixed (src_x), - pixman_int_to_fixed (src_y)); - - pixman_image_set_transform(src, &transform); - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || - scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); - pixman_image_set_filter(src, - (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ? - PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, - NULL, 0); - - pixman_image_composite32(PIXMAN_OP_SRC, - src, NULL, scaled, - 0, 0, /* src */ - 0, 0, /* mask */ - 0, 0, /* dst */ - dest_width, - dest_height); - - pixman_transform_init_identity(&transform); - pixman_image_set_transform(src, &transform); - - /* Translate back */ - pixman_region32_translate(region, dest_x, dest_y); - - rects = pixman_region32_rectangles(region, &n_rects); - - for (i = 0; i < n_rects; i++) { - spice_pixman_blit_rop(canvas->image, - scaled, - rects[i].x1 - dest_x, - rects[i].y1 - dest_y, - rects[i].x1, rects[i].y1, - rects[i].x2 - rects[i].x1, - rects[i].y2 - rects[i].y1, - rop); - } - - pixman_image_unref(scaled); -} - -static void scale_image_rop(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, SpiceROP rop) -{ - __scale_image_rop(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, - dest_y, dest_width, dest_height, scale_mode, rop); -} - -static void scale_image_rop_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - SpiceCanvas *surface_canvas, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, SpiceROP rop) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __scale_image_rop(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width, - src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop); -} - -static pixman_image_t *canvas_get_as_surface(SwCanvas *canvas, - int with_alpha) -{ - pixman_image_t *target; - - if (with_alpha && - canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) { - target = pixman_image_create_bits(PIXMAN_a8r8g8b8, - pixman_image_get_width(canvas->image), - pixman_image_get_height(canvas->image), - pixman_image_get_data(canvas->image), - pixman_image_get_stride(canvas->image)); - } else { - target = pixman_image_ref(canvas->image); - } - - return target; -} - -static void __blend_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - int dest_has_alpha, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - int overall_alpha) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_image_t *mask, *dest; - - dest = canvas_get_as_surface(canvas, dest_has_alpha); - - pixman_image_set_clip_region32(dest, region); - - mask = NULL; - if (overall_alpha != 0xff) { - pixman_color_t color = { 0 }; - color.alpha = overall_alpha * 0x101; - mask = pixman_image_create_solid_fill(&color); - } - - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - - pixman_image_composite32(PIXMAN_OP_OVER, - src, mask, dest, - src_x, src_y, /* src */ - 0, 0, /* mask */ - dest_x, dest_y, /* dst */ - width, - height); - - if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB && - !dest_has_alpha) { - clear_dest_alpha(dest, dest_x, dest_y, width, height); - } - - if (mask) { - pixman_image_unref(mask); - } - - pixman_image_set_clip_region32(dest, NULL); - pixman_image_unref(dest); -} - -static void blend_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - int dest_has_alpha, - pixman_image_t *src, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - int overall_alpha) -{ - __blend_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, - dest_x, dest_y, width, height, - overall_alpha); -} - -static void blend_image_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - int dest_has_alpha, - SpiceCanvas *surface_canvas, - int src_has_alpha, - int src_x, int src_y, - int dest_x, int dest_y, - int width, int height, - int overall_alpha) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - pixman_image_t *src; - - src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha); - __blend_image(spice_canvas, region, dest_has_alpha, - src, src_x, src_y, - dest_x, dest_y, - width, height, overall_alpha); - pixman_image_unref(src); -} - -static void __blend_scale_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - int dest_has_alpha, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, - int overall_alpha) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_transform_t transform; - pixman_image_t *mask, *dest; - pixman_fixed_t fsx, fsy; - - fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; - fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; - - dest = canvas_get_as_surface(canvas, dest_has_alpha); - - pixman_image_set_clip_region32(dest, region); - - pixman_transform_init_scale(&transform, fsx, fsy); - pixman_transform_translate(&transform, NULL, - pixman_int_to_fixed (src_x), - pixman_int_to_fixed (src_y)); - - mask = NULL; - if (overall_alpha != 0xff) { - pixman_color_t color = { 0 }; - color.alpha = overall_alpha * 0x101; - mask = pixman_image_create_solid_fill(&color); - } - - pixman_image_set_transform(src, &transform); - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE || - scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST); - pixman_image_set_filter(src, - (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ? - PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD, - NULL, 0); - - pixman_image_composite32(PIXMAN_OP_OVER, - src, mask, dest, - 0, 0, /* src */ - 0, 0, /* mask */ - dest_x, dest_y, /* dst */ - dest_width, dest_height); - - if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB && - !dest_has_alpha) { - clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height); - } - - pixman_transform_init_identity(&transform); - pixman_image_set_transform(src, &transform); - - if (mask) { - pixman_image_unref(mask); - } - - pixman_image_set_clip_region32(dest, NULL); - pixman_image_unref(dest); -} - -static void blend_scale_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - int dest_has_alpha, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, - int overall_alpha) -{ - __blend_scale_image(spice_canvas, region, dest_has_alpha, - src, src_x, src_y, src_width, src_height, - dest_x, dest_y, dest_width, dest_height, - scale_mode, overall_alpha); -} - -static void blend_scale_image_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - int dest_has_alpha, - SpiceCanvas *surface_canvas, - int src_has_alpha, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - int scale_mode, - int overall_alpha) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - pixman_image_t *src; - - src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha); - __blend_scale_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, src_width, - src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, - overall_alpha); - pixman_image_unref(src); -} - -static void __colorkey_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y, - uint32_t transparent_color) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_box32_t *rects; - int n_rects, i; - - rects = pixman_region32_rectangles(region, &n_rects); - - for (i = 0; i < n_rects; i++) { - int src_x, src_y, dest_x, dest_y, width, height; - - dest_x = rects[i].x1; - dest_y = rects[i].y1; - width = rects[i].x2 - rects[i].x1; - height = rects[i].y2 - rects[i].y1; - - src_x = rects[i].x1 - offset_x; - src_y = rects[i].y1 - offset_y; - - spice_pixman_blit_colorkey(canvas->image, - src_image, - src_x, src_y, - dest_x, dest_y, - width, height, - transparent_color); - } -} - -static void colorkey_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src_image, - int offset_x, int offset_y, - uint32_t transparent_color) -{ - __colorkey_image(spice_canvas, region, src_image, offset_x, offset_y, transparent_color); -} - -static void colorkey_image_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - SpiceCanvas *surface_canvas, - int offset_x, int offset_y, - uint32_t transparent_color) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __colorkey_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, - transparent_color); -} - -static void __colorkey_scale_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - uint32_t transparent_color) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_transform_t transform; - pixman_image_t *scaled; - pixman_box32_t *rects; - int n_rects, i; - pixman_fixed_t fsx, fsy; - - fsx = ((pixman_fixed_48_16_t) src_width * 65536) / dest_width; - fsy = ((pixman_fixed_48_16_t) src_height * 65536) / dest_height; - - scaled = pixman_image_create_bits(spice_pixman_image_get_format (src), - dest_width, - dest_height, - NULL, 0); - - pixman_region32_translate(region, -dest_x, -dest_y); - pixman_image_set_clip_region32(scaled, region); - - pixman_transform_init_scale(&transform, fsx, fsy); - pixman_transform_translate(&transform, NULL, - pixman_int_to_fixed (src_x), - pixman_int_to_fixed (src_y)); - - pixman_image_set_transform(src, &transform); - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - pixman_image_set_filter(src, - PIXMAN_FILTER_NEAREST, - NULL, 0); - - pixman_image_composite32(PIXMAN_OP_SRC, - src, NULL, scaled, - 0, 0, /* src */ - 0, 0, /* mask */ - 0, 0, /* dst */ - dest_width, - dest_height); - - pixman_transform_init_identity(&transform); - pixman_image_set_transform(src, &transform); - - /* Translate back */ - pixman_region32_translate(region, dest_x, dest_y); - - rects = pixman_region32_rectangles(region, &n_rects); - - for (i = 0; i < n_rects; i++) { - spice_pixman_blit_colorkey(canvas->image, - scaled, - rects[i].x1 - dest_x, - rects[i].y1 - dest_y, - rects[i].x1, rects[i].y1, - rects[i].x2 - rects[i].x1, - rects[i].y2 - rects[i].y1, - transparent_color); - } - - pixman_image_unref(scaled); -} - -static void colorkey_scale_image(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - pixman_image_t *src, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - uint32_t transparent_color) -{ - __colorkey_scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, - dest_y, dest_width, dest_height, transparent_color); -} - -static void colorkey_scale_image_from_surface(SpiceCanvas *spice_canvas, - pixman_region32_t *region, - SpiceCanvas *surface_canvas, - int src_x, int src_y, - int src_width, int src_height, - int dest_x, int dest_y, - int dest_width, int dest_height, - uint32_t transparent_color) -{ - SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas; - __colorkey_scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, - src_width, src_height, dest_x, dest_y, dest_width, dest_height, - transparent_color); -} - -static void canvas_put_image(SpiceCanvas *spice_canvas, -#ifdef WIN32 - HDC dc, -#endif - const SpiceRect *dest, const uint8_t *src_data, - uint32_t src_width, uint32_t src_height, int src_stride, - const QRegion *clip) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_image_t *src; - uint32_t dest_width; - uint32_t dest_height; - double sx, sy; - pixman_transform_t transform; - - src = pixman_image_create_bits(PIXMAN_x8r8g8b8, - src_width, - src_height, - (uint32_t*)src_data, - src_stride); - - - if (clip) { - pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip); - } - - dest_width = dest->right - dest->left; - dest_height = dest->bottom - dest->top; - - if (dest_width != src_width || dest_height != src_height) { - sx = (double)(src_width) / (dest_width); - sy = (double)(src_height) / (dest_height); - - pixman_transform_init_scale(&transform, - pixman_double_to_fixed(sx), - pixman_double_to_fixed(sy)); - pixman_image_set_transform(src, &transform); - pixman_image_set_filter(src, - PIXMAN_FILTER_NEAREST, - NULL, 0); - } - - pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE); - - pixman_image_composite32(PIXMAN_OP_SRC, - src, NULL, canvas->image, - 0, 0, /* src */ - 0, 0, /* mask */ - dest->left, dest->top, /* dst */ - dest_width, dest_height); - - - if (clip) { - pixman_image_set_clip_region32(canvas->image, NULL); - } - pixman_image_unref(src); -} - - -static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox, - SpiceClip *clip, SpiceText *text) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_region32_t dest_region; - pixman_image_t *str_mask, *brush; - SpiceString *str; - SpicePoint pos; - int depth; - - pixman_region32_init_rect(&dest_region, - bbox->left, bbox->top, - bbox->right - bbox->left, - bbox->bottom - bbox->top); - - canvas_clip_pixman(&canvas->base, &dest_region, clip); - - if (!pixman_region32_not_empty(&dest_region)) { - touch_brush(&canvas->base, &text->fore_brush); - touch_brush(&canvas->base, &text->back_brush); - pixman_region32_fini(&dest_region); - return; - } - - if (!rect_is_empty(&text->back_area)) { - pixman_region32_t back_region; - - /* Nothing else makes sense for text and we should deprecate it - * and actually it means OVER really */ - ASSERT(text->fore_mode == SPICE_ROPD_OP_PUT); - - pixman_region32_init_rect(&back_region, - text->back_area.left, - text->back_area.top, - text->back_area.right - text->back_area.left, - text->back_area.bottom - text->back_area.top); - - pixman_region32_intersect(&back_region, &back_region, &dest_region); - - if (pixman_region32_not_empty(&back_region)) { - draw_brush(spice_canvas, &back_region, &text->back_brush, SPICE_ROP_COPY); - } - - pixman_region32_fini(&back_region); - } - str = (SpiceString *)SPICE_GET_ADDRESS(text->str); - - if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) { - depth = 1; - } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) { - depth = 4; - } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) { - WARN("untested path A8 glyphs"); - depth = 8; - } else { - WARN("unsupported path vector glyphs"); - pixman_region32_fini (&dest_region); - return; - } - - brush = canvas_get_pixman_brush(canvas, &text->fore_brush); - - str_mask = canvas_get_str_mask(&canvas->base, str, depth, &pos); - if (brush) { - pixman_image_set_clip_region32(canvas->image, &dest_region); - - pixman_image_composite32(PIXMAN_OP_OVER, - brush, - str_mask, - canvas->image, - 0, 0, - 0, 0, - pos.x, pos.y, - pixman_image_get_width(str_mask), - pixman_image_get_height(str_mask)); - if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) { - clear_dest_alpha(canvas->image, pos.x, pos.y, - pixman_image_get_width(str_mask), - pixman_image_get_height(str_mask)); - } - pixman_image_unref(brush); - - pixman_image_set_clip_region32(canvas->image, NULL); - } - pixman_image_unref(str_mask); - pixman_region32_fini(&dest_region); -} - -static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest, - int dest_stride, const SpiceRect *area) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - pixman_image_t* surface; - uint8_t *src; - int src_stride; - uint8_t *dest_end; - int bpp; - - ASSERT(canvas && area); - - surface = canvas->image; - - bpp = spice_pixman_image_get_bpp(surface) / 8; - - src_stride = pixman_image_get_stride(surface); - src = (uint8_t *)pixman_image_get_data(surface) + - area->top * src_stride + area->left * bpp; - dest_end = dest + (area->bottom - area->top) * dest_stride; - for (; dest != dest_end; dest += dest_stride, src += src_stride) { - memcpy(dest, src, (area->right - area->left) * bpp); - } -} - -static void canvas_clear(SpiceCanvas *spice_canvas) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - spice_pixman_fill_rect(canvas->image, - 0, 0, - pixman_image_get_width(canvas->image), - pixman_image_get_height(canvas->image), - 0); -} - -static void canvas_destroy(SpiceCanvas *spice_canvas) -{ - SwCanvas *canvas = (SwCanvas *)spice_canvas; - if (!canvas) { - return; - } - pixman_image_unref(canvas->image); - canvas_base_destroy(&canvas->base); - free(canvas->private_data); - free(canvas); -} - -static int need_init = 1; -static SpiceCanvasOps sw_canvas_ops; - -static SpiceCanvas *canvas_create_common(pixman_image_t *image, - uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ) -{ - SwCanvas *canvas; - - if (need_init) { - return NULL; - } - spice_pixman_image_set_format(image, - spice_surface_format_to_pixman (format)); - - canvas = spice_new0(SwCanvas, 1); - canvas_base_init(&canvas->base, &sw_canvas_ops, - pixman_image_get_width (image), - pixman_image_get_height (image), - format -#ifdef SW_CANVAS_CACHE - , bits_cache - , palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , bits_cache -#endif - , surfaces - , glz_decoder - , jpeg_decoder - , zlib_decoder - ); - canvas->private_data = NULL; - canvas->private_data_size = 0; - - canvas->image = image; - - return (SpiceCanvas *)canvas; -} - -SpiceCanvas *canvas_create(int width, int height, uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ) -{ - 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 SW_CANVAS_CACHE - , bits_cache - , palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , bits_cache -#endif - , surfaces - , glz_decoder - , jpeg_decoder - , zlib_decoder - ); -} - -SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, - uint8_t *data, int stride -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ) -{ - 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 SW_CANVAS_CACHE - , bits_cache - , palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , bits_cache -#endif - , surfaces - , glz_decoder - , jpeg_decoder - , zlib_decoder - ); -} - -void sw_canvas_init(void) //unsafe global function -{ - if (!need_init) { - return; - } - need_init = 0; - - canvas_base_init_ops(&sw_canvas_ops); - sw_canvas_ops.draw_text = canvas_draw_text; - sw_canvas_ops.put_image = canvas_put_image; - sw_canvas_ops.clear = canvas_clear; - sw_canvas_ops.read_bits = canvas_read_bits; - sw_canvas_ops.destroy = canvas_destroy; - - sw_canvas_ops.fill_solid_spans = fill_solid_spans; - sw_canvas_ops.fill_solid_rects = fill_solid_rects; - sw_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop; - sw_canvas_ops.fill_tiled_rects = fill_tiled_rects; - sw_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface; - sw_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop; - sw_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface; - sw_canvas_ops.blit_image = blit_image; - sw_canvas_ops.blit_image_from_surface = blit_image_from_surface; - sw_canvas_ops.blit_image_rop = blit_image_rop; - sw_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface; - sw_canvas_ops.scale_image = scale_image; - sw_canvas_ops.scale_image_from_surface = scale_image_from_surface; - sw_canvas_ops.scale_image_rop = scale_image_rop; - sw_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface; - sw_canvas_ops.blend_image = blend_image; - sw_canvas_ops.blend_image_from_surface = blend_image_from_surface; - sw_canvas_ops.blend_scale_image = blend_scale_image; - sw_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface; - sw_canvas_ops.colorkey_image = colorkey_image; - sw_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface; - sw_canvas_ops.colorkey_scale_image = colorkey_scale_image; - sw_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface; - sw_canvas_ops.copy_region = copy_region; - sw_canvas_ops.get_image = get_image; - rop3_init(); -} diff --git a/common/sw_canvas.h b/common/sw_canvas.h deleted file mode 100644 index 8667fccc..00000000 --- a/common/sw_canvas.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - Copyright (C) 2009 Red Hat, Inc. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _H__CANVAS -#define _H__CANVAS - -#ifndef SPICE_CANVAS_INTERNAL -#error "This header shouldn't be included directly" -#endif - -#include <stdint.h> - -#include "draw.h" -#include "pixman_utils.h" -#include "canvas_base.h" -#include "region.h" - -#ifdef __cplusplus -extern "C" { -#endif - -SpiceCanvas *canvas_create(int width, int height, uint32_t format -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ); - -SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, int stride -#ifdef SW_CANVAS_CACHE - , SpiceImageCache *bits_cache - , SpicePaletteCache *palette_cache -#elif defined(SW_CANVAS_IMAGE_CACHE) - , SpiceImageCache *bits_cache -#endif - , SpiceImageSurfaces *surfaces - , SpiceGlzDecoder *glz_decoder - , SpiceJpegDecoder *jpeg_decoder - , SpiceZlibDecoder *zlib_decoder - ); - - -void sw_canvas_init(void); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/common/win/Makefile.am b/common/win/Makefile.am deleted file mode 100644 index 201691ba..00000000 --- a/common/win/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = my_getopt-1.5 diff --git a/common/win/my_getopt-1.5/ChangeLog b/common/win/my_getopt-1.5/ChangeLog deleted file mode 100644 index a671fdb9..00000000 --- a/common/win/my_getopt-1.5/ChangeLog +++ /dev/null @@ -1,22 +0,0 @@ -2006-12-09 Benjamin C. W. Sittler <bsittler@> - - * my_getopt.c: add my_getopt_reset to reset the argument parser - - * README: updated email address, updated for version 1.5 - -2002-07-26 Benjamin C. W. Sittler <bsittler@knownow.com> - - * README: updated for version 1.4 - - * my_getopt.c: now we include <sys/types.h> explicitly for those - systems that narrowly (mis-)interpret ANSI C and POSIX - (_my_getopt_internal): added an explicit cast to size_t to make - g++ happy - - * getopt.h, my_getopt.h: added extern "C" { ... } for C++ - compilation (thanks to Jeff Lawson <bovine@ud.com> and others) - -2001-08-20 Benjamin C. W. Sittler <bsittler@knownow.com> - - * getopt.h (getopt_long_only): fixed typo (thanks to Justin Lee - <justin_lee@ud.com>) diff --git a/common/win/my_getopt-1.5/LICENSE b/common/win/my_getopt-1.5/LICENSE deleted file mode 100644 index 2224aba0..00000000 --- a/common/win/my_getopt-1.5/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -my_getopt - a command-line argument parser -Copyright 1997-2001, Benjamin Sittler - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, copy, -modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/common/win/my_getopt-1.5/Makefile.am b/common/win/my_getopt-1.5/Makefile.am deleted file mode 100644 index 73cbf780..00000000 --- a/common/win/my_getopt-1.5/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -NULL = - -EXTRA_DIST = \ - ChangeLog \ - getopt.3 \ - getopt.h \ - getopt.txt \ - LICENSE \ - main.c \ - Makefile \ - my_getopt.c \ - my_getopt.h \ - README \ - $(NULL) diff --git a/common/win/my_getopt-1.5/Makefile.test b/common/win/my_getopt-1.5/Makefile.test deleted file mode 100644 index 083cc4aa..00000000 --- a/common/win/my_getopt-1.5/Makefile.test +++ /dev/null @@ -1,26 +0,0 @@ -all: copy - -# Compiler options -#CCOPTS = -g -O3 -Wall -Werror -CCOPTS = - -# Compiler -CC = gcc -Wall -Werror -#CC = cc - -# Linker -LD = $(CC) - -# Utility to remove a file -RM = rm - -OBJS = main.o my_getopt.o - -copy: $(OBJS) - $(LD) -o $@ $(OBJS) - -clean: - $(RM) -f copy $(OBJS) *~ - -%.o: %.c getopt.h my_getopt.h - $(CC) $(CCOPTS) -o $@ -c $< diff --git a/common/win/my_getopt-1.5/README b/common/win/my_getopt-1.5/README deleted file mode 100644 index 3a9afad7..00000000 --- a/common/win/my_getopt-1.5/README +++ /dev/null @@ -1,140 +0,0 @@ -my_getopt - a command-line argument parser -Copyright 1997-2006, Benjamin Sittler - -The author can be reached by sending email to <bsittler@gmail.com>. - -The version of my_getopt in this package (1.5) has a BSD-like license; -see the file LICENSE for details. Version 1.0 of my_getopt was similar -to the GPL'ed version of my_getopt included with SMOKE-16 Version 1, -Release 19990717. SMOKE-16 packages are available from: - - http://geocities.com/bsittler/#smoke16 - -OVERVIEW OF THE ARGUMENT PARSER -=============================== - -The getopt(), getopt_long() and getopt_long_only() functions parse -command line arguments. The argc and argv parameters passed to these -functions correspond to the argument count and argument list passed to -your program's main() function at program start-up. Element 0 of the -argument list conventionally contains the name of your program. Any -remaining arguments starting with "-" (except for "-" or "--" by -themselves) are option arguments, some of include option values. This -family of getopt() functions allows intermixed option and non-option -arguments anywhere in the argument list, except that "--" by itself -causes the remaining elements of the argument list to be treated as -non-option arguments. - -[ See the parts of this document labeled "DOCUMENTATION" and - "WHY RE-INVENT THE WHEEL?" for a more information. ] - -FILES -===== - -The following four files constitute the my_getopt package: - - LICENSE - license and warranty information for my_getopt - my_getopt.c - implementation of my getopt replacement - my_getopt.h - interface for my getopt replacement - getopt.h - a header file to make my getopt look like GNU getopt - -USAGE -===== - -To use my_getopt in your application, include the following line to -your main program source: - - #include "getopt.h" - -This line should appear after your standard system header files to -avoid conflicting with your system's built-in getopt. - -Then compile my_getopt.c into my_getopt.o, and link my_getopt.o into -your application: - - $ cc -c my_getopt.c - $ ld -o app app.o ... my_getopt.o - -To avoid conflicting with standard library functions, the function -names and global variables used by my_getopt all begin with `my_'. To -ensure compatibility with existing C programs, the `getopt.h' header -file uses the C preprocessor to redefine names like getopt, optarg, -optind, and so forth to my_getopt, my_optarg, my_optind, etc. - -SAMPLE PROGRAM -============== - -There is also a public-domain sample program: - - main.c - main() for a sample program using my_getopt - Makefile - build script for the sample program (called `copy') - -To build and test the sample program: - - $ make - $ ./copy -help - $ ./copy -version - -The sample program bears a slight resemblance to the UNIX `cat' -utility, but can be used rot13-encode streams, and can redirect output -to a file. - -DOCUMENTATION -============= - -There is not yet any real documentation for my_getopt. For the moment, -use the Linux manual page for getopt. It has its own copyright and -license; view the file `getopt.3' in a text editor for more details. - - getopt.3 - the manual page for GNU getopt - getopt.txt - preformatted copy of the manual page for GNU getopt, - for your convenience - -WHY RE-INVENT THE WHEEL? -======================== - -I re-implemented getopt, getopt_long, and getopt_long_only because -there were noticable bugs in several versions of the GNU -implementations, and because the GNU versions aren't always available -on some systems (*BSD, for example.) Other systems don't include any -sort of standard argument parser (Win32 with Microsoft tools, for -example, has no getopt.) - -These should do all the expected Unix- and GNU-style argument -parsing, including permution, bunching, long options with single or -double dashes (double dashes are required if you use -my_getopt_long,) and optional arguments for both long and short -options. A word with double dashes all by themselves halts argument -parsing. A required long option argument can be in the same word as -the option name, separated by '=', or in the next word. An optional -long option argument must be in the same word as the option name, -separated by '='. - -As with the GNU versions, a '+' prefix to the short option -specification (or the POSIXLY_CORRECT environment variable) disables -permution, a '-' prefix to the short option specification returns 1 -for non-options, ':' after a short option indicates a required -argument, and '::' after a short option specification indicates an -optional argument (which must appear in the same word.) If you'd like -to recieve ':' instead of '?' for missing option arguments, prefix the -short option specification with ':'. - -The original intent was to re-implement the documented behavior of -the GNU versions, but I have found it necessary to emulate some of -the undocumented behavior as well. Some programs depend on it. - -KNOWN BUGS -========== - -The GNU versions support POSIX-style -W "name=value" long -options. Currently, my_getopt does not support these, because I -don't have any documentation on them (other than the fact that they -are enabled by "W;" in the short option specification.) As a -temporary workaround, my_getopt treats "W;" in the short option -string identically to "W:". - -The GNU versions support internationalized/localized -messages. Currently, my_getopt does not. - -There should be re-entrant versions of all these functions so that -multiple threads can parse arguments simultaneously. diff --git a/common/win/my_getopt-1.5/getopt.3 b/common/win/my_getopt-1.5/getopt.3 deleted file mode 100644 index a63fcd82..00000000 --- a/common/win/my_getopt-1.5/getopt.3 +++ /dev/null @@ -1,288 +0,0 @@ -.\" (c) 1993 by Thomas Koenig (ig25@rz.uni-karlsruhe.de) -.\" -.\" Permission is granted to make and distribute verbatim copies of this -.\" manual provided the copyright notice and this permission notice are -.\" preserved on all copies. -.\" -.\" Permission is granted to copy and distribute modified versions of this -.\" manual under the conditions for verbatim copying, provided that the -.\" entire resulting derived work is distributed under the terms of a -.\" permission notice identical to this one -.\" -.\" Since the Linux kernel and libraries are constantly changing, this -.\" manual page may be incorrect or out-of-date. The author(s) assume no -.\" responsibility for errors or omissions, or for damages resulting from -.\" the use of the information contained herein. The author(s) may not -.\" have taken the same level of care in the production of this manual, -.\" which is licensed free of charge, as they might when working -.\" professionally. -.\" -.\" Formatted or processed versions of this manual, if unaccompanied by -.\" the source, must acknowledge the copyright and authors of this work. -.\" License. -.\" Modified Sat Jul 24 19:27:50 1993 by Rik Faith (faith@cs.unc.edu) -.\" Modified Mon Aug 30 22:02:34 1995 by Jim Van Zandt <jrv@vanzandt.mv.com> -.\" longindex is a pointer, has_arg can take 3 values, using consistent -.\" names for optstring and longindex, "\n" in formats fixed. Documenting -.\" opterr and getopt_long_only. Clarified explanations (borrowing heavily -.\" from the source code). -.TH GETOPT 3 "Aug 30, 1995" "GNU" "Linux Programmer's Manual" -.SH NAME -getopt \- Parse command line options -.SH SYNOPSIS -.nf -.B #include <unistd.h> -.sp -.BI "int getopt(int " argc ", char * const " argv[] "," -.BI " const char *" optstring ");" -.sp -.BI "extern char *" optarg ; -.BI "extern int " optind ", " opterr ", " optopt ; -.sp -.B #include <getopt.h> -.sp -.BI "int getopt_long(int " argc ", char * const " argv[] ", -.BI " const char *" optstring , -.BI " const struct option *" longopts ", int *" longindex ");" -.sp -.BI "int getopt_long_only(int " argc ", char * const " argv[] ", -.BI " const char *" optstring , -.BI " const struct option *" longopts ", int *" longindex ");" -.fi -.SH DESCRIPTION -The -.B getopt() -function parses the command line arguments. Its arguments -.I argc -and -.I argv -are the argument count and array as passed to the -.B main() -function on program invocation. -An element of \fIargv\fP that starts with `-' (and is not exactly "-" or "--") -is an option element. The characters of this element -(aside from the initial `-') are option characters. If \fBgetopt()\fP -is called repeatedly, it returns successively each of the option characters -from each of the option elements. -.PP -If \fBgetopt()\fP finds another option character, it returns that -character, updating the external variable \fIoptind\fP and a static -variable \fInextchar\fP so that the next call to \fBgetopt()\fP can -resume the scan with the following option character or -\fIargv\fP-element. -.PP -If there are no more option characters, \fBgetopt()\fP returns -\fBEOF\fP. Then \fIoptind\fP is the index in \fIargv\fP of the first -\fIargv\fP-element that is not an option. -.PP -.I optstring -is a string containing the legitimate option characters. If such a -character is followed by a colon, the option requires an argument, so -\fBgetopt\fP places a pointer to the following text in the same -\fIargv\fP-element, or the text of the following \fIargv\fP-element, in -.IR optarg . -Two colons mean an option takes -an optional arg; if there is text in the current \fIargv\fP-element, -it is returned in \fIoptarg\fP, otherwise \fIoptarg\fP is set to zero. -.PP -By default, \fBgetargs()\fP permutes the contents of \fIargv\fP as it -scans, so that eventually all the non-options are at the end. Two -other modes are also implemented. If the first character of -\fIoptstring\fP is `+' or the environment variable POSIXLY_CORRECT is -set, then option processing stops as soon as a non-option argument is -encountered. If the first character of \fIoptstring\fP is `-', then -each non-option \fIargv\fP-element is handled as if it were the argument of -an option with character code 1. (This is used by programs that were -written to expect options and other \fIargv\fP-elements in any order -and that care about the ordering of the two.) -The special argument `--' forces an end of option-scanning regardless -of the scanning mode. -.PP -If \fBgetopt()\fP does not recognize an option character, it prints an -error message to stderr, stores the character in \fIoptopt\fP, and -returns `?'. The calling program may prevent the error message by -setting \fIopterr\fP to 0. -.PP -The -.B getopt_long() -function works like -.B getopt() -except that it also accepts long options, started out by two dashes. -Long option names may be abbreviated if the abbreviation is -unique or is an exact match for some defined option. A long option -may take a parameter, of the form -.B --arg=param -or -.BR "--arg param" . -.PP -.I longopts -is a pointer to the first element of an array of -.B struct option -declared in -.B <getopt.h> -as -.nf -.sp -.in 10 -struct option { -.in 14 -const char *name; -int has_arg; -int *flag; -int val; -.in 10 -}; -.fi -.PP -The meanings of the different fields are: -.TP -.I name -is the name of the long option. -.TP -.I has_arg -is: -\fBno_argument\fP (or 0) if the option does not take an argument, -\fBrequired_argument\fP (or 1) if the option requires an argument, or -\fBoptional_argument\fP (or 2) if the option takes an optional argument. -.TP -.I flag -specifies how results are returned for a long option. If \fIflag\fP -is \fBNULL\fP, then \fBgetopt_long()\fP returns \fIval\fP. (For -example, the calling program may set \fIval\fP to the equivalent short -option character.) Otherwise, \fBgetopt_long()\fP returns 0, and -\fIflag\fP points to a variable which is set to \fIval\fP if the -option is found, but left unchanged if the option is not found. -.TP -\fIval\fP -is the value to return, or to load into the variable pointed -to by \fIflag\fP. -.PP -The last element of the array has to be filled with zeroes. -.PP -If \fIlongindex\fP is not \fBNULL\fP, it -points to a variable which is set to the index of the long option relative to -.IR longopts . -.PP -\fBgetopt_long_only()\fP is like \fBgetopt_long()\fP, but `-' as well -as `--' can indicate a long option. If an option that starts with `-' -(not `--') doesn't match a long option, but does match a short option, -it is parsed as a short option instead. -.SH "RETURN VALUE" -The -.B getopt() -function returns the option character if the option was found -successfully, `:' if there was a missing parameter for one of the -options, `?' for an unknown option character, or \fBEOF\fP -for the end of the option list. -.PP -\fBgetopt_long()\fP and \fBgetopt_long_only()\fP also return the option -character when a short option is recognized. For a long option, they -return \fIval\fP if \fIflag\fP is \fBNULL\fP, and 0 otherwise. Error -and EOF returns are the same as for \fBgetopt()\fP, plus `?' for an -ambiguous match or an extraneous parameter. -.SH "ENVIRONMENT VARIABLES" -.TP -.SM -.B POSIXLY_CORRECT -If this is set, then option processing stops as soon as a non-option -argument is encountered. -.SH "EXAMPLE" -The following example program, from the source code, illustrates the -use of -.BR getopt_long() -with most of its features. -.nf -.sp -#include <stdio.h> - -int -main (argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 1, 0, 'c'}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:012", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\\n"); - break; - - case '0': - case '1': - case '2': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\\n"); - digit_optind = this_option_optind; - printf ("option %c\\n", c); - break; - - case 'a': - printf ("option a\\n"); - break; - - case 'b': - printf ("option b\\n"); - break; - - case 'c': - printf ("option c with value `%s'\\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\\n"); - } - - exit (0); -} -.fi -.SH "BUGS" -This manpage is confusing. -.SH "CONFORMING TO" -.TP -\fBgetopt()\fP: -POSIX.1, provided the environment variable POSIXLY_CORRECT is set. -Otherwise, the elements of \fIargv\fP aren't really const, because we -permute them. We pretend they're const in the prototype to be -compatible with other systems. - diff --git a/common/win/my_getopt-1.5/getopt.h b/common/win/my_getopt-1.5/getopt.h deleted file mode 100644 index df07082a..00000000 --- a/common/win/my_getopt-1.5/getopt.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * getopt.h - cpp wrapper for my_getopt to make it look like getopt. - * Copyright 1997, 2000, 2001, 2002, Benjamin Sittler - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef MY_WRAPPER_GETOPT_H_INCLUDED -#define MY_WRAPPER_GETOPT_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -#include "my_getopt.h" - -#undef getopt -#define getopt my_getopt -#undef getopt_long -#define getopt_long my_getopt_long -#undef getopt_long_only -#define getopt_long_only my_getopt_long_only -#undef _getopt_internal -#define _getopt_internal _my_getopt_internal -#undef opterr -#define opterr my_opterr -#undef optind -#define optind my_optind -#undef optopt -#define optopt my_optopt -#undef optarg -#define optarg my_optarg - -#ifdef __cplusplus -} -#endif - -#endif /* MY_WRAPPER_GETOPT_H_INCLUDED */ diff --git a/common/win/my_getopt-1.5/getopt.txt b/common/win/my_getopt-1.5/getopt.txt deleted file mode 100644 index ae08824e..00000000 --- a/common/win/my_getopt-1.5/getopt.txt +++ /dev/null @@ -1,330 +0,0 @@ - - - -GETOPT(3) Linux Programmer's Manual GETOPT(3) - - -NAME - getopt - Parse command line options - -SYNOPSIS - #include <unistd.h> - - int getopt(int argc, char * const argv[], - const char *optstring); - - extern char *optarg; - extern int optind, opterr, optopt; - - #include <getopt.h> - - int getopt_long(int argc, char * const argv[], - const char *optstring, - const struct option *longopts, int *longindex); - - int getopt_long_only(int argc, char * const argv[], - const char *optstring, - const struct option *longopts, int *longindex); - -DESCRIPTION - The getopt() function parses the command line arguments. - Its arguments argc and argv are the argument count and - array as passed to the main() function on program invoca- - tion. An element of argv that starts with `-' (and is not - exactly "-" or "--") is an option element. The characters - of this element (aside from the initial `-') are option - characters. If getopt() is called repeatedly, it returns - successively each of the option characters from each of - the option elements. - - If getopt() finds another option character, it returns - that character, updating the external variable optind and - a static variable nextchar so that the next call to - getopt() can resume the scan with the following option - character or argv-element. - - If there are no more option characters, getopt() returns - EOF. Then optind is the index in argv of the first argv- - element that is not an option. - - optstring is a string containing the legitimate option - characters. If such a character is followed by a colon, - the option requires an argument, so getopt places a - pointer to the following text in the same argv-element, or - the text of the following argv-element, in optarg. Two - colons mean an option takes an optional arg; if there is - text in the current argv-element, it is returned in - optarg, otherwise optarg is set to zero. - - By default, getargs() permutes the contents of argv as it - scans, so that eventually all the non-options are at the - - - -GNU Aug 30, 1995 1 - - - - - -GETOPT(3) Linux Programmer's Manual GETOPT(3) - - - end. Two other modes are also implemented. If the first - character of optstring is `+' or the environment variable - POSIXLY_CORRECT is set, then option processing stops as - soon as a non-option argument is encountered. If the - first character of optstring is `-', then each non-option - argv-element is handled as if it were the argument of an - option with character code 1. (This is used by programs - that were written to expect options and other argv-ele- - ments in any order and that care about the ordering of the - two.) The special argument `--' forces an end of option- - scanning regardless of the scanning mode. - - If getopt() does not recognize an option character, it - prints an error message to stderr, stores the character in - optopt, and returns `?'. The calling program may prevent - the error message by setting opterr to 0. - - The getopt_long() function works like getopt() except that - it also accepts long options, started out by two dashes. - Long option names may be abbreviated if the abbreviation - is unique or is an exact match for some defined option. A - long option may take a parameter, of the form --arg=param - or --arg param. - - longopts is a pointer to the first element of an array of - struct option declared in <getopt.h> as - - struct option { - const char *name; - int has_arg; - int *flag; - int val; - }; - - The meanings of the different fields are: - - name is the name of the long option. - - has_arg - is: no_argument (or 0) if the option does not take - an argument, required_argument (or 1) if the option - requires an argument, or optional_argument (or 2) - if the option takes an optional argument. - - flag specifies how results are returned for a long - option. If flag is NULL, then getopt_long() - returns val. (For example, the calling program may - set val to the equivalent short option character.) - Otherwise, getopt_long() returns 0, and flag points - to a variable which is set to val if the option is - found, but left unchanged if the option is not - found. - - val is the value to return, or to load into the - - - -GNU Aug 30, 1995 2 - - - - - -GETOPT(3) Linux Programmer's Manual GETOPT(3) - - - variable pointed to by flag. - - The last element of the array has to be filled with - zeroes. - - If longindex is not NULL, it points to a variable which is - set to the index of the long option relative to longopts. - - getopt_long_only() is like getopt_long(), but `-' as well - as `--' can indicate a long option. If an option that - starts with `-' (not `--') doesn't match a long option, - but does match a short option, it is parsed as a short - option instead. - -RETURN VALUE - The getopt() function returns the option character if the - option was found successfully, `:' if there was a missing - parameter for one of the options, `?' for an unknown - option character, or EOF for the end of the option list. - - getopt_long() and getopt_long_only() also return the - option character when a short option is recognized. For a - long option, they return val if flag is NULL, and 0 other- - wise. Error and EOF returns are the same as for getopt(), - plus `?' for an ambiguous match or an extraneous parame- - ter. - -ENVIRONMENT VARIABLES - POSIXLY_CORRECT - If this is set, then option processing stops as - soon as a non-option argument is encountered. - -EXAMPLE - The following example program, from the source code, - illustrates the use of getopt_long() with most of its fea- - tures. - - #include <stdio.h> - - int - main (argc, argv) - int argc; - char **argv; - { - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - - - -GNU Aug 30, 1995 3 - - - - - -GETOPT(3) Linux Programmer's Manual GETOPT(3) - - - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 1, 0, 'c'}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:012", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - - -GNU Aug 30, 1995 4 - - - - - -GETOPT(3) Linux Programmer's Manual GETOPT(3) - - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); - } - -BUGS - This manpage is confusing. - -CONFORMING TO - getopt(): - POSIX.1, provided the environment variable - POSIXLY_CORRECT is set. Otherwise, the elements of - argv aren't really const, because we permute them. - We pretend they're const in the prototype to be - compatible with other systems. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -GNU Aug 30, 1995 5 - - diff --git a/common/win/my_getopt-1.5/main.c b/common/win/my_getopt-1.5/main.c deleted file mode 100644 index a9de2723..00000000 --- a/common/win/my_getopt-1.5/main.c +++ /dev/null @@ -1,387 +0,0 @@ -/* - * copy - test program for my getopt() re-implementation - * - * This program is in the public domain. - */ - -#define VERSION \ -"0.3" - -#define COPYRIGHT \ -"This program is in the public domain." - -/* for isprint(), printf(), fopen(), perror(), getenv(), strcmp(), etc. */ -#include <ctype.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* for my getopt() re-implementation */ -#include "getopt.h" - -/* the default verbosity level is 0 (no verbose reporting) */ -static unsigned verbose = 0; - -/* print version and copyright information */ -static void -version(char *progname) -{ - printf("%s version %s\n" - "%s\n", - progname, - VERSION, - COPYRIGHT); -} - -/* print a help summary */ -static void -help(char *progname) -{ - printf("Usage: %s [options] [FILE]...\n" - "Options:\n" - "-h or -help show this message and exit\n" - "-append append to the output file\n" - "-o FILE or\n" - "-output FILE send output to FILE (default is stdout)\n" - "-r or --rotate rotate letters 13 positions (rot13)\n" - "-rNUM or\n" - "--rotate=NUM rotate letters NUM positions\n" - "-truncate truncate the output file " - "(this is the default)\n" - "-v or -verbose increase the level of verbosity by 1" - "(the default is 0)\n" - "-vNUM or\n" - "-verbose=NUM set the level of verbosity to NUM\n" - "-V or -version print program version and exit\n" - "\n" - "This program reads the specified FILEs " - "(or stdin if none are given)\n" - "and writes their bytes to the specified output FILE " - "(or stdout if none is\n" - "given.) It can optionally rotate letters.\n", - progname); -} - -/* print usage information to stderr */ -static void -usage(char *progname) -{ - fprintf(stderr, - "Summary: %s [-help] [-version] [options] [FILE]...\n", - progname); -} - -/* input file handler -- returns nonzero or exit()s on failure */ -static int -handle(char *progname, - FILE *infile, char *infilename, - FILE *outfile, char *outfilename, - int rotate) -{ - int c; - unsigned long bytes_copied = 0; - - if (verbose > 2) - { - fprintf(stderr, - "%s: copying from `%s' to `%s'\n", - progname, - infilename, - outfilename); - } - while ((c = getc(infile)) != EOF) - { - if (rotate && isalpha(c)) - { - const char *letters = "abcdefghijklmnopqrstuvwxyz"; - char *match; - if ((match = strchr(letters, tolower(c)))) - { - char rc = letters[(match - letters + rotate) % 26]; - if (isupper(c)) - rc = toupper(rc); - c = rc; - } - } - if (putc(c, outfile) == EOF) - { - perror(outfilename); - exit(1); - } - bytes_copied ++; - } - if (! feof(infile)) - { - perror(infilename); - return 1; - } - if (verbose > 2) - { - fprintf(stderr, - "%s: %lu bytes copied from `%s' to `%s'\n", - progname, - bytes_copied, - infilename, - outfilename); - } - return 0; -} - -/* argument parser and dispatcher */ -int -main(int argc, char * argv[]) -{ - /* the program name */ - char *progname = argv[0]; - /* during argument parsing, opt contains the return value from getopt() */ - int opt; - /* the output filename is initially 0 (a.k.a. stdout) */ - char *outfilename = 0; - /* the default return value is initially 0 (success) */ - int retval = 0; - /* initially we truncate */ - int append = 0; - /* initially we don't rotate letters */ - int rotate = 0; - - /* short options string */ - char *shortopts = "Vho:r::v::"; - /* long options list */ - struct option longopts[] = - { - /* name, has_arg, flag, val */ /* longind */ - { "append", no_argument, 0, 0 }, /* 0 */ - { "truncate", no_argument, 0, 0 }, /* 1 */ - { "version", no_argument, 0, 'V' }, /* 3 */ - { "help", no_argument, 0, 'h' }, /* 4 */ - { "output", required_argument, 0, 'o' }, /* 5 */ - { "rotate", optional_argument, 0, 'r' }, /* 6 */ - { "verbose", optional_argument, 0, 'v' }, /* 7 */ - /* end-of-list marker */ - { 0, 0, 0, 0 } - }; - /* long option list index */ - int longind = 0; - - /* - * print a warning when the POSIXLY_CORRECT environment variable will - * interfere with argument placement - */ - if (getenv("POSIXLY_CORRECT")) - { - fprintf(stderr, - "%s: " - "Warning: implicit argument reordering disallowed by " - "POSIXLY_CORRECT\n", - progname); - } - - /* parse all options from the command line */ - while ((opt = - getopt_long_only(argc, argv, shortopts, longopts, &longind)) != -1) - switch (opt) - { - case 0: /* a long option without an equivalent short option */ - switch (longind) - { - case 0: /* -append */ - append = 1; - break; - case 1: /* -truncate */ - append = 0; - break; - default: /* something unexpected has happened */ - fprintf(stderr, - "%s: " - "getopt_long_only unexpectedly returned %d for `--%s'\n", - progname, - opt, - longopts[longind].name); - return 1; - } - break; - case 'V': /* -version */ - version(progname); - return 0; - case 'h': /* -help */ - help(progname); - return 0; - case 'r': /* -rotate[=NUM] */ - if (optarg) - { - /* we use this while trying to parse a numeric argument */ - char ignored; - if (sscanf(optarg, - "%d%c", - &rotate, - &ignored) != 1) - { - fprintf(stderr, - "%s: " - "rotation `%s' is not a number\n", - progname, - optarg); - usage(progname); - return 2; - } - /* normalize rotation */ - while (rotate < 0) - { - rotate += 26; - } - rotate %= 26; - } - else - rotate = 13; - break; - case 'o': /* -output=FILE */ - outfilename = optarg; - /* we allow "-" as a synonym for stdout here */ - if (! strcmp(optarg, "-")) - { - outfilename = 0; - } - break; - case 'v': /* -verbose[=NUM] */ - if (optarg) - { - /* we use this while trying to parse a numeric argument */ - char ignored; - if (sscanf(optarg, - "%u%c", - &verbose, - &ignored) != 1) - { - fprintf(stderr, - "%s: " - "verbosity level `%s' is not a number\n", - progname, - optarg); - usage(progname); - return 2; - } - } - else - verbose ++; - break; - case '?': /* getopt_long_only noticed an error */ - usage(progname); - return 2; - default: /* something unexpected has happened */ - fprintf(stderr, - "%s: " - "getopt_long_only returned an unexpected value (%d)\n", - progname, - opt); - return 1; - } - - /* re-open stdout to outfilename, if requested */ - if (outfilename) - { - if (! freopen(outfilename, (append ? "a" : "w"), stdout)) - { - perror(outfilename); - return 1; - } - } - else - { - /* make a human-readable version of the output filename "-" */ - outfilename = "stdout"; - /* you can't truncate stdout */ - append = 1; - } - - if (verbose) - { - fprintf(stderr, - "%s: verbosity level is %u; %s `%s'; rotation %d\n", - progname, - verbose, - (append ? "appending to" : "truncating"), - outfilename, - rotate); - } - - if (verbose > 1) - { - fprintf(stderr, - "%s: %d input file(s) were given\n", - progname, - ((argc > optind) ? (argc - optind) : 0)); - } - - if (verbose > 3) - { - fprintf(stderr, - "\topterr: %d\n\toptind: %d\n\toptopt: %d (%c)\n\toptarg: %s\n", - opterr, - optind, - optopt, optopt, - optarg ? optarg : "(null)"); - } - - /* handle each of the input files (or stdin, if no files were given) */ - if (optind < argc) - { - int argindex; - - for (argindex = optind; argindex < argc; argindex ++) - { - char *infilename = argv[argindex]; - FILE *infile; - - /* we allow "-" as a synonym for stdin here */ - if (! strcmp(infilename, "-")) - { - infile = stdin; - infilename = "stdin"; - } - else if (! (infile = fopen(infilename, "r"))) - { - perror(infilename); - retval = 1; - continue; - } - if (handle(progname, - infile, argv[optind], - stdout, outfilename, - rotate)) - { - retval = 1; - fclose(infile); - continue; - } - if ((infile != stdin) && fclose(infile)) - { - perror(infilename); - retval = 1; - } - } - } - else - { - retval = - handle(progname, - stdin, "stdin", - stdout, outfilename, - rotate); - } - - /* close stdout */ - if (fclose(stdout)) - { - perror(outfilename); - return 1; - } - - if (verbose > 3) - { - fprintf(stderr, - "%s: normal return, exit code is %d\n", - progname, - retval); - } - return retval; -} diff --git a/common/win/my_getopt-1.5/my_getopt.c b/common/win/my_getopt-1.5/my_getopt.c deleted file mode 100644 index 5237b8e8..00000000 --- a/common/win/my_getopt-1.5/my_getopt.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * my_getopt.c - my re-implementation of getopt. - * Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <sys/types.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include "my_getopt.h" - -int my_optind=1, my_opterr=1, my_optopt=0; -char *my_optarg=0; - -/* reset argument parser to start-up values */ -int my_getopt_reset(void) -{ - my_optind = 1; - my_opterr = 1; - my_optopt = 0; - my_optarg = 0; - return 0; -} - -/* this is the plain old UNIX getopt, with GNU-style extensions. */ -/* if you're porting some piece of UNIX software, this is all you need. */ -/* this supports GNU-style permution and optional arguments */ - -int my_getopt(int argc, char * argv[], const char *opts) -{ - static int charind=0; - char mode, colon_mode; - int off = 0, opt = -1; - - if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+'; - else { - if((colon_mode = *opts) == ':') off ++; - if(((mode = opts[off]) == '+') || (mode == '-')) { - off++; - if((colon_mode != ':') && ((colon_mode = opts[off]) == ':')) - off ++; - } - } - my_optarg = 0; - if(charind) { - const char *s; - my_optopt = argv[my_optind][charind]; - for(s=opts+off; *s; s++) if(my_optopt == *s) { - charind++; - if((*(++s) == ':') || ((my_optopt == 'W') && (*s == ';'))) { - if(argv[my_optind][charind]) { - my_optarg = &(argv[my_optind++][charind]); - charind = 0; - } else if(*(++s) != ':') { - charind = 0; - if(++my_optind >= argc) { - if(my_opterr) fprintf(stderr, - "%s: option requires an argument -- %c\n", - argv[0], my_optopt); - opt = (colon_mode == ':') ? ':' : '?'; - goto my_getopt_ok; - } - my_optarg = argv[my_optind++]; - } - } - opt = my_optopt; - goto my_getopt_ok; - } - if(my_opterr) fprintf(stderr, - "%s: illegal option -- %c\n", - argv[0], my_optopt); - opt = '?'; - if(argv[my_optind][++charind] == '\0') { - my_optind++; - charind = 0; - } - my_getopt_ok: - if(charind && ! argv[my_optind][charind]) { - my_optind++; - charind = 0; - } - } else if((my_optind >= argc) || - ((argv[my_optind][0] == '-') && - (argv[my_optind][1] == '-') && - (argv[my_optind][2] == '\0'))) { - my_optind++; - opt = -1; - } else if((argv[my_optind][0] != '-') || - (argv[my_optind][1] == '\0')) { - char *tmp; - int i, j, k; - - if(mode == '+') opt = -1; - else if(mode == '-') { - my_optarg = argv[my_optind++]; - charind = 0; - opt = 1; - } else { - for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') && - (argv[i][1] != '\0')) { - my_optind=i; - opt=my_getopt(argc, argv, opts); - while(i > j) { - tmp=argv[--i]; - for(k=i; k+1<my_optind; k++) argv[k]=argv[k+1]; - argv[--my_optind]=tmp; - } - break; - } - if(i == argc) opt = -1; - } - } else { - charind++; - opt = my_getopt(argc, argv, opts); - } - if (my_optind > argc) my_optind = argc; - return opt; -} - -/* this is the extended getopt_long{,_only}, with some GNU-like - * extensions. Implements _getopt_internal in case any programs - * expecting GNU libc getopt call it. - */ - -int _my_getopt_internal(int argc, char * argv[], const char *shortopts, - const struct option *longopts, int *longind, - int long_only) -{ - char mode, colon_mode = *shortopts; - int shortoff = 0, opt = -1; - - if(getenv("POSIXLY_CORRECT")) colon_mode = mode = '+'; - else { - if((colon_mode = *shortopts) == ':') shortoff ++; - if(((mode = shortopts[shortoff]) == '+') || (mode == '-')) { - shortoff++; - if((colon_mode != ':') && ((colon_mode = shortopts[shortoff]) == ':')) - shortoff ++; - } - } - my_optarg = 0; - if((my_optind >= argc) || - ((argv[my_optind][0] == '-') && - (argv[my_optind][1] == '-') && - (argv[my_optind][2] == '\0'))) { - my_optind++; - opt = -1; - } else if((argv[my_optind][0] != '-') || - (argv[my_optind][1] == '\0')) { - char *tmp; - int i, j, k; - - opt = -1; - if(mode == '+') return -1; - else if(mode == '-') { - my_optarg = argv[my_optind++]; - return 1; - } - for(i=j=my_optind; i<argc; i++) if((argv[i][0] == '-') && - (argv[i][1] != '\0')) { - my_optind=i; - opt=_my_getopt_internal(argc, argv, shortopts, - longopts, longind, - long_only); - while(i > j) { - tmp=argv[--i]; - for(k=i; k+1<my_optind; k++) - argv[k]=argv[k+1]; - argv[--my_optind]=tmp; - } - break; - } - } else if((!long_only) && (argv[my_optind][1] != '-')) - opt = my_getopt(argc, argv, shortopts); - else { - int charind, offset; - int found = 0, ind, hits = 0; - - if(((my_optopt = argv[my_optind][1]) != '-') && ! argv[my_optind][2]) { - int c; - - ind = shortoff; - while((c = shortopts[ind++])) { - if(((shortopts[ind] == ':') || - ((c == 'W') && (shortopts[ind] == ';'))) && - (shortopts[++ind] == ':')) - ind ++; - if(my_optopt == c) return my_getopt(argc, argv, shortopts); - } - } - offset = 2 - (argv[my_optind][1] != '-'); - for(charind = offset; - (argv[my_optind][charind] != '\0') && - (argv[my_optind][charind] != '='); - charind++); - for(ind = 0; longopts[ind].name && !hits; ind++) - if((strlen(longopts[ind].name) == (size_t) (charind - offset)) && - (strncmp(longopts[ind].name, - argv[my_optind] + offset, charind - offset) == 0)) - found = ind, hits++; - if(!hits) for(ind = 0; longopts[ind].name; ind++) - if(strncmp(longopts[ind].name, - argv[my_optind] + offset, charind - offset) == 0) - found = ind, hits++; - if(hits == 1) { - opt = 0; - - if(argv[my_optind][charind] == '=') { - if(longopts[found].has_arg == 0) { - opt = '?'; - if(my_opterr) fprintf(stderr, - "%s: option `--%s' doesn't allow an argument\n", - argv[0], longopts[found].name); - } else { - my_optarg = argv[my_optind] + ++charind; - charind = 0; - } - } else if(longopts[found].has_arg == 1) { - if(++my_optind >= argc) { - opt = (colon_mode == ':') ? ':' : '?'; - if(my_opterr) fprintf(stderr, - "%s: option `--%s' requires an argument\n", - argv[0], longopts[found].name); - } else my_optarg = argv[my_optind]; - } - if(!opt) { - if (longind) *longind = found; - if(!longopts[found].flag) opt = longopts[found].val; - else *(longopts[found].flag) = longopts[found].val; - } - my_optind++; - } else if(!hits) { - if(offset == 1) opt = my_getopt(argc, argv, shortopts); - else { - opt = '?'; - if(my_opterr) fprintf(stderr, - "%s: unrecognized option `%s'\n", - argv[0], argv[my_optind++]); - } - } else { - opt = '?'; - if(my_opterr) fprintf(stderr, - "%s: option `%s' is ambiguous\n", - argv[0], argv[my_optind++]); - } - } - if (my_optind > argc) my_optind = argc; - return opt; -} - -int my_getopt_long(int argc, char * argv[], const char *shortopts, - const struct option *longopts, int *longind) -{ - return _my_getopt_internal(argc, argv, shortopts, longopts, longind, 0); -} - -int my_getopt_long_only(int argc, char * argv[], const char *shortopts, - const struct option *longopts, int *longind) -{ - return _my_getopt_internal(argc, argv, shortopts, longopts, longind, 1); -} diff --git a/common/win/my_getopt-1.5/my_getopt.h b/common/win/my_getopt-1.5/my_getopt.h deleted file mode 100644 index c75101a1..00000000 --- a/common/win/my_getopt-1.5/my_getopt.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * my_getopt.h - interface to my re-implementation of getopt. - * Copyright 1997, 2000, 2001, 2002, 2006, Benjamin Sittler - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef MY_GETOPT_H_INCLUDED -#define MY_GETOPT_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -/* reset argument parser to start-up values */ -extern int my_getopt_reset(void); - -/* UNIX-style short-argument parser */ -extern int my_getopt(int argc, char * argv[], const char *opts); - -extern int my_optind, my_opterr, my_optopt; -extern char *my_optarg; - -struct option { - const char *name; - int has_arg; - int *flag; - int val; -}; - -/* human-readable values for has_arg */ -#undef no_argument -#define no_argument 0 -#undef required_argument -#define required_argument 1 -#undef optional_argument -#define optional_argument 2 - -/* GNU-style long-argument parsers */ -extern int my_getopt_long(int argc, char * argv[], const char *shortopts, - const struct option *longopts, int *longind); - -extern int my_getopt_long_only(int argc, char * argv[], const char *shortopts, - const struct option *longopts, int *longind); - -extern int _my_getopt_internal(int argc, char * argv[], const char *shortopts, - const struct option *longopts, int *longind, - int long_only); - -#ifdef __cplusplus -} -#endif - -#endif /* MY_GETOPT_H_INCLUDED */ diff --git a/configure.ac b/configure.ac index 1ca5e774..1feb36db 100644 --- a/configure.ac +++ b/configure.ac @@ -140,9 +140,9 @@ AM_CONDITIONAL(SUPPORT_AUTOMATED_TESTS, test "x$enable_automated_tests" != "xno" dnl ========================================================================= dnl Check deps -AC_CONFIG_SUBDIRS([spice-protocol]) -PROTOCOL_CFLAGS='-I ${top_srcdir}/spice-protocol' -AC_SUBST(PROTOCOL_CFLAGS) +AC_CONFIG_SUBDIRS([spice-common]) +COMMON_CFLAGS='-I ${top_srcdir}/spice-common/ -I ${top_srcdir}/spice-common/spice-protocol/' +AC_SUBST(COMMON_CFLAGS) AC_CHECK_LIBM AC_SUBST(LIBM) @@ -541,10 +541,6 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) AC_OUTPUT([ Makefile spice-server.pc -common/Makefile -common/win/Makefile -common/win/my_getopt-1.5/Makefile -python_modules/Makefile server/Makefile server/tests/Makefile client/Makefile diff --git a/server/Makefile.am b/server/Makefile.am index a88e464a..97e7dfed 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -1,14 +1,11 @@ -SUBDIRS = . tests - NULL = +SUBDIRS = . tests -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/common \ +AM_CPPFLAGS = \ -DRED_STATISTICS \ $(CELT051_CFLAGS) \ + $(COMMON_CFLAGS) \ $(PIXMAN_CFLAGS) \ - $(PROTOCOL_CFLAGS) \ $(SASL_CFLAGS) \ $(SLIRP_CFLAGS) \ $(SMARTCARD_CFLAGS) \ @@ -17,18 +14,6 @@ INCLUDES = \ $(WARN_CFLAGS) \ $(NULL) -spice_built_sources = generated_marshallers.c generated_marshallers.h generated_demarshallers.c - -generated_demarshallers.c: $(top_srcdir)/spice.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-demarshallers --server --include red_common.h $(top_srcdir)/spice.proto generated_demarshallers.c - -STRUCTS=-M String -M Rect -M Point -M DisplayBase -M Fill -M Opaque -M Copy -M Blend -M Blackness -M Whiteness -M Invers -M Rop3 -M Stroke -M Text -M Transparent -M AlphaBlend -generated_marshallers.c: $(top_srcdir)/spice.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --include red_common.h --generate-marshallers $(STRUCTS) --server $(top_srcdir)/spice.proto generated_marshallers.c - -generated_marshallers.h: $(top_srcdir)/spice.proto - $(AM_V_GEN)$(PYTHON) $(top_srcdir)/spice_codegen.py --generate-marshallers $(STRUCTS) --server -H $(top_srcdir)/spice.proto generated_marshallers.h - lib_LTLIBRARIES = libspice-server.la libspice_server_la_LDFLAGS = \ @@ -41,17 +26,18 @@ libspice_server_la_LDFLAGS += \ -Wl,--version-script=$(top_srcdir)/server/spice-server.syms endif -libspice_server_la_LIBADD = \ - $(top_builddir)/common/libspice-common.la \ - $(CELT051_LIBS) \ - $(GL_LIBS) \ - $(JPEG_LIBS) \ - $(LIBRT) \ - $(PIXMAN_LIBS) \ - $(SASL_LIBS) \ - $(SLIRP_LIBS) \ - $(SSL_LIBS) \ - $(Z_LIBS) \ +libspice_server_la_LIBADD = \ + $(top_builddir)/spice-common/common/libspice-common.la \ + $(top_builddir)/spice-common/common/libspice-common-server.la \ + $(CELT051_LIBS) \ + $(GL_LIBS) \ + $(JPEG_LIBS) \ + $(LIBRT) \ + $(PIXMAN_LIBS) \ + $(SASL_LIBS) \ + $(SLIRP_LIBS) \ + $(SSL_LIBS) \ + $(Z_LIBS) \ $(NULL) libspice_server_la_SOURCES = \ @@ -59,9 +45,6 @@ libspice_server_la_SOURCES = \ agent-msg-filter.h \ char_device.h \ demarshallers.h \ - generated_demarshallers.c \ - generated_marshallers.c \ - generated_marshallers.h \ glz_encoder.c \ glz_encoder.h \ glz_encoder_config.h \ diff --git a/server/dispatcher.c b/server/dispatcher.c index 94ae5569..c15a7a18 100644 --- a/server/dispatcher.c +++ b/server/dispatcher.c @@ -1,4 +1,24 @@ +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* + Copyright (C) 2009-2012 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +#ifdef HAVE_CONFIG_H #include <config.h> +#endif + #include <unistd.h> #include <errno.h> #include <assert.h> @@ -7,8 +27,9 @@ #include <fcntl.h> #include <poll.h> -#include "mem.h" -#include "spice_common.h" +#include "common/mem.h" +#include "common/spice_common.h" + #include "dispatcher.h" #define DISPATCHER_DEBUG_PRINTF(level, ...) \ diff --git a/server/glz_encoder.h b/server/glz_encoder.h index 9b4f9108..34c363a3 100644 --- a/server/glz_encoder.h +++ b/server/glz_encoder.h @@ -21,7 +21,7 @@ /* Manging the lz encoding using a dictionary that is shared among encoders */ #include <stdint.h> -#include "lz_common.h" +#include "common/lz_common.h" #include "glz_encoder_dictionary.h" #include "glz_encoder_config.h" diff --git a/server/glz_encoder_config.h b/server/glz_encoder_config.h index 2d1626a7..157e3a21 100644 --- a/server/glz_encoder_config.h +++ b/server/glz_encoder_config.h @@ -19,7 +19,7 @@ #define _H_GLZ_ENCODER_CONFIG #include <spice/macros.h> -#include "lz_common.h" +#include "common/lz_common.h" typedef void GlzUsrImageContext; typedef struct GlzEncoderUsrContext GlzEncoderUsrContext; diff --git a/server/inputs_channel.c b/server/inputs_channel.c index 42247613..da4c53c4 100644 --- a/server/inputs_channel.c +++ b/server/inputs_channel.c @@ -26,10 +26,12 @@ #include <errno.h> #include <spice/macros.h> #include <spice/vd_agent.h> + #include "common/marshaller.h" #include "common/messages.h" -#include "server/demarshallers.h" -#include "server/generated_marshallers.h" +#include "common/generated_server_marshallers.h" + +#include "demarshallers.h" #include "spice.h" #include "red_common.h" #include "reds.h" diff --git a/server/main_channel.c b/server/main_channel.c index dbac010a..7a2938c6 100644 --- a/server/main_channel.c +++ b/server/main_channel.c @@ -36,14 +36,15 @@ #include <errno.h> #include <ctype.h> -#include "server/red_common.h" -#include "server/demarshallers.h" -#include "common/ring.h" +#include "common/generated_server_marshallers.h" #include "common/messages.h" +#include "common/ring.h" + +#include "demarshallers.h" #include "main_channel.h" -#include "reds.h" #include "red_channel.h" -#include "generated_marshallers.h" +#include "red_common.h" +#include "reds.h" #define ZERO_BUF_SIZE 4096 diff --git a/server/red_channel.c b/server/red_channel.c index ecb512d3..f27abeda 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -29,11 +29,13 @@ #include <fcntl.h> #include <unistd.h> #include <errno.h> -#include "ring.h" + +#include "common/generated_server_marshallers.h" +#include "common/ring.h" + #include "stat.h" #include "red_channel.h" #include "reds.h" -#include "generated_marshallers.h" static void red_channel_client_event(int fd, int event, void *data); static void red_client_add_channel(RedClient *client, RedChannelClient *rcc); diff --git a/server/red_channel.h b/server/red_channel.h index 5dfd187b..54182106 100644 --- a/server/red_channel.h +++ b/server/red_channel.h @@ -25,11 +25,12 @@ #include <pthread.h> #include <limits.h> -#include "red_common.h" -#include "spice.h" -#include "ring.h" +#include "common/ring.h" #include "common/marshaller.h" -#include "server/demarshallers.h" + +#include "spice.h" +#include "red_common.h" +#include "demarshallers.h" #define MAX_SEND_BUFS 1000 #define CLIENT_ACK_WINDOW 20 diff --git a/server/red_common.h b/server/red_common.h index 86be95dd..cb7bf716 100644 --- a/server/red_common.h +++ b/server/red_common.h @@ -20,12 +20,13 @@ #include <sys/uio.h> #include <openssl/ssl.h> +#include <spice/macros.h> + +#include "common/mem.h" +#include "common/spice_common.h" +#include "common/messages.h" #include "spice.h" -#include "mem.h" -#include "spice_common.h" -#include <messages.h> -#include <spice/macros.h> enum { STREAM_VIDEO_INVALID, diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c index 1aa619c1..9a049488 100644 --- a/server/red_dispatcher.c +++ b/server/red_dispatcher.c @@ -29,9 +29,10 @@ #include <inttypes.h> #include <spice/qxl_dev.h> +#include "common/quic.h" + #include "spice.h" #include "red_worker.h" -#include "quic.h" #include "reds_sw_canvas.h" #ifdef USE_OPENGL #include "reds_gl_canvas.h" diff --git a/server/red_worker.c b/server/red_worker.c index 45260ee7..172a5716 100644 --- a/server/red_worker.c +++ b/server/red_worker.c @@ -44,31 +44,33 @@ #include <setjmp.h> #include <openssl/ssl.h> -#include <spice/qxl_dev.h> -#include "spice.h" -#include "region.h" #include <spice/protocol.h> -#include "red_worker.h" -#include "reds_sw_canvas.h" +#include <spice/qxl_dev.h> +#include "common/lz.h" +#include "common/marshaller.h" +#include "common/quic.h" +#include "common/rect.h" +#include "common/region.h" +#include "common/ring.h" +#include "common/generated_server_marshallers.h" + #ifdef USE_OPENGL +#include "common/ogl_ctx.h" #include "reds_gl_canvas.h" -#include "ogl_ctx.h" #endif /* USE_OPENGL */ -#include "quic.h" -#include "lz.h" + +#include "spice.h" +#include "red_worker.h" +#include "reds_sw_canvas.h" #include "glz_encoder_dictionary.h" #include "glz_encoder.h" #include "stat.h" #include "reds.h" -#include "ring.h" #include "mjpeg_encoder.h" #include "red_memslots.h" #include "red_parse_qxl.h" #include "jpeg_encoder.h" -#include "rect.h" -#include "marshaller.h" #include "demarshallers.h" -#include "generated_marshallers.h" #include "zlib_encoder.h" #include "red_channel.h" #include "red_dispatcher.h" diff --git a/server/reds.c b/server/reds.c index 30e3ac04..cf493dde 100644 --- a/server/reds.c +++ b/server/reds.c @@ -47,26 +47,26 @@ #include <sasl/sasl.h> #endif +#include <spice/protocol.h> +#include <spice/vd_agent.h> +#include <spice/stats.h> + +#include "common/generated_server_marshallers.h" +#include "common/ring.h" + #include "spice.h" #include "spice-experimental.h" #include "reds.h" -#include <spice/protocol.h> -#include <spice/vd_agent.h> #include "agent-msg-filter.h" - #include "inputs_channel.h" #include "main_channel.h" #include "red_common.h" #include "red_dispatcher.h" #include "main_dispatcher.h" #include "snd_worker.h" -#include <spice/stats.h> #include "stat.h" -#include "ring.h" #include "demarshallers.h" -#include "marshaller.h" -#include "generated_marshallers.h" -#include "server/char_device.h" +#include "char_device.h" #ifdef USE_TUNNEL #include "red_tunnel_worker.h" #endif diff --git a/server/reds_gl_canvas.c b/server/reds_gl_canvas.c index deec4403..da03ee53 100644 --- a/server/reds_gl_canvas.c +++ b/server/reds_gl_canvas.c @@ -18,11 +18,11 @@ #include <config.h> #endif -#include "spice_common.h" +#include "common/spice_common.h" #include "reds_gl_canvas.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_IMAGE_CACHE -#include "gl_canvas.c" +#include "common/gl_canvas.c" #undef SW_CANVAS_IMAGE_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/server/reds_gl_canvas.h b/server/reds_gl_canvas.h index c20cca50..c9da25c8 100644 --- a/server/reds_gl_canvas.h +++ b/server/reds_gl_canvas.h @@ -20,7 +20,7 @@ #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_IMAGE_CACHE -#include "gl_canvas.h" +#include "common/gl_canvas.h" #undef SW_CANVAS_IMAGE_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/server/reds_sw_canvas.c b/server/reds_sw_canvas.c index 43e086d6..e7ace3b4 100644 --- a/server/reds_sw_canvas.c +++ b/server/reds_sw_canvas.c @@ -18,11 +18,11 @@ #include <config.h> #endif -#include "spice_common.h" +#include "common/spice_common.h" #include "reds_sw_canvas.h" #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_IMAGE_CACHE -#include "sw_canvas.c" +#include "common/sw_canvas.c" #undef SW_CANVAS_IMAGE_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/server/reds_sw_canvas.h b/server/reds_sw_canvas.h index 00e61562..f065be53 100644 --- a/server/reds_sw_canvas.h +++ b/server/reds_sw_canvas.h @@ -19,7 +19,7 @@ #define SPICE_CANVAS_INTERNAL #define SW_CANVAS_IMAGE_CACHE -#include "sw_canvas.h" +#include "common/sw_canvas.h" #undef SW_CANVAS_IMAGE_CACHE #undef SPICE_CANVAS_INTERNAL diff --git a/server/smartcard.c b/server/smartcard.c index 84aa18b3..d023331f 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -20,12 +20,12 @@ #endif #include <arpa/inet.h> - #include <vscard_common.h> -#include "server/reds.h" -#include "server/char_device.h" -#include "server/red_channel.h" -#include "server/smartcard.h" + +#include "reds.h" +#include "char_device.h" +#include "red_channel.h" +#include "smartcard.h" #define SMARTCARD_MAX_READERS 10 diff --git a/server/smartcard.h b/server/smartcard.h index 60cc2c6c..7881e1fd 100644 --- a/server/smartcard.h +++ b/server/smartcard.h @@ -18,7 +18,7 @@ #ifndef __SMART_CARD_H__ #define __SMART_CARD_H__ -#include "server/spice-experimental.h" +#include "spice-experimental.h" // Maximal length of APDU #define APDUBufSize 270 diff --git a/server/snd_worker.c b/server/snd_worker.c index 4c511905..be980947 100644 --- a/server/snd_worker.c +++ b/server/snd_worker.c @@ -27,14 +27,15 @@ #include <netinet/tcp.h> #include <celt051/celt.h> +#include "common/marshaller.h" +#include "common/generated_server_marshallers.h" + #include "spice.h" #include "red_common.h" #include "main_channel.h" #include "reds.h" #include "red_dispatcher.h" #include "snd_worker.h" -#include "marshaller.h" -#include "generated_marshallers.h" #include "demarshallers.h" #ifndef IOV_MAX diff --git a/server/spicevmc.c b/server/spicevmc.c index 2f1b8f77..18ae6279 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -28,9 +28,9 @@ #include <netinet/in.h> // IPPROTO_TCP #include <netinet/tcp.h> // TCP_NODELAY -#include "server/char_device.h" -#include "server/red_channel.h" -#include "server/reds.h" +#include "char_device.h" +#include "red_channel.h" +#include "reds.h" /* 64K should be enough for all but the largest writes + 32 bytes hdr */ #define BUF_SIZE (64 * 1024 + 32) diff --git a/server/tests/Makefile.am b/server/tests/Makefile.am index 52e55a88..e77865c7 100644 --- a/server/tests/Makefile.am +++ b/server/tests/Makefile.am @@ -1,21 +1,22 @@ NULL = -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/common \ - -I$(top_srcdir)/server \ - -I$(top_srcdir)/server/tests \ - $(PROTOCOL_CFLAGS) \ - $(SPICE_NONPKGCONFIG_CFLAGS) \ +INCLUDES = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/common \ + -I$(top_srcdir)/server \ + -I$(top_srcdir)/server/tests \ + $(COMMON_CFLAGS) \ + $(SMARTCARD_CFLAGS) \ + $(SPICE_NONPKGCONFIG_CFLAGS) \ $(NULL) if SUPPORT_AUTOMATED_TESTS INCLUDES += -DAUTOMATED_TESTS endif -LDADD = \ - $(top_builddir)/common/libspice-common.la \ - $(top_builddir)/server/libspice-server.la \ +LDADD = \ + $(top_builddir)/spice-common/common/libspice-common.la \ + $(top_builddir)/server/libspice-server.la \ $(NULL) COMMON_BASE = \ diff --git a/spice-common b/spice-common new file mode 160000 +Subproject fb24e4e28bad0b0e2bb670deb9fb56223be49ad diff --git a/spice-protocol b/spice-protocol deleted file mode 160000 -Subproject 1a3b563171ad81f6b44f6e5ef6f244b16941970 |