From dd7595a3475407a7fa96a97393bae8c5220e8762 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Wed, 4 Jan 2012 18:41:13 +1000 Subject: Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje. Note that embryo wont be used, but I'm not sure yet if you can build edje without it. --- .../engines/direct3d/evas_direct3d_main.cpp | 774 +++++++++++++++++++++ 1 file changed, 774 insertions(+) create mode 100644 libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp (limited to 'libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp') diff --git a/libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp b/libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp new file mode 100644 index 0000000..fe1e13f --- /dev/null +++ b/libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp @@ -0,0 +1,774 @@ +// Force the layered windows APIs to be visible. +#define _WIN32_WINNT 0x0500 + +#include "evas_engine.h" +#include + +#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) + { + 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 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 line = scene->GetFreeObject(); + 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 rect = scene->GetFreeObject(); + 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 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 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 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)) + 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 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; + 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 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" -- cgit v1.1