aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/engines/psl1ght/evas_engine.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/engines/psl1ght/evas_engine.c')
-rw-r--r--libraries/evas/src/modules/engines/psl1ght/evas_engine.c511
1 files changed, 511 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/psl1ght/evas_engine.c b/libraries/evas/src/modules/engines/psl1ght/evas_engine.c
new file mode 100644
index 0000000..750c098
--- /dev/null
+++ b/libraries/evas/src/modules/engines/psl1ght/evas_engine.c
@@ -0,0 +1,511 @@
1#include "evas_common.h"
2#include "evas_private.h"
3#include "evas_engine.h"
4#include "rsxutil.h"
5#include "Evas_Engine_PSL1GHT.h"
6
7#include <malloc.h>
8
9int _evas_engine_psl1ght_log_dom = -1;
10
11/* function tables - filled in later (func and parent func) */
12static Evas_Func func, pfunc;
13
14/* engine struct data */
15typedef struct _Render_Engine Render_Engine;
16
17#define MAX_BUFFERS 2
18
19struct _Render_Engine
20{
21 Tilebuf *tb;
22 Tilebuf_Rect *rects;
23 Eina_Inlist *cur_rect;
24
25 /* RSX device context */
26 gcmContextData *context;
27 void *host_addr;
28
29 /* The buffers we will be drawing into. */
30 rsxBuffer buffers[MAX_BUFFERS];
31 int currentBuffer;
32 int width;
33 int height;
34 RGBA_Image *rgba_image;
35 uint32_t rgba_image_offset;
36
37 int end : 1;
38};
39
40/* prototypes we will use here */
41static void *_output_setup(int w, int h);
42
43static void *eng_info(Evas *e);
44static void
45 eng_info_free(Evas *e, void *info);
46static int
47 eng_setup(Evas *e, void *info);
48static void
49 eng_output_free(void *data);
50static void
51 eng_output_resize(void *data, int w, int h);
52static void
53 eng_output_tile_size_set(void *data, int w, int h);
54static void
55 eng_output_redraws_rect_add(void *data, int x, int y, int w, int h);
56static void
57 eng_output_redraws_rect_del(void *data, int x, int y, int w, int h);
58static void
59 eng_output_redraws_clear(void *data);
60static void *eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch);
61static void
62 eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h);
63static void
64 eng_output_flush(void *data);
65static void
66 eng_output_idle_flush(void *data);
67
68/* internal engine routines */
69static void *
70_output_setup(int w, int h)
71{
72 Render_Engine *re;
73 int i;
74 u16 width, height;
75 DATA32 *image_data = NULL;
76 int image_size;
77
78 printf ("_output_setup called : %dx%d\n", w, h);
79 re = calloc(1, sizeof(Render_Engine));
80 if (!re)
81 return NULL;
82
83 /* Allocate a 1Mb buffer, alligned to a 1Mb boundary
84 * to be our shared IO memory with the RSX. */
85 re->host_addr = memalign (1024 * 1024, HOST_SIZE);
86 if (re->host_addr == NULL)
87 {
88 free (re);
89 return NULL;
90 }
91 re->context = initScreen (re->host_addr, HOST_SIZE);
92 if (re->context == NULL)
93 {
94 free (re->host_addr);
95 free (re);
96 return NULL;
97 }
98 width = w;
99 height = h;
100 setResolution (re->context, &width, &height);
101 re->currentBuffer = 0;
102 re->width = width;
103 re->height = height;
104
105 for (i = 0; i < MAX_BUFFERS; i++)
106 makeBuffer (&re->buffers[i], width, height, i);
107
108 flipBuffer(re->context, MAX_BUFFERS - 1);
109
110 /* if we haven't initialized - init (automatic abort if already done) */
111 evas_common_cpu_init();
112 evas_common_blend_init();
113 evas_common_image_init();
114 evas_common_convert_init();
115 evas_common_scale_init();
116 evas_common_rectangle_init();
117 evas_common_polygon_init();
118 evas_common_line_init();
119 evas_common_font_init();
120 evas_common_draw_init();
121 evas_common_tilebuf_init();
122
123 re->tb = evas_common_tilebuf_new(w, h);
124
125 /* in preliminary tests 16x16 gave highest framerates */
126 evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
127
128 /* Allocate our memaligned backbuffer */
129 image_size = ((w * h * sizeof(u32)) + 0xfffff) & - 0x100000;
130 image_data = memalign (1024 * 1024, image_size);
131 re->rgba_image = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
132 w, h, image_data, 1, EVAS_COLORSPACE_ARGB8888);
133 gcmMapMainMemory(image_data, image_size, &re->rgba_image_offset);
134
135 return re;
136}
137
138/* engine api this module provides */
139static void *
140eng_info(Evas *e)
141{
142 Evas_Engine_Info_PSL1GHT *info;
143
144 printf ("eng_info called\n");
145 info = calloc(1, sizeof(Evas_Engine_Info_PSL1GHT));
146 if (!info)
147 return NULL;
148
149 info->magic.magic = rand();
150 info->render_mode = EVAS_RENDER_MODE_BLOCKING;
151
152 return info;
153}
154
155static void
156eng_info_free(Evas *e __UNUSED__, void *info)
157{
158 Evas_Engine_Info_PSL1GHT *in;
159
160 printf ("eng_info_free called\n");
161 in = (Evas_Engine_Info_PSL1GHT *)info;
162 free(in);
163}
164
165static int
166eng_setup(Evas *e, void *in)
167{
168 Evas_Engine_Info_PSL1GHT *info;
169
170 printf ("eng_setup called\n");
171 info = (Evas_Engine_Info_PSL1GHT *)in;
172
173 e->engine.data.output = _output_setup(e->output.w, e->output.h);
174 if (!e->engine.data.output)
175 return 0;
176
177 e->engine.func = &func;
178 e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
179
180 return 1;
181}
182
183static void
184eng_output_free(void *data)
185{
186 Render_Engine *re;
187 int i;
188
189 printf ("eng_output_free called\n");
190 re = (Render_Engine *)data;
191
192 gcmSetWaitFlip(re->context);
193 for (i = 0; i < MAX_BUFFERS; i++)
194 rsxFree (re->buffers[i].ptr);
195
196 if (re->rgba_image)
197 {
198 DATA32 *image_data;
199
200 image_data = re->rgba_image->image.data;
201 evas_cache_image_drop(&re->rgba_image->cache_entry);
202 free (image_data);
203 }
204
205 freeScreen (re->context);
206 free (re->host_addr);
207
208 evas_common_tilebuf_free(re->tb);
209 if (re->rects)
210 evas_common_tilebuf_free_render_rects(re->rects);
211
212 free(re);
213
214 evas_common_font_shutdown();
215 evas_common_image_shutdown();
216}
217
218static void
219eng_output_resize(void *data, int w, int h)
220{
221 Render_Engine *re;
222 int i;
223 u16 width, height;
224 DATA32 *image_data;
225 int image_size;
226
227 printf ("eng_output_resize called : %dx%d\n", w, h);
228 re = (Render_Engine *)data;
229
230 width = w;
231 height = h;
232 if (setResolution (re->context, &width, &height))
233 {
234 re->width = width;
235 re->height = height;
236
237 gcmSetWaitFlip(re->context);
238 for (i = 0; i < MAX_BUFFERS; i++) {
239 rsxFree (re->buffers[i].ptr);
240 makeBuffer (&re->buffers[i], width, height, i);
241 }
242
243 flipBuffer(re->context, MAX_BUFFERS - 1);
244
245 evas_common_tilebuf_free(re->tb);
246 re->tb = evas_common_tilebuf_new(w, h);
247 evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
248
249 /* Realloc our backbuf image */
250 if (re->rgba_image)
251 {
252 image_data = re->rgba_image->image.data;
253 evas_cache_image_drop(&re->rgba_image->cache_entry);
254 free (image_data);
255 }
256 image_size = ((w * h * sizeof(u32)) + 0xfffff) & - 0x100000;
257 image_data = memalign (1024 * 1024, image_size);
258 re->rgba_image = (RGBA_Image *)evas_cache_image_data(evas_common_image_cache_get(),
259 w, h, image_data, 1, EVAS_COLORSPACE_ARGB8888);
260 gcmMapMainMemory(image_data, image_size, &re->rgba_image_offset);
261 }
262}
263
264static void
265eng_output_tile_size_set(void *data, int w, int h)
266{
267 Render_Engine *re;
268
269 printf ("eng_output_tile_size_set called : %dx%d\n", w, h);
270 re = (Render_Engine *)data;
271 evas_common_tilebuf_set_tile_size(re->tb, w, h);
272}
273
274static void
275eng_output_redraws_rect_add(void *data, int x, int y, int w, int h)
276{
277 Render_Engine *re;
278
279 //printf ("eng_output_redraws_rect_add called : %d,%d %dx%d\n", x, y, w, h);
280 re = (Render_Engine *)data;
281 evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
282}
283
284static void
285eng_output_redraws_rect_del(void *data, int x, int y, int w, int h)
286{
287 Render_Engine *re;
288
289 //printf ("eng_output_redraws_rect_del called : %d,%d %dx%d\n", x, y, w, h);
290 re = (Render_Engine *)data;
291 evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
292}
293
294static void
295eng_output_redraws_clear(void *data)
296{
297 Render_Engine *re;
298
299 //printf ("eng_output_redraws_clear called\n");
300 re = (Render_Engine *)data;
301 evas_common_tilebuf_clear(re->tb);
302}
303
304static void *
305eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch)
306{
307 Render_Engine *re;
308 Tilebuf_Rect *rect;
309 int ux, uy, uw, uh;
310
311 re = (Render_Engine *)data;
312 /*printf ("eng_output_redraws_next_update_get called : %d,%d %dx%d -- %d,%d %dx%d\n",
313 *x, *y, *w, *h, *cx, *cy, *cw, *ch);*/
314 if (re->end)
315 {
316 re->end = 0;
317 return NULL;
318 }
319 if (!re->rects)
320 {
321 re->rects = evas_common_tilebuf_get_render_rects(re->tb);
322 re->cur_rect = EINA_INLIST_GET(re->rects);
323 }
324 if (!re->cur_rect)
325 return NULL;
326
327 rect = (Tilebuf_Rect *)re->cur_rect;
328 ux = rect->x; uy = rect->y; uw = rect->w; uh = rect->h;
329 re->cur_rect = re->cur_rect->next;
330 if (!re->cur_rect)
331 {
332 evas_common_tilebuf_free_render_rects(re->rects);
333 re->rects = NULL;
334 re->end = 1;
335 }
336
337 *x = *cx = ux;
338 *y = *cy = uy;
339 *w = *cw = uw;
340 *h = *ch = uh;
341 /*printf ("eng_output_redraws_next_update_get returning : %d,%d %dx%d -- %d,%d %dx%d\n",
342 *x, *y, *w, *h, *cx, *cy, *cw, *ch);*/
343
344 return re->rgba_image;
345}
346
347static void
348eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
349{
350 /* Don't do anything, we'll just coy the whole buffer when it's time to flush */
351}
352
353static void
354eng_output_flush(void *data)
355{
356 Render_Engine *re;
357 rsxBuffer *buffer;
358 int width;
359 int height;
360
361 //printf ("eng_output_flush called\n");
362 re = (Render_Engine *)data;
363 buffer = &re->buffers[re->currentBuffer];
364 width = re->rgba_image->cache_entry.w;
365 height = re->rgba_image->cache_entry.h;
366
367 /* Wait for the flip before copying the buffer */
368 waitFlip ();
369
370 if (re->width == width &&
371 re->height == height)
372 {
373 /* DMA the back buffer into the rsx buffer */
374 rsxSetTransferImage (re->context,
375 GCM_TRANSFER_MAIN_TO_LOCAL,
376 buffer->offset, buffer->width * sizeof(u32),
377 0, 0,
378 re->rgba_image_offset, re->width * sizeof(u32),
379 0, 0, re->width, re->height, sizeof(u32));
380 }
381 else
382 {
383 gcmTransferScale gcm_scale;
384 gcmTransferSurface gcm_surface;
385
386 gcm_surface.format = GCM_TRANSFER_SURFACE_FORMAT_A8R8G8B8;
387 gcm_surface.pitch = buffer->width * sizeof(u32);
388 gcm_surface._pad0[0] = gcm_surface._pad0[1] = 0;
389 gcm_surface.offset = buffer->offset;
390
391 gcm_scale.interp = GCM_TRANSFER_INTERPOLATOR_LINEAR;
392 gcm_scale.conversion = GCM_TRANSFER_CONVERSION_TRUNCATE;
393 gcm_scale.format = GCM_TRANSFER_SCALE_FORMAT_A8R8G8B8;
394 gcm_scale.origin = GCM_TRANSFER_ORIGIN_CORNER;
395 gcm_scale.operation = GCM_TRANSFER_OPERATION_SRCCOPY;
396 gcm_scale.offset = re->rgba_image_offset;
397 gcm_scale.clipX = 0;
398 gcm_scale.clipY = 0;
399 gcm_scale.clipW = re->width;
400 gcm_scale.clipH = re->height;
401 gcm_scale.outX = 0;
402 gcm_scale.outY = 0;
403 gcm_scale.outW = re->width;
404 gcm_scale.outH = re->height;
405 gcm_scale.ratioX = rsxGetFixedSint32 ((float)width / (float)re->width);
406 gcm_scale.ratioY = rsxGetFixedSint32 ((float)height / (float)re->height);
407 gcm_scale.inX = 0;
408 gcm_scale.inY = 0;
409 gcm_scale.inW = (width & ~1); // Width must be a multiple of 2
410 gcm_scale.inH = height;
411 if (gcm_scale.inW < 2) // Minimum inW value is 2
412 gcm_scale.inW = 2;
413 if (gcm_scale.inW > 2046) // Maximum inW value is 2046
414 gcm_scale.inW = 2046;
415 if (gcm_scale.inH < 1) // Minimum inH value is 1
416 gcm_scale.inH = 1;
417 if (gcm_scale.inH > 2047) // Maximum inW value is 2047
418 gcm_scale.inH = 2047;
419 gcm_scale.pitch = sizeof(u32) * width;
420
421 rsxSetTransferScaleMode (re->context, GCM_TRANSFER_MAIN_TO_LOCAL, GCM_TRANSFER_SURFACE);
422 rsxSetTransferScaleSurface (re->context, &gcm_scale, &gcm_surface);
423 }
424 /* Wait for the DMA to finish */
425 flushRSX (re->context);
426
427 /* Flip buffer onto screen */
428 flipBuffer (re->context, re->currentBuffer);
429 re->currentBuffer = (re->currentBuffer + 1) % MAX_BUFFERS;
430}
431
432static void
433eng_output_idle_flush(void *data)
434{
435 Render_Engine *re;
436
437 printf ("eng_output_idle_flush called\n");
438 re = (Render_Engine *)data;
439}
440
441static Eina_Bool
442eng_canvas_alpha_get(void *data, void *context __UNUSED__)
443{
444 Render_Engine *re;
445
446 // printf ("eng_output_alpha_get called\n");
447 re = (Render_Engine *)data;
448 return EINA_TRUE;
449}
450
451/* module advertising code */
452static int
453module_open(Evas_Module *em)
454{
455 if (!em) return 0;
456 /* get whatever engine module we inherit from */
457 if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
458 _evas_engine_psl1ght_log_dom = eina_log_domain_register
459 ("evas-psl1ght", EVAS_DEFAULT_LOG_COLOR);
460 if (_evas_engine_psl1ght_log_dom < 0)
461 {
462 EINA_LOG_ERR("Can not create a module log domain.");
463 return 0;
464 }
465
466 /* store it for later use */
467 func = pfunc;
468 /* now to override methods */
469#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
470 ORD(info);
471 ORD(info_free);
472 ORD(setup);
473 ORD(canvas_alpha_get);
474 ORD(output_free);
475 ORD(output_resize);
476 ORD(output_tile_size_set);
477 ORD(output_redraws_rect_add);
478 ORD(output_redraws_rect_del);
479 ORD(output_redraws_clear);
480 ORD(output_redraws_next_update_get);
481 ORD(output_redraws_next_update_push);
482 ORD(output_flush);
483 ORD(output_idle_flush);
484
485 /* now advertise out own api */
486 em->functions = (void *)(&func);
487 return 1;
488}
489
490static void
491module_close(Evas_Module *em __UNUSED__)
492{
493 eina_log_domain_unregister(_evas_engine_psl1ght_log_dom);
494}
495
496static Evas_Module_Api evas_modapi =
497{
498 EVAS_MODULE_API_VERSION,
499 "psl1ght",
500 "none",
501 {
502 module_open,
503 module_close
504 }
505};
506
507EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, psl1ght);
508
509#ifndef EVAS_STATIC_BUILD_PSL1GHT
510EVAS_EINA_MODULE_DEFINE(engine, psl1ght);
511#endif