From c989841ab6b2a80b77fd1ce2aa85c6b2be695207 Mon Sep 17 00:00:00 2001 From: Vincent Torri Date: Sat, 20 Dec 2008 13:22:46 +0000 Subject: [PATCH] * src/modules/engines/direct3d/: fast direct3d engine written by Dmitriy Mazovka. You rock ! * m4/evas_check_engine.m: * m4/evas_check_loader.m4: use m4_popdef for each macro (otherwise, fail if aclocal is too old) * src/lib/canvas/evas_font_dir.c: include evas_common.h and evas_private.h after Eet.h and Evil.h so that EAPI is correctly defined SVN revision: 38244 --- legacy/evas/m4/evas_check_engine.m4 | 5 +- legacy/evas/m4/evas_check_loader.m4 | 3 +- legacy/evas/src/lib/canvas/evas_font_dir.c | 6 +- .../engines/direct3d/Evas_Engine_Direct3D.h | 21 +- .../src/modules/engines/direct3d/Makefile.am | 33 +- .../evas/src/modules/engines/direct3d/array.h | 305 +++++++ .../engines/direct3d/evas_direct3d_buffer.c | 88 -- .../direct3d/evas_direct3d_context.cpp | 8 + .../engines/direct3d/evas_direct3d_context.h | 22 + .../engines/direct3d/evas_direct3d_device.cpp | 393 +++++++++ .../engines/direct3d/evas_direct3d_device.h | 87 ++ .../direct3d/evas_direct3d_image_cache.cpp | 436 ++++++++++ .../direct3d/evas_direct3d_image_cache.h | 108 +++ .../engines/direct3d/evas_direct3d_main.cpp | 816 ++++++++++++++++-- .../engines/direct3d/evas_direct3d_object.cpp | 12 + .../engines/direct3d/evas_direct3d_object.h | 35 + .../direct3d/evas_direct3d_object_font.cpp | 231 +++++ .../direct3d/evas_direct3d_object_font.h | 113 +++ .../direct3d/evas_direct3d_object_image.cpp | 318 +++++++ .../direct3d/evas_direct3d_object_image.h | 127 +++ .../direct3d/evas_direct3d_object_line.cpp | 60 ++ .../direct3d/evas_direct3d_object_line.h | 37 + .../direct3d/evas_direct3d_object_rect.cpp | 65 ++ .../direct3d/evas_direct3d_object_rect.h | 37 + .../engines/direct3d/evas_direct3d_scene.cpp | 33 + .../engines/direct3d/evas_direct3d_scene.h | 63 ++ .../direct3d/evas_direct3d_shader_pack.cpp | 340 ++++++++ .../direct3d/evas_direct3d_shader_pack.h | 75 ++ .../evas_direct3d_vertex_buffer_cache.cpp | 154 ++++ .../evas_direct3d_vertex_buffer_cache.h | 60 ++ .../modules/engines/direct3d/evas_engine.c | 627 +++++++++----- .../modules/engines/direct3d/evas_engine.h | 181 ++-- .../modules/engines/direct3d/evas_outbuf.c | 328 ------- .../evas/src/modules/engines/direct3d/ref.h | 210 +++++ 34 files changed, 4622 insertions(+), 815 deletions(-) create mode 100644 legacy/evas/src/modules/engines/direct3d/array.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.h create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp create mode 100644 legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.h create mode 100644 legacy/evas/src/modules/engines/direct3d/ref.h diff --git a/legacy/evas/m4/evas_check_engine.m4 b/legacy/evas/m4/evas_check_engine.m4 index a38cd2f72f..b88508f6ab 100644 --- a/legacy/evas/m4/evas_check_engine.m4 +++ b/legacy/evas/m4/evas_check_engine.m4 @@ -311,7 +311,7 @@ evas_engine_[]$1[]_libs="" AC_CHECK_HEADERS([d3d9.h d3dx9.h.h], [ have_dep="yes" - evas_engine_[]$1[]_libs="-ld3d9 -ld3dx9d" + evas_engine_[]$1[]_libs="-ld3d9 -ld3dx9 -lgdi32" ] ) @@ -630,6 +630,7 @@ fi AM_CONDITIONAL(BUILD_ENGINE_[]UP, [test "x${have_evas_engine_[]DOWN}" = "xyes"]) -m4_popdef([UP], [DOWN]) +m4_popdef([UP]) +m4_popdef([DOWN]) ]) diff --git a/legacy/evas/m4/evas_check_loader.m4 b/legacy/evas/m4/evas_check_loader.m4 index ff946d57bf..c0112948a7 100644 --- a/legacy/evas/m4/evas_check_loader.m4 +++ b/legacy/evas/m4/evas_check_loader.m4 @@ -304,7 +304,8 @@ fi AM_CONDITIONAL(BUILD_LOADER_[]UP, [test "x${have_evas_image_loader_[]DOWN}" = "xyes"]) -m4_popdef([UP], [DOWN]) +m4_popdef([UP]) +m4_popdef([DOWN]) ]) diff --git a/legacy/evas/src/lib/canvas/evas_font_dir.c b/legacy/evas/src/lib/canvas/evas_font_dir.c index 2b473ce78f..0a24723cf8 100644 --- a/legacy/evas/src/lib/canvas/evas_font_dir.c +++ b/legacy/evas/src/lib/canvas/evas_font_dir.c @@ -7,9 +7,6 @@ # include #endif -#include "evas_common.h" -#include "evas_private.h" - #ifdef BUILD_FONT_LOADER_EET #include #endif @@ -18,6 +15,9 @@ #include #endif +#include "evas_common.h" +#include "evas_private.h" + /* font dir cache */ static Eina_Hash *font_dirs = NULL; static Eina_List *fonts_cache = NULL; diff --git a/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h b/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h index 753f523063..001a7822ae 100644 --- a/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h +++ b/legacy/evas/src/modules/engines/direct3d/Evas_Engine_Direct3D.h @@ -3,8 +3,6 @@ #include -#include -#include typedef struct _Evas_Engine_Info_Direct3D Evas_Engine_Info_Direct3D; @@ -15,15 +13,18 @@ struct _Evas_Engine_Info_Direct3D 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; + HWND window; + int rotation; + int depth; + int fullscreen : 1; + int layered : 1; } info; + + struct { + unsigned short width; + unsigned short height; + unsigned char *mask; + } *shape; }; diff --git a/legacy/evas/src/modules/engines/direct3d/Makefile.am b/legacy/evas/src/modules/engines/direct3d/Makefile.am index ae826b46aa..fda6fac1b9 100644 --- a/legacy/evas/src/modules/engines/direct3d/Makefile.am +++ b/legacy/evas/src/modules/engines/direct3d/Makefile.am @@ -17,11 +17,20 @@ pkgdir = $(libdir)/evas/modules/engines/direct3d/$(MODULE_ARCH) pkg_LTLIBRARIES = module.la module_la_SOURCES = \ evas_engine.c \ -evas_outbuf.c \ -evas_direct3d_buffer.c \ -evas_direct3d_main.cpp +evas_direct3d_context.cpp \ +evas_direct3d_device.cpp \ +evas_direct3d_image_cache.cpp \ +evas_direct3d_main.cpp \ +evas_direct3d_object.cpp \ +evas_direct3d_object_font.cpp \ +evas_direct3d_object_image.cpp \ +evas_direct3d_object_line.cpp \ +evas_direct3d_object_rect.cpp \ +evas_direct3d_scene.cpp \ +evas_direct3d_shader_pack.cpp \ +evas_direct3d_vertex_buffer_cache.cpp -module_la_CXXFLAGS = -fno-rtti -fno-exceptions +module_la_CXXFLAGS = -fno-exceptions module_la_LIBADD = $(top_builddir)/src/lib/libevas.la @EINA_LIBS@ @evas_engine_direct3d_libs@ module_la_LDFLAGS = -no-undefined -module -avoid-version module_la_LIBTOOLFLAGS = --tag=disable-static @@ -30,4 +39,18 @@ include_HEADERS = Evas_Engine_Direct3D.h endif -EXTRA_DIST = evas_engine.h +EXTRA_DIST = \ +array.h \ +evas_direct3d_context.h \ +evas_direct3d_device.h \ +evas_direct3d_image_cache.h \ +evas_direct3d_object.h \ +evas_direct3d_object_font.h \ +evas_direct3d_object_image.h \ +evas_direct3d_object_line.h \ +evas_direct3d_object_rect.h \ +evas_direct3d_scene.h \ +evas_direct3d_shader_pack.h \ +evas_direct3d_vertex_buffer_cache.h \ +evas_engine.h \ +ref.h diff --git a/legacy/evas/src/modules/engines/direct3d/array.h b/legacy/evas/src/modules/engines/direct3d/array.h new file mode 100644 index 0000000000..dfd80b7236 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/array.h @@ -0,0 +1,305 @@ +#ifndef __ARRAY_H__ +#define __ARRAY_H__ + +#include "ref.h" +#include + +template +class TArray : virtual public Referenc +{ +public: + TArray(); + TArray(const TArray &arr) + { + data = NULL; + size = num = 0; + block_size = arr.block_size; + keep_order = arr.keep_order; + + //assert(0 && "Direct assignment for arrays is NOT allowed"); + // risky probably, but anyway + arr.CopyTo(*this); + } + ~TArray(); + + bool Allocate(int new_num); + bool Resize(int new_size = 0); + bool Add(T &el); + bool Add(const T &el); + + inline T &operator[](int i); + inline const T &operator[](int i) const; + inline const TArray &operator =(const TArray &arr) + { + block_size = arr.block_size; + keep_order = arr.keep_order; + + //assert(0 && "Direct assignment for arrays is NOT allowed"); + // risky probably, but anyway + arr.CopyTo(*this); + return *this; + } + + T *Last() + { + if (num > 0) + return &data[num - 1]; + return NULL; + } + + inline int Length() const + { + return num; + } + + inline int Size() const + { + return size; + } + + inline int BlockSize() const + { + return block_size; + } + + inline T *Data() + { + return data; + } + + inline T **DataPtr() + { + return &data; + } + + inline const T *Data() const + { + return data; + } + + inline void SetKeepOrder(bool enable) + { + keep_order = enable; + } + + bool Find(const T &el); + + bool Add(TArray &arr); + bool CopyTo(TArray &dest) const; + bool Init(const T *arr, int len); + + void Swap(int to, int from); + void Replace(int i); + + bool SetBlockSize(int new_size); + void Set(T &el); + void Set(const T &el); + +protected: + T *data; + int size; + int num; + int block_size; + // Some operations restricted, order of the elements is fixed + bool keep_order; + +}; + +namespace Array +{ + const int default_block_size = 16; + const int max_array_size = 0xffffff; +} + + +template TArray::TArray() +: data(NULL), size(0), num(0), block_size(Array::default_block_size), keep_order(false) +{ +} + +template TArray::~TArray() +{ + if (data != NULL) + Resize(); +} + +template bool TArray::Allocate(int new_num) +{ + assert(new_num >= 0 && new_num <= Array::max_array_size); + if (new_num > size) + { + if (!Resize(new_num)) + return false; + } + num = new_num; + return true; +} + +template bool TArray::Resize(int new_size) +{ + assert(new_size >= 0 && new_size <= Array::max_array_size); + if (new_size == 0) + { + delete[] data; + data = NULL; + size = 0; + num = 0; + return true; + } + if (new_size == size) + return true; + + T *new_data = new T[new_size]; + if (new_data == NULL) + return false; + + if (data != NULL && num > 0) + { + //CopyMemory(new_data, data, num * sizeof(T)); + for (int i = 0; i < num && i < new_size; i++) + new_data[i] = data[i]; + } + delete[] data; + + data = new_data; + size = new_size; + return true; +} + +template bool TArray::Add(T &el) +{ + if (data == NULL) + Resize(1); + + if (num < size) + { + data[num++] = el; + return true; + } + // num >= size + int new_size = size + block_size; + if (!Resize(new_size)) + return false; + + data[num++] = el; + return true; +} + +template bool TArray::Add(const T &el) +{ + if (data == NULL) + Resize(1); + + if (num < size) + { + data[num++] = *(T *)⪙ + return true; + } + // num >= size + int new_size = size + block_size; + if (!Resize(new_size)) + return false; + + data[num++] = *(T *)⪙ + return true; +} + +template bool TArray::Add(TArray &arr) +{ + if (arr.Length() == 0) + return true; + int numf = num; + if (!Allocate(Length() + arr.Length())) + return false; + CopyMemory(&data[numf], arr.Data(), arr.Length() * sizeof(T)); + return true; +} + +template T &TArray::operator [](int i) +{ + assert(i >= 0 && i < num); + return data[i]; +} + +template const T &TArray::operator [](int i) const +{ + assert(i >= 0 && i < num); + return data[i]; +} + +template bool TArray::SetBlockSize(int new_size) +{ + assert(new_size >= 0 && new_size <= Array::max_array_size); + block_size = new_size; + return true; +} + +template void TArray::Set(T &el) +{ + for (int i = 0; i < num; i++) + data[i] = el; +} + +template void TArray::Set(const T &el) +{ + for (int i = 0; i < num; i++) + data[i] = el; +} + +template bool TArray::CopyTo(TArray &dest) const +{ + if (!dest.Resize(size)) + return false; + dest.num = 0; + for (int i = 0; i < num; i++) + dest.Add(data[i]); + + return true; +} + +template bool TArray::Init(const T *arr, int len) +{ + assert(arr != NULL); + if (!Resize(len)) + return false; + num = 0; + for (int i = 0; i < len; i++) + Add((T)arr[i]); + + return true; +} + +template void TArray::Swap(int to, int from) +{ + assert(to >= 0 && to < num && from >= 0 && from < num); + if (keep_order) + return; + T t = data[to]; + data[to] = data[from]; + data[from] = t; +} + +template void TArray::Replace(int i) +{ + assert(i >= 0 && i < num); + if (keep_order) + return; + if (num >= 1) + { + data[i] = data[num - 1]; + num--; + } +} + +// operator == for type T should be defined +template bool TArray::Find(const T &el) +{ + for (int i = 0; i < num; i++) + { + if (data[i] == el) + return true; + } + return false; +} + +#endif // __ARRAY_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 index cfa44e98a5..e69de29bb2 100644 --- a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_buffer.c +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_buffer.c @@ -1,88 +0,0 @@ -#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_context.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.cpp new file mode 100644 index 0000000000..07cfa3d08b --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.cpp @@ -0,0 +1,8 @@ + +#include "evas_direct3d_context.h" + +D3DContext::D3DContext() +{ + color = 0xff000000; + color_mul = 0xffffffff; +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.h new file mode 100644 index 0000000000..763d1890be --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_context.h @@ -0,0 +1,22 @@ +#ifndef __EVAS_DIRECT3D_CONTEXT_H__ +#define __EVAS_DIRECT3D_CONTEXT_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "evas_direct3d_object.h" + +class D3DContext : virtual public Referenc +{ +public: + D3DContext(); + +public: + DWORD color; + DWORD color_mul; + + Ref font; + +}; + +#endif // __EVAS_DIRECT3D_CONTEXT_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.cpp new file mode 100644 index 0000000000..5be8ddbb89 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.cpp @@ -0,0 +1,393 @@ +//#define ENABLE_LOG_PRINTF + +#include "evas_direct3d_device.h" + +#include "evas_direct3d_vertex_buffer_cache.h" + +D3DDevice::D3DDevice() +{ + ResetParams(); +} + +bool D3DDevice::Init(HWND window, int depth, bool fullscreen) +{ + D3DPRESENT_PARAMETERS pp; + D3DDISPLAYMODE dm; + D3DCAPS9 caps; + RECT rect; + DWORD flag; + HRESULT hr; + + if (window == NULL) + return false; + + Destroy(); + + _object = Direct3DCreate9(D3D_SDK_VERSION); + if (_object == NULL) + return false; + + if (FAILED(hr = _object->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dm))) + { + Log("GetAdapterDisplayMode failed: %x", hr); + Destroy(); + return false; + } + + if (FAILED(hr = _object->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps))) + { + Log("GetDeviceCaps failed: %x", hr); + Destroy(); + return false; + } + + if (!GetClientRect(window, &rect)) + { + Log("GetClientRect failed: %x", GetLastError()); + Destroy(); + return false; + } + + if (SUCCEEDED(_object->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + dm.Format, 0, D3DRTYPE_TEXTURE, (depth == 16) ? D3DFMT_R5G6B5 : D3DFMT_A8R8G8B8))) + { + dm.Format = (depth == 16) ? D3DFMT_R5G6B5 : D3DFMT_A8R8G8B8; + } + + flag = (caps.VertexProcessingCaps != 0) ? + (D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE) : + D3DCREATE_SOFTWARE_VERTEXPROCESSING; + + ZeroMemory(&pp, sizeof(pp)); + if (!fullscreen) + { + pp.BackBufferWidth = rect.right - rect.left; + pp.BackBufferHeight = rect.bottom - rect.top; + } + else + { + pp.BackBufferWidth = ::GetSystemMetrics(SM_CXSCREEN); + pp.BackBufferHeight = ::GetSystemMetrics(SM_CYSCREEN); + } + pp.BackBufferFormat = dm.Format; + pp.BackBufferCount = 1; + pp.MultiSampleType = D3DMULTISAMPLE_NONE; + pp.MultiSampleQuality = 0; + pp.SwapEffect = D3DSWAPEFFECT_DISCARD; + pp.hDeviceWindow = window; + pp.Windowed = fullscreen ? FALSE : TRUE; + //pp.EnableAutoDepthStencil = TRUE; + //pp.AutoDepthStencilFormat = D3DFMT_D16; + pp.FullScreen_RefreshRateInHz = 0; + pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + + if (FAILED(hr = _object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, + window, flag, &pp, &_device))) + { + Log("CreateDevice failed: %x", hr); + Destroy(); + return false; + } + + LPDIRECT3DSURFACE9 backbuffer = NULL; + _device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + backbuffer->GetDesc(&_backbuffer_desc); + backbuffer->Release(); + + switch (dm.Format) { + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + _depth = 32; + break; + case D3DFMT_R5G6B5: + _depth = 16; + break; + default: + Log("No supported format found"); + Destroy(); + return false; + } + + //_render_to_texture = false; + + _d3dpp = pp; + _device_lost = FALSE; + _scene_rendering = FALSE; + _width = rect.right - rect.left; + _height = rect.bottom - rect.top; + _window = window; + + if (FAILED(CreateRenderTarget())) + { + Log("Failed to create render target"); + Destroy(); + return false; + } + + Log("initialized"); + return true; +} + +bool D3DDevice::Reset(int width, int height, int fullscreen) +{ + D3DPRESENT_PARAMETERS pp = _d3dpp; + _d3dpp.BackBufferWidth = (width > 0) ? width : _d3dpp.BackBufferWidth; + _d3dpp.BackBufferHeight = (height > 0) ? height : _d3dpp.BackBufferHeight; + _d3dpp.Windowed = (fullscreen == 1) ? FALSE : ((fullscreen == 0) ? TRUE : _d3dpp.Windowed); + if (FAILED(ResetDevice())) + { + Log("Couldnt restore device"); + _d3dpp = pp; + return SUCCEEDED(ResetDevice()); + } + _width = _d3dpp.BackBufferWidth; + _height = _d3dpp.BackBufferHeight; + return true; +} + +void D3DDevice::Destroy() +{ + //if (_render_target != NULL) + //{ + // _render_target->Release(); + // _render_target = NULL; + //} + if (_render_target_data != NULL) + { + _render_target_data->Release(); + _render_target_data = NULL; + } + if (_device != NULL) + { + int num = _device->Release(); + assert(num == 0); + } + if (_object != NULL) + _object->Release(); + ResetParams(); + + Log("uninitialized"); +} + +void D3DDevice::ResetParams() +{ + _window = NULL; + _object = NULL; + _device = NULL; + _width = 0; + _height = 0; + _rot = 0; + _depth = 0; + _device_lost = false; + _scene_rendering = false; + ZeroMemory(&_d3dpp, sizeof(_d3dpp)); + ZeroMemory(&_backbuffer_desc, sizeof(_backbuffer_desc)); + //_render_target = NULL; + _render_target_data = NULL; + _render_data_updated = false; + _render_data.Resize(); + //_original_render_target = NULL; + //_render_to_texture = false; +} + +HRESULT D3DDevice::RestoreDevice() +{ + Log("restore"); + assert(_device != NULL); + + HRESULT hr = S_OK; + + // Test the cooperative level to see if it's okay to render + if (SUCCEEDED(hr = _device->TestCooperativeLevel())) + { + _device_lost = FALSE; + Log("render test ok"); + return S_OK; + } + + // If the device was lost, do not render until we get it back + if (hr == D3DERR_DEVICELOST) + return E_FAIL; + + // Check if the device needs to be reset. + if (hr == D3DERR_DEVICENOTRESET) + { + if (FAILED(hr = ResetDevice())) + return hr; + } + return hr; +} + +HRESULT D3DDevice::ResetDevice() +{ + Log("reset"); + HRESULT hr = S_OK; + + _scene_rendering = FALSE; + + // Release all video memory objects + // Bad to call such, make better + D3DVertexBufferCache::Current()->Uninitialize(); + + //if (_render_target != NULL) + //{ + // _render_target->Release(); + // _render_target = NULL; + //} + if (_render_target_data != NULL) + { + _render_target_data->Release(); + _render_target_data = NULL; + } + + // Reset the device + if (FAILED(hr = _device->Reset(&_d3dpp))) + { + Log("D3DDevice: Reset of the device failed! Error (%X)", (DWORD)hr); + return hr; + } + + // Store render target surface desc + LPDIRECT3DSURFACE9 backbuffer = NULL; + _device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer); + if (backbuffer != NULL) + { + backbuffer->GetDesc(&_backbuffer_desc); + backbuffer->Release(); + } + + // Initialize the app's device-dependent objects + hr = CreateRenderTarget(); + + if (FAILED(hr)) + { + Log("Restoration of device objects failed"); + // Invalidate objects + + return E_FAIL; + } + + Log("Device objects were successfuly restored"); + _textures.Set(NULL); + + //_device_objects_restored = true; + return S_OK; +} + +bool D3DDevice::Begin() +{ + if (FAILED(RestoreDevice())) + return false; + + //if (_render_to_texture && _render_target != NULL) + //{ + // if (FAILED(_device->GetRenderTarget(0, &_original_render_target))) + // return false; + // if (FAILED(_device->SetRenderTarget(0, _render_target))) + // return false; + //} + + HRESULT hr; + if (FAILED(hr = _device->BeginScene())) + { + Log("Cannot begin scene: %X", (DWORD)hr); + return false; + } + + //static const D3DVIEWPORT9 vp = {0, 0, _width, _height, 0.f, 1.f}; + //_device->SetViewport(&vp); + //_device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + + //_device->Clear(0, NULL, D3DCLEAR_TARGET /*| D3DCLEAR_ZBUFFER*/, 0xff8080ff, 1.f, 0); + return true; +} + +bool D3DDevice::End() +{ + _device->EndScene(); + _device->Present(NULL, NULL, NULL, NULL); + + _render_data_updated = false; + + //if (_render_to_texture && _render_target != NULL && _original_render_target != NULL) + //{ + // if (FAILED(_device->SetRenderTarget(0, _original_render_target))) + // return false; + //} + + return true; +} + +TArray &D3DDevice::GetRenderData() +{ + if (_render_data_updated) + return _render_data; + _render_data.Allocate(0); + if (_render_target_data == NULL) + return _render_data; + + LPDIRECT3DSURFACE9 surf = NULL; + HRESULT hr; + if (FAILED(_device->GetRenderTarget(0, &surf))) + return _render_data; + if (FAILED(hr = _device->GetRenderTargetData(surf, _render_target_data))) + { + Log("Failed to get render target data (%X)", (DWORD)hr); + surf->Release(); + return _render_data; + } + D3DLOCKED_RECT lr; + if (FAILED(_render_target_data->LockRect(&lr, NULL, D3DLOCK_READONLY))) + { + surf->Release(); + return _render_data; + } + _render_data.Allocate(_width * _height); + + for (int i = 0; i < _height; i++) + { + CopyMemory(&_render_data[i * _width], (BYTE *)lr.pBits + i * lr.Pitch, + _width * sizeof(DWORD)); + } + + _render_target_data->UnlockRect(); + _render_data_updated = true; + surf->Release(); + return _render_data; +} + +HRESULT D3DDevice::SetTexture(DWORD stage, LPDIRECT3DTEXTURE9 tex) +{ + if (stage >= 8) + return E_FAIL; + if (_textures.Length() <= (int)stage) + _textures.Allocate(stage + 1); + if (_textures[stage] != tex) + { + _textures[stage] = tex; + return _device->SetTexture(stage, tex); + } + return S_OK; +} + +HRESULT D3DDevice::CreateRenderTarget() +{ + if (_device == NULL) + return E_FAIL; + //if (_render_target != NULL && + if (_render_target_data != NULL) + return S_OK; + + //if (FAILED(_device->CreateRenderTarget(_width, _height, _backbuffer_desc.Format, + // D3DMULTISAMPLE_NONE, 0, FALSE, &_render_target, NULL))) + //{ + // return E_FAIL; + //} + if (FAILED(_device->CreateOffscreenPlainSurface(_backbuffer_desc.Width, + _backbuffer_desc.Height, _backbuffer_desc.Format, D3DPOOL_SYSTEMMEM, + &_render_target_data, NULL))) + { + return E_FAIL; + } + return S_OK; +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.h new file mode 100644 index 0000000000..c5a4b49b66 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_device.h @@ -0,0 +1,87 @@ +#ifndef __EVAS_DIRECT3D_DEVICE_H__ +#define __EVAS_DIRECT3D_DEVICE_H__ + +#include "evas_engine.h" + +#include + +#include "ref.h" +#include "array.h" + + +class D3DDevice : virtual public Referenc +{ +public: + D3DDevice(); + + bool Init(HWND window, int depth, bool fullscreen = false); + bool Reset(int width, int height, int fullscreen); + void Destroy(); + bool Begin(); + bool End(); + + inline LPDIRECT3DDEVICE9 GetDevice(); + inline int GetWidth(); + inline int GetHeight(); + inline HWND GetWindow(); + inline bool GetFullscreen(); + + TArray &GetRenderData(); + + HRESULT SetTexture(DWORD stage, LPDIRECT3DTEXTURE9 tex); + +private: + HRESULT RestoreDevice(); + HRESULT ResetDevice(); + void ResetParams(); + + HRESULT CreateRenderTarget(); + +private: + HWND _window; + LPDIRECT3D9 _object; + LPDIRECT3DDEVICE9 _device; + int _width; + int _height; + int _rot; + int _depth; + bool _device_lost; + bool _scene_rendering; + D3DPRESENT_PARAMETERS _d3dpp; + D3DSURFACE_DESC _backbuffer_desc; + //LPDIRECT3DSURFACE9 _render_target; + LPDIRECT3DSURFACE9 _render_target_data; + //LPDIRECT3DSURFACE9 _original_render_target; + //bool _render_to_texture; + TArray _render_data; + bool _render_data_updated; + + TArray _textures; +}; + +LPDIRECT3DDEVICE9 D3DDevice::GetDevice() +{ + return _device; +} + +int D3DDevice::GetWidth() +{ + return _width; +} + +int D3DDevice::GetHeight() +{ + return _height; +} + +HWND D3DDevice::GetWindow() +{ + return _window; +} + +bool D3DDevice::GetFullscreen() +{ + return (_d3dpp.Windowed == 0); +} + +#endif // __EVAS_DIRECT3D_DEVICE_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.cpp new file mode 100644 index 0000000000..a92ee5bbb7 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.cpp @@ -0,0 +1,436 @@ +#include "evas_direct3d_image_cache.h" + +#include "evas_direct3d_device.h" + +#include + +Ref D3DImageCache::_this; + +D3DImageCache::D3DImageCache() +{ + _max_width = 512; + _max_height = 512; + _margin = 0; +} + +D3DImageCache::~D3DImageCache() +{ + Uninitialize(); +} + +D3DImageCache *D3DImageCache::Current() +{ + if (_this.IsNull()) + _this = new D3DImageCache(); + return _this; +} + +void D3DImageCache::SetCurrent(D3DImageCache *obj) +{ + _this = obj; +} + +void D3DImageCache::Uninitialize() +{ + for (int i = 0; i < _cache.Length(); i++) + { + // In normal case they all will be NULL + if (_cache[i].texture != NULL) + _cache[i].texture->Release(); + } + _cache.Resize(); +} + +bool D3DImageCache::SelectImageToDevice(D3DDevice *d3d, int id) +{ + if (id < 0 || id >= _cache.Length()) + return false; + assert(_cache[id].texture != NULL); + return SUCCEEDED(d3d->SetTexture(_cache[id].stage, _cache[id].texture)); +} + +void D3DImageCache::RemoveImageUser(int id) +{ + if (id < 0 || id >= _cache.Length()) + return; + assert(_cache[id].texture != NULL); + _cache[id].users--; + if (_cache[id].users == 0) + { + _cache[id].texture->Release(); + ZeroMemory(&_cache[id], sizeof(_cache[id])); + } +} + +void D3DImageCache::AddImageUser(int id) +{ + if (id < 0 || id >= _cache.Length()) + return; + assert(_cache[id].texture != NULL); + _cache[id].users++; +} + +bool D3DImageCache::InsertImage(D3DDevice *d3d, DWORD *data, int w, int h, CacheEntryInfo &info) +{ + CacheEntry *ce = NULL; + int id = -1; + for (int i = 0; i < _cache.Length(); i++) + { + if (!_cache[i].locked && RequestInsert(_cache[i], w, h)) + { + ce = &_cache[i]; + id = i; + break; + } + } + if (ce == NULL) + { + CacheEntry new_entry; + if (!CreateEntry(d3d, new_entry, w, h)) + return false; + for (id = 0; id < _cache.Length(); id++) + { + if (_cache[id].texture == NULL) + break; + } + + if (id < _cache.Length()) + { + _cache[id] = new_entry; + ce = &_cache[id]; + } + else + { + _cache.Add(new_entry); + ce = _cache.Last(); + id = _cache.Length() - 1; + } + } + + assert(ce != NULL && ce->texture != NULL); + + if (!InsertData(*ce, data, w, h)) + return false; + + info.id = id; + info.u = FLOAT(ce->cur_x) / FLOAT(ce->width); + info.v = FLOAT(ce->cur_y) / FLOAT(ce->height); + info.du = FLOAT(w) / FLOAT(ce->width); + info.dv = FLOAT(h) / FLOAT(ce->height); + info.width = w; + info.height = h; + + UpdateInsert(*ce, w, h); + return true; +} + +bool D3DImageCache::InsertImage(D3DDevice *d3d, int id, DWORD *data, int w, int h, CacheEntryInfo &info) +{ + if (id < 0 || id >= _cache.Length()) + return false; + assert(_cache[id].texture != NULL); + CacheEntry *ce = &_cache[id]; + if (!RequestInsert(*ce, w, h)) + return false; + if (!InsertData(*ce, data, w, h)) + return false; + + info.id = id; + info.u = FLOAT(ce->cur_x) / FLOAT(ce->width); + info.v = FLOAT(ce->cur_y) / FLOAT(ce->height); + info.du = FLOAT(w) / FLOAT(ce->width); + info.dv = FLOAT(h) / FLOAT(ce->height); + info.width = w; + info.height = h; + + UpdateInsert(*ce, w, h); + return true; +} + +bool D3DImageCache::CreateImage(D3DDevice *d3d, int w, int h, bool locked, CacheEntryInfo &info) +{ + int id; + CacheEntry new_entry; + CacheEntry *ce = NULL; + + if (!CreateEntry(d3d, new_entry, w, h, true)) + return false; + for (id = 0; id < _cache.Length(); id++) + { + if (_cache[id].texture == NULL) + break; + } + + if (id < _cache.Length()) + { + _cache[id] = new_entry; + ce = &_cache[id]; + } + else + { + _cache.Add(new_entry); + ce = _cache.Last(); + id = _cache.Length() - 1; + } + + assert(ce != NULL && ce->texture != NULL); + + // Fill with zero + if (!InsertData(*ce, NULL, w, h)) + return false; + + info.id = id; + info.u = 0; + info.v = 0; + info.du = 1; + info.dv = 1; + info.width = w; + info.height = h; + + UpdateInsert(*ce, 0, 0); + ce->locked = locked; + return true; +} + +bool D3DImageCache::ResizeImage(D3DDevice *d3d, int nw, int nh, int id) +{ + if (id < 0 || id >= _cache.Length()) + return false; + assert(_cache[id].texture != NULL); + CacheEntry *ce = &_cache[id]; + + if (ce->width == nw && ce->height == nh) + return true; + + LPDIRECT3DTEXTURE9 tex = NULL; + + HRESULT hr; + if (FAILED(hr = d3d->GetDevice()->CreateTexture(nw, nh, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &tex, NULL))) + { + Log("Failed to create texture: %X", hr); + return false; + } + assert(tex != NULL); + + ce->texture->Release(); + ce->texture = tex; + ce->width = nw; + ce->height = nh; + return true; +} + +bool D3DImageCache::RequestInsert(CacheEntry &entry, int w, int h) +{ + // If we already have large image entry + if (entry.width > _max_width || entry.height > _max_height) + return false; + // If requested size does not fit into this entry at all + if (entry.height - entry.cur_h < h + _margin * 2 || entry.width < w + _margin * 2) + return false; + + // If requested size does not fit into the current line of the entry + if (entry.width - entry.cur_x < w + _margin * 2) + { + entry.cur_y = entry.cur_h + _margin; + entry.cur_x = _margin; + return true; + } + entry.cur_x += _margin; + + return true; +} + +bool D3DImageCache::CreateEntry(D3DDevice *d3d, CacheEntry &entry, int w, int h, bool exact_size) +{ + int width = exact_size ? w : max(_max_width, w); + int height = exact_size ? h : max(_max_height, h); + HRESULT hr; + if (FAILED(hr = d3d->GetDevice()->CreateTexture(width, height, 0, 0, D3DFMT_A8R8G8B8, + D3DPOOL_MANAGED, &entry.texture, NULL))) + { + Log("Failed to create texture: %X", hr); + return false; + } + + entry.cur_x = entry.cur_y = entry.cur_h = 0; + entry.width = width; + entry.height = height; + entry.users = 0; + entry.locked = false; + entry.stage = 0; + return true; +} + +bool D3DImageCache::InsertData(CacheEntry &entry, DWORD *data, int w, int h) +{ + if (entry.texture == NULL) + return false; + + RECT rc = {entry.cur_x, entry.cur_y, entry.cur_x + w, entry.cur_y + h}; + D3DLOCKED_RECT lr; + if (FAILED(entry.texture->LockRect(0, &lr, &rc, 0))) + { + Log("Failed to lock texture"); + return false; + } + + if (data != NULL) + { + for (int i = 0; i < h; i++) + CopyMemory(((BYTE *)lr.pBits) + i * lr.Pitch, data + i * w, sizeof(DWORD) * w); + } + else + { + for (int i = 0; i < h; i++) + ZeroMemory(((BYTE *)lr.pBits) + i * lr.Pitch, sizeof(DWORD) * w); + } + + if (FAILED(entry.texture->UnlockRect(0))) + { + Log("Failed to unlock texture"); + return false; + } + return true; +} + + +bool D3DImageCache::RetrieveData(CacheEntry &entry, DWORD *data, int w, int h) +{ + if (entry.texture == NULL || data == NULL) + return false; + + RECT rc = {entry.cur_x, entry.cur_y, entry.cur_x + w, entry.cur_y + h}; + D3DLOCKED_RECT lr; + if (FAILED(entry.texture->LockRect(0, &lr, &rc, D3DLOCK_READONLY))) + { + Log("Failed to lock texture"); + return false; + } + + for (int i = 0; i < h; i++) + CopyMemory(data + i * w, ((BYTE *)lr.pBits) + i * lr.Pitch, sizeof(DWORD) * w); + + if (FAILED(entry.texture->UnlockRect(0))) + { + Log("Failed to unlock texture"); + return false; + } + return true; +} + +void D3DImageCache::UpdateInsert(CacheEntry &entry, int w, int h) +{ + entry.cur_h = max(entry.cur_h, entry.cur_y + h + _margin); + entry.cur_x += w + _margin; + entry.users++; +} + +bool D3DImageCache::UpdateImageData(CacheEntryInfo &info, DWORD *data) +{ + assert(data != NULL); + if (info.id < 0 || info.id >= _cache.Length()) + return false; + CacheEntry ce_copy = _cache[info.id]; + ce_copy.cur_x = int(info.u * FLOAT(ce_copy.width)); + ce_copy.cur_y = int(info.v * FLOAT(ce_copy.height)); + return InsertData(ce_copy, data, info.width, info.height); +} + +bool D3DImageCache::UpdateImageDataWithDirtyInfo(CacheEntryInfo &info, DWORD *data, POINT *dirty) +{ + if (info.id < 0 || info.id >= _cache.Length()) + return false; + CacheEntry &entry = _cache[info.id]; + if (entry.texture == NULL) + return false; + + RECT rc = {0, 0, entry.width, entry.height}; + D3DLOCKED_RECT lr; + if (FAILED(entry.texture->LockRect(0, &lr, &rc, 0))) + { + Log("Failed to lock texture"); + return false; + } + + if (data != NULL) + { + for (int i = 0; i < rc.bottom; i++) + { + if (dirty[i].x < 0 && dirty[i].y < 0) + continue; + if (dirty[i].x >= 0 && dirty[i].y >= 0) + { + CopyMemory(((BYTE *)lr.pBits) + i * lr.Pitch + dirty[i].x * 4, + data + i * rc.right + dirty[i].x, sizeof(DWORD) * (dirty[i].y - dirty[i].x + 1)); + dirty[i].y = -dirty[i].y; + } + else if (dirty[i].x >= 0 && dirty[i].y < 0) + { + ZeroMemory(((BYTE *)lr.pBits) + i * lr.Pitch + dirty[i].x * 4, + sizeof(DWORD) * (-dirty[i].y - dirty[i].x + 1)); + dirty[i].x = -dirty[i].x; + } + } + } + else + { + for (int i = 0; i < rc.bottom; i++) + { + if (dirty[i].x < 0 || dirty[i].y < 0) + continue; + ZeroMemory(((BYTE *)lr.pBits) + i * lr.Pitch + dirty[i].x * 4, + sizeof(DWORD) * (dirty[i].y - dirty[i].x + 1)); + } + } + + if (FAILED(entry.texture->UnlockRect(0))) + { + Log("Failed to unlock texture"); + return false; + } + return true; +} + +bool D3DImageCache::UpdateImageDataDiscard(CacheEntryInfo &info, DWORD *data) +{ + assert(data != NULL); + if (info.id < 0 || info.id >= _cache.Length()) + return false; + CacheEntry &entry = _cache[info.id]; + if (entry.texture == NULL) + return false; + + RECT rc = {0, 0, entry.width, entry.height}; + D3DLOCKED_RECT lr; + if (FAILED(entry.texture->LockRect(0, &lr, &rc, 0))) + { + Log("Failed to lock texture"); + return false; + } + + for (int i = 0; i < rc.bottom; i++) + { + CopyMemory(((BYTE *)lr.pBits) + i * lr.Pitch, + data + i * rc.right, sizeof(DWORD) * rc.right); + } + + if (FAILED(entry.texture->UnlockRect(0))) + { + Log("Failed to unlock texture"); + return false; + } + return true; +} + +bool D3DImageCache::GetImageData(CacheEntryInfo &info, TArray &data) +{ + if (info.id < 0 || info.id >= _cache.Length()) + return false; + CacheEntry ce_copy = _cache[info.id]; + ce_copy.cur_x = int(info.u * FLOAT(ce_copy.width)); + ce_copy.cur_y = int(info.v * FLOAT(ce_copy.height)); + data.Allocate(info.width * info.height); + + return RetrieveData(ce_copy, data.Data(), info.width, info.height); +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.h new file mode 100644 index 0000000000..6fb4c18120 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_image_cache.h @@ -0,0 +1,108 @@ +#ifndef __EVAS_DIRECT3D_IMAGE_CACHE_H__ +#define __EVAS_DIRECT3D_IMAGE_CACHE_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +class D3DDevice; + +class D3DImageCache : virtual public Referenc +{ +public: + struct CacheEntryInfo + { + int id; + int width, height; + FLOAT u, v; + FLOAT du, dv; + }; + +public: + ~D3DImageCache(); + + static D3DImageCache *Current(); + static void SetCurrent(D3DImageCache *obj); + + inline void SetMaxSize(int w, int h); + inline void SetMargin(int margin); + + bool InsertImage(D3DDevice *d3d, DWORD *data, int w, int h, CacheEntryInfo &info); + bool InsertImage(D3DDevice *d3d, int id, DWORD *data, int w, int h, CacheEntryInfo &info); + bool CreateImage(D3DDevice *d3d, int w, int h, bool locked, CacheEntryInfo &info); + bool ResizeImage(D3DDevice *d3d, int nw, int nh, int id); + bool SelectImageToDevice(D3DDevice *d3d, int id); + void RemoveImageUser(int id); + void AddImageUser(int id); + bool UpdateImageData(CacheEntryInfo &info, DWORD *data); + bool UpdateImageDataWithDirtyInfo(CacheEntryInfo &info, DWORD *data, POINT *dirty); + bool UpdateImageDataDiscard(CacheEntryInfo &info, DWORD *data); + bool GetImageData(CacheEntryInfo &info, TArray &data); + void Uninitialize(); + + inline int GetImageWidth(int image_id); + inline int GetImageHeight(int image_id); + + inline void SetImageStage(int image_id, int stage); + +private: + struct CacheEntry + { + LPDIRECT3DTEXTURE9 texture; + int width; + int height; + int cur_x; + int cur_y; + int cur_h; + int users; + bool locked; + int stage; + }; + +private: + D3DImageCache(); + + bool RequestInsert(CacheEntry &entry, int w, int h); + bool CreateEntry(D3DDevice *d3d, CacheEntry &entry, int w, int h, bool exact_size = false); + bool InsertData(CacheEntry &entry, DWORD *data, int w, int h); + bool RetrieveData(CacheEntry &entry, DWORD *data, int w, int h); + void UpdateInsert(CacheEntry &entry, int w, int h); + +private: + TArray _cache; + int _max_width; + int _max_height; + + int _margin; + + static Ref _this; +}; + +void D3DImageCache::SetMaxSize(int w, int h) +{ + _max_width = w; + _max_height = h; +} + +void D3DImageCache::SetMargin(int margin) +{ + _margin = margin; +} + +int D3DImageCache::GetImageWidth(int image_id) +{ + return _cache[image_id].width; +} + +int D3DImageCache::GetImageHeight(int image_id) +{ + return _cache[image_id].height; +} + +void D3DImageCache::SetImageStage(int image_id, int stage) +{ + _cache[image_id].stage = stage; +} + +#endif // __EVAS_DIRECT3D_IMAGE_CACHE_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp index c58c6eba4d..b1074b9a15 100644 --- a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp @@ -1,84 +1,772 @@ +// Force the layered windows APIs to be visible. +#define _WIN32_WINNT 0x0500 + #include "evas_engine.h" +#include + +#include "evas_direct3d_device.h" +#include "evas_direct3d_context.h" +#include "evas_direct3d_shader_pack.h" +#include "evas_direct3d_scene.h" +#include "evas_direct3d_image_cache.h" +#include "evas_direct3d_object_line.h" +#include "evas_direct3d_object_rect.h" +#include "evas_direct3d_object_image.h" +#include "evas_direct3d_vertex_buffer_cache.h" +#include "evas_direct3d_object_font.h" + +// Internal structure that joins two types of objects +struct ImagePtr +{ + Ref ref; + RGBA_Image *img; +}; + +struct DevicePtr +{ + Ref device; + Ref scene; + Ref context; + Ref image_cache; + Ref shader_pack; + Ref vb_cache; + + int fonts_buffer_image_id; + + // Layered windows cannot render D3D in the normal way + bool layered; + + // Window shape mask + struct + { + // Width and height may be different from target size + int width; + int height; + // Pointer to external memory location, dont do anything with it + unsigned char *mask; + } shape; + + // GDI output target + struct + { + HBITMAP image; + HDC hdc; + BITMAPINFO info; + BYTE *data; + } dib; + +}; + +DevicePtr *SelectDevice(Direct3DDeviceHandler d3d) +{ + DevicePtr *dev_ptr = (DevicePtr *)d3d; + D3DImageCache::SetCurrent(dev_ptr->image_cache); + D3DShaderPack::SetCurrent(dev_ptr->shader_pack); + D3DVertexBufferCache::SetCurrent(dev_ptr->vb_cache); + return dev_ptr; +} + +void DeleteDIBObjects(DevicePtr *dev_ptr) +{ + assert(dev_ptr != NULL); + if (dev_ptr->dib.image != NULL) + DeleteObject(dev_ptr->dib.image); + if (dev_ptr->dib.hdc != NULL) + DeleteDC(dev_ptr->dib.hdc); + ZeroMemory(&dev_ptr->dib, sizeof(dev_ptr->dib)); +} + +bool CreateDIBObjects(DevicePtr *dev_ptr) +{ + assert(dev_ptr != NULL); + if ((dev_ptr->dib.hdc = CreateCompatibleDC(NULL)) == NULL) + { + Log("Failed to create compatible DC"); + return false; + } + ZeroMemory(&dev_ptr->dib.info, sizeof(dev_ptr->dib.info)); + dev_ptr->dib.info.bmiHeader.biSize = sizeof(dev_ptr->dib.info.bmiHeader); + dev_ptr->dib.info.bmiHeader.biBitCount = 32; + dev_ptr->dib.info.bmiHeader.biWidth = dev_ptr->device->GetWidth(); + dev_ptr->dib.info.bmiHeader.biHeight = -dev_ptr->device->GetHeight(); + dev_ptr->dib.info.bmiHeader.biCompression = BI_RGB; + dev_ptr->dib.info.bmiHeader.biPlanes = 1; + if ((dev_ptr->dib.image = CreateDIBSection(dev_ptr->dib.hdc, &dev_ptr->dib.info, + DIB_RGB_COLORS, (void **)&dev_ptr->dib.data, NULL, 0)) == NULL) + { + Log("Failed to create dib section"); + DeleteDIBObjects(dev_ptr); + return false; + } + assert(dev_ptr->dib.data != NULL); + GdiFlush(); + return true; +} + + extern "C" { -int -evas_direct3d_masks_get(Outbuf *buf) +Direct3DDeviceHandler evas_direct3d_init(HWND window, int depth, int fullscreen) { - D3DSURFACE_DESC sd; + Ref device = new D3DDevice(); + if (!device->Init(window, depth, fullscreen == 1)) + return NULL; - if (FAILED(buf->priv.d3d.texture->GetLevelDesc(0, &sd))) - return 0; + D3DImageCache::SetCurrent(NULL); + D3DShaderPack::SetCurrent(NULL); + D3DVertexBufferCache::SetCurrent(NULL); - 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; - } + if (!D3DShaderPack::Current()->Initialize(device)) + { + Log("Failed to build shader pack"); + device->Destroy(); + return NULL; + } - return 1; -} + DevicePtr *dev_ptr = new DevicePtr; + ZeroMemory(dev_ptr, sizeof(DevicePtr)); + dev_ptr->device = device; + dev_ptr->scene = new D3DScene(); + dev_ptr->context = new D3DContext(); + dev_ptr->image_cache = D3DImageCache::Current(); + dev_ptr->shader_pack = D3DShaderPack::Current(); + dev_ptr->vb_cache = D3DVertexBufferCache::Current(); + dev_ptr->fonts_buffer_image_id = -1; -void * -evas_direct3d_lock(Outbuf *buf, int *d3d_width, int *d3d_height, int *d3d_pitch) -{ - D3DSURFACE_DESC sd; - D3DLOCKED_RECT d3d_rect; + D3DImageCache::CacheEntryInfo info; + if (!D3DImageCache::Current()->CreateImage(device, device->GetWidth(), device->GetHeight(), + true, info)) + { + Log("Failed to create fonts image buffer"); + return NULL; + } + dev_ptr->fonts_buffer_image_id = info.id; + D3DImageCache::Current()->SetImageStage(info.id, 1); - /* 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; + return (Direct3DDeviceHandler)dev_ptr; } void -evas_direct3d_unlock(Outbuf *buf) +evas_direct3d_free(Direct3DDeviceHandler d3d) { - if (FAILED(buf->priv.d3d.texture->UnlockRect(0))) - return; + DevicePtr *dev_ptr = SelectDevice(d3d); - 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; + DeleteDIBObjects(dev_ptr); - if (FAILED(buf->priv.d3d.device->EndScene())) - return; - if (FAILED(buf->priv.d3d.device->Present(NULL, NULL, NULL, NULL))) - return; + dev_ptr->context = NULL; + dev_ptr->scene = NULL; + dev_ptr->image_cache = NULL; + dev_ptr->shader_pack = NULL; + D3DShaderPack::Current()->Uninitialize(); + D3DImageCache::Current()->Uninitialize(); + D3DVertexBufferCache::Current()->Uninitialize(); + D3DShaderPack::SetCurrent(NULL); + D3DImageCache::SetCurrent(NULL); + D3DVertexBufferCache::SetCurrent(NULL); + + dev_ptr->device = NULL; + delete dev_ptr; + + Log("uninitialized"); } +void +evas_direct3d_resize(Direct3DDeviceHandler d3d, int width, int height) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + if (!device->Reset(width, height, -1)) + { + Log("Failed to resize"); + return; + } + if (!D3DImageCache::Current()->ResizeImage(device, width, height, + dev_ptr->fonts_buffer_image_id)) + { + Log("Failed to resize fonts image buffer"); + } + if (dev_ptr->layered) + { + DeleteDIBObjects(dev_ptr); + if (!CreateDIBObjects(dev_ptr)) + Log("Failed to create dib objects"); + } } + +void +evas_direct3d_set_fullscreen(Direct3DDeviceHandler d3d, int width, int height, int fullscreen) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + + if (width < 0) + width = ::GetSystemMetrics(SM_CXSCREEN); + if (height < 0) + height = ::GetSystemMetrics(SM_CYSCREEN); + + if (!device->Reset(width, height, fullscreen)) + { + Log("Failed to resize"); + return; + } + if (!D3DImageCache::Current()->ResizeImage(device, width, height, + dev_ptr->fonts_buffer_image_id)) + { + Log("Failed to resize fonts image buffer"); + } + + if (fullscreen == 0) + InvalidateRect(HWND_DESKTOP, NULL, TRUE); +} + +void +evas_direct3d_set_layered(Direct3DDeviceHandler d3d, int layered, + int mask_width, int mask_height, unsigned char *mask) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + dev_ptr->layered = (layered != 0); + dev_ptr->shape.width = mask_width; + dev_ptr->shape.height = mask_height; + dev_ptr->shape.mask = mask; + + if (dev_ptr->layered && dev_ptr->dib.data == NULL) + CreateDIBObjects(dev_ptr); + else if (!dev_ptr->layered) + DeleteDIBObjects(dev_ptr); +} + +void +evas_direct3d_context_color_set(Direct3DDeviceHandler d3d, int r, int g, int b, int a) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + dev_ptr->context->color = ((a & 0xff) << 24) | ((r & 0xff) << 16) | + ((g & 0xff) << 8) | (b & 0xff); +} + +void +evas_direct3d_context_set_multiplier(Direct3DDeviceHandler d3d, int r, int g, int b, int a) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + dev_ptr->context->color_mul = ((a & 0xff) << 24) | ((r & 0xff) << 16) | + ((g & 0xff) << 8) | (b & 0xff); +} + +void +evas_direct3d_render_all(Direct3DDeviceHandler d3d) +{ + Log("render"); + assert(d3d != NULL); + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + + if (!device->Begin()) + return; + + device->GetDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + device->GetDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + device->GetDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + + //device->GetDevice()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + //device->GetDevice()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + + D3DObjectLine::BeginCache(); + D3DObjectRect::BeginCache(); + D3DObjectImage::BeginCache(); + scene->DrawAll(device); + D3DObjectLine::EndCache(device); + D3DObjectRect::EndCache(device); + D3DObjectImage::EndCache(device); + D3DObjectFont::EndCache(device); + + device->End(); + + if (dev_ptr->layered && !device->GetFullscreen() && dev_ptr->dib.data != NULL) + { + HDC hdc = GetDC(device->GetWindow()); + if (hdc != NULL) + { + POINT dest = {0, 0}; + POINT src = {0, 0}; + SIZE client = {device->GetWidth(), device->GetHeight()}; + BLENDFUNCTION blend_func = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA}; + + if (device->GetRenderData().Length() == client.cx * client.cy) + { + CopyMemory(dev_ptr->dib.data, device->GetRenderData().Data(), + sizeof(DWORD) * client.cx * client.cy); + } + + for (int i = 0; i < client.cy; i++) + { + for (int j = 0; j < client.cx; j++) + { + int mask_i = int(dev_ptr->shape.height * float(i) / float(client.cy)); + int mask_j = int(dev_ptr->shape.width * float(j) / float(client.cx)); + if (mask_i < 0) + mask_i = 0; + else if (mask_i >= dev_ptr->shape.height) + mask_i = dev_ptr->shape.height - 1; + if (mask_j < 0) + mask_j = 0; + else if (mask_j >= dev_ptr->shape.width) + mask_j = dev_ptr->shape.width - 1; + BYTE mask_b = dev_ptr->shape.mask[mask_i * dev_ptr->shape.width + mask_j]; + float alpha = float(mask_b) / 255.f; + + dev_ptr->dib.data[j * 4 + 0 + i * 4 * client.cx] = BYTE(float(dev_ptr->dib.data[j * 4 + 0 + i * 4 * client.cx]) * alpha); + dev_ptr->dib.data[j * 4 + 1 + i * 4 * client.cx] = BYTE(float(dev_ptr->dib.data[j * 4 + 1 + i * 4 * client.cx]) * alpha); + dev_ptr->dib.data[j * 4 + 2 + i * 4 * client.cx] = BYTE(float(dev_ptr->dib.data[j * 4 + 2 + i * 4 * client.cx]) * alpha); + dev_ptr->dib.data[j * 4 + 3 + i * 4 * client.cx] = mask_b; + } + } + HGDIOBJ prev_obj = SelectObject(dev_ptr->dib.hdc, dev_ptr->dib.image); + ClientToScreen(device->GetWindow(), &dest); + + UpdateLayeredWindow(device->GetWindow(), hdc, &dest, &client, + dev_ptr->dib.hdc, &src, 0, &blend_func, ULW_ALPHA); + + SelectObject(dev_ptr->dib.hdc, prev_obj); + ReleaseDC(device->GetWindow(), hdc); + } + } + scene->FreeObjects(); +} + +void evas_direct3d_line_draw(Direct3DDeviceHandler d3d, int x1, int y1, int x2, int y2) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + D3DContext *context = dev_ptr->context; + + Ref line = scene->GetFreeObject(); + if (line == NULL) + { + line = new D3DObjectLine(); + scene->AddObject(line); + Log("New line object (total objects: %d)", scene->GetObjectCount()); + } + else + { + line->SetFree(false); + Log("Line reused (object: %p)", line.Addr()); + } + + line->Setup( + 2.f * float(x1) / float(device->GetWidth()) - 1.f, + 2.f * (1.f - float(y1) / float(device->GetHeight())) - 1.f, + 2.f * float(x2) / float(device->GetWidth()) - 1.f, + 2.f * (1.f - float(y2) / float(device->GetHeight())) - 1.f, + context->color); +} + +void evas_direct3d_rectangle_draw(Direct3DDeviceHandler d3d, int x, int y, int w, int h) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + D3DContext *context = dev_ptr->context; + + Ref rect = scene->GetFreeObject(); + if (rect == NULL) + { + rect = new D3DObjectRect(); + scene->AddObject(rect); + Log("New rect object (total objects: %d)", scene->GetObjectCount()); + } + else + { + rect->SetFree(false); + Log("Rect reused (object: %p)", rect.Addr()); + } + + rect->Setup( + 2.f * float(x) / float(device->GetWidth()) - 1.f, + 2.f * (1.f - float(y) / float(device->GetHeight())) - 1.f, + 2.f * float(w) / float(device->GetWidth()), + -2.f * float(h) / float(device->GetHeight()), + context->color); +} + +Direct3DImageHandler evas_direct3d_image_load(Direct3DDeviceHandler d3d, + const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + + RGBA_Image *evas_image = evas_common_load_image_from_file(file, key, lo); + if (evas_image == NULL) + { + Log("Failed to load image from %s", file); + return NULL; + } + int image_width = evas_image->cache_entry.w; + int image_height = evas_image->cache_entry.h; + assert(image_width > 0 && image_height > 0); + + D3DImageCache::CacheEntryInfo info; + ZeroMemory(&info, sizeof(info)); + info.id = -1; + + Ref image = new D3DObjectImage(); + image->Init(info.u, info.v, info.du, info.dv, info.id, + info.width, info.height, evas_image->cache_entry.file); + image->SetFree(true); + scene->AddObject(image); + + Log("New image object (total objects: %d)", scene->GetObjectCount()); + + ImagePtr *ptr = new ImagePtr; + ptr->ref = image; + ptr->img = evas_image; + + return (Direct3DImageHandler)ptr; +} + +Direct3DImageHandler evas_direct3d_image_new_from_data(Direct3DDeviceHandler d3d, + int w, int h, DWORD *image_data, int alpha, int cspace) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + + int image_width = w; + int image_height = h; + assert(image_width > 0 && image_height > 0); + + Ref image = new D3DObjectImage(); + + D3DImageCache::CacheEntryInfo info; + ZeroMemory(&info, sizeof(info)); + if (!D3DImageCache::Current()->InsertImage(device, image_data, + image_width, image_height, info)) + { + Log("Couldnt add image to the cache"); + return NULL; + } + char buf[64]; + sprintf(buf, "%p", image_data); + image->Init(info.u, info.v, info.du, info.dv, info.id, + info.width, info.height, buf); + + image->SetFree(true); + scene->AddObject(image); + + Log("New image object (total objects: %d)", scene->GetObjectCount()); + + ImagePtr *ptr = new ImagePtr; + ptr->ref = image; + ptr->img = NULL; + + return (Direct3DImageHandler)ptr; +} + +Direct3DImageHandler evas_direct3d_image_new_from_copied_data(Direct3DDeviceHandler d3d, + int w, int h, DWORD *image_data, int alpha, int cspace) +{ + return evas_direct3d_image_new_from_data(d3d, w, h, image_data, alpha, cspace); +} + +void evas_direct3d_image_free(Direct3DDeviceHandler d3d, Direct3DImageHandler image) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + + ImagePtr *ptr = (ImagePtr *)image; + + Ref image_ref = ptr->ref; + assert(!image_ref.IsNull()); + scene->DeleteObject(image_ref); + + delete ptr; +} + +void evas_direct3d_image_data_put(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + DWORD *image_data) +{ + ImagePtr *ptr = (ImagePtr *)image; + Ref image_ref = ptr->ref; + //assert(!image_ref.IsNull()); + if (image_ref.IsNull()) + return; + + if (!image_ref->UpdateImageData(image_data)) + Log("Failed to update image data"); +} + +void evas_direct3d_image_data_get(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int to_write, DATA32 **image_data) +{ + ImagePtr *ptr = (ImagePtr *)image; + Ref image_ref = ptr->ref; + if (image_ref.IsNull()) + return; + if (image_data == NULL) + return; + assert(sizeof(DATA32) == sizeof(DWORD)); + *image_data = (DATA32 *)image_ref->GetImageData(); +} + +void evas_direct3d_image_draw(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, int smooth) +{ + ImagePtr *ptr = (ImagePtr *)image; + Ref image_ref = ptr->ref; + RGBA_Image *evas_image = ptr->img; + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + D3DScene *scene = dev_ptr->scene; + //assert(!image_ref.IsNull()); + if (image_ref.IsNull()) + return; + + if (!image_ref->IsValid()) + { + TArray images; + scene->GetObjectsOfType(images); + bool found = false; + for (int i = 0; i < images.Length(); i++) + { + if (images[i]->IsValid() && + _stricmp(images[i]->GetSource(), image_ref->GetSource()) == 0) + { + images[i]->CopyTo(image_ref); + found = true; + Log("Image object info reused, source: \"%s\"", image_ref->GetSource()); + break; + } + } + if (!found && evas_image != NULL) + evas_cache_image_load_data(&evas_image->cache_entry); + } + + // If the image object wasnt initialized yet + if (evas_image != NULL && evas_image->image.data != NULL && !image_ref->IsValid()) + { + D3DImageCache::CacheEntryInfo info; + ZeroMemory(&info, sizeof(info)); + if (!D3DImageCache::Current()->InsertImage(device, (DWORD *)evas_image->image.data, + evas_image->cache_entry.w, evas_image->cache_entry.h, info)) + { + Log("Couldnt add image to the cache"); + return; + } + image_ref->Init(info.u, info.v, info.du, info.dv, info.id, + info.width, info.height, evas_image->cache_entry.file); + } + + // Do not draw invalid objects + if (!image_ref->IsValid()) + { + image_ref->SetFree(true); + return; + } + + image_ref->Setup( + 2.f * float(dst_x) / float(device->GetWidth()) - 1.f, + 2.f * (1.f - float(dst_y) / float(device->GetHeight())) - 1.f, + 2.f * float(dst_w) / float(device->GetWidth()), + -2.f * float(dst_h) / float(device->GetHeight()), + src_x, src_y, src_w, src_h); + + image_ref->SetupColorFilter(dev_ptr->context->color_mul); + + image_ref->SetFree(false); +} + +void evas_direct3d_image_size_get(Direct3DImageHandler image, int *w, int *h) +{ + ImagePtr *ptr = (ImagePtr *)image; + if (ptr == NULL) + return; + if (ptr->img != NULL) + { + if (w != NULL) + *w = ptr->img->cache_entry.w; + if (h != NULL) + *h = ptr->img->cache_entry.h; + } + else if (!ptr->ref.IsNull()) + { + if (w != NULL) + *w = ptr->ref->GetWidth(); + if (h != NULL) + *h = ptr->ref->GetHeight(); + } +} + +void evas_direct3d_image_border_set(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int l, int r, int t, int b) +{ + ImagePtr *ptr = (ImagePtr *)image; + Ref image_ref = ptr->ref; + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + if (image_ref.IsNull()) + return; + + int im_w, im_h; + if (ptr->img != NULL) + { + im_w = ptr->img->cache_entry.w; + im_h = ptr->img->cache_entry.h; + } + else + { + im_w = image_ref->GetWidth(); + im_h = image_ref->GetHeight(); + } + + image_ref->SetupBorder( + D3DXVECTOR4( + 2.f * float(l) / float(device->GetWidth()), + -2.f * float(t) / float(device->GetHeight()), + 2.f * float(r) / float(device->GetWidth()), + -2.f * float(b) / float(device->GetHeight())), + D3DXVECTOR4(float(l) / float(im_w), + float(t) / float(im_h), + float(r) / float(im_w), + float(b) / float(im_h))); +} + +void evas_direct3d_image_border_get(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int *l, int *r, int *t, int *b) +{ + ImagePtr *ptr = (ImagePtr *)image; + Ref image_ref = ptr->ref; + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DDevice *device = dev_ptr->device; + if (image_ref.IsNull()) + return; + assert(l != NULL && r != NULL && b != NULL && t != NULL); + *l = (int)(0.5f * image_ref->GetBorderLeft() * device->GetWidth()); + *r = (int)(0.5f * image_ref->GetBorderRight() * device->GetWidth()); + *t = (int)(-0.5f * image_ref->GetBorderTop() * device->GetHeight()); + *b = (int)(-0.5f * image_ref->GetBorderBottom() * device->GetHeight()); +} + + +Direct3DFontGlyphHandler evas_direct3d_font_texture_new(Direct3DDeviceHandler d3d, + RGBA_Font_Glyph *fg) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DContext *context = dev_ptr->context; + D3DDevice *device = dev_ptr->device; + + if (context->font.IsNull()) + return NULL; + + D3DObjectFont *font = (D3DObjectFont *)context->font.Addr(); + // This is not reliable + //D3DObjectFont::Glyph *glyph = (D3DObjectFont::Glyph *)fg->ext_dat; + D3DObjectFont::Glyph *glyph = font->GetGlyph(fg); + if (glyph != NULL) + { + assert(glyph->Compare(fg)); + return glyph; + } + glyph = font->AddGlyph(device, fg, fg->glyph_out->bitmap.buffer, + fg->glyph_out->bitmap.width, fg->glyph_out->bitmap.rows, fg->glyph_out->bitmap.pitch); + return (Direct3DFontGlyphHandler)glyph; +} + +void evas_direct3d_font_texture_free(Direct3DFontGlyphHandler ft) +{ + if (ft == NULL) + return; + D3DObjectFont::Glyph *glyph = (D3DObjectFont::Glyph *)ft; + RGBA_Font_Glyph *fg = (RGBA_Font_Glyph *)glyph->Source(); + fg->ext_dat = NULL; +} + +void evas_direct3d_font_texture_draw(Direct3DDeviceHandler d3d, void *, void *, + RGBA_Font_Glyph *fg, int x, int y) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DContext *context = dev_ptr->context; + D3DDevice *device = dev_ptr->device; + + if (context->font.IsNull()) + return; + + D3DObjectFont *font = (D3DObjectFont *)context->font.Addr(); + D3DObjectFont::Glyph *glyph = (D3DObjectFont::Glyph *)fg->ext_dat; + if (glyph == NULL) + return; + assert(glyph->Compare(fg)); + + font->SetColor(context->color); + font->PushForDraw(glyph, x, y); + font->SetFree(false); +} + +void evas_direct3d_select_or_create_font(Direct3DDeviceHandler d3d, void *font) +{ + // The Plan + // 1. Create D3DObjectFont with source string = "%p" (font) + // 2. Or find this object in the scene + // 3. On each texture_new call - fill internal texture with glyph, remember the + // glyph pointer - we'll use it. + + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DContext *context = dev_ptr->context; + + if (!context->font.IsNull() && ((D3DObjectFont *)context->font.Addr())->Compare(font)) + return; + + D3DScene *scene = dev_ptr->scene; + + static TArray fonts; + scene->GetObjectsOfType(fonts); + for (int i = 0; i < fonts.Length(); i++) + { + if (fonts[i]->Compare(font)) + { + context->font = fonts[i]; + return; + } + } + + D3DDevice *device = dev_ptr->device; + + assert(dev_ptr->fonts_buffer_image_id >= 0); + + Ref new_font = new D3DObjectFont(font, dev_ptr->fonts_buffer_image_id); + scene->AddObject(new_font); + context->font = new_font; +} + +void evas_direct3d_font_free(Direct3DDeviceHandler d3d, void *font) +{ + DevicePtr *dev_ptr = SelectDevice(d3d); + D3DContext *context = dev_ptr->context; + D3DScene *scene = dev_ptr->scene; + + if (context->font.IsNull() || !((D3DObjectFont *)context->font.Addr())->Compare(font)) + { + D3DScene *scene = dev_ptr->scene; + + static TArray fonts; + scene->GetObjectsOfType(fonts); + for (int i = 0; i < fonts.Length(); i++) + { + if (fonts[i]->Compare(font)) + { + context->font = fonts[i]; + break; + } + } + } + + scene->DeleteObject(context->font); + context->font = NULL; +} + + +} // extern "C" diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.cpp new file mode 100644 index 0000000000..15a801e0af --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.cpp @@ -0,0 +1,12 @@ + +#include "evas_direct3d_object.h" + +D3DObject::D3DObject() +{ + _free = false; +} + +D3DObject::~D3DObject() +{ +} + diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.h new file mode 100644 index 0000000000..8c4e6df202 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object.h @@ -0,0 +1,35 @@ +#ifndef __EVAS_DIRECT3D_OBJECT_H__ +#define __EVAS_DIRECT3D_OBJECT_H__ + +#include "evas_engine.h" + +#include "ref.h" + +class D3DDevice; + +class D3DObject : virtual public Referenc +{ +public: + D3DObject(); + virtual ~D3DObject(); + + virtual void Draw(D3DDevice *d3d) = 0; + + inline bool IsFree(); + inline void SetFree(bool state); + +private: + bool _free; +}; + +bool D3DObject::IsFree() +{ + return _free; +} + +void D3DObject::SetFree(bool state) +{ + _free = state; +} + +#endif // __EVAS_DIRECT3D_OBJECT_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp new file mode 100644 index 0000000000..7730f7c8e4 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.cpp @@ -0,0 +1,231 @@ +//#define ENABLE_LOG_PRINTF + +#include + +#include "evas_direct3d_object_font.h" +#include "evas_direct3d_image_cache.h" +#include "evas_direct3d_device.h" +#include "evas_direct3d_shader_pack.h" +#include "evas_direct3d_vertex_buffer_cache.h" + +D3DObjectFont::Cache D3DObjectFont::_cache; + +D3DObjectFont::D3DObjectFont(void *source, int image_id) +{ + _image_id = image_id; + _color = 0xff000000; + _source = source; + D3DImageCache::Current()->AddImageUser(_image_id); +} + +D3DObjectFont::~D3DObjectFont() +{ + D3DImageCache::Current()->RemoveImageUser(_image_id); +} + +void D3DObjectFont::CopyTo(D3DObjectFont *font) +{ + assert(font != NULL); + font->_image_id = _image_id; + font->_source = _source; + D3DImageCache::Current()->AddImageUser(font->_image_id); + _glyphs.CopyTo(font->_glyphs); +} + +void D3DObjectFont::BeginCache(int image_id) +{ + if (_cache.enabled) + return; + int w = D3DImageCache::Current()->GetImageWidth(image_id); + int h = D3DImageCache::Current()->GetImageHeight(image_id); + _cache.enabled = true; + _cache.image_id = image_id; + _cache.data.Allocate(w * h); + + if (_cache.dirty.Length() != h) + { + _cache.dirty.Allocate(h); + memset(_cache.dirty.Data(), 0xff, sizeof(POINT) * _cache.dirty.Length()); + } + + ZeroMemory(_cache.data.Data(), sizeof(DWORD) * _cache.data.Length()); + _cache.width = w; + _cache.height = h; + + _cache.valid_rect.left = w; + _cache.valid_rect.right = 0; + _cache.valid_rect.top = h; + _cache.valid_rect.bottom = 0; +} + +void D3DObjectFont::Draw(D3DDevice *d3d) +{ + assert(_cache.image_id == _image_id); +} + +void D3DObjectFont::EndCache(D3DDevice *d3d) +{ + if (!_cache.enabled) + return; + _cache.enabled = false; + + if (_cache.data.Length() == 0) + return; + + D3DImageCache::CacheEntryInfo info; + ZeroMemory(&info, sizeof(info)); + info.id = _cache.image_id; + info.width = _cache.width; + info.height = _cache.height; + if (!D3DImageCache::Current()->UpdateImageDataWithDirtyInfo(info, + _cache.data.Data(), _cache.dirty.Data())) + //if (!D3DImageCache::Current()->UpdateImageDataDiscard(info, _cache.data.Data())); + { + return; + } + + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYUV); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_UV); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_TEX_2); // This image is in s1 + D3DImageCache::Current()->SelectImageToDevice(d3d, _cache.image_id); + + const FLOAT half_x = 0.5f / FLOAT(_cache.width); + const FLOAT half_y = 0.5f / FLOAT(_cache.height); + FLOAT left = FLOAT(_cache.valid_rect.left - 5) / FLOAT(_cache.width), + top = FLOAT(_cache.valid_rect.top - 5) / FLOAT(_cache.height), + right = FLOAT(_cache.valid_rect.right + 5) / FLOAT(_cache.width), + bottom = FLOAT(_cache.valid_rect.bottom + 5) / FLOAT(_cache.height); + + const Vertex data[6] = { + {left * 2 - 1, 2 * (1 - bottom) - 1, left + half_x, bottom + half_y}, + {left * 2 - 1, 2 * (1 - top) - 1, left + half_x, top + half_y}, + {right * 2 - 1, 2 * (1 - bottom) - 1, right + half_x, bottom + half_y}, + {right * 2 - 1, 2 * (1 - bottom) - 1, right + half_x, bottom + half_y}, + {left * 2 - 1, 2 * (1 - top) - 1, left + half_x, top + half_y}, + {right * 2 - 1, 2 * (1 - top) - 1, right + half_x, top + half_y}}; + + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, data, sizeof(Vertex)); + + //D3DImageCache::Current()->UpdateImageDataWithDirtyInfo(info, NULL, _cache.dirty.Data()); +} + +D3DObjectFont::Glyph *D3DObjectFont::GetGlyph(void *source) +{ + if (_image_id < 0) + { + Log("Font is not initialized"); + return NULL; + } + for (int i = 0; i < _glyphs.Length(); i++) + { + if (_glyphs[i]->Compare(source)) + return _glyphs[i]; + } + return NULL; +} + +D3DObjectFont::Glyph *D3DObjectFont::AddGlyph(D3DDevice *d3d, void *source, + BYTE *data8, int width, int height, int pitch) +{ + if (_image_id < 0) + { + Log("Font is not initialized"); + return NULL; + } + for (int i = 0; i < _glyphs.Length(); i++) + { + if (_glyphs[i]->Compare(source)) + return _glyphs[i]; + } + Ref glyph = new Glyph(source); + glyph->_data.Allocate(width * height); + glyph->_width = width; + glyph->_height = height; + + for (int i = 0; i < height; i++) + CopyMemory(&glyph->_data[i * width], &data8[i * pitch], width); + + Log("Glyph added (%p) (%dx%d)", source, width, height); + _glyphs.Add(glyph); + return _glyphs.Last()->Addr(); +} + +void D3DObjectFont::PushForDraw(Glyph *glyph, int x, int y) +{ + BeginCache(_image_id); + + // Uff, I'm not sure about multiple windows... + +#define LERP(a, b, t1, t2) (BYTE)(FLOAT(a) * (t1) + FLOAT(b) * (t2)) + + Color dc, sc; + FLOAT a; + sc.color = _color; + + const FLOAT color_alpha = sc.Alpha(); + + DWORD *data = _cache.data.Data(); + BYTE *gdata = glyph->_data.Data(); + const int glyph_height = glyph->_height; + const int cache_height = _cache.height; + const int glyph_width = glyph->_width; + const int cache_width = _cache.width; + + for (int i = 0, yi = y; i < glyph_height && yi < cache_height; i++, yi++) + { + if (yi < 0) + continue; + DWORD *dst = data + ((yi) * cache_width + x); + BYTE *src = gdata + (i * glyph_width); + POINT *dirty_yi = &_cache.dirty[yi]; + + if (_cache.valid_rect.top > yi) + _cache.valid_rect.top = yi; + if (_cache.valid_rect.bottom < yi) + _cache.valid_rect.bottom = yi; + + for (int j = 0, xj = x; j < glyph_width && xj < cache_width; j++, xj++, dst++, src++) + { + if (xj < 0) + continue; + BYTE glyph_pix = *src; + if (glyph_pix == 0) + continue; + + if (dirty_yi->x >= 0 && dirty_yi->y < 0) + dirty_yi->x = 0, dirty_yi->y = cache_width - 1; + else + { + if (dirty_yi->x < 0 || dirty_yi->x > xj) + dirty_yi->x = xj; + if (dirty_yi->y < 0 || dirty_yi->y < xj) + dirty_yi->y = xj; + } + + if (_cache.valid_rect.left > xj) + _cache.valid_rect.left = xj; + if (_cache.valid_rect.right < xj) + _cache.valid_rect.right = xj; + + if (glyph_pix == 0xff && sc.a == 0xff) + { + *dst = sc.color; + continue; + } + a = FLOAT(glyph_pix) * color_alpha / 255.f; + if (*dst == 0) + { + *dst = (BYTE(255.f * a) << 24) | (0x00ffffff & sc.color); + continue; + } + + dc.color = *dst; + + dc.r = LERP(dc.r, sc.r, 1 - a, a); + dc.g = LERP(dc.g, sc.g, 1 - a, a); + dc.b = LERP(dc.b, sc.b, 1 - a, a); + dc.a = max(dc.a, BYTE(255.f * a)); + *dst = dc.color; + } + } +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.h new file mode 100644 index 0000000000..e8c0196827 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_font.h @@ -0,0 +1,113 @@ +#ifndef __EVAS_DIRECT3D_OBJECT_FONT_H__ +#define __EVAS_DIRECT3D_OBJECT_FONT_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +#include "evas_direct3d_object.h" + +class D3DObjectFont : public D3DObject +{ +public: + + class Glyph : public Referenc + { + public: + Glyph(void *source) + : _source(source), _width(0), _height(0) {}; + + bool Compare(void *source) + { + return (_source == source); + } + void *Source() + { + return _source; + } + + private: + friend class D3DObjectFont; + void *_source; + TArray _data; + int _width; + int _height; + }; + +public: + D3DObjectFont(void *source, int image_id); + ~D3DObjectFont(); + + inline bool Compare(void *source); + void CopyTo(D3DObjectFont *font); + + virtual void Draw(D3DDevice *d3d); + static void EndCache(D3DDevice *d3d); + + inline void SetColor(DWORD color); + + Glyph *GetGlyph(void *source); + Glyph *AddGlyph(D3DDevice *d3d, void *source, BYTE *data8, int width, int height, int pitch); + void PushForDraw(Glyph *glyph, int x, int y); + +protected: + static void BeginCache(int image_id); + +private: + struct Vertex + { + FLOAT x, y; + FLOAT u, v; + }; + + struct Color + { + union + { + struct + { + BYTE b, g, r, a; + }; + DWORD color; + }; + + FLOAT Alpha() { return FLOAT(a) / 255.f; } + }; + + class Cache + { + public: + Cache() + : enabled(false), image_id(-1), width(0), height(0) {}; + public: + TArray data; + TArray dirty; // Start, End + bool enabled; + int image_id; + int width; + int height; + RECT valid_rect; + }; + +private: + DWORD _color; + void *_source; + int _image_id; + + TArray > _glyphs; + + static Cache _cache; +}; + +bool D3DObjectFont::Compare(void *source) +{ + return (_source == source); +} + +void D3DObjectFont::SetColor(DWORD color) +{ + _color = color; +} + +#endif // __EVAS_DIRECT3D_OBJECT_FONT_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.cpp new file mode 100644 index 0000000000..a989aaa60a --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.cpp @@ -0,0 +1,318 @@ +//#define ENABLE_LOG_PRINTF + +#include + +#include "evas_direct3d_object_image.h" +#include "evas_direct3d_image_cache.h" +#include "evas_direct3d_device.h" +#include "evas_direct3d_shader_pack.h" +#include "evas_direct3d_vertex_buffer_cache.h" + +TArray D3DObjectImage::_cache; +bool D3DObjectImage::_cache_enabled = false; + +D3DObjectImage::D3DObjectImage() +{ + _x = _y = _w = _h = 0; + _sx = _sy = _sw = _sh = 0; + _u = _v = _du = _dv = 0; + _image_id = -1; + _width = _height = 0; + _source[0] = 0; + _color = 0xffffffff; + _cache_i = 0; + _border = D3DXVECTOR4(0, 0, 0, 0); + _uvborder = D3DXVECTOR4(0, 0, 0, 0); + _with_border = false; + _dirty = false; + _image_data_updated = false; +} + +D3DObjectImage::~D3DObjectImage() +{ + D3DImageCache::Current()->RemoveImageUser(_image_id); +} + +void D3DObjectImage::CopyTo(D3DObjectImage *image) +{ + assert(image != NULL); + image->_u = _u; + image->_v = _v; + image->_du = _du; + image->_dv = _dv; + image->_image_id = _image_id; + image->_width = _width; + image->_height = _height; + CopyMemory(image->_source, _source, sizeof(_source)); + D3DImageCache::Current()->AddImageUser(image->_image_id); +} + +void D3DObjectImage::BeginCache() +{ + _cache.Allocate(0); + _cache_enabled = true; +} + +void D3DObjectImage::EndCache(D3DDevice *d3d) +{ + if (!_cache_enabled || _cache.Length() == 0) + return; + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYUVC); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_UV_COLOR); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_TEX_COLOR_FILTER); + + static TArray sorted; + static TArray groups; + sorted.Allocate(0); + groups.Allocate(0); + + bool found = true; + while (found) + { + found = false; + int cur_id = -1; + int num = 0; + for (int i = 0; i < _cache.Length(); i++) + { + // We have processed this + if (_cache[i]->_image_id < 0) + continue; + found = true; + if (cur_id < 0) + cur_id = _cache[i]->_image_id; + if (_cache[i]->_image_id == cur_id) + { + if (!_cache[i]->_with_border) + { + Vertex *data = _cache[i]->MakeData(); + sorted.Add(data[0]); + sorted.Add(data[1]); + sorted.Add(data[2]); + sorted.Add(data[3]); + sorted.Add(data[4]); + sorted.Add(data[5]); + _cache[i]->_image_id = -_cache[i]->_image_id - 1; + num++; + } + else + { + Vertex *data = _cache[i]->MakeDataBorder(); + int last_len = sorted.Length(); + sorted.Allocate(last_len + 6 * 9); + CopyMemory(&sorted[last_len], data, sizeof(Vertex) * 6 * 9); + _cache[i]->_image_id = -_cache[i]->_image_id - 1; + num += 9; + } + } + } + if (num > 0) + { + GroupDesc gd = {num, cur_id}; + groups.Add(gd); + } + } + + // Restore ids + for (int i = 0; i < _cache.Length(); i++) + _cache[i]->_image_id = -_cache[i]->_image_id - 1; + + D3DVertexBufferCache::CacheEntryInfo ce_info; + if (!D3DVertexBufferCache::Current()->InitBuffer(d3d, (BYTE *)sorted.Data(), + sorted.Length() * sizeof(Vertex), ce_info)) + { + return; + } + D3DVertexBufferCache::Current()->SelectBufferToDevice(d3d, ce_info.id, sizeof(Vertex)); + + HRESULT hr; + for (int i = 0, cur = 0; i < groups.Length(); i++) + { + if (FAILED(hr = D3DImageCache::Current()->SelectImageToDevice(d3d, groups[i].id))) + { + Log("Failed to select texture: %X", (DWORD)hr); + } +// d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, groups[i].num * 2, +// &sorted[cur], sizeof(Vertex)); + d3d->GetDevice()->DrawPrimitive(D3DPT_TRIANGLELIST, cur, groups[i].num * 2); + cur += groups[i].num * 6; + } + + Log("Image cache drawn: %d items, %d groups", _cache.Length(), groups.Length()); + _cache_enabled = false; +} + +void D3DObjectImage::Draw(D3DDevice *d3d) +{ + _dirty = false; + + Log("Image draw: (%.3f, %.3f, %.3f, %.3f)", _x, _y, _w, _h); + + if (_cache_enabled) + { + _cache.Add(this); + _cache_i = _cache.Length() - 1; + return; + } + + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYUVC); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_UV_COLOR); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_TEX_COLOR_FILTER); + D3DImageCache::Current()->SelectImageToDevice(d3d, _image_id); + + if (!_with_border) + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, MakeData(), sizeof(Vertex)); + else + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 18, MakeDataBorder(), sizeof(Vertex)); +} + +void D3DObjectImage::Init(FLOAT u, FLOAT v, FLOAT du, FLOAT dv, + int image_id, int width, int height, const char *source) +{ + _u = u; + _v = v; + _du = du; + _dv = dv; + _image_id = image_id; + _width = width; + _height = height; +#ifdef __MINGW32__ + strncpy(_source, source, sizeof(_source) - 1); +#else + strncpy_s(_source, sizeof(_source), source, sizeof(_source) - 1); +#endif // ! __MINGW32__ +} + +void D3DObjectImage::Setup(FLOAT x, FLOAT y, FLOAT w, FLOAT h, + int sx, int sy, int sw, int sh) +{ + if (!_dirty) + { + _x = 1.f; + _y = -1.f; + _w = _h = 0.f; + _sx = _sy = 1.f; + _sw = _sh = 0.f; + } + + if (!_with_border) + { + _x = x; + _y = y; + _w = w; + _h = h; + _sx = FLOAT(sx) / FLOAT(_width); + _sy = FLOAT(sy) / FLOAT(_height); + _sw = FLOAT(sw) / FLOAT(_width); + _sh = FLOAT(sh) / FLOAT(_height); + } + else + { + _x = min(_x, x); + _y = max(_y, y); + _w += w / 3; + _h += h / 3; + _sx = min(_sx, FLOAT(sx) / FLOAT(_width)); + _sy = min(_sy, FLOAT(sy) / FLOAT(_height)); + _sw += FLOAT(sw) / (3.f * FLOAT(_width)); + _sh += FLOAT(sh) / (3.f * FLOAT(_height)); + } + _dirty = true; + +} + +void D3DObjectImage::SetupColorFilter(DWORD color) +{ + //_color = ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); + _color = color; +} + +D3DObjectImage::Vertex *D3DObjectImage::MakeData() +{ + //FLOAT z = (FLOAT(_cache_i) + 0.5f) / _cache.Length(); + Vertex data[6] = { + {_x, _y, _u + _sx * _du, _v + _sy * _dv, _color}, + {_x + _w, _y, _u + (_sx + _sw) * _du, _v + _sy * _dv, _color}, + {_x, _y + _h, _u + _sx * _du, _v + (_sy + _sh) * _dv, _color}, + {_x, _y + _h, _u + _sx * _du, _v + (_sy + _sh) * _dv, _color}, + {_x + _w, _y, _u + (_sx + _sw) * _du, _v + _sy * _dv, _color}, + {_x + _w, _y + _h, _u + (_sx + _sw) * _du, _v + (_sy + _sh) * _dv, _color}}; + CopyMemory(_data, data, sizeof(data)); + return _data; +} + +D3DObjectImage::Vertex *D3DObjectImage::MakeDataBorder() +{ + //FLOAT z = (FLOAT(_cache_i) + 0.5f) / _cache.Length(); + if (_border.x + _border.z > _w) + _border.x = _border.z = _w / 2; + if (_border.y + _border.w < _h) + _border.y = _border.w = _h / 2; + + FLOAT ul, ut, ur, ub; + ul = _uvborder.x * _du; + ut = _uvborder.y * _dv; + ur = _uvborder.z * _du; + ub = _uvborder.w * _dv; + FLOAT bl, bt, br, bb; + bl = _border.x; + bt = _border.y; + br = _border.z; + bb = _border.w; + + const FLOAT half_x = 0.5f * _du / FLOAT(_width); + const FLOAT half_y = 0.5f * _dv / FLOAT(_height); + + // Diagonal knots + Vertex data[4] = { + {_x, _y, _u + _sx * _du + half_x, _v + _sy * _dv + half_y, _color}, + {_x + bl, _y + bt, _u + ul + _sx * _du, _v + ut + _sy * _dv, _color}, + {_x + _w - br, _y + _h - bb, _u - ur + (_sx + _sw) * _du, _v - ub + (_sy + _sh) * _dv, _color}, + {_x + _w, _y + _h, _u + (_sx + _sw) * _du - half_x, _v + (_sy + _sh) * _dv - half_y, _color}}; + + static const int yshift[6] = {0, 0, 1, 1, 0, 1}; + static const int xshift[6] = {0, 1, 0, 0, 1, 1}; + + int vi = 0; + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + for (int v = 0; v < 6; v++) + { + _data[vi].x = data[xshift[v] + j].x; + _data[vi].y = data[yshift[v] + i].y; + _data[vi].u = data[xshift[v] + j].u; + _data[vi].v = data[yshift[v] + i].v; + _data[vi].col = data[0].col; + vi++; + } + } + } + + return _data; +} + +void D3DObjectImage::SetupBorder(const D3DXVECTOR4 &world_border, const D3DXVECTOR4 &pix_border) +{ + _border = world_border; + _uvborder = pix_border; + _with_border = (_border.x > 0.0001f || _border.y > 0.0001f || + _border.z > 0.0001f || _border.w > 0.0001f); +} + +bool D3DObjectImage::UpdateImageData(DWORD *image_data) +{ + D3DImageCache::CacheEntryInfo info = {_image_id, _width, _height, _u, _v, _du, _dv}; + _image_data_updated = false; + return D3DImageCache::Current()->UpdateImageData(info, image_data); +} + +DWORD *D3DObjectImage::GetImageData() +{ + if (_image_data_updated) + return _image_data.Data(); + _image_data_updated = true; + D3DImageCache::CacheEntryInfo info = {_image_id, _width, _height, _u, _v, _du, _dv}; + D3DImageCache::Current()->GetImageData(info, _image_data); + return _image_data.Data(); +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.h new file mode 100644 index 0000000000..379207b114 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_image.h @@ -0,0 +1,127 @@ +#ifndef __EVAS_DIRECT3D_OBJECT_IMAGE_H__ +#define __EVAS_DIRECT3D_OBJECT_IMAGE_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +#include "evas_direct3d_object.h" + +class D3DObjectImage : public D3DObject +{ +public: + D3DObjectImage(); + virtual ~D3DObjectImage(); + + void CopyTo(D3DObjectImage *image); + + static void BeginCache(); + virtual void Draw(D3DDevice *d3d); + static void EndCache(D3DDevice *d3d); + + void Init(FLOAT u, FLOAT v, FLOAT du, FLOAT dv, int image_id, + int width, int height, const char *source); + void Setup(FLOAT x, FLOAT y, FLOAT w, FLOAT h, + int sx, int sy, int sw, int sh); + void SetupColorFilter(DWORD color); + void SetupBorder(const D3DXVECTOR4 &world_border, const D3DXVECTOR4 &pix_border); + + inline bool IsValid(); + inline const char *GetSource(); + inline int GetWidth(); + inline int GetHeight(); + inline FLOAT GetBorderLeft(); + inline FLOAT GetBorderRight(); + inline FLOAT GetBorderTop(); + inline FLOAT GetBorderBottom(); + + bool UpdateImageData(DWORD *image_data); + DWORD *GetImageData(); + +private: + struct Vertex + { + FLOAT x, y; + FLOAT u, v; + D3DCOLOR col; + }; + + struct GroupDesc + { + int num; + int id; + }; + +private: + Vertex *MakeData(); + Vertex *MakeDataBorder(); + +private: + FLOAT _x, _y, _w, _h; + FLOAT _sx, _sy, _sw, _sh; + D3DXVECTOR4 _border; + D3DXVECTOR4 _uvborder; + + FLOAT _u, _v, _du, _dv; + int _image_id; + int _width, _height; + + D3DCOLOR _color; + int _cache_i; + bool _with_border; + bool _dirty; + + TArray _image_data; + bool _image_data_updated; + + char _source[256]; + + Vertex _data[54]; + + static TArray _cache; + static bool _cache_enabled; +}; + +bool D3DObjectImage::IsValid() +{ + return _image_id >= 0 && _width > 0 && _height > 0; +} + +const char *D3DObjectImage::GetSource() +{ + return _source; +} + +int D3DObjectImage::GetWidth() +{ + return _width; +} + +int D3DObjectImage::GetHeight() +{ + return _height; +} + +FLOAT D3DObjectImage::GetBorderLeft() +{ + return _border.x; +} + +FLOAT D3DObjectImage::GetBorderRight() +{ + return _border.z; +} + +FLOAT D3DObjectImage::GetBorderTop() +{ + return _border.y; +} + +FLOAT D3DObjectImage::GetBorderBottom() +{ + return _border.w; +} + + +#endif // __EVAS_DIRECT3D_OBJECT_IMAGE_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.cpp new file mode 100644 index 0000000000..5c0f774ef4 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.cpp @@ -0,0 +1,60 @@ + +#include "evas_direct3d_object_line.h" +#include "evas_direct3d_device.h" +#include "evas_direct3d_shader_pack.h" + +TArray D3DObjectLine::_cache; +bool D3DObjectLine::_cache_enabled = false; + +D3DObjectLine::D3DObjectLine() +{ + _x1 = _y1 = 0; + _x2 = _y2 = 0; +} + +void D3DObjectLine::BeginCache() +{ + _cache.Allocate(0); + _cache_enabled = true; +} + +void D3DObjectLine::EndCache(D3DDevice *d3d) +{ + if (!_cache_enabled || _cache.Length() == 0) + return; + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYC); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_COLOR); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_COLOR); + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_LINELIST, _cache.Length() / 2, + _cache.Data(), sizeof(Vertex)); + + Log("Line cache drawn: %d items", _cache.Length() / 2); + _cache_enabled = false; +} + +void D3DObjectLine::Draw(D3DDevice *d3d) +{ + Vertex data[2] = {{_x1, _y1, _color}, {_x2, _y2, _color}}; + + if (!_cache_enabled) + { + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYC); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_COLOR); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_COLOR); + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_LINELIST, 1, data, sizeof(Vertex)); + } + else + { + _cache.Add(data[0]); + _cache.Add(data[1]); + } +} + +void D3DObjectLine::Setup(FLOAT x1, FLOAT y1, FLOAT x2, FLOAT y2, DWORD color) +{ + _x1 = x1; + _y1 = y1; + _x2 = x2; + _y2 = y2; + _color = color; +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.h new file mode 100644 index 0000000000..0e5d8078dc --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_line.h @@ -0,0 +1,37 @@ +#ifndef __EVAS_DIRECT3D_OBJECT_LINE_H__ +#define __EVAS_DIRECT3D_OBJECT_LINE_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +#include "evas_direct3d_object.h" + +class D3DObjectLine : public D3DObject +{ +public: + D3DObjectLine(); + + static void BeginCache(); + virtual void Draw(D3DDevice *d3d); + static void EndCache(D3DDevice *d3d); + + void Setup(FLOAT x1, FLOAT y1, FLOAT x2, FLOAT y2, DWORD color); + +private: + FLOAT _x1, _y1, _x2, _y2; + DWORD _color; + +private: + struct Vertex + { + FLOAT x, y; + DWORD color; + }; + + static TArray _cache; + static bool _cache_enabled; +}; + +#endif // __EVAS_DIRECT3D_OBJECT_LINE_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.cpp new file mode 100644 index 0000000000..f37e28ebcc --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.cpp @@ -0,0 +1,65 @@ +#include "evas_direct3d_object_rect.h" +#include "evas_direct3d_device.h" +#include "evas_direct3d_shader_pack.h" + +TArray D3DObjectRect::_cache; +bool D3DObjectRect::_cache_enabled = false; + +D3DObjectRect::D3DObjectRect() +{ + _x = _y = 0; + _w = _h = 0; +} + +void D3DObjectRect::BeginCache() +{ + _cache.Allocate(0); + _cache_enabled = true; +} + +void D3DObjectRect::EndCache(D3DDevice *d3d) +{ + if (!_cache_enabled || _cache.Length() == 0) + return; + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYC); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_COLOR); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_COLOR); + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, _cache.Length() / 3, + _cache.Data(), sizeof(Vertex)); + + Log("Rect cache drawn: %d items", _cache.Length() / 6); + _cache_enabled = false; +} + +void D3DObjectRect::Draw(D3DDevice *d3d) +{ + Vertex data[6] = { + {_x, _y, _color}, {_x + _w, _y, _color}, {_x, _y + _h, _color}, + {_x, _y + _h, _color}, {_x + _w, _y, _color}, {_x + _w, _y + _h, _color}}; + + if (!_cache_enabled) + { + D3DShaderPack::Current()->SetVDecl(d3d, D3DShaderPack::VDECL_XYC); + D3DShaderPack::Current()->SetVS(d3d, D3DShaderPack::VS_COPY_COLOR); + D3DShaderPack::Current()->SetPS(d3d, D3DShaderPack::PS_COLOR); + d3d->GetDevice()->DrawPrimitiveUP(D3DPT_TRIANGLELIST, 2, data, sizeof(Vertex)); + } + else + { + _cache.Add(data[0]); + _cache.Add(data[1]); + _cache.Add(data[2]); + _cache.Add(data[3]); + _cache.Add(data[4]); + _cache.Add(data[5]); + } +} + +void D3DObjectRect::Setup(FLOAT x, FLOAT y, FLOAT w, FLOAT h, DWORD color) +{ + _x = x; + _y = y; + _w = w; + _h = h; + _color = color; +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.h new file mode 100644 index 0000000000..f7ef084ab2 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_object_rect.h @@ -0,0 +1,37 @@ +#ifndef __EVAS_DIRECT3D_OBJECT_RECT_H__ +#define __EVAS_DIRECT3D_OBJECT_RECT_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +#include "evas_direct3d_object.h" + +class D3DObjectRect : public D3DObject +{ +public: + D3DObjectRect(); + + static void BeginCache(); + virtual void Draw(D3DDevice *d3d); + static void EndCache(D3DDevice *d3d); + + void Setup(FLOAT x, FLOAT y, FLOAT w, FLOAT h, DWORD color); + +private: + FLOAT _x, _y, _w, _h; + DWORD _color; + +private: + struct Vertex + { + FLOAT x, y; + DWORD color; + }; + + static TArray _cache; + static bool _cache_enabled; +}; + +#endif // __EVAS_DIRECT3D_OBJECT_RECT_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.cpp new file mode 100644 index 0000000000..b171fc0d8c --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.cpp @@ -0,0 +1,33 @@ + +#include "evas_direct3d_scene.h" + +D3DScene::D3DScene() +{ +} + +void D3DScene::FreeObjects() +{ + for (int i = 0; i < _objects.Length(); i++) + _objects[i]->SetFree(true); +} + +void D3DScene::DrawAll(D3DDevice *d3d) +{ + for (int i = 0; i < _objects.Length(); i++) + { + if (!_objects[i]->IsFree()) + _objects[i]->Draw(d3d); + } +} + +void D3DScene::DeleteObject(D3DObject *object) +{ + for (int i = 0; i < _objects.Length(); i++) + { + if (_objects[i].Addr() == object) + { + _objects.Replace(i); + return; + } + } +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.h new file mode 100644 index 0000000000..e2f5f944ce --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_scene.h @@ -0,0 +1,63 @@ +#ifndef __EVAS_DIRECT3D_SCENE_H__ +#define __EVAS_DIRECT3D_SCENE_H__ + +#include "evas_engine.h" + +#include +#include + +#include "ref.h" +#include "array.h" + +#include "evas_direct3d_object.h" + +class D3DDevice; + +class D3DScene : virtual public Referenc +{ +public: + D3DScene(); + + void FreeObjects(); + + inline void AddObject(D3DObject *object); + inline int GetObjectCount(); + void DeleteObject(D3DObject *object); + + void DrawAll(D3DDevice *d3d); + + template T *GetFreeObject() + { + for (int i = 0; i < _objects.Length(); i++) + { + if (typeid(T) == typeid(*_objects[i].Addr()) && _objects[i]->IsFree()) + return (T *)_objects[i].Addr(); + } + return NULL; + } + + template void GetObjectsOfType(TArray &res) + { + for (int i = 0; i < _objects.Length(); i++) + { + if (typeid(T) == typeid(*_objects[i].Addr())) + res.Add((T *)_objects[i].Addr()); + } + } + +private: + TArray > _objects; +}; + +void D3DScene::AddObject(D3DObject *object) +{ + assert(object != NULL); + _objects.Add(object); +} + +int D3DScene::GetObjectCount() +{ + return _objects.Length(); +} + +#endif // __EVAS_DIRECT3D_SCENE_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.cpp new file mode 100644 index 0000000000..c646141741 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.cpp @@ -0,0 +1,340 @@ +#include "evas_direct3d_shader_pack.h" +#include "evas_direct3d_device.h" +#include + +Ref D3DShaderPack::_this; + +D3DShaderPack::D3DShaderPack() +{ +} + +D3DShaderPack::~D3DShaderPack() +{ + Uninitialize(); +} + +D3DShaderPack *D3DShaderPack::Current() +{ + if (_this.IsNull()) + _this = new D3DShaderPack(); + return _this; +} + +void D3DShaderPack::SetCurrent(D3DShaderPack *obj) +{ + _this = obj; +} + + +bool D3DShaderPack::Initialize(D3DDevice *d3d) +{ + bool res = true; + if (!(res = InitVertexDeclarations(d3d) && res)) + Log("Failed to create vdecl set"); + if (!(res = InitVertexShaders(d3d) && res)) + Log("Failed to create vs set"); + if (!(res = InitPixelShaders(d3d) && res)) + Log("Failed to create ps set"); + return res; +} + +void D3DShaderPack::Uninitialize() +{ + for (int i = 0; i < _vdecl.Length(); i++) + { + if (_vdecl[i] != NULL) + { + _vdecl[i]->Release(); + _vdecl[i] = NULL; + } + } + + for (int i = 0; i < _vs.Length(); i++) + { + if (_vs[i] != NULL) + { + _vs[i]->Release(); + _vs[i] = NULL; + } + } + + for (int i = 0; i < _ps.Length(); i++) + { + if (_ps[i] != NULL) + { + _ps[i]->Release(); + _ps[i] = NULL; + } + } +} + +bool D3DShaderPack::InitVertexDeclarations(D3DDevice *d3d) +{ + _vdecl.Allocate(VDECL_NUM); + _vdecl.Set(NULL); + + LPDIRECT3DVERTEXDECLARATION9 vdecl = NULL; + { + D3DVERTEXELEMENT9 elements[] = { + {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + if (FAILED(d3d->GetDevice()->CreateVertexDeclaration(elements, &vdecl))) + return false; + if (vdecl == NULL) + return false; + } + _vdecl[VDECL_XYC] = vdecl; + vdecl = NULL; + { + D3DVERTEXELEMENT9 elements[] = { + {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + D3DDECL_END() + }; + if (FAILED(d3d->GetDevice()->CreateVertexDeclaration(elements, &vdecl))) + return false; + if (vdecl == NULL) + return false; + } + _vdecl[VDECL_XYUV] = vdecl; + vdecl = NULL; + { + D3DVERTEXELEMENT9 elements[] = { + {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + if (FAILED(d3d->GetDevice()->CreateVertexDeclaration(elements, &vdecl))) + return false; + if (vdecl == NULL) + return false; + } + _vdecl[VDECL_XYUVC] = vdecl; + vdecl = NULL; + { + D3DVERTEXELEMENT9 elements[] = { + {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, + {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, + {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, + D3DDECL_END() + }; + if (FAILED(d3d->GetDevice()->CreateVertexDeclaration(elements, &vdecl))) + return false; + if (vdecl == NULL) + return false; + } + _vdecl[VDECL_XYZUVC] = vdecl; + + return true; +} + +bool D3DShaderPack::InitVertexShaders(D3DDevice *d3d) +{ + _vs.Allocate(VS_NUM); + _vs.Set(NULL); + + { + char buf[] = + "struct VsInput { float2 pos : POSITION; float4 col : COLOR; };\n" + "struct VsOutput { float4 pos : POSITION; float4 col : COLOR0; };\n" + "VsOutput main(VsInput vs_in) {\n" + "VsOutput vs_out;\n" + "vs_out.pos = float4(vs_in.pos, 0, 1);\n" + "vs_out.col = vs_in.col;\n" + "return vs_out;}"; + + _vs[VS_COPY_COLOR] = (LPDIRECT3DVERTEXSHADER9) + CompileShader(d3d, true, "CopyColor", buf, sizeof(buf) - 1); + if (_vs[VS_COPY_COLOR] == NULL) + return false; + } + + { + char buf[] = + "struct VsInput { float2 pos : POSITION; float2 tex : TEXCOORD0; };\n" + "struct VsOutput { float4 pos : POSITION; float2 tex : TEXCOORD0; };\n" + "VsOutput main(VsInput vs_in) {\n" + "VsOutput vs_out;\n" + "vs_out.pos = float4(vs_in.pos, 0, 1);\n" + "vs_out.tex = vs_in.tex;\n" + "return vs_out;}"; + + _vs[VS_COPY_UV] = (LPDIRECT3DVERTEXSHADER9) + CompileShader(d3d, true, "CopyUV", buf, sizeof(buf) - 1); + if (_vs[VS_COPY_UV] == NULL) + return false; + } + + { + char buf[] = + "struct VsInput { float2 pos : POSITION; float2 tex : TEXCOORD0; float4 col : COLOR; };\n" + "struct VsOutput { float4 pos : POSITION; float2 tex : TEXCOORD0; float4 col : COLOR0; };\n" + "VsOutput main(VsInput vs_in) {\n" + "VsOutput vs_out;\n" + "vs_out.pos = float4(vs_in.pos, 0, 1);\n" + "vs_out.tex = vs_in.tex;\n" + "vs_out.col = vs_in.col;\n" + "return vs_out;}"; + + _vs[VS_COPY_UV_COLOR] = (LPDIRECT3DVERTEXSHADER9) + CompileShader(d3d, true, "CopyUVColor", buf, sizeof(buf) - 1); + if (_vs[VS_COPY_UV_COLOR] == NULL) + return false; + } + + { + char buf[] = + "struct VsInput { float3 pos : POSITION; float2 tex : TEXCOORD0; float4 col : COLOR; };\n" + "struct VsOutput { float4 pos : POSITION; float2 tex : TEXCOORD0; float4 col : COLOR0; };\n" + "VsOutput main(VsInput vs_in) {\n" + "VsOutput vs_out;\n" + "vs_out.pos = float4(vs_in.pos, 1);\n" + "vs_out.tex = vs_in.tex;\n" + "vs_out.col = vs_in.col;\n" + "return vs_out;}"; + + _vs[VS_COPY_UV_COLOR_Z] = (LPDIRECT3DVERTEXSHADER9) + CompileShader(d3d, true, "CopyUVColorZ", buf, sizeof(buf) - 1); + if (_vs[VS_COPY_UV_COLOR_Z] == NULL) + return false; + } + + return true; +} + +bool D3DShaderPack::InitPixelShaders(D3DDevice *d3d) +{ + _ps.Allocate(PS_NUM); + _ps.Set(NULL); + + { + char buf[] = + "struct VsOutput { float4 pos : POSITION; float4 col : COLOR0; };\n" + "float4 main(VsOutput ps_in) : COLOR0 {\n" + "return ps_in.col;}"; + + _ps[PS_COLOR] = (LPDIRECT3DPIXELSHADER9) + CompileShader(d3d, false, "Color", buf, sizeof(buf) - 1); + if (_ps[PS_COLOR] == NULL) + return false; + } + + { + char buf[] = + "sampler Texture : register(s0);\n" + "struct VsOutput { float4 pos : POSITION; float2 tex : TEXCOORD0; };\n" + "float4 main(VsOutput ps_in) : COLOR0 {\n" + "return tex2D(Texture, ps_in.tex);}"; + + _ps[PS_TEX] = (LPDIRECT3DPIXELSHADER9) + CompileShader(d3d, false, "Tex", buf, sizeof(buf) - 1); + if (_ps[PS_TEX] == NULL) + return false; + } + + { + char buf[] = + "sampler Texture : register(s0);\n" + "struct VsOutput { float4 pos : POSITION; float2 tex : TEXCOORD0; float4 col : COLOR0; };\n" + "float4 main(VsOutput ps_in) : COLOR0 {\n" + "return tex2D(Texture, ps_in.tex) * ps_in.col;}"; + + _ps[PS_TEX_COLOR_FILTER] = (LPDIRECT3DPIXELSHADER9) + CompileShader(d3d, false, "TexColorFilter", buf, sizeof(buf) - 1); + if (_ps[PS_TEX_COLOR_FILTER] == NULL) + return false; + } + + { + char buf[] = + "sampler Texture : register(s1);\n" + "struct VsOutput { float4 pos : POSITION; float2 tex : TEXCOORD0; };\n" + "float4 main(VsOutput ps_in) : COLOR0 {\n" + "return tex2D(Texture, ps_in.tex);}"; + + _ps[PS_TEX_2] = (LPDIRECT3DPIXELSHADER9) + CompileShader(d3d, false, "Tex2", buf, sizeof(buf) - 1); + if (_ps[PS_TEX_2] == NULL) + return false; + } + + return true; +} + +void *D3DShaderPack::CompileShader(D3DDevice *d3d, bool make_vs, + const char *name, const char *buf, int size) +{ + LPD3DXBUFFER compiled_res = NULL; + LPD3DXBUFFER error_msgs = NULL; + + HRESULT res = D3DXCompileShader(buf, size, NULL, NULL, + "main", make_vs ? "vs_2_0" : "ps_2_0", // ? + 0, &compiled_res, &error_msgs, NULL); + + if (FAILED(res)) + { + Log("Shader %s compilation failed, code = %X", name, res); + if (error_msgs == NULL) + return NULL; + const char *mess = (const char *)error_msgs->GetBufferPointer(); + Log("Error output:\n%s", mess); + error_msgs->Release(); + return NULL; + } + + if (error_msgs != NULL) + error_msgs->Release(); + + void *res_ptr = NULL; + if (make_vs) + { + LPDIRECT3DVERTEXSHADER9 vs; + res = d3d->GetDevice()->CreateVertexShader((DWORD *)compiled_res->GetBufferPointer(), &vs); + res_ptr = (void *)vs; + } + else + { + LPDIRECT3DPIXELSHADER9 ps; + res = d3d->GetDevice()->CreatePixelShader((DWORD *)compiled_res->GetBufferPointer(), &ps); + res_ptr = (void *)ps; + } + + compiled_res->Release(); + + if (FAILED(res)) + { + Log("Shader %s creation failed, code = %X", name, res); + return NULL; + } + return res_ptr; +} + +bool D3DShaderPack::SetVDecl(D3DDevice *d3d, int id) +{ + if (id < 0 || id >= _vdecl.Length() || _vdecl[id] == NULL) + return false; + assert(d3d != NULL); + d3d->GetDevice()->SetVertexDeclaration(_vdecl[id]); + return true; +} + +bool D3DShaderPack::SetVS(D3DDevice *d3d, int id) +{ + if (id < 0 || id >= _vs.Length() || _vs[id] == NULL) + return false; + assert(d3d != NULL); + d3d->GetDevice()->SetVertexShader(_vs[id]); + return true; +} + +bool D3DShaderPack::SetPS(D3DDevice *d3d, int id) +{ + if (id < 0 || id >= _ps.Length() || _ps[id] == NULL) + return false; + assert(d3d != NULL); + d3d->GetDevice()->SetPixelShader(_ps[id]); + return true; +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.h new file mode 100644 index 0000000000..b865f783ed --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_shader_pack.h @@ -0,0 +1,75 @@ +#ifndef __EVAS_DIRECT3D_SHADER_PACK_H__ +#define __EVAS_DIRECT3D_SHADER_PACK_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +class D3DDevice; + +class D3DShaderPack : virtual public Referenc +{ +public: + ~D3DShaderPack(); + + static D3DShaderPack *Current(); + static void SetCurrent(D3DShaderPack *obj); + + bool Initialize(D3DDevice *d3d); + void Uninitialize(); + + bool SetVDecl(D3DDevice *d3d, int id); + bool SetVS(D3DDevice *d3d, int id); + bool SetPS(D3DDevice *d3d, int id); + +public: + enum VDECL + { + VDECL_XYC = 0, + VDECL_XYUV, + VDECL_XYUVC, + VDECL_XYZUVC, + + VDECL_NUM + }; + + enum VS + { + VS_COPY_COLOR = 0, + VS_COPY_UV, + VS_COPY_UV_COLOR, + VS_COPY_UV_COLOR_Z, + + VS_NUM + }; + + enum PS + { + PS_COLOR = 0, + PS_TEX, + PS_TEX_COLOR_FILTER, + PS_TEX_2, + + PS_NUM + }; + +private: + D3DShaderPack(); + + bool InitVertexDeclarations(D3DDevice *d3d); + bool InitVertexShaders(D3DDevice *d3d); + bool InitPixelShaders(D3DDevice *d3d); + + void *CompileShader(D3DDevice *d3d, bool make_vs, const char *name, + const char *buf, int size); + +private: + TArray _vdecl; + TArray _vs; + TArray _ps; + + static Ref _this; +}; + +#endif // __EVAS_DIRECT3D_SHADER_PACK_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp new file mode 100644 index 0000000000..5b5da7b977 --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.cpp @@ -0,0 +1,154 @@ + +//#define ENABLE_LOG_PRINTF + +#include "evas_direct3d_vertex_buffer_cache.h" +#include "evas_direct3d_device.h" + +#include + + +Ref D3DVertexBufferCache::_this; + +D3DVertexBufferCache::D3DVertexBufferCache() +{ + size_border_low = 0.6; // We can reuse buffer on 60% + size_border_high = 0.2; // We can reallocate the buffer on 20% +} + +D3DVertexBufferCache::~D3DVertexBufferCache() +{ + Uninitialize(); +} + +D3DVertexBufferCache *D3DVertexBufferCache::Current() +{ + if (_this.IsNull()) + _this = new D3DVertexBufferCache(); + return _this; +} + +void D3DVertexBufferCache::SetCurrent(D3DVertexBufferCache *obj) +{ + _this = obj; +} + +void D3DVertexBufferCache::Uninitialize() +{ + for (int i = 0; i < _cache.Length(); i++) + { + assert(_cache[i].vb != NULL); + _cache[i].vb->Release(); + } + _cache.Resize(); +} + +bool D3DVertexBufferCache::InitBuffer(D3DDevice *d3d, BYTE *data, int size, CacheEntryInfo &info) +{ + assert(d3d != NULL); + assert(data != NULL); + assert(size > 0); + + int best = FindBestEntry(size); + CacheEntry *ce = NULL; + + // Reallocate + if (best >= 0 && _cache[best].size < size) + { + DeleteEntry(best); + best = -1; + } + + // New + if (best < 0) + { + CacheEntry new_entry; + if (!CreateEntry(d3d, new_entry, size)) + { + Log("Failed to create new vbcache entry"); + return false; + } + _cache.Add(new_entry); + info.id = _cache.Length() - 1; + ce = _cache.Last(); + } + else + { + info.id = best; + ce = &_cache[best]; + } + + assert(ce != NULL); + if (!InsertData(*ce, data, size)) + { + Log("Failed to insert vbcache data"); + return false; + } + return true; +} + +bool D3DVertexBufferCache::SelectBufferToDevice(D3DDevice *device, int id, int vertex_size) +{ + if (id < 0 || id >= _cache.Length()) + return false; + return SUCCEEDED(device->GetDevice()->SetStreamSource(0, _cache[id].vb, 0, vertex_size)); +} + +int D3DVertexBufferCache::FindBestEntry(int size) +{ + // Search for buffer that fits in borders + for (int i = 0; i < _cache.Length(); i++) + { + const int vs = _cache[i].size; + if (size >= (vs - FLOAT(vs) * size_border_low) && size <= vs) + return i; + } + bool less_than_all = true; + for (int i = 0; i < _cache.Length(); i++) + { + const int vs = _cache[i].size; + if (size >= (vs - FLOAT(vs) * size_border_low)) + less_than_all = false; + } + // Requested size is too small to reuse in any buffer + if (less_than_all) + return -1; + // Search for buffer that can be reallocated + for (int i = 0; i < _cache.Length(); i++) + { + const int vs = _cache[i].size; + if (size <= (vs + FLOAT(vs) * size_border_high)) + return i; + } + // No buffer can be reused or reallocated, create a new one + return -1; +} + +bool D3DVertexBufferCache::CreateEntry(D3DDevice *d3d, CacheEntry &entry, int size) +{ + assert(d3d != NULL); + if (FAILED(d3d->GetDevice()->CreateVertexBuffer(size, D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, + 0, D3DPOOL_DEFAULT, &entry.vb, NULL))) + { + return false; + } + entry.size = size; + return true; +} + +void D3DVertexBufferCache::DeleteEntry(int id) +{ + if (id < 0 || id >= _cache.Length()) + return; + assert(_cache[id].vb != NULL); + _cache[id].vb->Release(); + _cache.Replace(id); +} + +bool D3DVertexBufferCache::InsertData(CacheEntry &entry, BYTE *data, int size) +{ + BYTE *ptr = NULL; + if (FAILED(entry.vb->Lock(0, size, (void **)&ptr, D3DLOCK_DISCARD))) + return false; + CopyMemory(ptr, data, size); + return SUCCEEDED(entry.vb->Unlock()); +} diff --git a/legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.h b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.h new file mode 100644 index 0000000000..822ac8022e --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/evas_direct3d_vertex_buffer_cache.h @@ -0,0 +1,60 @@ +#ifndef __EVAS_DIRECT3D_VERTEX_BUFFER_CACHE_H__ +#define __EVAS_DIRECT3D_VERTEX_BUFFER_CACHE_H__ + +#include "evas_engine.h" + +#include "ref.h" +#include "array.h" + +class D3DDevice; + +class D3DVertexBufferCache : virtual public Referenc +{ +public: + struct CacheEntryInfo + { + int id; + }; + +public: + ~D3DVertexBufferCache(); + + static D3DVertexBufferCache *Current(); + static void SetCurrent(D3DVertexBufferCache *obj); + + inline void SetSizeBorders(FLOAT low, FLOAT high); + + bool InitBuffer(D3DDevice *d3d, BYTE *data, int size, CacheEntryInfo &info); + bool SelectBufferToDevice(D3DDevice *device, int id, int vertex_size); + void Uninitialize(); + +private: + struct CacheEntry + { + LPDIRECT3DVERTEXBUFFER9 vb; + int size; + }; + +private: + D3DVertexBufferCache(); + + int FindBestEntry(int size); + bool CreateEntry(D3DDevice *d3d, CacheEntry &entry, int size); + void DeleteEntry(int id); + bool InsertData(CacheEntry &entry, BYTE *data, int size); + +private: + TArray _cache; + FLOAT size_border_low; + FLOAT size_border_high; + + static Ref _this; +}; + +void D3DVertexBufferCache::SetSizeBorders(FLOAT low, FLOAT high) +{ + size_border_low = low; + size_border_high = high; +} + +#endif // __EVAS_DIRECT3D_VERTEX_BUFFER_CACHE_H__ diff --git a/legacy/evas/src/modules/engines/direct3d/evas_engine.c b/legacy/evas/src/modules/engines/direct3d/evas_engine.c index cf0d266902..88bb6ded42 100644 --- a/legacy/evas/src/modules/engines/direct3d/evas_engine.c +++ b/legacy/evas/src/modules/engines/direct3d/evas_engine.c @@ -2,73 +2,44 @@ #include "evas_private.h" #include "Evas_Engine_Direct3D.h" +#undef EAPI +#define EAPI __declspec(dllexport) + /* 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; + Direct3DDeviceHandler d3d; + int width, height; + int end : 1; + int in_redraw : 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); +////////////////////////////////////////////////////////////////////////////// +// Prototypes 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_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); +static void eng_output_resize(void *data, int width, int height); + +////////////////////////////////////////////////////////////////////////////// +// Init / shutdown methods +// -/* 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) +_output_setup(int width, int height, int rotation, HWND window, int depth, int fullscreen) { Render_Engine *re; re = (Render_Engine *)calloc(1, sizeof(Render_Engine)); - if (!re) return NULL; + if (!re) + return NULL; /* if we haven't initialized - init (automatic abort if already done) */ evas_common_cpu_init(); @@ -85,247 +56,460 @@ _output_setup(int width, 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) + if ((re->d3d = evas_direct3d_init(window, depth, fullscreen)) == 0) { - free(re); - return NULL; + 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); + re->width = width; + re->height = height; 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(); + memset(&info->info, 0, sizeof(info->info)); return info; e = NULL; } static void -eng_info_free(Evas *e, - void *info) +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) +eng_setup(Evas *e, void *info) { - Render_Engine *re; + Render_Engine *re; Evas_Engine_Info_Direct3D *in; + re = (Render_Engine *)e->engine.data.output; 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); + if (e->engine.data.output == NULL) + { + e->engine.data.output = _output_setup(e->output.w, e->output.h, + in->info.rotation, in->info.window, in->info.depth, in->info.fullscreen); + } + else if (in->info.fullscreen != 0) + { + if (re != NULL) + evas_direct3d_set_layered(re->d3d, 0, 0, 0, NULL); + evas_direct3d_set_fullscreen(re->d3d, -1, -1, 1); + } + else if (in->info.fullscreen == 0) + { + evas_direct3d_set_fullscreen(re->d3d, re->width, re->height, 0); + if (re != NULL && in->info.layered == 0) + evas_direct3d_set_layered(re->d3d, 0, 0, 0, NULL); + else if (re != NULL && in->info.layered != 0 && in->shape != NULL) + evas_direct3d_set_layered(re->d3d, 1, in->shape->width, in->shape->height, in->shape->mask); + } + + if (e->engine.data.output == NULL) + return; + if (e->engine.data.context == NULL) + 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; + Render_Engine *re = (Render_Engine *)data; + + evas_direct3d_free(re->d3d); - 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; +////////////////////////////////////////////////////////////////////////////// +// Context +// - 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_context_color_set(void *data, void *context, int r, int g, int b, int a) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_context_color_set(re->d3d, r, g, b, a); + + evas_common_draw_context_set_color(context, r, g, b, a); } static void -eng_output_tile_size_set(void *data, - int width, - int height) +eng_context_multiplier_set(void *data, void *context, int r, int g, int b, int a) { - Render_Engine *re; + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_context_set_multiplier(re->d3d, 255, 255, 255, a); - re = (Render_Engine *)data; - evas_common_tilebuf_set_tile_size(re->tb, width, height); + evas_common_draw_context_set_multiplier(context, r, g, b, a); } static void -eng_output_redraws_rect_add(void *data, - int x, - int y, - int width, - int height) +eng_context_multiplier_unset(void *data, void *context) { - Render_Engine *re; + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_context_set_multiplier(re->d3d, 255, 255, 255, 255); - re = (Render_Engine *)data; - evas_common_tilebuf_add_redraw(re->tb, x, y, width, height); + evas_common_draw_context_unset_multiplier(context); +} + + +////////////////////////////////////////////////////////////////////////////// +// Output manipulating +// + +static void +eng_output_resize(void *data, int width, int height) +{ + Render_Engine *re = (Render_Engine *)data; + re->width = width; + re->height = height; + evas_direct3d_resize(re->d3d, width, height); } static void -eng_output_redraws_rect_del(void *data, - int x, - int y, - int width, - int height) +eng_output_redraws_rect_add(void *data, int x, int y, int width, int height) { - Render_Engine *re; + Render_Engine *re = (Render_Engine *)data; +} - re = (Render_Engine *)data; - evas_common_tilebuf_del_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 = (Render_Engine *)data; } static void eng_output_redraws_clear(void *data) { - Render_Engine *re; - - re = (Render_Engine *)data; - evas_common_tilebuf_clear(re->tb); + Render_Engine *re = (Render_Engine *)data; } 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) +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; + re->end = 0; + re->in_redraw = 0; + return NULL; } - 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; + if (x) *x = 0; + if (y) *y = 0; + if (w) *w = 800; //re->d3d.width; + if (h) *h = 600; //re->d3d.height; + if (cx) *cx = 0; + if (cy) *cy = 0; + if (cw) *cw = 800; //re->d3d.width; + if (ch) *ch = 600; //re->d3d.height; - return surface; + re->in_redraw = 1; + + return re; } static void -eng_output_redraws_next_update_push(void *data, - void *surface, - int x, - int y, - int w, - int h) +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(); + Render_Engine *re = (Render_Engine *)data; + re->end = 1; } static void eng_output_flush(void *data) { - Render_Engine *re; - - re = (Render_Engine *)data; - evas_direct3d_outbuf_flush(re->ob); + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_render_all(re->d3d); } static void eng_output_idle_flush(void *data) { - Render_Engine *re; - - re = (Render_Engine *)data; + Render_Engine *re = (Render_Engine *)data; } + +////////////////////////////////////////////////////////////////////////////// +// Draw objects +// + +static void +eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2) +{ + Render_Engine *re = (Render_Engine *)data; + if (re->in_redraw == 0) + return; + evas_direct3d_line_draw(re->d3d, x1, y1, x2, y2); +} + +static void +eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h) +{ + Render_Engine *re = (Render_Engine *)data; + if (re->in_redraw == 0) + return; + evas_direct3d_rectangle_draw(re->d3d, x, y, w, h); +} + +static void * +eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo) +{ + Render_Engine *re = (Render_Engine *)data; + *error = 0; + return evas_direct3d_image_load(re->d3d, file, key, NULL, lo); +} + +static void * +eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace) +{ + Render_Engine *re = (Render_Engine *)data; + return evas_direct3d_image_new_from_data(re->d3d, w, h, image_data, alpha, cspace); +} + +static void * +eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace) +{ + Render_Engine *re = (Render_Engine *)data; + return evas_direct3d_image_new_from_copied_data(re->d3d, w, h, image_data, alpha, cspace); +} + +static void +eng_image_free(void *data, void *image) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_image_free(re->d3d, image); +} + +static void * +eng_image_data_put(void *data, void *image, DATA32 *image_data) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_image_data_put(re->d3d, image, image_data); + return image; +} + +static void * +eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h) +{ + return image; +} + +static void * +eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_image_data_get(re->d3d, image, to_write, image_data); + return image; +} + +static void +eng_image_draw(void *data, void *context, void *surface, void *image, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, int smooth) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_image_draw(re->d3d, image, + src_x, src_y, src_w, src_h, + dst_x, dst_y, dst_w, dst_h, smooth); +} + +static void +eng_image_size_get(void *data, void *image, int *w, int *h) +{ + evas_direct3d_image_size_get(image, w, h); +} + +static int +eng_image_alpha_get(void *data, void *image) +{ + // Hm:) + if (!image) + return 1; + return 0; +} + +static int +eng_image_colorspace_get(void *data, void *image) +{ + // Well, change that when you think about other colorspace + return EVAS_COLORSPACE_ARGB8888; +} + +static void * +eng_image_border_set(void *data, void *image, int l, int r, int t, int b) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_image_border_set(re->d3d, image, l, t, r, b); + return image; +} + +static void +eng_image_border_get(void *data, void *image, int *l, int *r, int *t, int *b) +{ + Render_Engine *re = (Render_Engine *)data; + evas_direct3d_image_border_get(re->d3d, image, l, t, r, b); +} + +static void +eng_font_draw(void *data, void *context, void *surface, void *font, int x, int y, int w, int h, int ow, int oh, const char *text) +{ + Render_Engine *re = (Render_Engine *)data; + RGBA_Image im; + im.image.data = NULL; + im.cache_entry.w = re->width; + im.cache_entry.h = re->height; + + evas_direct3d_select_or_create_font(re->d3d, font); + + evas_common_draw_context_font_ext_set(context, re->d3d, + evas_direct3d_font_texture_new, + evas_direct3d_font_texture_free, + evas_direct3d_font_texture_draw); + evas_common_font_draw(&im, context, font, x, y, text); + evas_common_draw_context_font_ext_set(context, NULL, NULL, NULL, NULL); +} + +static void +eng_font_free(void *data, void *font) +{ + Render_Engine *re = (Render_Engine *)data; + evas_common_font_free(font); + evas_direct3d_font_free(re->d3d, font); +} + + + +////////////////////////////////////////////////////////////////////////////// +// Gradients +// + +static void +eng_gradient2_color_np_stop_insert(void *data, void *gradient, int r, int g, int b, int a, float pos) +{ +} + +static void +eng_gradient2_clear(void *data, void *gradient) +{ +} + +static void +eng_gradient2_fill_transform_set(void *data, void *gradient, void *transform) +{ +} + +static void +eng_gradient2_fill_spread_set(void *data, void *gradient, int spread) +{ +} + +static void * +eng_gradient2_linear_new(void *data) +{ + return NULL; +} + +static void +eng_gradient2_linear_free(void *data, void *linear_gradient) +{ +} + +static void +eng_gradient2_linear_fill_set(void *data, void *linear_gradient, int x0, int y0, int x1, int y1) +{ +} + +static int +eng_gradient2_linear_is_opaque(void *data, void *context, void *linear_gradient, int x, int y, int w, int h) +{ + return 1; +} + +static int +eng_gradient2_linear_is_visible(void *data, void *context, void *linear_gradient, int x, int y, int w, int h) +{ + return 1; +} + +static void +eng_gradient2_linear_render_pre(void *data, void *context, void *linear_gradient) +{ +} + +static void +eng_gradient2_linear_render_post(void *data, void *linear_gradient) +{ +} + +static void +eng_gradient2_linear_draw(void *data, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h) +{ +} + +static void * +eng_gradient2_radial_new(void *data) +{ + return NULL; +} + +static void +eng_gradient2_radial_free(void *data, void *radial_gradient) +{ +} + +static void +eng_gradient2_radial_fill_set(void *data, void *radial_gradient, float cx, float cy, float rx, float ry) +{ +} + +static int +eng_gradient2_radial_is_opaque(void *data, void *context, void *radial_gradient, int x, int y, int w, int h) +{ + return 1; +} + +static int +eng_gradient2_radial_is_visible(void *data, void *context, void *radial_gradient, int x, int y, int w, int h) +{ + return 1; +} + +static void +eng_gradient2_radial_render_pre(void *data, void *context, void *radial_gradient) +{ +} + +static void +eng_gradient2_radial_render_post(void *data, void *radial_gradient) +{ +} + +static void +eng_gradient2_radial_draw(void *data, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h) +{ +} + + /* module advertising code */ EAPI int module_open(Evas_Module *em) @@ -340,9 +524,11 @@ module_open(Evas_Module *em) ORD(info); ORD(info_free); ORD(setup); + ORD(context_color_set); + ORD(context_multiplier_set); + ORD(context_multiplier_unset); 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); @@ -350,6 +536,45 @@ module_open(Evas_Module *em) ORD(output_redraws_next_update_push); ORD(output_flush); ORD(output_idle_flush); + ORD(line_draw); + ORD(rectangle_draw); + ORD(image_load); + ORD(image_new_from_data); + ORD(image_new_from_copied_data); + ORD(image_free); + ORD(image_data_put); + ORD(image_dirty_region); + ORD(image_data_get); + ORD(image_draw); + ORD(image_size_get); + ORD(image_alpha_get); + ORD(image_colorspace_get); + ORD(image_border_set); + ORD(image_border_get); + ORD(font_draw); + ORD(font_free); +/* + ORD(gradient2_color_np_stop_insert); + ORD(gradient2_clear); + ORD(gradient2_fill_transform_set); + ORD(gradient2_fill_spread_set); + ORD(gradient2_linear_new); + ORD(gradient2_linear_free); + ORD(gradient2_linear_fill_set); + ORD(gradient2_linear_is_opaque); + ORD(gradient2_linear_is_visible); + ORD(gradient2_linear_render_pre); + ORD(gradient2_linear_render_post); + ORD(gradient2_linear_draw); + ORD(gradient2_radial_new); + ORD(gradient2_radial_free); + ORD(gradient2_radial_fill_set); + ORD(gradient2_radial_is_opaque); + ORD(gradient2_radial_is_visible); + ORD(gradient2_radial_render_pre); + ORD(gradient2_radial_render_post); + ORD(gradient2_radial_draw); +*/ /* now advertise out own api */ em->functions = (void *)(&func); return 1; @@ -363,7 +588,7 @@ module_close(void) EAPI Evas_Module_Api evas_modapi = { EVAS_MODULE_API_VERSION, - EVAS_MODULE_TYPE_ENGINE, - "direct3d", - "none" + 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 index deb4501417..a5170a3570 100644 --- a/legacy/evas/src/modules/engines/direct3d/evas_engine.h +++ b/legacy/evas/src/modules/engines/direct3d/evas_engine.h @@ -6,132 +6,87 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + +#define EVAS_INLINE_ARRAY_H // We dont need that and it is buggy + #include "evas_common.h" +#include "evas_private.h" +#ifdef __cplusplus +} +#endif -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 */ - Eina_List *pending_writes; - } priv; -}; - -struct _Direct3D_Output_Buffer -{ - void *image; - int x; - int y; - int width; - int height; - int depth; - int pitch; -}; +//#define ENABLE_LOG_PRINTF +#ifdef ENABLE_LOG_PRINTF +#define Log(str, ...) printf("D3D "str"\n", __VA_ARGS__) +#else +#define Log(str, ...) +#endif +typedef void * Direct3DDeviceHandler; +typedef void * Direct3DImageHandler; +typedef void * Direct3DFontGlyphHandler; #ifdef __cplusplus extern "C" { #endif +// Main engine functions -/* 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); +Direct3DDeviceHandler evas_direct3d_init(HWND window, int depth, int fullscreen); +void evas_direct3d_free(Direct3DDeviceHandler d3d); +void evas_direct3d_render_all(Direct3DDeviceHandler d3d); +void evas_direct3d_resize(Direct3DDeviceHandler d3d, int width, int height); +void evas_direct3d_set_fullscreen(Direct3DDeviceHandler d3d, + int width, int height, int fullscreen); +void evas_direct3d_set_layered(Direct3DDeviceHandler d3d, int layered, + int mask_width, int mask_height, unsigned char *mask); -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); +// Context manipulations +void evas_direct3d_context_color_set(Direct3DDeviceHandler d3d, int r, int g, int b, int a); +void evas_direct3d_context_set_multiplier(Direct3DDeviceHandler d3d, int r, int g, int b, int a); + +// Simple objects + +void evas_direct3d_line_draw(Direct3DDeviceHandler d3d, int x1, int y1, int x2, int y2); +void evas_direct3d_rectangle_draw(Direct3DDeviceHandler d3d, int x, int y, int w, int h); + +// Images + +Direct3DImageHandler evas_direct3d_image_load(Direct3DDeviceHandler d3d, + const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo); +Direct3DImageHandler evas_direct3d_image_new_from_data(Direct3DDeviceHandler d3d, + int w, int h, DWORD *image_data, int alpha, int cspace); +Direct3DImageHandler evas_direct3d_image_new_from_copied_data(Direct3DDeviceHandler d3d, + int w, int h, DWORD *image_data, int alpha, int cspace); +void evas_direct3d_image_free(Direct3DDeviceHandler d3d, Direct3DImageHandler image); +void evas_direct3d_image_data_put(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + DWORD *image_data); +void evas_direct3d_image_data_get(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int to_write, DATA32 **image_data); +void evas_direct3d_image_draw(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int src_x, int src_y, int src_w, int src_h, + int dst_x, int dst_y, int dst_w, int dst_h, int smooth); +void evas_direct3d_image_size_get(Direct3DImageHandler image, int *w, int *h); +void evas_direct3d_image_border_set(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int l, int r, int t, int b); +void evas_direct3d_image_border_get(Direct3DDeviceHandler d3d, Direct3DImageHandler image, + int *l, int *r, int *t, int *b); + +// Fonts + +Direct3DFontGlyphHandler evas_direct3d_font_texture_new(Direct3DDeviceHandler d3d, + RGBA_Font_Glyph *fg); +void evas_direct3d_font_texture_free(Direct3DFontGlyphHandler ft); +void evas_direct3d_font_texture_draw(Direct3DDeviceHandler d3d, void *dest, void *context, + RGBA_Font_Glyph *fg, int x, int y); +void evas_direct3d_select_or_create_font(Direct3DDeviceHandler d3d, void *font); +void evas_direct3d_font_free(Direct3DDeviceHandler d3d, void *font); #ifdef __cplusplus } diff --git a/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c b/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c index 73f6f4fbb4..e69de29bb2 100644 --- a/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c +++ b/legacy/evas/src/modules/engines/direct3d/evas_outbuf.c @@ -1,328 +0,0 @@ -#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 = (RGBA_Image*) evas_cache_image_empty(evas_common_image_cache_get()); - evas_cache_image_surface_alloc(&im->cache_entry, width, height); - 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 = eina_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) -{ - Eina_List *l; - void *d3d_data; - int d3d_width; - int d3d_height; - int d3d_pitch; - RGBA_Image *im; - Direct3D_Output_Buffer *d3dob; - - /* 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 */ - EINA_LIST_FOREACH(buf->priv.pending_writes, l, im) - { - 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) - { - im = buf->priv.pending_writes->data; - buf->priv.pending_writes = eina_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; -} diff --git a/legacy/evas/src/modules/engines/direct3d/ref.h b/legacy/evas/src/modules/engines/direct3d/ref.h new file mode 100644 index 0000000000..0853f2e1ad --- /dev/null +++ b/legacy/evas/src/modules/engines/direct3d/ref.h @@ -0,0 +1,210 @@ +#ifndef __REF_H__ +#define __REF_H__ + +////////////////////////////////////////////////////////////////////////////// +// class Referenc +// Desc: Base class enabling reference interface +// Note: Class should derive as virtual +// +class Referenc +{ +public: + Referenc() + : refs_count(0) {}; + + inline int AddRef() + { + return ++refs_count; + } + inline int RemRef() + { + return --refs_count; + } + inline int RefCount() + { + return refs_count; + } + +private: + int refs_count; +}; + + +////////////////////////////////////////////////////////////////////////////// +// template Ref +// Desc: Holder in smart-pointers system. +// Important: Only Referenc subclasses may be used as template param. +// + +template +class Ref +{ +public: + // Constructors & destructor + Ref(); + //Ref(Ref &ref); + Ref(const Ref &ref); + Ref(T *ptr); + Ref(const T *ptr); + ~Ref(); + + Ref &operator =(Ref &ref); + Ref &operator =(T *ptr); + + inline T *Addr(); + inline T *Addr() const; + inline int RefCount(); + inline bool IsNull(); + + inline T *operator ->(); + inline operator const T *() const; + inline operator T *(); + +//private: + void RemRef(); + +private: + T *m_ptr; +}; + +////////////////////////////////////////////////////////////////////////////// +// Constructors & destructor +template Ref::Ref() +: m_ptr(NULL) +{ +} + +//template Ref::Ref(Ref &ref) +//: m_ptr(NULL) +//{ +// if (ref.Addr() != NULL) +// { +// m_ptr = ref.Addr(); +// ((Referenc *)m_ptr)->AddRef(); +// } +//} + +template Ref::Ref(const Ref &ref) +: m_ptr(NULL) +{ + if (ref.Addr() != NULL) + { + m_ptr = ref.Addr(); + ((Referenc *)m_ptr)->AddRef(); + } +} + +template Ref::Ref(T *ptr) +: m_ptr(NULL) +{ + if (ptr != NULL) + { + m_ptr = ptr; + ((Referenc *)m_ptr)->AddRef(); + } +} + +template Ref::Ref(const T *ptr) +: m_ptr(NULL) +{ + if (ptr != NULL) + { + m_ptr = ptr; + ((Referenc *)m_ptr)->AddRef(); + } +} + +template Ref::~Ref() +{ + if (m_ptr == NULL) + return; + RemRef(); +} + +// Check pointer on correctness +template bool Ref::IsNull() +{ + return (m_ptr == NULL); +} + +////////////////////////////////////////////////////////////////////////////// +// Operators + +template Ref &Ref::operator =(T *ptr) +{ + if (ptr != NULL) + { + if (m_ptr != ptr) + { + RemRef(); + m_ptr = ptr; + ((Referenc *)m_ptr)->AddRef(); + } + } + else if (m_ptr != NULL) + RemRef(); + return *this; +} + +template Ref &Ref::operator =(Ref &ref) +{ + if (ref.Addr() != NULL) + { + if (m_ptr != ref.Addr()) + { + RemRef(); + m_ptr = ref.Addr(); + ((Referenc *)m_ptr)->AddRef(); + } + } + else if (m_ptr != NULL) + RemRef(); + return *this; +} + +// Get pointer +template T *Ref::Addr() +{ + return m_ptr; +} + +template T *Ref::Addr() const +{ + return m_ptr; +} + +// Get refs count +template int Ref::RefCount() +{ + if (m_ptr == NULL) + return 0; + return ((Referenc *)m_ptr)->RefCount(); +} + +// Remove ref to the object and delete it if necessary +// WARNING: arrays cannot be deleted +template void Ref::RemRef() +{ + if (m_ptr == NULL) + return; + if (((Referenc *)m_ptr)->RemRef() == 0) + delete m_ptr; + m_ptr = NULL; +} + +template T *Ref::operator ->() +{ + return m_ptr; +} + +template Ref::operator const T *() const +{ + return m_ptr; +} + +template Ref::operator T *() +{ + return m_ptr; +} + +#endif // __REF_H__