add GDI engine.
authorcaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 23 Apr 2009 03:20:51 +0000 (03:20 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 23 Apr 2009 03:20:51 +0000 (03:20 +0000)
todo: fullscreen and shape support

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@40310 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

13 files changed:
Makefile.am
configure.ac
evas-software-gdi.pc.in [new file with mode: 0644]
m4/evas_check_engine.m4
src/lib/canvas/evas_main.c
src/modules/engines/Makefile.am
src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h [new file with mode: 0644]
src/modules/engines/software_gdi/Makefile.am [new file with mode: 0644]
src/modules/engines/software_gdi/evas_engine.c [new file with mode: 0644]
src/modules/engines/software_gdi/evas_engine.h [new file with mode: 0644]
src/modules/engines/software_gdi/evas_gdi_buffer.c [new file with mode: 0644]
src/modules/engines/software_gdi/evas_gdi_main.c [new file with mode: 0644]
src/modules/engines/software_gdi/evas_outbuf.c [new file with mode: 0644]

index 0f3d285..41103ea 100644 (file)
@@ -32,6 +32,7 @@ evas-software-16-x11.pc \
 evas-software-xcb.pc \
 evas-xrender-x11.pc \
 evas-xrender-xcb.pc \
+evas-software-gdi.pc \
 evas-software-ddraw.pc \
 evas-software-16-ddraw.pc \
 evas-direct3d.pc \
@@ -70,6 +71,7 @@ evas-software-16-x11.pc.in \
 evas-software-xcb.pc.in \
 evas-xrender-x11.pc.in \
 evas-xrender-xcb.pc.in \
+evas-software-gdi.pc.in \
 evas-software-ddraw.pc.in \
 evas-software-16-ddraw.pc.in \
 evas-direct3d.pc.in \
@@ -129,6 +131,10 @@ if BUILD_ENGINE_XRENDER_XCB
 pxrenderxcb = evas-xrender-xcb.pc
 endif
 
+if BUILD_ENGINE_SOFTWARE_GDI
+psoftwaregdi = evas-software-gdi.pc
+endif
+
 if BUILD_ENGINE_SOFTWARE_DDRAW
 psoftwareddraw = evas-software-ddraw.pc
 endif
@@ -153,7 +159,7 @@ pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = \
        evas.pc $(psoftwarex11) $(psoftwarexcb) $(pdirectfb) $(pfb) \
        $(psoftwarebuffer) $(psoftwareqtopia) $(popenglx11) $(pquartz) $(pcairox11) \
-       $(pxrenderx11) $(pxrenderxcb) $(psoftwareddraw) $(psoftwaresdl) \
+       $(pxrenderx11) $(pxrenderxcb) $(psoftwaregdi) $(psoftwareddraw) $(psoftwaresdl) \
        $(psoftware16x11) $(pdirect3d) $(psoftware16ddraw) $(psoftware16wince) $(popenglglew)
 
 .PHONY: doc
index a5d0195..4834e86 100644 (file)
@@ -11,8 +11,8 @@ AC_ISC_POSIX
 AM_INIT_AUTOMAKE(1.6 dist-bzip2)
 AM_CONFIG_HEADER(config.h)
 
-AC_PROG_CXX
-AC_PROG_CC
+AC_PROG_CXX([icl g++])
+AC_PROG_CC([icl gcc]
 AM_PROG_CC_STDC
 AC_HEADER_STDC
 AC_C_BIGENDIAN
@@ -42,6 +42,7 @@ want_evas_engine_gl_x11="no"
 want_evas_engine_cairo_x11="no"
 want_evas_engine_software_xcb="no"
 want_evas_engine_xrender_xcb="no"
+want_evas_engine_software_gdi="no"
 want_evas_engine_software_ddraw="no"
 want_evas_engine_direct3d="no"
 want_evas_engine_quartz="no"
@@ -76,6 +77,7 @@ case "$host_os" in
       want_evas_image_loader_tiff="no"
       ;;
    mingw*)
+      want_evas_engine_software_gdi="yes"
       want_evas_engine_software_ddraw="yes"
       want_evas_engine_direct3d="yes"
       want_evas_engine_software_16_ddraw="yes"
@@ -251,6 +253,8 @@ EVAS_CHECK_ENGINE([software-xcb], [${want_evas_engine_software_xcb}], [no], [Sof
 
 EVAS_CHECK_ENGINE([xrender-xcb], [${want_evas_engine_xrender_xcb}], [no], [XRender XCB])
 
+EVAS_CHECK_ENGINE([software-gdi], [${want_evas_engine_software_gdi}], [no], [Software GDI])
+
 EVAS_CHECK_ENGINE([software-ddraw], [${want_evas_engine_software_ddraw}], [no], [Software DirectDraw])
 
 EVAS_CHECK_ENGINE([direct3d], [${want_evas_engine_direct3d}], [no], [Direct3D])
@@ -1035,6 +1039,7 @@ evas-software-16-x11.pc
 evas-software-xcb.pc
 evas-xrender-x11.pc
 evas-xrender-xcb.pc
+evas-software-gdi.pc
 evas-software-ddraw.pc
 evas-software-16-ddraw.pc
 evas-direct3d.pc
@@ -1062,6 +1067,7 @@ src/lib/engines/common_16/Makefile
 src/modules/Makefile
 src/modules/engines/Makefile
 src/modules/engines/software_generic/Makefile
+src/modules/engines/software_gdi/Makefile
 src/modules/engines/software_ddraw/Makefile
 src/modules/engines/direct3d/Makefile
 src/modules/engines/software_16_wince/Makefile
@@ -1127,6 +1133,7 @@ echo "  Software X11...............: $have_evas_engine_software_x11 (XCB: $have_
 echo "  XRender X11................: $have_evas_engine_xrender_x11 (XCB: $have_evas_engine_xrender_xcb)"
 echo "  OpenGL X11.................: $have_evas_engine_gl_x11"
 #echo "  Cairo X11..................: $have_evas_engine_cairo_x11"
+echo "  Software GDI...............: $have_evas_engine_software_gdi"
 echo "  Software DirectDraw........: $have_evas_engine_software_ddraw"
 echo "  Direct3d...................: $have_evas_engine_direct3d"
 echo "  Quartz.....................: $have_evas_engine_quartz"
diff --git a/evas-software-gdi.pc.in b/evas-software-gdi.pc.in
new file mode 100644 (file)
index 0000000..097c4e1
--- /dev/null
@@ -0,0 +1,3 @@
+Name: evas-software-gdi
+Description: Evas software GDI engine
+Version: @VERSION@
index 367c281..2ad18f8 100644 (file)
@@ -232,6 +232,33 @@ fi
 
 ])
 
+dnl use: EVAS_CHECK_ENGINE_DEP_SOFTWARE_GDI(engine, simple[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN([EVAS_CHECK_ENGINE_DEP_SOFTWARE_GDI],
+[
+
+have_dep="no"
+evas_engine_[]$1[]_cflags=""
+evas_engine_[]$1[]_libs=""
+
+AC_CHECK_HEADER([windows.h],
+   [
+    have_dep="yes"
+    evas_engine_[]$1[]_libs="-lgdi32"
+   ]
+)
+
+AC_SUBST([evas_engine_$1_cflags])
+AC_SUBST([evas_engine_$1_libs])
+
+if test "x${have_dep}" = "xyes" ; then
+  m4_default([$3], [:])
+else
+  m4_default([$4], [:])
+fi
+
+])
+
 dnl use: EVAS_CHECK_ENGINE_DEP_SOFTWARE_DDRAW(engine, simple[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
 
 AC_DEFUN([EVAS_CHECK_ENGINE_DEP_SOFTWARE_DDRAW],
index a07a0bd..fe2d2c2 100644 (file)
@@ -742,6 +742,9 @@ evas_render_method_list(void)
    Eina_List *methods = NULL;
 
    /* FIXME: get from modules - this is currently coded-in */
+#ifdef BUILD_ENGINE_SOFTWARE_GDI
+   methods = eina_list_append(methods, strdup("software_gdi"));
+#endif
 #ifdef BUILD_ENGINE_SOFTWARE_DDRAW
    methods = eina_list_append(methods, strdup("software_ddraw"));
 #endif
index 897e3a8..3ddd1f3 100644 (file)
@@ -8,7 +8,7 @@ fb \
 gl_common \
 gl_x11 \
 gl_glew \
-software_win32_gdi \
+software_gdi \
 software_ddraw \
 software_x11 \
 xrender_x11 \
diff --git a/src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h b/src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h
new file mode 100644 (file)
index 0000000..a95b07e
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef __EVAS_ENGINE_SOFTWARE_GDI_H__
+#define __EVAS_ENGINE_SOFTWARE_GDI_H__
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+
+typedef struct _Evas_Engine_Info_Software_Gdi Evas_Engine_Info_Software_Gdi;
+
+struct _Evas_Engine_Info_Software_Gdi
+{
+   /* PRIVATE - don't mess with this baby or evas will poke its tongue out */
+   /* at you and make nasty noises */
+   Evas_Engine_Info magic;
+
+   struct {
+      HWND         window;
+      HBITMAP      mask;
+      int          depth;
+      int          rotation;
+      unsigned int layered    : 1;
+      unsigned int fullscreen : 1;
+   } info;
+};
+
+
+#endif /* __EVAS_ENGINE_SOFTWARE_GDI_H__ */
diff --git a/src/modules/engines/software_gdi/Makefile.am b/src/modules/engines/software_gdi/Makefile.am
new file mode 100644 (file)
index 0000000..daf5f85
--- /dev/null
@@ -0,0 +1,32 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+-I$(top_srcdir)/src/modules/engines \
+@EINA_CFLAGS@ \
+@FREETYPE_CFLAGS@ \
+@evas_engine_software_gdi_cflags@
+
+if BUILD_ENGINE_SOFTWARE_GDI
+
+pkgdir = $(libdir)/evas/modules/engines/software_gdi/$(MODULE_ARCH)
+
+pkg_LTLIBRARIES = module.la
+module_la_SOURCES = \
+evas_engine.c \
+evas_outbuf.c \
+evas_gdi_buffer.c \
+evas_gdi_main.c
+
+module_la_LIBADD = $(top_builddir)/src/lib/libevas.la @EINA_LIBS@ @evas_engine_software_gdi_libs@
+module_la_LDFLAGS = -no-undefined -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
+
+include_HEADERS = Evas_Engine_Software_Gdi.h
+
+endif
+
+EXTRA_DIST = evas_engine.h
diff --git a/src/modules/engines/software_gdi/evas_engine.c b/src/modules/engines/software_gdi/evas_engine.c
new file mode 100644 (file)
index 0000000..5b73cad
--- /dev/null
@@ -0,0 +1,363 @@
+#include "evas_common.h"
+#include "evas_private.h"
+#include "evas_engine.h"
+#include "Evas_Engine_Software_Gdi.h"
+
+/* function tables - filled in later (func and parent func) */
+static Evas_Func func, pfunc;
+
+/* engine struct data */
+typedef struct _Render_Engine Render_Engine;
+
+struct _Render_Engine
+{
+   Tilebuf          *tb;
+   Outbuf           *ob;
+   Tilebuf_Rect     *rects;
+   Eina_Inlist      *cur_rect;
+   int               end : 1;
+};
+
+
+static void *
+_output_setup(int          width,
+              int          height,
+              int          rot,
+              HWND         window,
+              HBITMAP      mask,
+              int          depth,
+              unsigned int layered,
+              unsigned int fullscreen)
+{
+   Render_Engine *re;
+
+   re = calloc(1, sizeof(Render_Engine));
+   if (!re)
+     return NULL;
+
+   /* if we haven't initialized - init (automatic abort if already done) */
+   evas_common_cpu_init();
+
+   evas_common_blend_init();
+   evas_common_image_init();
+   evas_common_convert_init();
+   evas_common_scale_init();
+   evas_common_rectangle_init();
+   evas_common_gradient_init();
+   evas_common_polygon_init();
+   evas_common_line_init();
+   evas_common_font_init();
+   evas_common_draw_init();
+   evas_common_tilebuf_init();
+
+   evas_software_gdi_outbuf_init();
+
+   if (width <= 0)
+     width = 1;
+   if (height <= 0)
+     height = 1;
+
+   re->ob = evas_software_gdi_outbuf_setup(width, height, rot,
+                                           OUTBUF_DEPTH_INHERIT,
+                                           window, mask, depth, layered, fullscreen,
+                                           0, 0);
+   if (!re->ob)
+     {
+       free(re);
+       return NULL;
+     }
+
+   /* for updates return 1 big buffer, but only use portions of it, also cache
+    it and keep it around until an idle_flush */
+   /* disable for now - i am hunting down why some expedite tests are slower,
+    * as well as shaped stuff is broken and probable non-32bpp is broken as
+    * convert funcs dont do the right thing
+    *
+   re->ob->onebuf = 1;
+    */
+
+   re->tb = evas_common_tilebuf_new(width, height);
+   if (!re->tb)
+     {
+       evas_software_gdi_outbuf_free(re->ob);
+       free(re);
+       return NULL;
+     }
+   /* in preliminary tests 16x16 gave highest framerates */
+   evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+
+   return re;
+}
+
+
+/* engine api this module provides */
+
+static void *
+eng_info(Evas *e __UNUSED__)
+{
+   Evas_Engine_Info_Software_Gdi *info;
+
+   info = calloc(1, sizeof(Evas_Engine_Info_Software_Gdi));
+   if (!info) return NULL;
+   info->magic.magic = rand();
+   return info;
+}
+
+static void
+eng_info_free(Evas *e __UNUSED__, void *info)
+{
+   Evas_Engine_Info_Software_Gdi *in;
+
+   in = (Evas_Engine_Info_Software_Gdi *)info;
+   free(in);
+}
+
+static int
+eng_setup(Evas *e, void *in)
+{
+   Render_Engine                 *re;
+   Evas_Engine_Info_Software_Gdi *info;
+
+   info = (Evas_Engine_Info_Software_Gdi *)in;
+   if (!e->engine.data.output)
+     e->engine.data.output = _output_setup(e->output.w,
+                                           e->output.h,
+                                           info->info.rotation,
+                                           info->info.window,
+                                           info->info.mask,
+                                           info->info.depth,
+                                           info->info.layered,
+                                           info->info.fullscreen);
+   else
+     {
+       int ponebuf = 0;
+
+       re = e->engine.data.output;
+       ponebuf = re->ob->onebuf;
+       evas_software_gdi_outbuf_free(re->ob);
+       re->ob = evas_software_gdi_outbuf_setup(e->output.w,
+                                                e->output.h,
+                                                info->info.rotation,
+                                                OUTBUF_DEPTH_INHERIT,
+                                                info->info.window,
+                                                info->info.mask,
+                                                info->info.depth,
+                                                info->info.layered,
+                                                info->info.fullscreen,
+                                                0, 0);
+       re->ob->onebuf = ponebuf;
+     }
+   if (!e->engine.data.output) return;
+   if (!e->engine.data.context)
+     e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
+
+   re = e->engine.data.output;
+}
+
+static void
+eng_output_free(void *data)
+{
+   Render_Engine *re;
+
+   if (!data) return;
+
+   re = (Render_Engine *)data;
+   evas_software_gdi_outbuf_free(re->ob);
+   evas_common_tilebuf_free(re->tb);
+   if (re->rects) evas_common_tilebuf_free_render_rects(re->rects);
+   free(re);
+
+   evas_common_font_shutdown();
+   evas_common_image_shutdown();
+}
+
+static void
+eng_output_resize(void *data, int width, int height)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_software_gdi_outbuf_reconfigure(re->ob,
+                                        width,
+                                        height,
+                                        evas_software_gdi_outbuf_rot_get(re->ob),
+                                        OUTBUF_DEPTH_INHERIT);
+   evas_common_tilebuf_free(re->tb);
+   re->tb = evas_common_tilebuf_new(width, height);
+   if (re->tb)
+     evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+}
+
+static void
+eng_output_tile_size_set(void *data, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_common_tilebuf_set_tile_size(re->tb, w, h);
+}
+
+static void
+eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
+}
+
+static void
+eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
+}
+
+static void
+eng_output_redraws_clear(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_common_tilebuf_clear(re->tb);
+}
+
+static void *
+eng_output_redraws_next_update_get(void *data,
+                                   int  *x,
+                                   int  *y,
+                                   int  *w,
+                                   int  *h,
+                                   int  *cx,
+                                   int  *cy,
+                                   int  *cw,
+                                   int  *ch)
+{
+   Render_Engine *re;
+   RGBA_Image    *surface;
+   Tilebuf_Rect  *rect;
+   int            ux;
+   int            uy;
+   int            uw;
+   int            uh;
+
+   re = (Render_Engine *)data;
+   if (re->end)
+     {
+       re->end = 0;
+       return NULL;
+     }
+   if (!re->rects)
+     {
+       re->rects = evas_common_tilebuf_get_render_rects(re->tb);
+       re->cur_rect = EINA_INLIST_GET(re->rects);
+     }
+   if (!re->cur_rect) return NULL;
+   rect = (Tilebuf_Rect *)re->cur_rect;
+   ux = rect->x;
+   uy = rect->y;
+   uw = rect->w;
+   uh = rect->h;
+   re->cur_rect = re->cur_rect->next;
+   if (!re->cur_rect)
+     {
+       evas_common_tilebuf_free_render_rects(re->rects);
+       re->rects = NULL;
+       re->end = 1;
+     }
+
+   surface = evas_software_gdi_outbuf_new_region_for_update(re->ob,
+                                                            ux,
+                                                            uy,
+                                                            uw,
+                                                            uh,
+                                                            cx,
+                                                            cy,
+                                                            cw,
+                                                            ch);
+
+   *x = ux;
+   *y = uy;
+   *w = uw;
+   *h = uh;
+
+   return surface;
+}
+
+static void
+eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+#ifdef BUILD_PIPE_RENDER
+   evas_common_pipe_begin(surface);
+   evas_common_pipe_flush(surface);
+#endif
+   evas_software_gdi_outbuf_push_updated_region(re->ob, surface, x, y, w, h);
+   evas_software_gdi_outbuf_free_region_for_update(re->ob, surface);
+   evas_common_cpu_end_opt();
+}
+
+static void
+eng_output_flush(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_software_gdi_outbuf_flush(re->ob);
+}
+
+static void
+eng_output_idle_flush(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   evas_software_gdi_outbuf_idle_flush(re->ob);
+}
+
+
+/* module advertising code */
+EAPI int
+module_open(Evas_Module *em)
+{
+   if (!em) return 0;
+   /* get whatever engine module we inherit from */
+   if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
+   /* store it for later use */
+   func = pfunc;
+   /* now to override methods */
+#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
+   ORD(info);
+   ORD(info_free);
+   ORD(setup);
+   ORD(output_free);
+   ORD(output_resize);
+   ORD(output_tile_size_set);
+   ORD(output_redraws_rect_add);
+   ORD(output_redraws_rect_del);
+   ORD(output_redraws_clear);
+   ORD(output_redraws_next_update_get);
+   ORD(output_redraws_next_update_push);
+   ORD(output_flush);
+   ORD(output_idle_flush);
+   /* now advertise out own api */
+   em->functions = (void *)(&func);
+   return 1;
+}
+
+EAPI void
+module_close(void)
+{
+}
+
+EAPI Evas_Module_Api evas_modapi =
+{
+   EVAS_MODULE_API_VERSION,
+   EVAS_MODULE_TYPE_ENGINE,
+   "software_gdi",
+   "none"
+};
diff --git a/src/modules/engines/software_gdi/evas_engine.h b/src/modules/engines/software_gdi/evas_engine.h
new file mode 100644 (file)
index 0000000..551c52b
--- /dev/null
@@ -0,0 +1,180 @@
+#ifndef EVAS_ENGINE_H
+#define EVAS_ENGINE_H
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+
+typedef enum _Outbuf_Depth Outbuf_Depth;
+
+enum _Outbuf_Depth
+{
+   OUTBUF_DEPTH_NONE,
+   OUTBUF_DEPTH_INHERIT,
+   OUTBUF_DEPTH_RGB_16BPP_565_565_DITHERED,
+   OUTBUF_DEPTH_RGB_32BPP_888_8888,
+   OUTBUF_DEPTH_LAST
+};
+
+typedef struct BITMAPINFO_GDI     BITMAPINFO_GDI;
+typedef struct _Outbuf            Outbuf;
+typedef struct _Outbuf_Region     Outbuf_Region;
+typedef struct _Gdi_Output_Buffer Gdi_Output_Buffer;
+
+struct BITMAPINFO_GDI
+{
+   BITMAPINFOHEADER bih;
+   DWORD            masks[3];
+};
+
+struct _Outbuf
+{
+   Outbuf_Depth          depth;
+   int                   width;
+   int                   height;
+   int                   rot;
+   int                   onebuf;
+
+   struct {
+      Convert_Pal       *pal;
+      struct {
+         BITMAPINFO_GDI *bitmap_info;
+         HWND            window;
+         HBITMAP         mask;
+         HDC             dc;
+         int             depth;
+         unsigned char   layered    : 1;
+         unsigned char   fullscreen : 1;
+      } gdi;
+
+      /* 1 big buffer for updates - flush on idle_flush */
+      RGBA_Image        *onebuf;
+      Eina_List         *onebuf_regions;
+
+      /* a list of pending regions to write to the target */
+      Eina_List         *pending_writes;
+      /* a list of previous frame pending regions to write to the target */
+      Eina_List         *prev_pending_writes;
+
+      unsigned char      mask_dither       : 1;
+      unsigned char      destination_alpha : 1;
+      unsigned char      debug             : 1;
+      unsigned char      synced            : 1;
+   } priv;
+};
+
+struct _Outbuf_Region
+{
+   Gdi_Output_Buffer *gdiob;
+   int                x;
+   int                y;
+   int                width;
+   int                height;
+};
+
+struct _Gdi_Output_Buffer
+{
+   BITMAPINFO_GDI *bitmap_info;
+   HBITMAP         bitmap;
+   HDC             dc;
+   int             width;
+   int             height;
+   void           *data;
+   int             depth;
+   int             pitch;
+   int             psize;
+};
+
+/* evas_gdi_main.c */
+
+int evas_software_gdi_init (HWND         window,
+                            HBITMAP      mask,
+                            int          depth,
+                            unsigned int layered,
+                            unsigned int fullscreen,
+                            Outbuf      *buf);
+
+void evas_software_gdi_shutdown(Outbuf *buf);
+
+void evas_software_gdi_bitmap_resize(Outbuf *buf);
+
+/* evas_gdi_buffer.c */
+
+Gdi_Output_Buffer *evas_software_gdi_output_buffer_new(HDC             dc,
+                                                       BITMAPINFO_GDI *bitmap_info,
+                                                       int             depth,
+                                                       int             width,
+                                                       int             height,
+                                                       void           *data);
+
+void evas_software_gdi_output_buffer_free(Gdi_Output_Buffer *gdiob);
+
+void evas_software_gdi_output_buffer_paste(Gdi_Output_Buffer *gdiob,
+                                           int                x,
+                                           int                y);
+
+DATA8 *evas_software_gdi_output_buffer_data(Gdi_Output_Buffer *gdiob,
+                                            int               *pitch);
+
+int evas_software_gdi_output_buffer_depth(Gdi_Output_Buffer *gdiob);
+
+/* evas_outbuf.c */
+
+void evas_software_gdi_outbuf_init(void);
+
+void evas_software_gdi_outbuf_free(Outbuf *buf);
+
+Outbuf *evas_software_gdi_outbuf_setup(int          width,
+                                       int          height,
+                                       int          rotation,
+                                       Outbuf_Depth depth,
+                                       HWND         window,
+                                       HBITMAP      mask,
+                                       int          w_depth,
+                                       unsigned int layered,
+                                       unsigned int fullscreen,
+                                       int          mask_dither,
+                                       int          destination_alpha);
+
+void evas_software_gdi_outbuf_reconfigure(Outbuf      *buf,
+                                          int          width,
+                                          int          height,
+                                          int          rotation,
+                                          Outbuf_Depth depth);
+
+RGBA_Image *evas_software_gdi_outbuf_new_region_for_update(Outbuf *buf,
+                                                           int     x,
+                                                           int     y,
+                                                           int     w,
+                                                           int     h,
+                                                           int    *cx,
+                                                           int    *cy,
+                                                           int    *cw,
+                                                           int    *ch);
+
+void evas_software_gdi_outbuf_push_updated_region(Outbuf     *buf,
+                                                  RGBA_Image *update,
+                                                  int         x,
+                                                  int         y,
+                                                  int         w,
+                                                  int         h);
+
+void evas_software_gdi_outbuf_free_region_for_update(Outbuf     *buf,
+                                                     RGBA_Image *update);
+
+void evas_software_gdi_outbuf_flush(Outbuf *buf);
+
+void evas_software_gdi_outbuf_idle_flush(Outbuf *buf);
+
+int evas_software_gdi_outbuf_width_get(Outbuf *buf);
+
+int evas_software_gdi_outbuf_height_get(Outbuf *buf);
+
+Outbuf_Depth evas_software_gdi_outbuf_depth_get(Outbuf *buf);
+
+int evas_software_gdi_outbuf_rot_get(Outbuf *buf);
+
+
+#endif /* EVAS_ENGINE_H */
diff --git a/src/modules/engines/software_gdi/evas_gdi_buffer.c b/src/modules/engines/software_gdi/evas_gdi_buffer.c
new file mode 100644 (file)
index 0000000..66a5abf
--- /dev/null
@@ -0,0 +1,88 @@
+#include <string.h>
+
+#include "evas_common.h"
+#include "evas_engine.h"
+
+Gdi_Output_Buffer *
+evas_software_gdi_output_buffer_new(HDC             dc,
+                                    BITMAPINFO_GDI *bitmap_info,
+                                    int             depth,
+                                    int             width,
+                                    int             height,
+                                    void           *data)
+{
+   Gdi_Output_Buffer *gdiob;
+
+   gdiob = calloc(1, sizeof(Gdi_Output_Buffer));
+   if (!gdiob) return NULL;
+
+   if (!data)
+     {
+        bitmap_info->bih.biWidth = width;
+        bitmap_info->bih.biHeight = -height;
+        bitmap_info->bih.biSizeImage = (depth >> 3) * width * height;
+        gdiob->bitmap = CreateDIBSection(dc,
+                                         (const BITMAPINFO *)bitmap_info,
+                                         DIB_RGB_COLORS,
+                                         (void **)(&data),
+                                         NULL,
+                                         0);
+        if (!gdiob->bitmap)
+          {
+             free(gdiob);
+             return NULL;
+          }
+     }
+
+   gdiob->bitmap_info = bitmap_info;
+   gdiob->dc = dc;
+   gdiob->data = data;
+   gdiob->width = width;
+   gdiob->height = height;
+   gdiob->depth = depth;
+   gdiob->pitch = width * (depth >> 3);
+/*    gdiob->psize = gdiob->pitch * height; */
+
+   return gdiob;
+}
+
+void
+evas_software_gdi_output_buffer_free(Gdi_Output_Buffer *gdiob)
+{
+   DeleteObject(gdiob->bitmap);
+   free(gdiob);
+}
+
+void
+evas_software_gdi_output_buffer_paste(Gdi_Output_Buffer *gdiob,
+                                      int                x,
+                                      int                y)
+{
+   HDC     dc;
+
+   dc = CreateCompatibleDC(gdiob->dc);
+   if (!dc)
+     return;
+   SelectObject(dc, gdiob->bitmap);
+   BitBlt(gdiob->dc,
+          x, y,
+          gdiob->width, gdiob->height,
+          dc,
+          0, 0,
+          SRCCOPY);
+   DeleteDC(dc);
+}
+
+DATA8 *
+evas_software_gdi_output_buffer_data(Gdi_Output_Buffer *gdiob,
+                                     int               *pitch)
+{
+   if (pitch) *pitch = gdiob->pitch;
+   return gdiob->data;
+}
+
+int
+evas_software_gdi_output_buffer_depth(Gdi_Output_Buffer *gdiob)
+{
+   return gdiob->depth;
+}
diff --git a/src/modules/engines/software_gdi/evas_gdi_main.c b/src/modules/engines/software_gdi/evas_gdi_main.c
new file mode 100644 (file)
index 0000000..0a793a7
--- /dev/null
@@ -0,0 +1,116 @@
+#include "evas_common.h"
+#include "evas_engine.h"
+
+
+int
+evas_software_gdi_init (HWND         window,
+                        HBITMAP      mask,
+                        int          depth,
+                        unsigned int layered,
+                        unsigned int fullscreen __UNUSED__,
+                        Outbuf *buf)
+{
+   RECT window_rect;
+   SIZE mask_size;
+
+   if (!window)
+     {
+        fprintf (stderr, "[Evas] [Engine] [GDI] Window is NULL\n");
+        return 0;
+     }
+
+   buf->priv.gdi.window = window;
+   buf->priv.gdi.mask = mask;
+   buf->priv.gdi.dc = GetDC(window);
+   if (!buf->priv.gdi.dc)
+     {
+        fprintf (stderr, "[Evas] [Engine] [GDI] Can not get DC\n");
+        return 0;
+     }
+
+   /* FIXME: check depth */
+   if (depth != GetDeviceCaps(buf->priv.gdi.dc, BITSPIXEL))
+     {
+        fprintf (stderr, "[Evas] [Engine] [GDI] no compatible depth\n");
+        ReleaseDC(window, buf->priv.gdi.dc);
+        return 0;
+     }
+   buf->priv.gdi.depth = depth;
+
+   /* mask */
+   if (layered && mask)
+     {
+        if (GetBitmapDimensionEx(mask, &mask_size) &&
+            GetClientRect(window, &window_rect))
+          {
+             if ((mask_size.cx == window_rect.right) &&
+                 (mask_size.cy == window_rect.bottom))
+               {
+/*                  if (SetLayeredWindowAttributes(window, RGB(0, 0, 0), 255, LWA_COLORKEY)) */
+/*                    { */
+/*                    } */
+               }
+          }
+     }
+
+   /* FIXME: support fullscreen */
+
+   buf->priv.gdi.bitmap_info = (BITMAPINFO_GDI *)malloc(sizeof(BITMAPINFO_GDI));
+   if (!buf->priv.gdi.bitmap_info)
+     {
+        fprintf (stderr, "[Evas] [Engine] [GDI] Can not allocate bitmap info\n");
+        ReleaseDC(window, buf->priv.gdi.dc);
+        return 0;
+     }
+
+   buf->priv.gdi.bitmap_info->bih.biSize = sizeof(BITMAPINFOHEADER);
+   buf->priv.gdi.bitmap_info->bih.biWidth = buf->width;
+   buf->priv.gdi.bitmap_info->bih.biHeight = -buf->height;
+   buf->priv.gdi.bitmap_info->bih.biPlanes = 1;
+   buf->priv.gdi.bitmap_info->bih.biSizeImage = (buf->priv.gdi.depth >> 3) * buf->width * buf->height;
+   buf->priv.gdi.bitmap_info->bih.biXPelsPerMeter = 0;
+   buf->priv.gdi.bitmap_info->bih.biYPelsPerMeter = 0;
+   buf->priv.gdi.bitmap_info->bih.biClrUsed = 0;
+   buf->priv.gdi.bitmap_info->bih.biClrImportant = 0;
+   buf->priv.gdi.bitmap_info->bih.biBitCount = buf->priv.gdi.depth;
+   buf->priv.gdi.bitmap_info->bih.biCompression = BI_BITFIELDS;
+
+   switch (depth)
+     {
+      case 16:
+         buf->priv.gdi.bitmap_info->masks[0] = 0x0000f800;
+         buf->priv.gdi.bitmap_info->masks[1] = 0x000007e0;
+         buf->priv.gdi.bitmap_info->masks[2] = 0x0000001f;
+         break;
+      case 32:
+         buf->priv.gdi.bitmap_info->masks[0] = 0x00ff0000;
+         buf->priv.gdi.bitmap_info->masks[1] = 0x0000ff00;
+         buf->priv.gdi.bitmap_info->masks[2] = 0x000000ff;
+         break;
+      default:
+        fprintf (stderr, "[Evas] [Engine] [GDI] wrong depth\n");
+        free(buf->priv.gdi.bitmap_info);
+        ReleaseDC(window, buf->priv.gdi.dc);
+        return 0;
+     }
+
+   return 1;
+}
+
+void
+evas_software_gdi_shutdown(Outbuf *buf)
+{
+   if (!buf)
+     return;
+
+   free(buf->priv.gdi.bitmap_info);
+   ReleaseDC(buf->priv.gdi.window, buf->priv.gdi.dc);
+}
+
+void
+evas_software_gdi_bitmap_resize(Outbuf *buf)
+{
+   buf->priv.gdi.bitmap_info->bih.biWidth = buf->width;
+   buf->priv.gdi.bitmap_info->bih.biHeight = -buf->height;
+   buf->priv.gdi.bitmap_info->bih.biSizeImage = (buf->priv.gdi.depth >> 3) * buf->width * buf->height;
+}
diff --git a/src/modules/engines/software_gdi/evas_outbuf.c b/src/modules/engines/software_gdi/evas_outbuf.c
new file mode 100644 (file)
index 0000000..bc56dfd
--- /dev/null
@@ -0,0 +1,509 @@
+#include "evas_common.h"
+#include "evas_engine.h"
+
+
+static Eina_List *gdipool = NULL;
+static int gdisize = 0;
+static int gdimemlimit = 10 * 1024 * 1024;
+static int gdicountlimit = 32;
+
+static Gdi_Output_Buffer *
+_find_gdiob(HDC dc, BITMAPINFO_GDI *bitmap_info, int depth, int w, int h, void *data)
+{
+   Eina_List         *l;
+   Eina_List         *gdil;
+   Gdi_Output_Buffer *gdiob = NULL;
+   Gdi_Output_Buffer *gdiob2;
+   int                sz;
+   int                lbytes;
+   int                bpp;
+   int                fitness = 0x7fffffff;
+
+   bpp = depth >> 3;
+   if (bpp == 3) bpp = 4;
+   lbytes = (((w * bpp) + 3) / 4) * 4;
+   sz = lbytes * h;
+   EINA_LIST_FOREACH(gdipool, l, gdiob2)
+     {
+       int szdif;
+
+        if ((gdiob2->dc != dc) ||
+            (gdiob2->bitmap_info != bitmap_info) ||
+            (gdiob2->depth != depth))
+         continue;
+       szdif = gdiob2->psize - sz;
+       if (szdif < 0) continue;
+       if (szdif == 0)
+         {
+            gdiob = gdiob2;
+            gdil = l;
+            goto have_gdiob;
+         }
+       if (szdif < fitness)
+         {
+            fitness = szdif;
+            gdiob = gdiob2;
+            gdil = l;
+         }
+     }
+   if ((fitness > (100 * 100)) || (!gdiob))
+     return evas_software_gdi_output_buffer_new(dc, bitmap_info, depth, w, h, data);
+
+   have_gdiob:
+   gdipool = eina_list_remove_list(gdipool, gdil);
+   gdiob->width = w;
+   gdiob->height = h;
+   gdiob->pitch = lbytes;
+   gdisize -= gdiob->psize * (gdiob->depth >> 3);
+
+   return gdiob;
+}
+
+static void
+_unfind_gdiob(Gdi_Output_Buffer *gdiob)
+{
+   gdipool = eina_list_prepend(gdipool, gdiob);
+   gdisize += gdiob->psize * (gdiob->depth >> 3);
+   while ((gdisize > (gdimemlimit)) ||
+          (eina_list_count(gdipool) > gdicountlimit))
+     {
+        Eina_List *xl;
+
+        xl = eina_list_last(gdipool);
+        if (!xl)
+          {
+             gdisize = 0;
+             break;
+          }
+        gdiob = xl->data;
+        gdipool = eina_list_remove_list(gdipool, xl);
+        evas_software_gdi_output_buffer_free(gdiob);
+     }
+}
+
+static void
+_clear_gdiob()
+{
+   while (gdipool)
+     {
+       Gdi_Output_Buffer *gdiob;
+
+       gdiob = gdipool->data;
+       gdipool = eina_list_remove_list(gdipool, gdipool);
+       evas_software_gdi_output_buffer_free(gdiob);
+     }
+   gdisize = 0;
+}
+
+void
+evas_software_gdi_outbuf_init(void)
+{
+}
+
+void
+evas_software_gdi_outbuf_free(Outbuf *buf)
+{
+   if (!buf)
+     return;
+
+   while (buf->priv.pending_writes)
+     {
+       RGBA_Image *im;
+       Outbuf_Region *obr;
+
+       im = buf->priv.pending_writes->data;
+       buf->priv.pending_writes = eina_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
+       obr = im->extended_info;
+       evas_cache_image_drop(&im->cache_entry);
+       if (obr->gdiob) _unfind_gdiob(obr->gdiob);
+/*     if (obr->mxob) _unfind_xob(obr->mxob, 0); */
+       free(obr);
+     }
+   evas_software_gdi_outbuf_idle_flush(buf);
+   evas_software_gdi_outbuf_flush(buf);
+
+   evas_software_gdi_shutdown(buf);
+   free(buf);
+}
+
+Outbuf *
+evas_software_gdi_outbuf_setup(int          width,
+                               int          height,
+                               int          rotation,
+                               Outbuf_Depth depth,
+                               HWND         window,
+                               HBITMAP      mask,
+                               int          w_depth,
+                               unsigned int layered,
+                               unsigned int fullscreen,
+                               int          mask_dither,
+                               int          destination_alpha)
+{
+   Outbuf *buf;
+
+   buf = (Outbuf *)calloc(1, sizeof(Outbuf));
+   if (!buf)
+      return NULL;
+
+   buf->width = width;
+   buf->height = height;
+   buf->depth = depth;
+   buf->rot = rotation;
+
+   buf->priv.mask_dither = mask_dither;
+   buf->priv.destination_alpha = destination_alpha;
+
+   if (!evas_software_gdi_init(window, mask, w_depth, layered, fullscreen, buf))
+     {
+        free(buf);
+        return NULL;
+     }
+
+   {
+      Gfx_Func_Convert  conv_func;
+      Gdi_Output_Buffer *gdiob;
+
+      gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc, buf->priv.gdi.bitmap_info, w_depth, 1, 1, NULL);
+
+      conv_func = NULL;
+      if (gdiob)
+        {
+           if ((rotation == 0) || (rotation == 180))
+             conv_func = evas_common_convert_func_get(0,
+                                                      width,
+                                                      height,
+                                                      evas_software_gdi_output_buffer_depth (gdiob),
+                                                      buf->priv.gdi.bitmap_info->masks[0],
+                                                      buf->priv.gdi.bitmap_info->masks[1],
+                                                      buf->priv.gdi.bitmap_info->masks[2],
+                                                      PAL_MODE_NONE,
+                                                      rotation);
+           else if ((rotation == 90) || (rotation == 270))
+             conv_func = evas_common_convert_func_get(0,
+                                                      height,
+                                                      width,
+                                                      evas_software_gdi_output_buffer_depth (gdiob),
+                                                      buf->priv.gdi.bitmap_info->masks[0],
+                                                      buf->priv.gdi.bitmap_info->masks[1],
+                                                      buf->priv.gdi.bitmap_info->masks[2],
+                                                      PAL_MODE_NONE,
+                                                      rotation);
+
+           evas_software_gdi_output_buffer_free(gdiob);
+
+           if (!conv_func)
+             {
+                fprintf(stderr, ".[ Evas Error ].\n"
+                        " {\n"
+                        "  At depth         %i:\n"
+                        "  RGB format mask: %08lx, %08lx, %08lx\n"
+                        "  Not supported by and compiled in converters!\n"
+                        " }\n",
+                        buf->priv.gdi.depth,
+                        buf->priv.gdi.bitmap_info->masks[0],
+                        buf->priv.gdi.bitmap_info->masks[1],
+                        buf->priv.gdi.bitmap_info->masks[2]);
+             }
+        }
+      if (buf->priv.gdi.mask != mask)
+        buf->priv.gdi.mask = mask;
+   }
+
+   return buf;
+}
+
+void
+evas_software_gdi_outbuf_reconfigure(Outbuf      *buf,
+                                     int          width,
+                                     int          height,
+                                     int          rotation,
+                                     Outbuf_Depth depth)
+{
+   if ((width == buf->width) && (height == buf->height) &&
+       (rotation == buf->rot) && (depth == buf->depth))
+     return;
+   buf->width = width;
+   buf->height = height;
+   buf->rot = rotation;
+   evas_software_gdi_bitmap_resize(buf);
+}
+
+RGBA_Image *
+evas_software_gdi_outbuf_new_region_for_update(Outbuf *buf,
+                                               int     x,
+                                               int     y,
+                                               int     w,
+                                               int     h,
+                                               int    *cx,
+                                               int    *cy,
+                                               int    *cw,
+                                               int    *ch)
+{
+   RGBA_Image    *im;
+   Outbuf_Region *obr;
+   int            bpl = 0;
+   int            alpha = 0;
+
+   obr = calloc(1, sizeof(Outbuf_Region));
+   obr->x = x;
+   obr->y = y;
+   obr->width = w;
+   obr->height = h;
+   *cx = 0;
+   *cy = 0;
+   *cw = w;
+   *ch = h;
+
+   alpha = ((buf->priv.gdi.mask) || (buf->priv.destination_alpha));
+
+   if ((buf->rot == 0) &&
+       (buf->priv.gdi.bitmap_info->masks[0] == 0xff0000) &&
+       (buf->priv.gdi.bitmap_info->masks[1] == 0x00ff00) &&
+       (buf->priv.gdi.bitmap_info->masks[2] == 0x0000ff))
+     {
+        obr->gdiob = _find_gdiob(buf->priv.gdi.dc,
+                                 buf->priv.gdi.bitmap_info,
+                                 buf->priv.gdi.depth,
+                                 w, h, NULL);
+/*      obr->gdiob = evas_software_gdi_output_buffer_new(buf->priv.gdi.dc, */
+/*                                                         buf->priv.gdi.bitmap_info, */
+/*                                                         buf->priv.gdi.depth, */
+/*                                                         w, h, */
+/*                                                         NULL); */
+        im = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
+                                                 w, h,
+                                                 (DATA32 *)evas_software_gdi_output_buffer_data(obr->gdiob, &bpl),
+                                                 alpha, EVAS_COLORSPACE_ARGB8888);
+        im->extended_info = obr;
+/*     if (buf->priv.gdi.mask) */
+/*       obr->mgdiob = _find_gdiob(buf->priv.gdi.dc, */
+/*                                     buf->priv.gdi.bitmap_info, */
+/*                                     1, */
+/*                                     w, h, NULL); */
+     }
+   else
+     {
+        im = (RGBA_Image *) evas_cache_image_empty(evas_common_image_cache_get());
+        im->cache_entry.flags.alpha |= alpha ? 1 : 0;
+        evas_cache_image_surface_alloc(&im->cache_entry, w, h);
+        im->extended_info = obr;
+        if ((buf->rot == 0) || (buf->rot == 180))
+          obr->gdiob = _find_gdiob(buf->priv.gdi.dc,
+                                   buf->priv.gdi.bitmap_info,
+                                   buf->priv.gdi.depth,
+                                   w, h, NULL);
+/*
+          obr->gdiob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp,
+                                                           buf->priv.dd.vis,
+                                                           buf->priv.dd.depth,
+                                                           w, h,
+                                                           use_shm,
+                                                           NULL);
+ */
+        else if ((buf->rot == 90) || (buf->rot == 270))
+          obr->gdiob = _find_gdiob(buf->priv.gdi.dc,
+                                   buf->priv.gdi.bitmap_info,
+                                   buf->priv.gdi.depth,
+                                   w, h, NULL);
+/*
+          obr->gdiob = evas_software_x11_x_output_buffer_new(buf->priv.dd.disp,
+                                                           buf->priv.dd.vis,
+                                                           buf->priv.dd.depth,
+                                                           h, w,
+                                                           use_shm,
+                                                           NULL);
+ */
+/*     if (buf->priv.gdi.mask) */
+/*       obr->mgdiob = _find_gdiob(buf->priv.gdi.dc, */
+/*                                     buf->priv.gdi.bitmap_info, */
+/*                                     1, */
+/*                                     w, h, NULL); */
+     }
+   if ((buf->priv.gdi.mask) || (buf->priv.destination_alpha))
+     /* FIXME: faster memset! */
+     memset(im->image.data, 0, w * h * sizeof(DATA32));
+
+   buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
+   return im;
+}
+
+void
+evas_software_gdi_outbuf_push_updated_region(Outbuf     *buf,
+                                             RGBA_Image *update,
+                                             int         x,
+                                             int         y,
+                                             int         w,
+                                             int         h)
+{
+   Gfx_Func_Convert conv_func;
+   Outbuf_Region   *obr;
+   DATA32          *src_data;
+   void            *data;
+   int              bpl = 0;
+
+   conv_func = NULL;
+   obr = update->extended_info;
+
+   if ((buf->rot == 0) || (buf->rot == 180))
+     conv_func = evas_common_convert_func_get(0, w, h,
+                                              evas_software_gdi_output_buffer_depth(obr->gdiob),
+                                              buf->priv.gdi.bitmap_info->masks[0],
+                                              buf->priv.gdi.bitmap_info->masks[1],
+                                              buf->priv.gdi.bitmap_info->masks[2],
+                                              PAL_MODE_NONE,
+                                              buf->rot);
+   else if ((buf->rot == 90) || (buf->rot == 270))
+     conv_func = evas_common_convert_func_get(0, h, w,
+                                              evas_software_gdi_output_buffer_depth(obr->gdiob),
+                                              buf->priv.gdi.bitmap_info->masks[0],
+                                              buf->priv.gdi.bitmap_info->masks[1],
+                                              buf->priv.gdi.bitmap_info->masks[2],
+                                              PAL_MODE_NONE,
+                                              buf->rot);
+   if (!conv_func) return;
+
+   data = evas_software_gdi_output_buffer_data(obr->gdiob, &bpl);
+   src_data = update->image.data;
+   if (buf->rot == 0)
+     {
+       obr->x = x;
+       obr->y = y;
+     }
+   else if (buf->rot == 90)
+     {
+       obr->x = y;
+       obr->y = buf->width - x - w;
+     }
+   else if (buf->rot == 180)
+     {
+       obr->x = buf->width - x - w;
+       obr->y = buf->height - y - h;
+     }
+   else if (buf->rot == 270)
+     {
+       obr->x = buf->height - y - h;
+       obr->y = x;
+     }
+   if ((buf->rot == 0) || (buf->rot == 180))
+     {
+       obr->width = w;
+       obr->height = h;
+     }
+   else if ((buf->rot == 90) || (buf->rot == 270))
+     {
+       obr->width = h;
+       obr->height = w;
+     }
+
+   if (data != src_data)
+     conv_func(src_data, data,
+               0,
+               bpl / (evas_software_gdi_output_buffer_depth(obr->gdiob) >> 3) - obr->width,
+               obr->width,
+               obr->height,
+               x,
+               y,
+               NULL);
+/*    if (obr->mxob) */
+/*      { */
+/*    int              yy; */
+/*     for (yy = 0; yy < obr->h; yy++) */
+/*       evas_software_xlib_x_write_mask_line(buf, obr->mxob, */
+/*                                           src_data + */
+/*                                           (yy * obr->w), obr->w, yy); */
+}
+
+void
+evas_software_gdi_outbuf_free_region_for_update(Outbuf     *buf __UNUSED__,
+                                                RGBA_Image *update __UNUSED__)
+{
+   /* no need to do anything - they are cleaned up on flush */
+}
+
+void
+evas_software_gdi_outbuf_flush(Outbuf *buf)
+{
+   Eina_List     *l;
+   RGBA_Image    *im;
+   Outbuf_Region *obr;
+
+   /* copy safely the images that need to be drawn onto the back surface */
+   EINA_LIST_FOREACH(buf->priv.pending_writes, l, im)
+     {
+       Gdi_Output_Buffer *gdiob;
+
+        obr = im->extended_info;
+        gdiob = obr->gdiob;
+        evas_software_gdi_output_buffer_paste(gdiob,
+                                              obr->x,
+                                              obr->y);
+/*         if (obr->mgdiob) */
+/*           evas_software_gdi_output_buffer_paste(obr->mgdiob, */
+/*                                                 buf->priv.x11.xlib.mask, */
+/*                                                 buf->priv.x11.xlib.gcm, */
+/*                                                 obr->x, obr->y, 0); */
+     }
+
+   while (buf->priv.prev_pending_writes)
+     {
+        im = buf->priv.prev_pending_writes->data;
+        buf->priv.prev_pending_writes =
+          eina_list_remove_list(buf->priv.prev_pending_writes,
+                                buf->priv.prev_pending_writes);
+        obr = im->extended_info;
+        evas_cache_image_drop(&im->cache_entry);
+        if (obr->gdiob) _unfind_gdiob(obr->gdiob);
+/*         if (obr->mgdiob) _unfind_gdiob(obr->mgdiob); */
+/*         if (obr->gdiob) evas_software_x11_x_output_buffer_free(obr->gdiob); */
+        free(obr);
+     }
+   buf->priv.prev_pending_writes = buf->priv.pending_writes;
+   buf->priv.pending_writes = NULL;
+
+   evas_common_cpu_end_opt();
+}
+
+void
+evas_software_gdi_outbuf_idle_flush(Outbuf *buf)
+{
+   while (buf->priv.prev_pending_writes)
+     {
+        RGBA_Image *im;
+        Outbuf_Region *obr;
+
+        im = buf->priv.prev_pending_writes->data;
+        buf->priv.prev_pending_writes =
+          eina_list_remove_list(buf->priv.prev_pending_writes,
+                                buf->priv.prev_pending_writes);
+        obr = im->extended_info;
+        evas_cache_image_drop((Image_Entry *)im);
+        if (obr->gdiob) _unfind_gdiob(obr->gdiob);
+/*         if (obr->mxob) _unfind_xob(obr->mxob, 0); */
+        free(obr);
+     }
+   _clear_gdiob();
+}
+
+int
+evas_software_gdi_outbuf_width_get(Outbuf *buf)
+{
+   return buf->width;
+}
+
+int
+evas_software_gdi_outbuf_height_get(Outbuf *buf)
+{
+   return buf->height;
+}
+
+Outbuf_Depth
+evas_software_gdi_outbuf_depth_get(Outbuf *buf)
+{
+   return buf->depth;
+}
+
+int
+evas_software_gdi_outbuf_rot_get(Outbuf *buf)
+{
+   return buf->rot;
+}