diff --git a/legacy/evas/Makefile.am b/legacy/evas/Makefile.am index 47fccd545a..1c7612051a 100644 --- a/legacy/evas/Makefile.am +++ b/legacy/evas/Makefile.am @@ -21,6 +21,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess \ evas-xrender-x11.pc \ evas-xrender-xcb.pc \ evas-software-ddraw.pc \ + evas-direct3d.pc \ evas-sdl.pc \ evas.pc \ evas.spec \ @@ -45,6 +46,7 @@ EXTRA_DIST = AUTHORS COPYING COPYING-PLAIN evas.c.in gendoc \ evas-xrender-x11.pc \ evas-xrender-xcb.pc \ evas-software-ddraw.pc \ + evas-direct3d.pc \ evas-sdl.pc \ evas.pc \ evas.spec.in evas.spec \ @@ -128,6 +130,10 @@ if BUILD_ENGINE_SOFTWARE_DDRAW psoftwareddraw = evas-software-ddraw.pc endif +if BUILD_ENGINE_DIRECT3D +pdirect3d = evas-direct3d.pc +endif + if BUILD_ENGINE_SDL psdl = evas-sdl.pc endif @@ -137,4 +143,4 @@ pkgconfig_DATA = \ evas.pc $(psoftwarex11) $(psoftwarexcb) $(pdirectfb) $(pframebuffer) \ $(psoftwarebuffer) $(psoftwareqtopia) $(popenglx11) $(pcairox11) \ $(pxrenderx11) $(pxrenderxcb) $(pglitzx11) $(psoftwareddraw) $(psdl) \ - $(psoftware16x11) + $(psoftware16x11) $(pdirect3d) diff --git a/legacy/evas/configure.in b/legacy/evas/configure.in index ebcd5aa5e0..182d4c1452 100644 --- a/legacy/evas/configure.in +++ b/legacy/evas/configure.in @@ -195,6 +195,43 @@ fi AM_CONDITIONAL(BUILD_ENGINE_SOFTWARE_DDRAW, test "x$have_evas_software_ddraw" = "xyes") +####################################### +## Check if we should build the direct3d engine +have_evas_direct3d="no"; +## Automatic check... +AC_CHECK_HEADERS(d3d9.h d3dx9.h, + [ have_evas_direct3d="yes" ], + [ have_evas_direct3d="no" ] +) +## Manual override +AC_MSG_CHECKING(whether direct3d backend is to be built) +AC_ARG_ENABLE(direct3d, AC_HELP_STRING([--enable-direct3d],[enable the Direct3D rendering backend]), [ + if test x"$enableval" = x"yes" ; then + AC_MSG_RESULT(yes) + have_evas_direct3d="yes" + else + AC_MSG_RESULT(no) + have_evas_direct3d="no" + fi + ], [ + AC_MSG_RESULT($have_evas_direct3d) + ] +) +if test "x$have_evas_direct3d" = "xyes"; then + AC_CHECK_HEADERS(d3d9.h d3dx9.h, + [ + AC_DEFINE(BUILD_ENGINE_DIRECT3D, 1, [Direct3D Rendering Backend]) + direct3d_libs="-ld3d9 -ld3dx9d" + ], + [ + AC_MSG_RESULT(disabling Direct3D engine) + have_evas_direct3d="no" + ] + ) +fi +AM_CONDITIONAL(BUILD_ENGINE_DIRECT3D, test "x$have_evas_direct3d" = "xyes") + + ####################################### ## Check if we should build the software_x11 engine have_evas_software_x11="no"; @@ -2091,6 +2128,7 @@ fi AC_SUBST(VALGRIND_CFLAGS) AC_SUBST(ddraw_libs) +AC_SUBST(direct3d_libs) AC_SUBST(glew_libs) @@ -2147,6 +2185,7 @@ evas-software-xcb.pc evas-xrender-x11.pc evas-xrender-xcb.pc evas-software-ddraw.pc +evas-direct3d.pc evas-sdl.pc evas.pc src/Makefile @@ -2168,6 +2207,7 @@ src/modules/Makefile src/modules/engines/Makefile src/modules/engines/software_generic/Makefile src/modules/engines/software_ddraw/Makefile +src/modules/engines/direct3d/Makefile src/modules/engines/software_x11/Makefile src/modules/engines/software_xcb/Makefile src/modules/engines/fb/Makefile @@ -2221,6 +2261,7 @@ echo "Configuration Options Summary:" echo echo "Engines:" echo " Software DirectDraw.....: $have_evas_software_ddraw" +echo " Direct3d................: $have_evas_direct3d" echo " Software X11............: $have_evas_software_x11" echo " Software XCB............: $have_evas_software_xcb" echo " Software Framebuffer....: $have_evas_fb" diff --git a/legacy/evas/evas-direct3d.pc.in b/legacy/evas/evas-direct3d.pc.in new file mode 100644 index 0000000000..493f8cce07 --- /dev/null +++ b/legacy/evas/evas-direct3d.pc.in @@ -0,0 +1,3 @@ +Name: evas-direct3d +Description: Evas Direct3D engine +Version: @VERSION@ diff --git a/legacy/evas/src/lib/canvas/evas_main.c b/legacy/evas/src/lib/canvas/evas_main.c index c212ccad03..ef18a8793c 100644 --- a/legacy/evas/src/lib/canvas/evas_main.c +++ b/legacy/evas/src/lib/canvas/evas_main.c @@ -706,6 +706,9 @@ evas_render_method_list(void) #ifdef BUILD_ENGINE_SOFTWARE_DDRAW methods = evas_list_append(methods, strdup("software_ddraw")); #endif +#ifdef BUILD_ENGINE_DIRECT3D + methods = evas_list_append(methods, strdup("direct3d")); +#endif #ifdef BUILD_ENGINE_SOFTWARE_X11 methods = evas_list_append(methods, strdup("software_x11")); #endif diff --git a/legacy/evas/src/modules/engines/Makefile.am b/legacy/evas/src/modules/engines/Makefile.am index bb427409d6..a116118773 100644 --- a/legacy/evas/src/modules/engines/Makefile.am +++ b/legacy/evas/src/modules/engines/Makefile.am @@ -20,4 +20,5 @@ xrender_xcb \ software_sdl \ glitz_x11 \ software_16 \ -software_16_x11 +software_16_x11 \ +direct3d diff --git a/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h b/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h new file mode 100644 index 0000000000..753f523063 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h @@ -0,0 +1,30 @@ +#ifndef __EVAS_ENGINE_DIRECT3D_H__ +#define __EVAS_ENGINE_DIRECT3D_H__ + + +#include +#include +#include + +typedef struct _Evas_Engine_Info_Direct3D Evas_Engine_Info_Direct3D; + +struct _Evas_Engine_Info_Direct3D +{ + /* 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; + LPDIRECT3D9 object; /* Direct3D object */ + LPDIRECT3DDEVICE9 device; /* Direct3D device */ + LPD3DXSPRITE sprite; /* Direct3D sprite */ + LPDIRECT3DTEXTURE9 texture; /* Direct3D texture */ + + int depth; + int rotation; + } info; +}; + + +#endif /* __EVAS_ENGINE_DIRECT3D_H__ */ diff --git a/legacy/evas/src/modules/engines/direct3d/Makefile.am b/legacy/evas/src/modules/engines/direct3d/Makefile.am new file mode 100644 index 0000000000..e054a21afc --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/Makefile.am @@ -0,0 +1,33 @@ +AUTOMAKE_OPTIONS = 1.4 foreign + +MAINTAINERCLEANFILES = Makefile.in + +INCLUDES = -I. -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/lib/include -I$(top_srcdir)/src/modules/engines @FREETYPE_CFLAGS@ + +if BUILD_ENGINE_DIRECT3D + +pkgdir = $(libdir)/evas/modules/engines/direct3d/$(MODULE_ARCH) + +pkg_LTLIBRARIES = module.la +module_la_SOURCES = \ +evas_engine.h \ +evas_engine.c \ +evas_outbuf.c \ +evas_direct3d_buffer.c \ +evas_direct3d_main.cpp + +module_la_LIBADD = $(top_builddir)/src/lib/libevas.la @direct3d_libs@ +module_la_LDFLAGS = @create_shared_lib@ -module -avoid-version -L$(top_builddir)/src/lib -L$(top_builddir)/src/lib/.libs +module_la_DEPENDENCIES = $(top_builddir)/config.h + +include_HEADERS = Evas_Engine_Direct3d.h + +endif + +EXTRA_DIST = \ +evas_engine.h \ +evas_engine.c \ +evas_outbuf.c \ +evas_direct3d_buffer.c \ +evas_direct3d_main.cpp \ +Evas_Engine_Direct3d.h diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_buffer.c b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_buffer.c new file mode 100644 index 0000000000..cfa44e98a5 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_buffer.c @@ -0,0 +1,88 @@ +#include + +#include "evas_engine.h" + + +Direct3D_Output_Buffer * +evas_direct3d_output_buffer_new(int depth, + int width, + int height, + void *data) +{ + Direct3D_Output_Buffer *d3dob; + + d3dob = calloc(1, sizeof(Direct3D_Output_Buffer)); + if (!d3dob) return NULL; + + d3dob->image = data; + d3dob->depth = depth; + d3dob->width = width; + d3dob->height = height; + d3dob->pitch = width * (depth >> 3); + + if (!d3dob->image) + { + d3dob->image = malloc(d3dob->pitch * height); + if (!d3dob->image) + { + free(d3dob); + return NULL; + } + } + + return d3dob; +} + +void +evas_direct3d_output_buffer_free(Direct3D_Output_Buffer *d3dob) +{ + if (d3dob->image) free(d3dob->image); + free(d3dob); +} + +void +evas_direct3d_output_buffer_paste(Direct3D_Output_Buffer *d3dob, + DATA8 *d3d_data, + int d3d_width, + int d3d_height, + int d3d_pitch, + int x, + int y) +{ + DATA8 *evas_data; + int width; + int height; + int pitch; + int j; + + if ((x >= d3d_width) || (y >= d3d_height)) + return; + + /* compute the size of the data to copy on the back surface */ + width = ((x + d3dob->width) > d3d_width) + ? d3d_width - x + : d3dob->width; + height = ((y + d3dob->height) > d3d_height) + ? d3d_height - y + : d3dob->height; + pitch = width * (d3dob->depth >> 3); + + d3d_data += y * d3d_pitch + x * (d3dob->depth >> 3); + evas_data = (unsigned char *)d3dob->image; + for (j = 0; j < height; j++, evas_data += d3dob->pitch, d3d_data += d3d_pitch) + memcpy(d3d_data, evas_data, pitch); +} + +DATA8 * +evas_direct3d_output_buffer_data(Direct3D_Output_Buffer *d3dob, + int *bytes_per_line_ret) +{ + if (bytes_per_line_ret) *bytes_per_line_ret = d3dob->pitch; + return d3dob->image; +} + +int +evas_direct3d_output_buffer_depth(Direct3D_Output_Buffer *d3dob) +{ + return d3dob->depth; +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp new file mode 100644 index 0000000000..c58c6eba4d --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp @@ -0,0 +1,84 @@ +#include "evas_engine.h" + + +extern "C" { + +int +evas_direct3d_masks_get(Outbuf *buf) +{ + D3DSURFACE_DESC sd; + + if (FAILED(buf->priv.d3d.texture->GetLevelDesc(0, &sd))) + return 0; + + switch (sd.Format) + { + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + buf->priv.mask.r = 0x00ff0000; + buf->priv.mask.g = 0x0000ff00; + buf->priv.mask.b = 0x000000ff; + break; + case D3DFMT_R5G6B5: + buf->priv.mask.r = 0xf800; + buf->priv.mask.g = 0x07e0; + buf->priv.mask.b = 0x001f; + break; + default: + return 0; + } + + return 1; +} + +void * +evas_direct3d_lock(Outbuf *buf, int *d3d_width, int *d3d_height, int *d3d_pitch) +{ + D3DSURFACE_DESC sd; + D3DLOCKED_RECT d3d_rect; + + /* is that call needed / overkill ? */ + if (FAILED(buf->priv.d3d.texture->GetLevelDesc(0, &sd))) + return NULL; + + if (FAILED(buf->priv.d3d.device->BeginScene())) + return NULL; + if (FAILED(buf->priv.d3d.sprite->Begin(D3DXSPRITE_DO_NOT_ADDREF_TEXTURE))) + { + buf->priv.d3d.device->EndScene(); + return NULL; + } + if (FAILED(buf->priv.d3d.texture->LockRect(0, &d3d_rect, NULL, D3DLOCK_DISCARD))) + { + buf->priv.d3d.sprite->End(); + buf->priv.d3d.device->EndScene(); + return NULL; + } + + *d3d_width = sd.Width; + *d3d_height = sd.Height; + *d3d_pitch = d3d_rect.Pitch; + + return d3d_rect.pBits; +} + +void +evas_direct3d_unlock(Outbuf *buf) +{ + if (FAILED(buf->priv.d3d.texture->UnlockRect(0))) + return; + + if (FAILED(buf->priv.d3d.sprite->Draw(buf->priv.d3d.texture, + NULL, NULL, NULL, + D3DCOLOR_ARGB (255, 255, 255, 255)))) + return; + if (FAILED(buf->priv.d3d.sprite->End())) + return; + + if (FAILED(buf->priv.d3d.device->EndScene())) + return; + if (FAILED(buf->priv.d3d.device->Present(NULL, NULL, NULL, NULL))) + return; +} + +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_engine.c b/legacy/evas/src/modules/engines/direct3d/evas_engine.c new file mode 100644 index 0000000000..d63ba77446 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_engine.c @@ -0,0 +1,369 @@ +#include "evas_engine.h" +#include "evas_private.h" +#include "Evas_Engine_Direct3D.h" + +/* engine struct data */ +typedef struct _Render_Engine Render_Engine; + +struct _Render_Engine +{ + Tilebuf *tb; + Outbuf *ob; + Tilebuf_Rect *rects; + Evas_Object_List *cur_rect; + int end : 1; +}; + + +/* function tables - filled in later (func and parent func) */ +static Evas_Func func, pfunc; + +/* prototypes we will use here */ +static void *_output_setup(int width, + int height, + int rotation, + HWND window, + LPDIRECT3D9 object, + LPDIRECT3DDEVICE9 device, + LPD3DXSPRITE sprite, + LPDIRECT3DTEXTURE9 texture, + int w_depth); + +static void *eng_info(Evas *e); +static void eng_info_free(Evas *e, + void *info); +static void eng_setup(Evas *e, + void *info); +static void eng_output_free(void *data); +static void eng_output_resize(void *data, + int width, + int height); +static void eng_output_tile_size_set(void *data, + int width, + int height); +static void eng_output_redraws_rect_add(void *data, + int x, + int y, + int width, + int height); +static void eng_output_redraws_rect_del(void *data, + int x, + int y, + int width, + int height); +static void eng_output_redraws_clear(void *data); + +/* internal engine routines */ +static void * +_output_setup(int width, + int height, + int rotation, + HWND window, + LPDIRECT3D9 object, + LPDIRECT3DDEVICE9 device, + LPD3DXSPRITE sprite, + LPDIRECT3DTEXTURE9 texture, + int w_depth) +{ + Render_Engine *re; + + re = (Render_Engine *)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_direct3d_outbuf_init(); + + /* get any stored performance metrics from device */ + re->ob = evas_direct3d_outbuf_setup_d3d(width, height, rotation, OUTBUF_DEPTH_INHERIT, window, object, device, sprite, texture, w_depth); + if (!re->ob) + { + free(re); + return NULL; + } + + re->tb = evas_common_tilebuf_new(width, height); + if (!re->tb) + { + evas_direct3d_outbuf_free(re->ob); + free(re); + return NULL; + } + + /* FIXME: that comment :) */ + /* 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) +{ + Evas_Engine_Info_Direct3D *info; + + info = (Evas_Engine_Info_Direct3D *)calloc(1, sizeof(Evas_Engine_Info_Direct3D)); + if (!info) return NULL; + info->magic.magic = rand(); + return info; + e = NULL; +} + +static void +eng_info_free(Evas *e, + void *info) +{ + Evas_Engine_Info_Direct3D *in; + + in = (Evas_Engine_Info_Direct3D *)info; + free(in); +} + +static void +eng_setup(Evas *e, + void *info) +{ + Render_Engine *re; + Evas_Engine_Info_Direct3D *in; + + in = (Evas_Engine_Info_Direct3D *)info; + if (!e->engine.data.output) + e->engine.data.output = + _output_setup(e->output.w, + e->output.h, + in->info.rotation, + in->info.window, + in->info.object, + in->info.device, + in->info.sprite, + in->info.texture, + in->info.depth); + 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 = (Render_Engine *)e->engine.data.output; +} + +static void +eng_output_free(void *data) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_direct3d_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_direct3d_outbuf_reconfigure(re->ob, + width, + height, + evas_direct3d_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 width, + int height) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_common_tilebuf_set_tile_size(re->tb, width, height); +} + +static void +eng_output_redraws_rect_add(void *data, + int x, + int y, + int width, + int height) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_common_tilebuf_add_redraw(re->tb, x, y, width, height); +} + +static void +eng_output_redraws_rect_del(void *data, + int x, + int y, + int width, + int height) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_common_tilebuf_del_redraw(re->tb, x, y, width, height); +} + +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 = (Evas_Object_List *)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_direct3d_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; + evas_common_pipe_begin((RGBA_Image *)surface); + evas_common_pipe_flush((RGBA_Image *)surface); + evas_direct3d_outbuf_push_updated_region(re->ob, (RGBA_Image *)surface, x, y, w, h); + evas_direct3d_outbuf_free_region_for_update(re->ob, (RGBA_Image *)surface); + evas_common_cpu_end_opt(); +} + +static void +eng_output_flush(void *data) +{ + Render_Engine *re; + + re = (Render_Engine *)data; + evas_direct3d_outbuf_flush(re->ob); +} + +static void +eng_output_idle_flush(void *data) +{ + Render_Engine *re; + + re = (Render_Engine *)data; +} + +/* 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, + "direct3d", + "none" +}; diff --git a/legacy/evas/src/modules/engines/direct3d/evas_engine.h b/legacy/evas/src/modules/engines/direct3d/evas_engine.h new file mode 100644 index 0000000000..6be498fd68 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_engine.h @@ -0,0 +1,141 @@ +#ifndef __EVAS_ENGINE_H__ +#define __EVAS_ENGINE_H__ + + +#include +#include +#include + +#include "evas_common.h" + + +typedef struct _Outbuf Outbuf; +typedef struct _Direct3D_Output_Buffer Direct3D_Output_Buffer; + + +enum _Outbuf_Depth +{ + OUTBUF_DEPTH_NONE, + OUTBUF_DEPTH_INHERIT, + OUTBUF_DEPTH_RGB_16BPP_565_565_DITHERED, + OUTBUF_DEPTH_RGB_16BPP_555_555_DITHERED, + OUTBUF_DEPTH_RGB_16BPP_444_444_DITHERED, + OUTBUF_DEPTH_RGB_16BPP_565_444_DITHERED, + OUTBUF_DEPTH_RGB_32BPP_888_8888, + OUTBUF_DEPTH_LAST +}; +typedef enum _Outbuf_Depth Outbuf_Depth; + + +struct _Outbuf +{ + int width; + int height; + int rot; + Outbuf_Depth depth; + + struct { + struct { + HWND window; + LPDIRECT3D9 object; + LPDIRECT3DDEVICE9 device; + LPD3DXSPRITE sprite; + LPDIRECT3DTEXTURE9 texture; + int depth; + } d3d; + struct { + DATA32 r, g, b; + } mask; + + /* a list of pending regions to write to the target */ + Evas_List *pending_writes; + } priv; +}; + +struct _Direct3D_Output_Buffer +{ + void *image; + int x; + int y; + int width; + int height; + int depth; + int pitch; +}; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Outbuf functions */ +void evas_direct3d_outbuf_init(void); +void evas_direct3d_outbuf_free(Outbuf *buf); +Outbuf *evas_direct3d_outbuf_setup_d3d(int width, + int height, + int rotation, + Outbuf_Depth depth, + HWND window, + LPDIRECT3D9 object, + LPDIRECT3DDEVICE9 device, + LPD3DXSPRITE sprite, + LPDIRECT3DTEXTURE9 texture, + int w_depth); +RGBA_Image *evas_direct3d_outbuf_new_region_for_update(Outbuf *buf, + int x, + int y, + int width, + int height, + int *cx, + int *cy, + int *cw, + int *ch); +void evas_direct3d_outbuf_free_region_for_update(Outbuf *buf, + RGBA_Image *update); +void evas_direct3d_outbuf_flush(Outbuf *buf); +void evas_direct3d_outbuf_push_updated_region(Outbuf *buf, + RGBA_Image *update, + int x, + int y, + int width, + int height); +void evas_direct3d_outbuf_reconfigure(Outbuf *buf, + int width, + int height, + int rotation, + Outbuf_Depth depth); +int evas_direct3d_outbuf_width_get(Outbuf *buf); +int evas_direct3d_outbuf_height_get(Outbuf *buf); +Outbuf_Depth evas_direct3d_outbuf_depth_get(Outbuf *buf); +int evas_direct3d_outbuf_rot_get(Outbuf *buf); + +/* Output Buffer functions */ +Direct3D_Output_Buffer *evas_direct3d_output_buffer_new(int depth, + int width, + int height, + void *data); +void evas_direct3d_output_buffer_free(Direct3D_Output_Buffer *d3dob); +void evas_direct3d_output_buffer_paste(Direct3D_Output_Buffer *d3dob, + DATA8 *d3d_data, + int d3d_width, + int d3d_height, + int d3d_pitch, + int x, + int y); +DATA8 *evas_direct3d_output_buffer_data(Direct3D_Output_Buffer *d3dob, + int *bytes_per_line_ret); +int evas_direct3d_output_buffer_depth(Direct3D_Output_Buffer *d3dob); + + +int evas_direct3d_masks_get(Outbuf *buf); +void *evas_direct3d_lock(Outbuf *buf, int *d3d_width, int *d3d_height, int *d3d_pitch); +void evas_direct3d_unlock(Outbuf *buf); + + +#ifdef __cplusplus +} +#endif + + +#endif /* __EVAS_ENGINE_H__ */ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c b/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c new file mode 100644 index 0000000000..38c1f62727 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c @@ -0,0 +1,335 @@ +#include "evas_engine.h" + + +void +evas_direct3d_outbuf_init(void) +{ +} + +void +evas_direct3d_outbuf_free(Outbuf *buf) +{ + free(buf); +} + +Outbuf * +evas_direct3d_outbuf_setup_d3d(int width, + int height, + int rotation, + Outbuf_Depth depth, + HWND window, + LPDIRECT3D9 object, + LPDIRECT3DDEVICE9 device, + LPD3DXSPRITE sprite, + LPDIRECT3DTEXTURE9 texture, + int w_depth) +{ + 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.d3d.window = window; + buf->priv.d3d.object = object; + buf->priv.d3d.device = device; + buf->priv.d3d.sprite = sprite; + buf->priv.d3d.texture = texture; + buf->priv.d3d.depth = w_depth; + + { + Gfx_Func_Convert conv_func; + Direct3D_Output_Buffer *d3dob; + + d3dob = evas_direct3d_output_buffer_new(buf->priv.d3d.depth, 1, 1, NULL); + + conv_func = NULL; + if (d3dob) + { + if (evas_direct3d_masks_get(buf)) + { + if ((rotation == 0) || (rotation == 180)) + conv_func = evas_common_convert_func_get(0, + width, + height, + evas_direct3d_output_buffer_depth (d3dob), + buf->priv.mask.r, + buf->priv.mask.g, + buf->priv.mask.b, + PAL_MODE_NONE, + rotation); + else if ((rotation == 90) || (rotation == 270)) + conv_func = evas_common_convert_func_get(0, + height, + width, + evas_direct3d_output_buffer_depth (d3dob), + buf->priv.mask.r, + buf->priv.mask.g, + buf->priv.mask.b, + PAL_MODE_NONE, + rotation); + } + evas_direct3d_output_buffer_free(d3dob); + if (!conv_func) + { + printf(".[ Evas Error ].\n" + " {\n" + " At depth %i:\n" + " RGB format mask: %08x, %08x, %08x\n" + " Not supported by and compiled in converters!\n" + " }\n", + buf->priv.d3d.depth, + buf->priv.mask.r, + buf->priv.mask.g, + buf->priv.mask.b); + } + } + } + + return buf; +} + +RGBA_Image * +evas_direct3d_outbuf_new_region_for_update(Outbuf *buf, + int x, + int y, + int width, + int height, + int *cx, + int *cy, + int *cw, + int *ch) +{ + RGBA_Image *im; + Direct3D_Output_Buffer *d3dob = NULL; + int bpl = 0; + + *cx = 0; + *cy = 0; + *cw = width; + *ch = height; + + if ((buf->rot == 0) && + (buf->priv.mask.r == 0xff0000) && + (buf->priv.mask.g == 0x00ff00) && + (buf->priv.mask.b == 0x0000ff)) + { + im = evas_cache_image_empty(evas_common_image_cache_get()); + im->image->w = width; + im->image->h = height; + im->image->data = NULL; + im->image->no_free = 1; + d3dob = evas_direct3d_output_buffer_new(buf->priv.d3d.depth, + width, + height, + NULL); + im->extended_info = d3dob; + im->image->data = (DATA32 *)evas_direct3d_output_buffer_data(d3dob, &bpl); + } + else + { + im = evas_cache_image_empty(evas_common_image_cache_get()); + im->image->w = width; + im->image->h = height; + evas_common_image_surface_alloc(im->image); + im->extended_info = d3dob; + if ((buf->rot == 0) || (buf->rot == 180)) + d3dob = evas_direct3d_output_buffer_new(buf->priv.d3d.depth, + width, + height, + NULL); + else if ((buf->rot == 90) || (buf->rot == 270)) + d3dob = evas_direct3d_output_buffer_new(buf->priv.d3d.depth, + width, + height, + NULL); + im->extended_info = d3dob; + } + + buf->priv.pending_writes = evas_list_append(buf->priv.pending_writes, im); + + return im; +} + +void +evas_direct3d_outbuf_free_region_for_update(Outbuf *buf, + RGBA_Image *update) +{ + /* no need to do anything - they are cleaned up on flush */ +} + +void +evas_direct3d_outbuf_flush(Outbuf *buf) +{ + Evas_List *l; + void *d3d_data; + int d3d_width; + int d3d_height; + int d3d_pitch; + + /* lock the texture */ + if (!(d3d_data = evas_direct3d_lock(buf, + &d3d_width, &d3d_height, &d3d_pitch))) + goto free_images; + + /* copy safely the images that need to be drawn onto the back surface */ + for (l = buf->priv.pending_writes; l; l = l->next) + { + RGBA_Image *im; + Direct3D_Output_Buffer *d3dob; + + im = l->data; + d3dob = im->extended_info; + /* paste now */ + evas_direct3d_output_buffer_paste(d3dob, + d3d_data, + d3d_width, + d3d_height, + d3d_pitch, + d3dob->x, + d3dob->y); + } + + /* unlock the texture */ + evas_direct3d_unlock(buf); + + free_images: + while (buf->priv.pending_writes) + { + RGBA_Image *im; + Direct3D_Output_Buffer *d3dob; + + im = buf->priv.pending_writes->data; + buf->priv.pending_writes = evas_list_remove_list(buf->priv.pending_writes, + buf->priv.pending_writes); + d3dob = im->extended_info; + evas_cache_image_drop(im); + if (d3dob) evas_direct3d_output_buffer_free(d3dob); + } + evas_common_cpu_end_opt(); +} + +void +evas_direct3d_outbuf_push_updated_region(Outbuf *buf, + RGBA_Image *update, + int x, + int y, + int width, + int height) +{ + Gfx_Func_Convert conv_func; + Direct3D_Output_Buffer *d3dob; + DATA32 *src_data; + void *data; + int bpl = 0; + + conv_func = NULL; + d3dob = update->extended_info; + + if ((buf->rot == 0) || (buf->rot == 180)) + conv_func = evas_common_convert_func_get(NULL, + width, + height, + evas_direct3d_output_buffer_depth(d3dob), + buf->priv.mask.r, + buf->priv.mask.g, + buf->priv.mask.b, + PAL_MODE_NONE, + buf->rot); + else if ((buf->rot == 90) || (buf->rot == 270)) + conv_func = evas_common_convert_func_get(NULL, + height, + width, + evas_direct3d_output_buffer_depth(d3dob), + buf->priv.mask.r, + buf->priv.mask.g, + buf->priv.mask.b, + PAL_MODE_NONE, + buf->rot); + + if (!conv_func) return; + + data = evas_direct3d_output_buffer_data(d3dob, &bpl); + src_data = update->image->data; + if (buf->rot == 0) + { + d3dob->x = x; + d3dob->y = y; + } + else if (buf->rot == 90) + { + d3dob->x = y; + d3dob->y = buf->width - x - width; + } + else if (buf->rot == 180) + { + d3dob->x = buf->width - x - width; + d3dob->y = buf->height - y - height; + } + else if (buf->rot == 270) + { + d3dob->x = buf->height - y - height; + d3dob->y = x; + } + if ((buf->rot == 0) || (buf->rot == 180)) + { + d3dob->width = width; + d3dob->height = height; + } + else if ((buf->rot == 90) || (buf->rot == 270)) + { + d3dob->width = height; + d3dob->height = width; + } + + if (data != src_data) + conv_func(src_data, data, + 0, + bpl / + ((evas_direct3d_output_buffer_depth(d3dob))) - d3dob->width, + d3dob->width, d3dob->height, x, y, NULL); +} + +void +evas_direct3d_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; +} + +int +evas_direct3d_outbuf_width_get(Outbuf *buf) +{ + return buf->width; +} + +int +evas_direct3d_outbuf_height_get(Outbuf *buf) +{ + return buf->height; +} + +Outbuf_Depth +evas_direct3d_outbuf_depth_get(Outbuf *buf) +{ + return buf->depth; +} + +int +evas_direct3d_outbuf_rot_get(Outbuf *buf) +{ + return buf->rot; +}