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 \
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 \
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
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
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
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"
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"
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])
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
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
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"
--- /dev/null
+Name: evas-software-gdi
+Description: Evas software GDI engine
+Version: @VERSION@
])
+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],
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
gl_common \
gl_x11 \
gl_glew \
-software_win32_gdi \
+software_gdi \
software_ddraw \
software_x11 \
xrender_x11 \
--- /dev/null
+#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__ */
--- /dev/null
+
+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
--- /dev/null
+#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"
+};
--- /dev/null
+#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 */
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}
--- /dev/null
+#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;
+}