diff --git a/legacy/evas/Makefile.am b/legacy/evas/Makefile.am index 0f3d285dd8..41103eac96 100644 --- a/legacy/evas/Makefile.am +++ b/legacy/evas/Makefile.am @@ -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 diff --git a/legacy/evas/configure.ac b/legacy/evas/configure.ac index a5d01950b6..4834e867e0 100644 --- a/legacy/evas/configure.ac +++ b/legacy/evas/configure.ac @@ -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/legacy/evas/evas-software-gdi.pc.in b/legacy/evas/evas-software-gdi.pc.in new file mode 100644 index 0000000000..097c4e1e80 --- /dev/null +++ b/legacy/evas/evas-software-gdi.pc.in @@ -0,0 +1,3 @@ +Name: evas-software-gdi +Description: Evas software GDI engine +Version: @VERSION@ diff --git a/legacy/evas/m4/evas_check_engine.m4 b/legacy/evas/m4/evas_check_engine.m4 index 367c281a28..2ad18f8806 100644 --- a/legacy/evas/m4/evas_check_engine.m4 +++ b/legacy/evas/m4/evas_check_engine.m4 @@ -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], diff --git a/legacy/evas/src/lib/canvas/evas_main.c b/legacy/evas/src/lib/canvas/evas_main.c index a07a0bd56d..fe2d2c2388 100644 --- a/legacy/evas/src/lib/canvas/evas_main.c +++ b/legacy/evas/src/lib/canvas/evas_main.c @@ -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 diff --git a/legacy/evas/src/modules/engines/Makefile.am b/legacy/evas/src/modules/engines/Makefile.am index 897e3a8507..3ddd1f3873 100644 --- a/legacy/evas/src/modules/engines/Makefile.am +++ b/legacy/evas/src/modules/engines/Makefile.am @@ -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/legacy/evas/src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h b/legacy/evas/src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h new file mode 100644 index 0000000000..a95b07eb0d --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h @@ -0,0 +1,29 @@ +#ifndef __EVAS_ENGINE_SOFTWARE_GDI_H__ +#define __EVAS_ENGINE_SOFTWARE_GDI_H__ + + +#define WIN32_LEAN_AND_MEAN +#include +#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/legacy/evas/src/modules/engines/software_gdi/Makefile.am b/legacy/evas/src/modules/engines/software_gdi/Makefile.am new file mode 100644 index 0000000000..daf5f85ff6 --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/Makefile.am @@ -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/legacy/evas/src/modules/engines/software_gdi/evas_engine.c b/legacy/evas/src/modules/engines/software_gdi/evas_engine.c new file mode 100644 index 0000000000..5b73cadc26 --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/evas_engine.c @@ -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/legacy/evas/src/modules/engines/software_gdi/evas_engine.h b/legacy/evas/src/modules/engines/software_gdi/evas_engine.h new file mode 100644 index 0000000000..551c52bc32 --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/evas_engine.h @@ -0,0 +1,180 @@ +#ifndef EVAS_ENGINE_H +#define EVAS_ENGINE_H + + +#define WIN32_LEAN_AND_MEAN +#include +#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/legacy/evas/src/modules/engines/software_gdi/evas_gdi_buffer.c b/legacy/evas/src/modules/engines/software_gdi/evas_gdi_buffer.c new file mode 100644 index 0000000000..66a5abfb2c --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/evas_gdi_buffer.c @@ -0,0 +1,88 @@ +#include + +#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/legacy/evas/src/modules/engines/software_gdi/evas_gdi_main.c b/legacy/evas/src/modules/engines/software_gdi/evas_gdi_main.c new file mode 100644 index 0000000000..0a793a7586 --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/evas_gdi_main.c @@ -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/legacy/evas/src/modules/engines/software_gdi/evas_outbuf.c b/legacy/evas/src/modules/engines/software_gdi/evas_outbuf.c new file mode 100644 index 0000000000..bc56dfd7a4 --- /dev/null +++ b/legacy/evas/src/modules/engines/software_gdi/evas_outbuf.c @@ -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; +}