775 lines
23 KiB
C++
775 lines
23 KiB
C++
// Force the layered windows APIs to be visible.
|
|
#define _WIN32_WINNT 0x0500
|
|
|
|
#include "evas_engine.h"
|
|
#include <assert.h>
|
|
|
|
#include <d3dx9.h>
|
|
|
|
#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<D3DObjectImage> ref;
|
|
RGBA_Image *img;
|
|
};
|
|
|
|
struct DevicePtr
|
|
{
|
|
Ref<D3DDevice> device;
|
|
Ref<D3DScene> scene;
|
|
Ref<D3DContext> context;
|
|
Ref<D3DImageCache> image_cache;
|
|
Ref<D3DShaderPack> shader_pack;
|
|
Ref<D3DVertexBufferCache> 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)
|
|
{
|
|
WRN("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)
|
|
{
|
|
WRN("Failed to create dib section");
|
|
DeleteDIBObjects(dev_ptr);
|
|
return false;
|
|
}
|
|
assert(dev_ptr->dib.data != NULL);
|
|
GdiFlush();
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
Direct3DDeviceHandler evas_direct3d_init(HWND window, int depth, int fullscreen)
|
|
{
|
|
Ref<D3DDevice> device = new D3DDevice();
|
|
if (!device->Init(window, depth, fullscreen == 1))
|
|
return NULL;
|
|
|
|
D3DImageCache::SetCurrent(NULL);
|
|
D3DShaderPack::SetCurrent(NULL);
|
|
D3DVertexBufferCache::SetCurrent(NULL);
|
|
|
|
if (!D3DShaderPack::Current()->Initialize(device))
|
|
{
|
|
ERR("Failed to build shader pack");
|
|
device->Destroy();
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
|
|
D3DImageCache::CacheEntryInfo info;
|
|
if (!D3DImageCache::Current()->CreateImage(device, device->GetWidth(), device->GetHeight(),
|
|
true, info))
|
|
{
|
|
WRN("Failed to create fonts image buffer");
|
|
return NULL;
|
|
}
|
|
dev_ptr->fonts_buffer_image_id = info.id;
|
|
D3DImageCache::Current()->SetImageStage(info.id, 1);
|
|
|
|
return (Direct3DDeviceHandler)dev_ptr;
|
|
}
|
|
|
|
void
|
|
evas_direct3d_free(Direct3DDeviceHandler d3d)
|
|
{
|
|
DevicePtr *dev_ptr = SelectDevice(d3d);
|
|
|
|
DeleteDIBObjects(dev_ptr);
|
|
|
|
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;
|
|
|
|
DBG("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))
|
|
{
|
|
ERR("Failed to resize");
|
|
return;
|
|
}
|
|
if (!D3DImageCache::Current()->ResizeImage(device, width, height,
|
|
dev_ptr->fonts_buffer_image_id))
|
|
{
|
|
WRN("Failed to resize fonts image buffer");
|
|
}
|
|
if (dev_ptr->layered)
|
|
{
|
|
DeleteDIBObjects(dev_ptr);
|
|
if (!CreateDIBObjects(dev_ptr))
|
|
WRN("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))
|
|
{
|
|
WRN("Failed to resize");
|
|
return;
|
|
}
|
|
if (!D3DImageCache::Current()->ResizeImage(device, width, height,
|
|
dev_ptr->fonts_buffer_image_id))
|
|
{
|
|
WRN("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)
|
|
{
|
|
DBG("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<D3DObjectLine> line = scene->GetFreeObject<D3DObjectLine>();
|
|
if (line == NULL)
|
|
{
|
|
line = new D3DObjectLine();
|
|
scene->AddObject(line);
|
|
DBG("New line object (total objects: %d)", scene->GetObjectCount());
|
|
}
|
|
else
|
|
{
|
|
line->SetFree(false);
|
|
DBG("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<D3DObjectRect> rect = scene->GetFreeObject<D3DObjectRect>();
|
|
if (rect == NULL)
|
|
{
|
|
rect = new D3DObjectRect();
|
|
scene->AddObject(rect);
|
|
DBG("New rect object (total objects: %d)", scene->GetObjectCount());
|
|
}
|
|
else
|
|
{
|
|
rect->SetFree(false);
|
|
DBG("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)
|
|
{
|
|
WRN("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<D3DObjectImage> 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);
|
|
|
|
DBG("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<D3DObjectImage> image = new D3DObjectImage();
|
|
|
|
D3DImageCache::CacheEntryInfo info;
|
|
ZeroMemory(&info, sizeof(info));
|
|
if (!D3DImageCache::Current()->InsertImage(device, image_data,
|
|
image_width, image_height, info))
|
|
{
|
|
WRN("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);
|
|
|
|
DBG("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<D3DObjectImage> 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<D3DObjectImage> image_ref = ptr->ref;
|
|
//assert(!image_ref.IsNull());
|
|
if (image_ref.IsNull())
|
|
return;
|
|
|
|
if (!image_ref->UpdateImageData(image_data))
|
|
ERR("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<D3DObjectImage> 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<D3DObjectImage> 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<D3DObjectImage *> images;
|
|
scene->GetObjectsOfType<D3DObjectImage>(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;
|
|
WRN("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 wasn't 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))
|
|
{
|
|
WRN("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<D3DObjectImage> 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<D3DObjectImage> 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<D3DObjectFont *> fonts;
|
|
scene->GetObjectsOfType<D3DObjectFont>(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<D3DObjectFont> 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<D3DObjectFont *> fonts;
|
|
scene->GetObjectsOfType<D3DObjectFont>(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"
|