parent
7f1bde6cf4
commit
7f98415206
13 changed files with 1367 additions and 4 deletions
@ -0,0 +1,3 @@ |
||||
Name: evas-software-gdi |
||||
Description: Evas software GDI engine |
||||
Version: @VERSION@ |
@ -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__ */ |
@ -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
|
@ -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" |
||||
}; |
@ -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 */ |
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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, |
||||