PageRenderTime 28ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/evas/src/modules/engines/psl1ght/evas_engine.c

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