add GDI engine.

todo: fullscreen and shape support


SVN revision: 40310
This commit is contained in:
Vincent Torri 2009-04-23 03:20:51 +00:00
parent 7f1bde6cf4
commit 7f98415206
13 changed files with 1367 additions and 4 deletions

View 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

View 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"

View File

@ -0,0 +1,3 @@
Name: evas-software-gdi
Description: Evas software GDI engine
Version: @VERSION@

View 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],

View 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

View File

@ -8,7 +8,7 @@ fb \
gl_common \
gl_x11 \
gl_glew \
software_win32_gdi \
software_gdi \
software_ddraw \
software_x11 \
xrender_x11 \

View File

@ -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__ */

View File

@ -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

View File

@ -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"
};

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}