diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/evas/src/modules/engines/direct3d/evas_direct3d_main.cpp | 774 |
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 | ||
21 | struct ImagePtr | ||
22 | { | ||
23 | Ref<D3DObjectImage> ref; | ||
24 | RGBA_Image *img; | ||
25 | }; | ||
26 | |||
27 | struct 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 | |||
62 | DevicePtr *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 | |||
71 | void 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 | |||
81 | bool 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 | |||
111 | extern "C" { | ||
112 | |||
113 | Direct3DDeviceHandler 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 | |||
153 | void | ||
154 | evas_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 | |||
177 | void | ||
178 | evas_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 | |||
200 | void | ||
201 | evas_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 | |||
226 | void | ||
227 | evas_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 | |||
242 | void | ||
243 | evas_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 | |||
250 | void | ||
251 | evas_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 | |||
258 | void | ||
259 | evas_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 | |||
340 | void 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 | |||
368 | void 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 | |||
396 | Direct3DImageHandler 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 | |||
432 | Direct3DImageHandler 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 | |||
470 | Direct3DImageHandler 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 | |||
476 | void 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 | |||
491 | void 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 | |||
504 | void 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 | |||
517 | void 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 | |||
585 | void 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 | |||
606 | void 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 | |||
640 | void 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 | |||
657 | Direct3DFontGlyphHandler 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 | |||
681 | void 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 | |||
690 | void 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 | |||
711 | void 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 | |||
747 | void 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" | ||