aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp')
-rw-r--r--libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp774
1 files changed, 774 insertions, 0 deletions
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 @@
1// Force the layered windows APIs to be visible.
2#define _WIN32_WINNT 0x0500
3
4#include "evas_engine.h"
5#include <assert.h>
6
7#include <d3dx9.h>
8
9#include "evas_direct3d_device.h"
10#include "evas_direct3d_context.h"
11#include "evas_direct3d_shader_pack.h"
12#include "evas_direct3d_scene.h"
13#include "evas_direct3d_image_cache.h"
14#include "evas_direct3d_object_line.h"
15#include "evas_direct3d_object_rect.h"
16#include "evas_direct3d_object_image.h"
17#include "evas_direct3d_vertex_buffer_cache.h"
18#include "evas_direct3d_object_font.h"
19
20// Internal structure that joins two types of objects
21struct ImagePtr
22{
23 Ref<D3DObjectImage> ref;
24 RGBA_Image *img;
25};
26
27struct DevicePtr
28{
29 Ref<D3DDevice> device;
30 Ref<D3DScene> scene;
31 Ref<D3DContext> context;
32 Ref<D3DImageCache> image_cache;
33 Ref<D3DShaderPack> shader_pack;
34 Ref<D3DVertexBufferCache> vb_cache;
35
36 int fonts_buffer_image_id;
37
38 // Layered windows cannot render D3D in the normal way
39 bool layered;
40
41 // Window shape mask
42 struct
43 {
44 // Width and height may be different from target size
45 int width;
46 int height;
47 // Pointer to external memory location, dont do anything with it
48 unsigned char *mask;
49 } shape;
50
51 // GDI output target
52 struct
53 {
54 HBITMAP image;
55 HDC hdc;
56 BITMAPINFO info;
57 BYTE *data;
58 } dib;
59
60};
61
62DevicePtr *SelectDevice(Direct3DDeviceHandler d3d)
63{
64 DevicePtr *dev_ptr = (DevicePtr *)d3d;
65 D3DImageCache::SetCurrent(dev_ptr->image_cache);
66 D3DShaderPack::SetCurrent(dev_ptr->shader_pack);
67 D3DVertexBufferCache::SetCurrent(dev_ptr->vb_cache);
68 return dev_ptr;
69}
70
71void DeleteDIBObjects(DevicePtr *dev_ptr)
72{
73 assert(dev_ptr != NULL);
74 if (dev_ptr->dib.image != NULL)
75 DeleteObject(dev_ptr->dib.image);
76 if (dev_ptr->dib.hdc != NULL)
77 DeleteDC(dev_ptr->dib.hdc);
78 ZeroMemory(&dev_ptr->dib, sizeof(dev_ptr->dib));
79}
80
81bool CreateDIBObjects(DevicePtr *dev_ptr)
82{
83 assert(dev_ptr != NULL);
84 if ((dev_ptr->dib.hdc = CreateCompatibleDC(NULL)) == NULL)
85 {
86 WRN("Failed to create compatible DC");
87 return false;
88 }
89 ZeroMemory(&dev_ptr->dib.info, sizeof(dev_ptr->dib.info));
90 dev_ptr->dib.info.bmiHeader.biSize = sizeof(dev_ptr->dib.info.bmiHeader);
91 dev_ptr->dib.info.bmiHeader.biBitCount = 32;
92 dev_ptr->dib.info.bmiHeader.biWidth = dev_ptr->device->GetWidth();
93 dev_ptr->dib.info.bmiHeader.biHeight = -dev_ptr->device->GetHeight();
94 dev_ptr->dib.info.bmiHeader.biCompression = BI_RGB;
95 dev_ptr->dib.info.bmiHeader.biPlanes = 1;
96 if ((dev_ptr->dib.image = CreateDIBSection(dev_ptr->dib.hdc, &dev_ptr->dib.info,
97 DIB_RGB_COLORS, (void **)&dev_ptr->dib.data, NULL, 0)) == NULL)
98 {
99 WRN("Failed to create dib section");
100 DeleteDIBObjects(dev_ptr);
101 return false;
102 }
103 assert(dev_ptr->dib.data != NULL);
104 GdiFlush();
105 return true;
106}
107
108
109
110
111extern "C" {
112
113Direct3DDeviceHandler evas_direct3d_init(HWND window, int depth, int fullscreen)
114{
115 Ref<D3DDevice> device = new D3DDevice();
116 if (!device->Init(window, depth, fullscreen == 1))
117 return NULL;
118
119 D3DImageCache::SetCurrent(NULL);
120 D3DShaderPack::SetCurrent(NULL);
121 D3DVertexBufferCache::SetCurrent(NULL);
122
123 if (!D3DShaderPack::Current()->Initialize(device))
124 {
125 ERR("Failed to build shader pack");
126 device->Destroy();
127 return NULL;
128 }
129
130 DevicePtr *dev_ptr = new DevicePtr;
131 ZeroMemory(dev_ptr, sizeof(DevicePtr));
132 dev_ptr->device = device;
133 dev_ptr->scene = new D3DScene();
134 dev_ptr->context = new D3DContext();
135 dev_ptr->image_cache = D3DImageCache::Current();
136 dev_ptr->shader_pack = D3DShaderPack::Current();
137 dev_ptr->vb_cache = D3DVertexBufferCache::Current();
138 dev_ptr->fonts_buffer_image_id = -1;
139
140 D3DImageCache::CacheEntryInfo info;
141 if (!D3DImageCache::Current()->CreateImage(device, device->GetWidth(), device->GetHeight(),
142 true, info))
143 {
144 WRN("Failed to create fonts image buffer");
145 return NULL;
146 }
147 dev_ptr->fonts_buffer_image_id = info.id;
148 D3DImageCache::Current()->SetImageStage(info.id, 1);
149
150 return (Direct3DDeviceHandler)dev_ptr;
151}
152
153void
154evas_direct3d_free(Direct3DDeviceHandler d3d)
155{
156 DevicePtr *dev_ptr = SelectDevice(d3d);
157
158 DeleteDIBObjects(dev_ptr);
159
160 dev_ptr->context = NULL;
161 dev_ptr->scene = NULL;
162 dev_ptr->image_cache = NULL;
163 dev_ptr->shader_pack = NULL;
164 D3DShaderPack::Current()->Uninitialize();
165 D3DImageCache::Current()->Uninitialize();
166 D3DVertexBufferCache::Current()->Uninitialize();
167 D3DShaderPack::SetCurrent(NULL);
168 D3DImageCache::SetCurrent(NULL);
169 D3DVertexBufferCache::SetCurrent(NULL);
170
171 dev_ptr->device = NULL;
172 delete dev_ptr;
173
174 DBG("uninitialized");
175}
176
177void
178evas_direct3d_resize(Direct3DDeviceHandler d3d, int width, int height)
179{
180 DevicePtr *dev_ptr = SelectDevice(d3d);
181 D3DDevice *device = dev_ptr->device;
182 if (!device->Reset(width, height, -1))
183 {
184 ERR("Failed to resize");
185 return;
186 }
187 if (!D3DImageCache::Current()->ResizeImage(device, width, height,
188 dev_ptr->fonts_buffer_image_id))
189 {
190 WRN("Failed to resize fonts image buffer");
191 }
192 if (dev_ptr->layered)
193 {
194 DeleteDIBObjects(dev_ptr);
195 if (!CreateDIBObjects(dev_ptr))
196 WRN("Failed to create dib objects");
197 }
198}
199
200void
201evas_direct3d_set_fullscreen(Direct3DDeviceHandler d3d, int width, int height, int fullscreen)
202{
203 DevicePtr *dev_ptr = SelectDevice(d3d);
204 D3DDevice *device = dev_ptr->device;
205
206 if (width < 0)
207 width = ::GetSystemMetrics(SM_CXSCREEN);
208 if (height < 0)
209 height = ::GetSystemMetrics(SM_CYSCREEN);
210
211 if (!device->Reset(width, height, fullscreen))
212 {
213 WRN("Failed to resize");
214 return;
215 }
216 if (!D3DImageCache::Current()->ResizeImage(device, width, height,
217 dev_ptr->fonts_buffer_image_id))
218 {
219 WRN("Failed to resize fonts image buffer");
220 }
221
222 if (fullscreen == 0)
223 InvalidateRect(HWND_DESKTOP, NULL, TRUE);
224}
225
226void
227evas_direct3d_set_layered(Direct3DDeviceHandler d3d, int layered,
228 int mask_width, int mask_height, unsigned char *mask)
229{
230 DevicePtr *dev_ptr = SelectDevice(d3d);
231 dev_ptr->layered = (layered != 0);
232 dev_ptr->shape.width = mask_width;
233 dev_ptr->shape.height = mask_height;
234 dev_ptr->shape.mask = mask;
235
236 if (dev_ptr->layered && dev_ptr->dib.data == NULL)
237 CreateDIBObjects(dev_ptr);
238 else if (!dev_ptr->layered)
239 DeleteDIBObjects(dev_ptr);
240}
241
242void
243evas_direct3d_context_color_set(Direct3DDeviceHandler d3d, int r, int g, int b, int a)
244{
245 DevicePtr *dev_ptr = SelectDevice(d3d);
246 dev_ptr->context->color = ((a & 0xff) << 24) | ((r & 0xff) << 16) |
247 ((g & 0xff) << 8) | (b & 0xff);
248}
249
250void
251evas_direct3d_context_set_multiplier(Direct3DDeviceHandler d3d, int r, int g, int b, int a)
252{
253 DevicePtr *dev_ptr = SelectDevice(d3d);
254 dev_ptr->context->color_mul = ((a & 0xff) << 24) | ((r & 0xff) << 16) |
255 ((g & 0xff) << 8) | (b & 0xff);
256}
257
258void
259evas_direct3d_render_all(Direct3DDeviceHandler d3d)
260{
261 DBG("render");
262 assert(d3d != NULL);
263 DevicePtr *dev_ptr = SelectDevice(d3d);
264 D3DDevice *device = dev_ptr->device;
265 D3DScene *scene = dev_ptr->scene;
266
267 if (!device->Begin())
268 return;
269
270 device->GetDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
271 device->GetDevice()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
272 device->GetDevice()->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
273
274 //device->GetDevice()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
275 //device->GetDevice()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
276
277 D3DObjectLine::BeginCache();
278 D3DObjectRect::BeginCache();
279 D3DObjectImage::BeginCache();
280 scene->DrawAll(device);
281 D3DObjectLine::EndCache(device);
282 D3DObjectRect::EndCache(device);
283 D3DObjectImage::EndCache(device);
284 D3DObjectFont::EndCache(device);
285
286 device->End();
287
288 if (dev_ptr->layered && !device->GetFullscreen() && dev_ptr->dib.data != NULL)
289 {
290 HDC hdc = GetDC(device->GetWindow());
291 if (hdc != NULL)
292 {
293 POINT dest = {0, 0};
294 POINT src = {0, 0};
295 SIZE client = {device->GetWidth(), device->GetHeight()};
296 BLENDFUNCTION blend_func = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
297
298 if (device->GetRenderData().Length() == client.cx * client.cy)
299 {
300 CopyMemory(dev_ptr->dib.data, device->GetRenderData().Data(),
301 sizeof(DWORD) * client.cx * client.cy);
302 }
303
304 for (int i = 0; i < client.cy; i++)
305 {
306 for (int j = 0; j < client.cx; j++)
307 {
308 int mask_i = int(dev_ptr->shape.height * float(i) / float(client.cy));
309 int mask_j = int(dev_ptr->shape.width * float(j) / float(client.cx));
310 if (mask_i < 0)
311 mask_i = 0;
312 else if (mask_i >= dev_ptr->shape.height)
313 mask_i = dev_ptr->shape.height - 1;
314 if (mask_j < 0)
315 mask_j = 0;
316 else if (mask_j >= dev_ptr->shape.width)
317 mask_j = dev_ptr->shape.width - 1;
318 BYTE mask_b = dev_ptr->shape.mask[mask_i * dev_ptr->shape.width + mask_j];
319 float alpha = float(mask_b) / 255.f;
320
321 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);
322 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);
323 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);
324 dev_ptr->dib.data[j * 4 + 3 + i * 4 * client.cx] = mask_b;
325 }
326 }
327 HGDIOBJ prev_obj = SelectObject(dev_ptr->dib.hdc, dev_ptr->dib.image);
328 ClientToScreen(device->GetWindow(), &dest);
329
330 UpdateLayeredWindow(device->GetWindow(), hdc, &dest, &client,
331 dev_ptr->dib.hdc, &src, 0, &blend_func, ULW_ALPHA);
332
333 SelectObject(dev_ptr->dib.hdc, prev_obj);
334 ReleaseDC(device->GetWindow(), hdc);
335 }
336 }
337 scene->FreeObjects();
338}
339
340void evas_direct3d_line_draw(Direct3DDeviceHandler d3d, int x1, int y1, int x2, int y2)
341{
342 DevicePtr *dev_ptr = SelectDevice(d3d);
343 D3DDevice *device = dev_ptr->device;
344 D3DScene *scene = dev_ptr->scene;
345 D3DContext *context = dev_ptr->context;
346
347 Ref<D3DObjectLine> line = scene->GetFreeObject<D3DObjectLine>();
348 if (line == NULL)
349 {
350 line = new D3DObjectLine();
351 scene->AddObject(line);
352 DBG("New line object (total objects: %d)", scene->GetObjectCount());
353 }
354 else
355 {
356 line->SetFree(false);
357 DBG("Line reused (object: %p)", line.Addr());
358 }
359
360 line->Setup(
361 2.f * float(x1) / float(device->GetWidth()) - 1.f,
362 2.f * (1.f - float(y1) / float(device->GetHeight())) - 1.f,
363 2.f * float(x2) / float(device->GetWidth()) - 1.f,
364 2.f * (1.f - float(y2) / float(device->GetHeight())) - 1.f,
365 context->color);
366}
367
368void evas_direct3d_rectangle_draw(Direct3DDeviceHandler d3d, int x, int y, int w, int h)
369{
370 DevicePtr *dev_ptr = SelectDevice(d3d);
371 D3DDevice *device = dev_ptr->device;
372 D3DScene *scene = dev_ptr->scene;
373 D3DContext *context = dev_ptr->context;
374
375 Ref<D3DObjectRect> rect = scene->GetFreeObject<D3DObjectRect>();
376 if (rect == NULL)
377 {
378 rect = new D3DObjectRect();
379 scene->AddObject(rect);
380 DBG("New rect object (total objects: %d)", scene->GetObjectCount());
381 }
382 else
383 {
384 rect->SetFree(false);
385 DBG("Rect reused (object: %p)", rect.Addr());
386 }
387
388 rect->Setup(
389 2.f * float(x) / float(device->GetWidth()) - 1.f,
390 2.f * (1.f - float(y) / float(device->GetHeight())) - 1.f,
391 2.f * float(w) / float(device->GetWidth()),
392 -2.f * float(h) / float(device->GetHeight()),
393 context->color);
394}
395
396Direct3DImageHandler evas_direct3d_image_load(Direct3DDeviceHandler d3d,
397 const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo)
398{
399 DevicePtr *dev_ptr = SelectDevice(d3d);
400 D3DDevice *device = dev_ptr->device;
401 D3DScene *scene = dev_ptr->scene;
402
403 RGBA_Image *evas_image = evas_common_load_image_from_file(file, key, lo);
404 if (evas_image == NULL)
405 {
406 WRN("Failed to load image from %s", file);
407 return NULL;
408 }
409 int image_width = evas_image->cache_entry.w;
410 int image_height = evas_image->cache_entry.h;
411 assert(image_width > 0 && image_height > 0);
412
413 D3DImageCache::CacheEntryInfo info;
414 ZeroMemory(&info, sizeof(info));
415 info.id = -1;
416
417 Ref<D3DObjectImage> image = new D3DObjectImage();
418 image->Init(info.u, info.v, info.du, info.dv, info.id,
419 info.width, info.height, evas_image->cache_entry.file);
420 image->SetFree(true);
421 scene->AddObject(image);
422
423 DBG("New image object (total objects: %d)", scene->GetObjectCount());
424
425 ImagePtr *ptr = new ImagePtr;
426 ptr->ref = image;
427 ptr->img = evas_image;
428
429 return (Direct3DImageHandler)ptr;
430}
431
432Direct3DImageHandler evas_direct3d_image_new_from_data(Direct3DDeviceHandler d3d,
433 int w, int h, DWORD *image_data, int alpha, int cspace)
434{
435 DevicePtr *dev_ptr = SelectDevice(d3d);
436 D3DDevice *device = dev_ptr->device;
437 D3DScene *scene = dev_ptr->scene;
438
439 int image_width = w;
440 int image_height = h;
441 assert(image_width > 0 && image_height > 0);
442
443 Ref<D3DObjectImage> image = new D3DObjectImage();
444
445 D3DImageCache::CacheEntryInfo info;
446 ZeroMemory(&info, sizeof(info));
447 if (!D3DImageCache::Current()->InsertImage(device, image_data,
448 image_width, image_height, info))
449 {
450 WRN("Couldnt add image to the cache");
451 return NULL;
452 }
453 char buf[64];
454 sprintf(buf, "%p", image_data);
455 image->Init(info.u, info.v, info.du, info.dv, info.id,
456 info.width, info.height, buf);
457
458 image->SetFree(true);
459 scene->AddObject(image);
460
461 DBG("New image object (total objects: %d)", scene->GetObjectCount());
462
463 ImagePtr *ptr = new ImagePtr;
464 ptr->ref = image;
465 ptr->img = NULL;
466
467 return (Direct3DImageHandler)ptr;
468}
469
470Direct3DImageHandler evas_direct3d_image_new_from_copied_data(Direct3DDeviceHandler d3d,
471 int w, int h, DWORD *image_data, int alpha, int cspace)
472{
473 return evas_direct3d_image_new_from_data(d3d, w, h, image_data, alpha, cspace);
474}
475
476void evas_direct3d_image_free(Direct3DDeviceHandler d3d, Direct3DImageHandler image)
477{
478 DevicePtr *dev_ptr = SelectDevice(d3d);
479 D3DDevice *device = dev_ptr->device;
480 D3DScene *scene = dev_ptr->scene;
481
482 ImagePtr *ptr = (ImagePtr *)image;
483
484 Ref<D3DObjectImage> image_ref = ptr->ref;
485 assert(!image_ref.IsNull());
486 scene->DeleteObject(image_ref);
487
488 delete ptr;
489}
490
491void evas_direct3d_image_data_put(Direct3DDeviceHandler d3d, Direct3DImageHandler image,
492 DWORD *image_data)
493{
494 ImagePtr *ptr = (ImagePtr *)image;
495 Ref<D3DObjectImage> image_ref = ptr->ref;
496 //assert(!image_ref.IsNull());
497 if (image_ref.IsNull())
498 return;
499
500 if (!image_ref->UpdateImageData(image_data))
501 ERR("Failed to update image data");
502}
503
504void evas_direct3d_image_data_get(Direct3DDeviceHandler d3d, Direct3DImageHandler image,
505 int to_write, DATA32 **image_data)
506{
507 ImagePtr *ptr = (ImagePtr *)image;
508 Ref<D3DObjectImage> image_ref = ptr->ref;
509 if (image_ref.IsNull())
510 return;
511 if (image_data == NULL)
512 return;
513 assert(sizeof(DATA32) == sizeof(DWORD));
514 *image_data = (DATA32 *)image_ref->GetImageData();
515}
516
517void evas_direct3d_image_draw(Direct3DDeviceHandler d3d, Direct3DImageHandler image,
518 int src_x, int src_y, int src_w, int src_h,
519 int dst_x, int dst_y, int dst_w, int dst_h, int smooth)
520{
521 ImagePtr *ptr = (ImagePtr *)image;
522 Ref<D3DObjectImage> image_ref = ptr->ref;
523 RGBA_Image *evas_image = ptr->img;
524 DevicePtr *dev_ptr = SelectDevice(d3d);
525 D3DDevice *device = dev_ptr->device;
526 D3DScene *scene = dev_ptr->scene;
527 //assert(!image_ref.IsNull());
528 if (image_ref.IsNull())
529 return;
530
531 if (!image_ref->IsValid())
532 {
533 TArray<D3DObjectImage *> images;
534 scene->GetObjectsOfType<D3DObjectImage>(images);
535 bool found = false;
536 for (int i = 0; i < images.Length(); i++)
537 {
538 if (images[i]->IsValid() &&
539 _stricmp(images[i]->GetSource(), image_ref->GetSource()) == 0)
540 {
541 images[i]->CopyTo(image_ref);
542 found = true;
543 WRN("Image object info reused, source: \"%s\"", image_ref->GetSource());
544 break;
545 }
546 }
547 if (!found && evas_image != NULL)
548 evas_cache_image_load_data(&evas_image->cache_entry);
549 }
550
551 // If the image object wasn't initialized yet
552 if (evas_image != NULL && evas_image->image.data != NULL && !image_ref->IsValid())
553 {
554 D3DImageCache::CacheEntryInfo info;
555 ZeroMemory(&info, sizeof(info));
556 if (!D3DImageCache::Current()->InsertImage(device, (DWORD *)evas_image->image.data,
557 evas_image->cache_entry.w, evas_image->cache_entry.h, info))
558 {
559 WRN("Couldnt add image to the cache");
560 return;
561 }
562 image_ref->Init(info.u, info.v, info.du, info.dv, info.id,
563 info.width, info.height, evas_image->cache_entry.file);
564 }
565
566 // Do not draw invalid objects
567 if (!image_ref->IsValid())
568 {
569 image_ref->SetFree(true);
570 return;
571 }
572
573 image_ref->Setup(
574 2.f * float(dst_x) / float(device->GetWidth()) - 1.f,
575 2.f * (1.f - float(dst_y) / float(device->GetHeight())) - 1.f,
576 2.f * float(dst_w) / float(device->GetWidth()),
577 -2.f * float(dst_h) / float(device->GetHeight()),
578 src_x, src_y, src_w, src_h);
579
580 image_ref->SetupColorFilter(dev_ptr->context->color_mul);
581
582 image_ref->SetFree(false);
583}
584
585void evas_direct3d_image_size_get(Direct3DImageHandler image, int *w, int *h)
586{
587 ImagePtr *ptr = (ImagePtr *)image;
588 if (ptr == NULL)
589 return;
590 if (ptr->img != NULL)
591 {
592 if (w != NULL)
593 *w = ptr->img->cache_entry.w;
594 if (h != NULL)
595 *h = ptr->img->cache_entry.h;
596 }
597 else if (!ptr->ref.IsNull())
598 {
599 if (w != NULL)
600 *w = ptr->ref->GetWidth();
601 if (h != NULL)
602 *h = ptr->ref->GetHeight();
603 }
604}
605
606void evas_direct3d_image_border_set(Direct3DDeviceHandler d3d, Direct3DImageHandler image,
607 int l, int r, int t, int b)
608{
609 ImagePtr *ptr = (ImagePtr *)image;
610 Ref<D3DObjectImage> image_ref = ptr->ref;
611 DevicePtr *dev_ptr = SelectDevice(d3d);
612 D3DDevice *device = dev_ptr->device;
613 if (image_ref.IsNull())
614 return;
615
616 int im_w, im_h;
617 if (ptr->img != NULL)
618 {
619 im_w = ptr->img->cache_entry.w;
620 im_h = ptr->img->cache_entry.h;
621 }
622 else
623 {
624 im_w = image_ref->GetWidth();
625 im_h = image_ref->GetHeight();
626 }
627
628 image_ref->SetupBorder(
629 D3DXVECTOR4(
630 2.f * float(l) / float(device->GetWidth()),
631 -2.f * float(t) / float(device->GetHeight()),
632 2.f * float(r) / float(device->GetWidth()),
633 -2.f * float(b) / float(device->GetHeight())),
634 D3DXVECTOR4(float(l) / float(im_w),
635 float(t) / float(im_h),
636 float(r) / float(im_w),
637 float(b) / float(im_h)));
638}
639
640void evas_direct3d_image_border_get(Direct3DDeviceHandler d3d, Direct3DImageHandler image,
641 int *l, int *r, int *t, int *b)
642{
643 ImagePtr *ptr = (ImagePtr *)image;
644 Ref<D3DObjectImage> image_ref = ptr->ref;
645 DevicePtr *dev_ptr = SelectDevice(d3d);
646 D3DDevice *device = dev_ptr->device;
647 if (image_ref.IsNull())
648 return;
649 assert(l != NULL && r != NULL && b != NULL && t != NULL);
650 *l = (int)(0.5f * image_ref->GetBorderLeft() * device->GetWidth());
651 *r = (int)(0.5f * image_ref->GetBorderRight() * device->GetWidth());
652 *t = (int)(-0.5f * image_ref->GetBorderTop() * device->GetHeight());
653 *b = (int)(-0.5f * image_ref->GetBorderBottom() * device->GetHeight());
654}
655
656
657Direct3DFontGlyphHandler evas_direct3d_font_texture_new(Direct3DDeviceHandler d3d,
658 RGBA_Font_Glyph *fg)
659{
660 DevicePtr *dev_ptr = SelectDevice(d3d);
661 D3DContext *context = dev_ptr->context;
662 D3DDevice *device = dev_ptr->device;
663
664 if (context->font.IsNull())
665 return NULL;
666
667 D3DObjectFont *font = (D3DObjectFont *)context->font.Addr();
668 // This is not reliable
669 //D3DObjectFont::Glyph *glyph = (D3DObjectFont::Glyph *)fg->ext_dat;
670 D3DObjectFont::Glyph *glyph = font->GetGlyph(fg);
671 if (glyph != NULL)
672 {
673 assert(glyph->Compare(fg));
674 return glyph;
675 }
676 glyph = font->AddGlyph(device, fg, fg->glyph_out->bitmap.buffer,
677 fg->glyph_out->bitmap.width, fg->glyph_out->bitmap.rows, fg->glyph_out->bitmap.pitch);
678 return (Direct3DFontGlyphHandler)glyph;
679}
680
681void evas_direct3d_font_texture_free(Direct3DFontGlyphHandler ft)
682{
683 if (ft == NULL)
684 return;
685 D3DObjectFont::Glyph *glyph = (D3DObjectFont::Glyph *)ft;
686 RGBA_Font_Glyph *fg = (RGBA_Font_Glyph *)glyph->Source();
687 fg->ext_dat = NULL;
688}
689
690void evas_direct3d_font_texture_draw(Direct3DDeviceHandler d3d, void *, void *,
691 RGBA_Font_Glyph *fg, int x, int y)
692{
693 DevicePtr *dev_ptr = SelectDevice(d3d);
694 D3DContext *context = dev_ptr->context;
695 D3DDevice *device = dev_ptr->device;
696
697 if (context->font.IsNull())
698 return;
699
700 D3DObjectFont *font = (D3DObjectFont *)context->font.Addr();
701 D3DObjectFont::Glyph *glyph = (D3DObjectFont::Glyph *)fg->ext_dat;
702 if (glyph == NULL)
703 return;
704 assert(glyph->Compare(fg));
705
706 font->SetColor(context->color);
707 font->PushForDraw(glyph, x, y);
708 font->SetFree(false);
709}
710
711void evas_direct3d_select_or_create_font(Direct3DDeviceHandler d3d, void *font)
712{
713 // The Plan
714 // 1. Create D3DObjectFont with source string = "%p" (font)
715 // 2. Or find this object in the scene
716 // 3. On each texture_new call - fill internal texture with glyph, remember the
717 // glyph pointer - we'll use it.
718
719 DevicePtr *dev_ptr = SelectDevice(d3d);
720 D3DContext *context = dev_ptr->context;
721
722 if (!context->font.IsNull() && ((D3DObjectFont *)context->font.Addr())->Compare(font))
723 return;
724
725 D3DScene *scene = dev_ptr->scene;
726
727 static TArray<D3DObjectFont *> fonts;
728 scene->GetObjectsOfType<D3DObjectFont>(fonts);
729 for (int i = 0; i < fonts.Length(); i++)
730 {
731 if (fonts[i]->Compare(font))
732 {
733 context->font = fonts[i];
734 return;
735 }
736 }
737
738 D3DDevice *device = dev_ptr->device;
739
740 assert(dev_ptr->fonts_buffer_image_id >= 0);
741
742 Ref<D3DObjectFont> new_font = new D3DObjectFont(font, dev_ptr->fonts_buffer_image_id);
743 scene->AddObject(new_font);
744 context->font = new_font;
745}
746
747void evas_direct3d_font_free(Direct3DDeviceHandler d3d, void *font)
748{
749 DevicePtr *dev_ptr = SelectDevice(d3d);
750 D3DContext *context = dev_ptr->context;
751 D3DScene *scene = dev_ptr->scene;
752
753 if (context->font.IsNull() || !((D3DObjectFont *)context->font.Addr())->Compare(font))
754 {
755 D3DScene *scene = dev_ptr->scene;
756
757 static TArray<D3DObjectFont *> fonts;
758 scene->GetObjectsOfType<D3DObjectFont>(fonts);
759 for (int i = 0; i < fonts.Length(); i++)
760 {
761 if (fonts[i]->Compare(font))
762 {
763 context->font = fonts[i];
764 break;
765 }
766 }
767 }
768
769 scene->DeleteObject(context->font);
770 context->font = NULL;
771}
772
773
774} // extern "C"