diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/evas/src/modules/engines/gl_sdl/evas_engine.c | 1081 |
1 files changed, 1081 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/engines/gl_sdl/evas_engine.c b/libraries/evas/src/modules/engines/gl_sdl/evas_engine.c new file mode 100644 index 0000000..46588d9 --- /dev/null +++ b/libraries/evas/src/modules/engines/gl_sdl/evas_engine.c | |||
@@ -0,0 +1,1081 @@ | |||
1 | #include "evas_common.h" /* Also includes international specific stuff */ | ||
2 | #include "evas_engine.h" | ||
3 | |||
4 | static void* _sdl_output_setup (int w, int h, int fullscreen, int noframe); | ||
5 | |||
6 | int _evas_engine_GL_SDL_log_dom = -1; | ||
7 | /* function tables - filled in later (func and parent func) */ | ||
8 | static Evas_Func func, pfunc; | ||
9 | |||
10 | static void * | ||
11 | eng_info(Evas *e) | ||
12 | { | ||
13 | Evas_Engine_Info_GL_SDL *info; | ||
14 | |||
15 | info = calloc(1, sizeof(Evas_Engine_Info_GL_SDL)); | ||
16 | if (!info) return NULL; | ||
17 | info->magic.magic = rand(); | ||
18 | return info; | ||
19 | } | ||
20 | |||
21 | static void | ||
22 | eng_info_free(Evas *e __UNUSED__, void *info) | ||
23 | { | ||
24 | Evas_Engine_Info_GL_SDL *in; | ||
25 | in = (Evas_Engine_Info_GL_SDL *)info; | ||
26 | free(in); | ||
27 | } | ||
28 | |||
29 | static int | ||
30 | eng_setup(Evas *e, void *in) | ||
31 | { | ||
32 | Render_Engine *re; | ||
33 | Evas_Engine_Info_GL_SDL *info; | ||
34 | |||
35 | info = (Evas_Engine_Info_GL_SDL *)in; | ||
36 | |||
37 | SDL_Init(SDL_INIT_NOPARACHUTE); | ||
38 | |||
39 | if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) | ||
40 | { | ||
41 | ERR("SDL_Init failed with %s", SDL_GetError()); | ||
42 | SDL_Quit(); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | re = _sdl_output_setup(e->output.w, e->output.h, | ||
47 | info->flags.fullscreen, | ||
48 | info->flags.noframe); | ||
49 | re->info = info; | ||
50 | e->engine.data.output = re; | ||
51 | if (!e->engine.data.output) | ||
52 | return 0; | ||
53 | |||
54 | e->engine.func = &func; | ||
55 | e->engine.data.context = e->engine.func->context_new(e->engine.data.output); | ||
56 | |||
57 | return 1; | ||
58 | } | ||
59 | |||
60 | static void | ||
61 | eng_output_free(void *data) | ||
62 | { | ||
63 | Render_Engine *re; | ||
64 | |||
65 | re = (Render_Engine *)data; | ||
66 | evas_gl_common_context_free(re->gl_context); | ||
67 | free(re); | ||
68 | |||
69 | evas_common_font_shutdown(); | ||
70 | evas_common_image_shutdown(); | ||
71 | |||
72 | SDL_QuitSubSystem(SDL_INIT_VIDEO); | ||
73 | } | ||
74 | |||
75 | static void | ||
76 | eng_output_resize(void *data, int w, int h) | ||
77 | { | ||
78 | Render_Engine *re; | ||
79 | SDL_Surface *surface; | ||
80 | |||
81 | re = (Render_Engine *)data; | ||
82 | re->w = w; | ||
83 | re->h = h; | ||
84 | |||
85 | if(SDL_GetVideoSurface()->flags & SDL_RESIZABLE) | ||
86 | { | ||
87 | surface = SDL_SetVideoMode(w, h, 32, EVAS_SDL_GL_FLAG | ||
88 | | (re->info->flags.fullscreen ? SDL_FULLSCREEN : 0) | ||
89 | | (re->info->flags.noframe ? SDL_NOFRAME : 0)); | ||
90 | if (!surface) | ||
91 | { | ||
92 | ERR("Unable to change the resolution to : %ix%i", w, h); | ||
93 | SDL_Quit(); | ||
94 | exit(-1); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | evas_gl_common_context_resize(re->gl_context, w, h, re->gl_context->rot); | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | eng_output_tile_size_set(void *data, int w __UNUSED__, int h __UNUSED__) | ||
103 | { | ||
104 | // Render_Engine *re; | ||
105 | // | ||
106 | // re = (Render_Engine *)data; | ||
107 | } | ||
108 | |||
109 | static void | ||
110 | eng_output_redraws_rect_add(void *data, int x, int y, int w, int h) | ||
111 | { | ||
112 | Render_Engine *re; | ||
113 | |||
114 | re = (Render_Engine *)data; | ||
115 | evas_gl_common_context_resize(re->gl_context, re->w, re->h, re->gl_context->rot); | ||
116 | /* smple bounding box */ | ||
117 | if (!re->draw.redraw) | ||
118 | { | ||
119 | #if 0 | ||
120 | re->draw.x1 = x; | ||
121 | re->draw.y1 = y; | ||
122 | re->draw.x2 = x + w - 1; | ||
123 | re->draw.y2 = y + h - 1; | ||
124 | #else | ||
125 | re->draw.x1 = 0; | ||
126 | re->draw.y1 = 0; | ||
127 | re->draw.x2 = re->w - 1; | ||
128 | re->draw.y2 = re->h - 1; | ||
129 | #endif | ||
130 | } | ||
131 | else | ||
132 | { | ||
133 | if (x < re->draw.x1) re->draw.x1 = x; | ||
134 | if (y < re->draw.y1) re->draw.y1 = y; | ||
135 | if ((x + w - 1) > re->draw.x2) re->draw.x2 = x + w - 1; | ||
136 | if ((y + h - 1) > re->draw.y2) re->draw.y2 = y + h - 1; | ||
137 | } | ||
138 | re->draw.redraw = 1; | ||
139 | } | ||
140 | |||
141 | static void | ||
142 | eng_output_redraws_rect_del(void *data, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__) | ||
143 | { | ||
144 | // Render_Engine *re; | ||
145 | // | ||
146 | // re = (Render_Engine *)data; | ||
147 | } | ||
148 | |||
149 | static void | ||
150 | eng_output_redraws_clear(void *data) | ||
151 | { | ||
152 | Render_Engine *re; | ||
153 | |||
154 | re = (Render_Engine *)data; | ||
155 | re->draw.redraw = 0; | ||
156 | // INF("GL: finish update cycle!"); | ||
157 | } | ||
158 | |||
159 | /* at least the nvidia drivers are so abysmal that copying from the backbuffer | ||
160 | * to the front using glCopyPixels() that you literally can WATCH it draw the | ||
161 | * pixels slowly across the screen with a window update taking multiple | ||
162 | * seconds - so workaround by doing a full buffer render as frankly GL isn't | ||
163 | * up to doing anything that isn't done by quake (etc.) | ||
164 | */ | ||
165 | #define SLOW_GL_COPY_RECT 1 | ||
166 | /* vsync games - not for now though */ | ||
167 | //#define VSYNC_TO_SCREEN 1 | ||
168 | |||
169 | static void * | ||
170 | eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, int *cx, int *cy, int *cw, int *ch) | ||
171 | { | ||
172 | Render_Engine *re; | ||
173 | |||
174 | re = (Render_Engine *)data; | ||
175 | evas_gl_common_context_flush(re->gl_context); | ||
176 | evas_gl_common_context_newframe(re->gl_context); | ||
177 | /* get the upate rect surface - return engine data as dummy */ | ||
178 | if (!re->draw.redraw) | ||
179 | { | ||
180 | // printf("GL: NO updates!\n"); | ||
181 | return NULL; | ||
182 | } | ||
183 | // printf("GL: update....!\n"); | ||
184 | #ifdef SLOW_GL_COPY_RECT | ||
185 | /* if any update - just return the whole canvas - works with swap | ||
186 | * buffers then */ | ||
187 | if (x) *x = 0; | ||
188 | if (y) *y = 0; | ||
189 | if (w) *w = re->w; | ||
190 | if (h) *h = re->h; | ||
191 | if (cx) *cx = 0; | ||
192 | if (cy) *cy = 0; | ||
193 | if (cw) *cw = re->w; | ||
194 | if (ch) *ch = re->h; | ||
195 | #else | ||
196 | /* 1 update - INCREDIBLY SLOW if combined with swap_rect in flush. a gl | ||
197 | * problem where there just is no hardware path for somethnig that | ||
198 | * obviously SHOULD be there */ | ||
199 | /* only 1 update to minimise gl context games and rendering multiple update | ||
200 | * regions as evas does with other engines | ||
201 | */ | ||
202 | if (x) *x = re->draw.x1; | ||
203 | if (y) *y = re->draw.y1; | ||
204 | if (w) *w = re->draw.x2 - re->draw.x1 + 1; | ||
205 | if (h) *h = re->draw.y2 - re->draw.y1 + 1; | ||
206 | if (cx) *cx = re->draw.x1; | ||
207 | if (cy) *cy = re->draw.y1; | ||
208 | if (cw) *cw = re->draw.x2 - re->draw.x1 + 1; | ||
209 | if (ch) *ch = re->draw.y2 - re->draw.y1 + 1; | ||
210 | #endif | ||
211 | // clear buffer. only needed for dest alpha | ||
212 | // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | ||
213 | // glClear(GL_COLOR_BUFFER_BIT); | ||
214 | //x// printf("frame -> new\n"); | ||
215 | return re->gl_context->def_surface; | ||
216 | } | ||
217 | |||
218 | static void | ||
219 | eng_output_redraws_next_update_push(void *data, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__, int w __UNUSED__, int h __UNUSED__) | ||
220 | { | ||
221 | Render_Engine *re; | ||
222 | |||
223 | re = (Render_Engine *)data; | ||
224 | /* put back update surface.. in this case just unflag redraw */ | ||
225 | re->draw.redraw = 0; | ||
226 | re->draw.drew = 1; | ||
227 | evas_gl_common_context_flush(re->gl_context); | ||
228 | //x// printf("frame -> push\n"); | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | eng_output_flush(void *data) | ||
233 | { | ||
234 | Render_Engine *re; | ||
235 | |||
236 | re = (Render_Engine *)data; | ||
237 | if (!re->draw.drew) return; | ||
238 | //x// printf("frame -> flush\n"); | ||
239 | re->draw.drew = 0; | ||
240 | |||
241 | #if 0 | ||
242 | #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) | ||
243 | // glFlush(); | ||
244 | eglSwapBuffers(re->egl_disp, re->egl_surface[0]); | ||
245 | #else | ||
246 | glXSwapBuffers(re->win->disp, re->win); | ||
247 | #endif | ||
248 | #else | ||
249 | SDL_GL_SwapBuffers(); | ||
250 | #endif | ||
251 | } | ||
252 | |||
253 | static void | ||
254 | eng_output_idle_flush(void *data) | ||
255 | { | ||
256 | Render_Engine *re; | ||
257 | |||
258 | re = (Render_Engine *)data; | ||
259 | } | ||
260 | |||
261 | static void | ||
262 | eng_output_dump(void *data) | ||
263 | { | ||
264 | Render_Engine *re; | ||
265 | |||
266 | re = (Render_Engine *)data; | ||
267 | evas_common_image_image_all_unload(); | ||
268 | evas_common_font_font_all_unload(); | ||
269 | evas_gl_common_image_all_unload(re->gl_context); | ||
270 | } | ||
271 | |||
272 | static void | ||
273 | eng_context_cutout_add(void *data, void *context, int x, int y, int w, int h) | ||
274 | { | ||
275 | // Render_Engine *re; | ||
276 | // | ||
277 | // re = (Render_Engine *)data; | ||
278 | // re->gl_context->dc = context; | ||
279 | evas_common_draw_context_add_cutout(context, x, y, w, h); | ||
280 | } | ||
281 | |||
282 | static void | ||
283 | eng_context_cutout_clear(void *data, void *context) | ||
284 | { | ||
285 | // Render_Engine *re; | ||
286 | // | ||
287 | // re = (Render_Engine *)data; | ||
288 | // re->gl_context->dc = context; | ||
289 | evas_common_draw_context_clear_cutouts(context); | ||
290 | } | ||
291 | |||
292 | static void | ||
293 | eng_rectangle_draw(void *data, void *context, void *surface, int x, int y, int w, int h) | ||
294 | { | ||
295 | Render_Engine *re; | ||
296 | |||
297 | re = (Render_Engine *)data; | ||
298 | evas_gl_common_context_target_surface_set(re->gl_context, surface); | ||
299 | re->gl_context->dc = context; | ||
300 | evas_gl_common_rect_draw(re->gl_context, x, y, w, h); | ||
301 | } | ||
302 | |||
303 | static void | ||
304 | eng_line_draw(void *data, void *context, void *surface, int x1, int y1, int x2, int y2) | ||
305 | { | ||
306 | Render_Engine *re; | ||
307 | |||
308 | re = (Render_Engine *)data; | ||
309 | evas_gl_common_context_target_surface_set(re->gl_context, surface); | ||
310 | re->gl_context->dc = context; | ||
311 | evas_gl_common_line_draw(re->gl_context, x1, y1, x2, y2); | ||
312 | } | ||
313 | |||
314 | static void * | ||
315 | eng_polygon_point_add(void *data, void *context __UNUSED__, void *polygon, int x, int y) | ||
316 | { | ||
317 | Render_Engine *re; | ||
318 | |||
319 | re = (Render_Engine *)data; | ||
320 | return evas_gl_common_poly_point_add(polygon, x, y); | ||
321 | } | ||
322 | |||
323 | static void * | ||
324 | eng_polygon_points_clear(void *data, void *context __UNUSED__, void *polygon) | ||
325 | { | ||
326 | Render_Engine *re; | ||
327 | |||
328 | re = (Render_Engine *)data; | ||
329 | return evas_gl_common_poly_points_clear(polygon); | ||
330 | } | ||
331 | |||
332 | static void | ||
333 | eng_polygon_draw(void *data, void *context, void *surface, void *polygon, int x, int y) | ||
334 | { | ||
335 | Render_Engine *re; | ||
336 | |||
337 | re = (Render_Engine *)data; | ||
338 | evas_gl_common_context_target_surface_set(re->gl_context, surface); | ||
339 | re->gl_context->dc = context; | ||
340 | evas_gl_common_poly_draw(re->gl_context, polygon, x, y); | ||
341 | } | ||
342 | |||
343 | static int | ||
344 | eng_image_alpha_get(void *data, void *image) | ||
345 | { | ||
346 | // Render_Engine *re; | ||
347 | Evas_GL_Image *im; | ||
348 | |||
349 | // re = (Render_Engine *)data; | ||
350 | if (!image) return 1; | ||
351 | im = image; | ||
352 | return im->alpha; | ||
353 | } | ||
354 | |||
355 | static int | ||
356 | eng_image_colorspace_get(void *data, void *image) | ||
357 | { | ||
358 | // Render_Engine *re; | ||
359 | Evas_GL_Image *im; | ||
360 | |||
361 | // re = (Render_Engine *)data; | ||
362 | if (!image) return EVAS_COLORSPACE_ARGB8888; | ||
363 | im = image; | ||
364 | return im->cs.space; | ||
365 | } | ||
366 | |||
367 | static void * | ||
368 | eng_image_alpha_set(void *data, void *image, int has_alpha) | ||
369 | { | ||
370 | Render_Engine *re; | ||
371 | Evas_GL_Image *im; | ||
372 | |||
373 | re = (Render_Engine *)data; | ||
374 | if (!image) return NULL; | ||
375 | im = image; | ||
376 | if (im->native.data) | ||
377 | { | ||
378 | im->alpha = has_alpha; | ||
379 | return image; | ||
380 | } | ||
381 | /* FIXME: can move to gl_common */ | ||
382 | if (im->cs.space != EVAS_COLORSPACE_ARGB8888) return im; | ||
383 | if ((has_alpha) && (im->im->cache_entry.flags.alpha)) return image; | ||
384 | else if ((!has_alpha) && (!im->im->cache_entry.flags.alpha)) return image; | ||
385 | if (im->references > 1) | ||
386 | { | ||
387 | Evas_GL_Image *im_new; | ||
388 | |||
389 | im_new = evas_gl_common_image_new_from_copied_data(im->gc, im->im->cache_entry.w, im->im->cache_entry.h, im->im->image.data, | ||
390 | eng_image_alpha_get(data, image), | ||
391 | eng_image_colorspace_get(data, image)); | ||
392 | if (!im_new) return im; | ||
393 | evas_gl_common_image_free(im); | ||
394 | im = im_new; | ||
395 | } | ||
396 | else | ||
397 | evas_gl_common_image_dirty(im, 0, 0, 0, 0); | ||
398 | im->im->cache_entry.flags.alpha = has_alpha ? 1 : 0; | ||
399 | return image; | ||
400 | } | ||
401 | |||
402 | static void * | ||
403 | eng_image_border_set(void *data, void *image, int l __UNUSED__, int r __UNUSED__, int t __UNUSED__, int b __UNUSED__) | ||
404 | { | ||
405 | // Render_Engine *re; | ||
406 | // | ||
407 | // re = (Render_Engine *)data; | ||
408 | return image; | ||
409 | } | ||
410 | |||
411 | static void | ||
412 | eng_image_border_get(void *data, void *image __UNUSED__, int *l __UNUSED__, int *r __UNUSED__, int *t __UNUSED__, int *b __UNUSED__) | ||
413 | { | ||
414 | // Render_Engine *re; | ||
415 | // | ||
416 | // re = (Render_Engine *)data; | ||
417 | } | ||
418 | |||
419 | static char * | ||
420 | eng_image_comment_get(void *data, void *image, char *key __UNUSED__) | ||
421 | { | ||
422 | // Render_Engine *re; | ||
423 | Evas_GL_Image *im; | ||
424 | |||
425 | // re = (Render_Engine *)data; | ||
426 | if (!image) return NULL; | ||
427 | im = image; | ||
428 | if (!im->im) return NULL; | ||
429 | return im->im->info.comment; | ||
430 | } | ||
431 | |||
432 | static char * | ||
433 | eng_image_format_get(void *data, void *image) | ||
434 | { | ||
435 | // Render_Engine *re; | ||
436 | Evas_GL_Image *im; | ||
437 | |||
438 | // re = (Render_Engine *)data; | ||
439 | im = image; | ||
440 | return NULL; | ||
441 | } | ||
442 | |||
443 | static void | ||
444 | eng_image_colorspace_set(void *data, void *image, int cspace) | ||
445 | { | ||
446 | Render_Engine *re; | ||
447 | Evas_GL_Image *im; | ||
448 | |||
449 | re = (Render_Engine *)data; | ||
450 | if (!image) return; | ||
451 | im = image; | ||
452 | if (im->native.data) return; | ||
453 | /* FIXME: can move to gl_common */ | ||
454 | if (im->cs.space == cspace) return; | ||
455 | evas_cache_image_colorspace(&im->im->cache_entry, cspace); | ||
456 | switch (cspace) | ||
457 | { | ||
458 | case EVAS_COLORSPACE_ARGB8888: | ||
459 | if (im->cs.data) | ||
460 | { | ||
461 | if (!im->cs.no_free) free(im->cs.data); | ||
462 | im->cs.data = NULL; | ||
463 | im->cs.no_free = 0; | ||
464 | } | ||
465 | break; | ||
466 | case EVAS_COLORSPACE_YCBCR422P601_PL: | ||
467 | case EVAS_COLORSPACE_YCBCR422P709_PL: | ||
468 | case EVAS_COLORSPACE_YCBCR422601_PL: | ||
469 | case EVAS_COLORSPACE_YCBCR420NV12601_PL: | ||
470 | case EVAS_COLORSPACE_YCBCR420TM12601_PL: | ||
471 | if (im->tex) evas_gl_common_texture_free(im->tex); | ||
472 | im->tex = NULL; | ||
473 | if (im->cs.data) | ||
474 | { | ||
475 | if (!im->cs.no_free) free(im->cs.data); | ||
476 | } | ||
477 | im->cs.data = calloc(1, im->im->cache_entry.h * sizeof(unsigned char *) * 2); | ||
478 | im->cs.no_free = 0; | ||
479 | break; | ||
480 | default: | ||
481 | abort(); | ||
482 | break; | ||
483 | } | ||
484 | im->cs.space = cspace; | ||
485 | } | ||
486 | |||
487 | ///////////////////////////////////////////////////////////////////////// | ||
488 | // | ||
489 | // | ||
490 | typedef struct _Native Native; | ||
491 | |||
492 | struct _Native | ||
493 | { | ||
494 | Evas_Native_Surface ns; | ||
495 | |||
496 | #if defined (GLES_VARIETY_S3C6410) || defined (GLES_VARIETY_SGX) | ||
497 | EGLSurface egl_surface; | ||
498 | #endif | ||
499 | }; | ||
500 | |||
501 | static void | ||
502 | _native_bind_cb(void *data, void *image) | ||
503 | { | ||
504 | } | ||
505 | |||
506 | static void | ||
507 | _native_unbind_cb(void *data, void *image) | ||
508 | { | ||
509 | } | ||
510 | |||
511 | static void | ||
512 | _native_free_cb(void *data, void *image) | ||
513 | { | ||
514 | } | ||
515 | |||
516 | static void * | ||
517 | eng_image_native_set(void *data, void *image, void *native) | ||
518 | { | ||
519 | return NULL; | ||
520 | } | ||
521 | |||
522 | static void * | ||
523 | eng_image_native_get(void *data, void *image) | ||
524 | { | ||
525 | return NULL; | ||
526 | } | ||
527 | |||
528 | // | ||
529 | // | ||
530 | ///////////////////////////////////////////////////////////////////////// | ||
531 | |||
532 | static void * | ||
533 | eng_image_load(void *data, const char *file, const char *key, int *error, Evas_Image_Load_Opts *lo) | ||
534 | { | ||
535 | Render_Engine *re; | ||
536 | |||
537 | re = (Render_Engine *)data; | ||
538 | *error = EVAS_LOAD_ERROR_NONE; | ||
539 | return evas_gl_common_image_load(re->gl_context, file, key, lo, error); | ||
540 | } | ||
541 | |||
542 | static void * | ||
543 | eng_image_new_from_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace) | ||
544 | { | ||
545 | Render_Engine *re; | ||
546 | |||
547 | re = (Render_Engine *)data; | ||
548 | return evas_gl_common_image_new_from_data(re->gl_context, w, h, image_data, alpha, cspace); | ||
549 | } | ||
550 | |||
551 | static void * | ||
552 | eng_image_new_from_copied_data(void *data, int w, int h, DATA32 *image_data, int alpha, int cspace) | ||
553 | { | ||
554 | Render_Engine *re; | ||
555 | |||
556 | re = (Render_Engine *)data; | ||
557 | return evas_gl_common_image_new_from_copied_data(re->gl_context, w, h, image_data, alpha, cspace); | ||
558 | } | ||
559 | |||
560 | static void | ||
561 | eng_image_free(void *data, void *image) | ||
562 | { | ||
563 | Render_Engine *re; | ||
564 | |||
565 | re = (Render_Engine *)data; | ||
566 | if (!image) return; | ||
567 | evas_gl_common_image_free(image); | ||
568 | } | ||
569 | |||
570 | static void | ||
571 | eng_image_size_get(void *data, void *image, int *w, int *h) | ||
572 | { | ||
573 | // Render_Engine *re; | ||
574 | // | ||
575 | // re = (Render_Engine *)data; | ||
576 | if (!image) | ||
577 | { | ||
578 | *w = 0; | ||
579 | *h = 0; | ||
580 | return; | ||
581 | } | ||
582 | if (w) *w = ((Evas_GL_Image *)image)->w; | ||
583 | if (h) *h = ((Evas_GL_Image *)image)->h; | ||
584 | } | ||
585 | |||
586 | static void * | ||
587 | eng_image_size_set(void *data, void *image, int w, int h) | ||
588 | { | ||
589 | Render_Engine *re; | ||
590 | Evas_GL_Image *im = image; | ||
591 | Evas_GL_Image *im_old; | ||
592 | |||
593 | re = (Render_Engine *)data; | ||
594 | if (!im) return NULL; | ||
595 | if (im->native.data) | ||
596 | { | ||
597 | im->w = w; | ||
598 | im->h = h; | ||
599 | return image; | ||
600 | } | ||
601 | im_old = image; | ||
602 | |||
603 | switch (eng_image_colorspace_get(data, image)) | ||
604 | { | ||
605 | case EVAS_COLORSPACE_YCBCR422P601_PL: | ||
606 | case EVAS_COLORSPACE_YCBCR422P709_PL: | ||
607 | case EVAS_COLORSPACE_YCBCR422601_PL: | ||
608 | case EVAS_COLORSPACE_YCBCR420NV12601_PL: | ||
609 | case EVAS_COLORSPACE_YCBCR420TM12601_PL: | ||
610 | w &= ~0x1; | ||
611 | break; | ||
612 | } | ||
613 | |||
614 | if ((im_old) && (im_old->im->cache_entry.w == w) && (im_old->im->cache_entry.h == h)) | ||
615 | return image; | ||
616 | if (im_old) | ||
617 | { | ||
618 | im = evas_gl_common_image_new(re->gl_context, w, h, | ||
619 | eng_image_alpha_get(data, image), | ||
620 | eng_image_colorspace_get(data, image)); | ||
621 | /* | ||
622 | evas_common_load_image_data_from_file(im_old->im); | ||
623 | if (im_old->im->image->data) | ||
624 | { | ||
625 | evas_common_blit_rectangle(im_old->im, im->im, 0, 0, w, h, 0, 0); | ||
626 | evas_common_cpu_end_opt(); | ||
627 | } | ||
628 | */ | ||
629 | evas_gl_common_image_free(im_old); | ||
630 | } | ||
631 | else | ||
632 | im = evas_gl_common_image_new(re->gl_context, w, h, 1, EVAS_COLORSPACE_ARGB8888); | ||
633 | return im; | ||
634 | } | ||
635 | |||
636 | static void * | ||
637 | eng_image_dirty_region(void *data, void *image, int x, int y, int w, int h) | ||
638 | { | ||
639 | Render_Engine *re; | ||
640 | Evas_GL_Image *im = image; | ||
641 | |||
642 | re = (Render_Engine *)data; | ||
643 | if (!image) return NULL; | ||
644 | if (im->native.data) return image; | ||
645 | evas_gl_common_image_dirty(image, x, y, w, h); | ||
646 | return image; | ||
647 | } | ||
648 | |||
649 | static void * | ||
650 | eng_image_data_get(void *data, void *image, int to_write, DATA32 **image_data, int *err) | ||
651 | { | ||
652 | Render_Engine *re; | ||
653 | Evas_GL_Image *im; | ||
654 | int error; | ||
655 | |||
656 | re = (Render_Engine *)data; | ||
657 | if (!image) | ||
658 | { | ||
659 | *image_data = NULL; | ||
660 | if (err) *err = EVAS_LOAD_ERROR_GENERIC; | ||
661 | return NULL; | ||
662 | } | ||
663 | im = image; | ||
664 | if (im->native.data) | ||
665 | { | ||
666 | *image_data = NULL; | ||
667 | if (err) *err = EVAS_LOAD_ERROR_NONE; | ||
668 | return im; | ||
669 | } | ||
670 | error = evas_cache_image_load_data(&im->im->cache_entry); | ||
671 | switch (im->cs.space) | ||
672 | { | ||
673 | case EVAS_COLORSPACE_ARGB8888: | ||
674 | if (to_write) | ||
675 | { | ||
676 | if (im->references > 1) | ||
677 | { | ||
678 | Evas_GL_Image *im_new; | ||
679 | |||
680 | im_new = evas_gl_common_image_new_from_copied_data(im->gc, im->im->cache_entry.w, im->im->cache_entry.h, im->im->image.data, | ||
681 | eng_image_alpha_get(data, image), | ||
682 | eng_image_colorspace_get(data, image)); | ||
683 | if (!im_new) | ||
684 | { | ||
685 | *image_data = NULL; | ||
686 | if (err) *err = error; | ||
687 | return im; | ||
688 | } | ||
689 | evas_gl_common_image_free(im); | ||
690 | im = im_new; | ||
691 | } | ||
692 | else | ||
693 | evas_gl_common_image_dirty(im, 0, 0, 0, 0); | ||
694 | } | ||
695 | *image_data = im->im->image.data; | ||
696 | break; | ||
697 | case EVAS_COLORSPACE_YCBCR422P601_PL: | ||
698 | case EVAS_COLORSPACE_YCBCR422P709_PL: | ||
699 | case EVAS_COLORSPACE_YCBCR422601_PL: | ||
700 | case EVAS_COLORSPACE_YCBCR420NV12601_PL: | ||
701 | case EVAS_COLORSPACE_YCBCR420TM12601_PL: | ||
702 | *image_data = im->cs.data; | ||
703 | break; | ||
704 | default: | ||
705 | abort(); | ||
706 | break; | ||
707 | } | ||
708 | if (err) *err = error; | ||
709 | return im; | ||
710 | } | ||
711 | |||
712 | static void * | ||
713 | eng_image_data_put(void *data, void *image, DATA32 *image_data) | ||
714 | { | ||
715 | Render_Engine *re; | ||
716 | Evas_GL_Image *im, *im2; | ||
717 | |||
718 | re = (Render_Engine *)data; | ||
719 | if (!image) return NULL; | ||
720 | im = image; | ||
721 | if (im->native.data) return image; | ||
722 | switch (im->cs.space) | ||
723 | { | ||
724 | case EVAS_COLORSPACE_ARGB8888: | ||
725 | if (image_data != im->im->image.data) | ||
726 | { | ||
727 | int w, h; | ||
728 | |||
729 | w = im->im->cache_entry.w; | ||
730 | h = im->im->cache_entry.h; | ||
731 | im2 = eng_image_new_from_data(data, w, h, image_data, | ||
732 | eng_image_alpha_get(data, image), | ||
733 | eng_image_colorspace_get(data, image)); | ||
734 | if (!im2) return im; | ||
735 | evas_gl_common_image_free(im); | ||
736 | im = im2; | ||
737 | } | ||
738 | break; | ||
739 | case EVAS_COLORSPACE_YCBCR422P601_PL: | ||
740 | case EVAS_COLORSPACE_YCBCR422P709_PL: | ||
741 | case EVAS_COLORSPACE_YCBCR422601_PL: | ||
742 | case EVAS_COLORSPACE_YCBCR420NV12601_PL: | ||
743 | case EVAS_COLORSPACE_YCBCR420TM12601_PL: | ||
744 | if (image_data != im->cs.data) | ||
745 | { | ||
746 | if (im->cs.data) | ||
747 | { | ||
748 | if (!im->cs.no_free) free(im->cs.data); | ||
749 | } | ||
750 | im->cs.data = image_data; | ||
751 | } | ||
752 | break; | ||
753 | default: | ||
754 | abort(); | ||
755 | break; | ||
756 | } | ||
757 | /* hmmm - but if we wrote... why bother? */ | ||
758 | evas_gl_common_image_dirty(im, 0, 0, 0, 0); | ||
759 | return im; | ||
760 | } | ||
761 | |||
762 | static void | ||
763 | eng_image_data_preload_request(void *data __UNUSED__, void *image, const void *target) | ||
764 | { | ||
765 | Evas_GL_Image *gim = image; | ||
766 | RGBA_Image *im; | ||
767 | |||
768 | if (!gim) return; | ||
769 | if (gim->native.data) return; | ||
770 | im = (RGBA_Image *)gim->im; | ||
771 | if (!im) return; | ||
772 | evas_cache_image_preload_data(&im->cache_entry, target); | ||
773 | } | ||
774 | |||
775 | static void | ||
776 | eng_image_data_preload_cancel(void *data __UNUSED__, void *image, const void *target) | ||
777 | { | ||
778 | Evas_GL_Image *gim = image; | ||
779 | RGBA_Image *im; | ||
780 | |||
781 | if (!gim) return; | ||
782 | if (gim->native.data) return; | ||
783 | im = (RGBA_Image *)gim->im; | ||
784 | if (!im) return; | ||
785 | evas_cache_image_preload_cancel(&im->cache_entry, target); | ||
786 | } | ||
787 | |||
788 | static void | ||
789 | eng_image_draw(void *data, void *context, void *surface, void *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) | ||
790 | { | ||
791 | Render_Engine *re; | ||
792 | |||
793 | re = (Render_Engine *)data; | ||
794 | if (!image) return; | ||
795 | evas_gl_common_context_target_surface_set(re->gl_context, surface); | ||
796 | re->gl_context->dc = context; | ||
797 | evas_gl_common_image_draw(re->gl_context, image, | ||
798 | src_x, src_y, src_w, src_h, | ||
799 | dst_x, dst_y, dst_w, dst_h, | ||
800 | smooth); | ||
801 | } | ||
802 | |||
803 | static void | ||
804 | eng_image_scale_hint_set(void *data __UNUSED__, void *image, int hint) | ||
805 | { | ||
806 | } | ||
807 | |||
808 | static void | ||
809 | eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level) | ||
810 | { | ||
811 | Render_Engine *re; | ||
812 | |||
813 | re = (Render_Engine *)data; | ||
814 | evas_gl_common_context_target_surface_set(re->gl_context, surface); | ||
815 | re->gl_context->dc = context; | ||
816 | evas_gl_common_image_map_draw(re->gl_context, image, npoints, p, smooth, level); | ||
817 | } | ||
818 | |||
819 | static void * | ||
820 | eng_image_map_surface_new(void *data __UNUSED__, int w, int h, int alpha) | ||
821 | { | ||
822 | Render_Engine *re; | ||
823 | |||
824 | re = (Render_Engine *)data; | ||
825 | return evas_gl_common_image_surface_new(re->gl_context, w, h, alpha); | ||
826 | } | ||
827 | |||
828 | static void | ||
829 | eng_image_map_surface_free(void *data __UNUSED__, void *surface) | ||
830 | { | ||
831 | evas_gl_common_image_free(surface); | ||
832 | } | ||
833 | |||
834 | static int | ||
835 | eng_image_scale_hint_get(void *data __UNUSED__, void *image) | ||
836 | { | ||
837 | return EVAS_IMAGE_SCALE_HINT_NONE; | ||
838 | } | ||
839 | |||
840 | static void | ||
841 | eng_font_draw(void *data, void *context, void *surface, Evas_Font_Set *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const Evas_Text_Props *intl_props) | ||
842 | { | ||
843 | Render_Engine *re; | ||
844 | |||
845 | re = (Render_Engine *)data; | ||
846 | evas_gl_common_context_target_surface_set(re->gl_context, surface); | ||
847 | re->gl_context->dc = context; | ||
848 | { | ||
849 | // FIXME: put im into context so we can free it | ||
850 | static RGBA_Image *im = NULL; | ||
851 | |||
852 | if (!im) | ||
853 | im = (RGBA_Image *)evas_cache_image_empty(evas_common_image_cache_get()); | ||
854 | im->cache_entry.w = re->w; | ||
855 | im->cache_entry.h = re->h; | ||
856 | evas_common_draw_context_font_ext_set(context, | ||
857 | re->gl_context, | ||
858 | evas_gl_font_texture_new, | ||
859 | evas_gl_font_texture_free, | ||
860 | evas_gl_font_texture_draw); | ||
861 | evas_common_font_draw(im, context, (RGBA_Font *) font, x, y, | ||
862 | intl_props); | ||
863 | evas_common_draw_context_font_ext_set(context, | ||
864 | NULL, | ||
865 | NULL, | ||
866 | NULL, | ||
867 | NULL); | ||
868 | } | ||
869 | } | ||
870 | |||
871 | static Eina_Bool | ||
872 | eng_canvas_alpha_get(void *data __UNUSED__, void *info __UNUSED__) | ||
873 | { | ||
874 | // FIXME: support ARGB gl targets!!! | ||
875 | return EINA_FALSE; | ||
876 | } | ||
877 | |||
878 | static int | ||
879 | eng_image_load_error_get(void *data __UNUSED__, void *image) | ||
880 | { | ||
881 | Evas_GL_Image *im; | ||
882 | |||
883 | if (!image) return EVAS_LOAD_ERROR_NONE; | ||
884 | im = image; | ||
885 | return im->im->cache_entry.load_error; | ||
886 | } | ||
887 | |||
888 | |||
889 | static int | ||
890 | module_open(Evas_Module *em) | ||
891 | { | ||
892 | if (!em) return 0; | ||
893 | if (!evas_gl_common_module_open()) return 0; | ||
894 | /* get whatever engine module we inherit from */ | ||
895 | if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0; | ||
896 | if (_evas_engine_GL_SDL_log_dom < 0) | ||
897 | _evas_engine_GL_SDL_log_dom = eina_log_domain_register | ||
898 | ("evas-gl_sdl", EVAS_DEFAULT_LOG_COLOR); | ||
899 | if (_evas_engine_GL_SDL_log_dom < 0) | ||
900 | { | ||
901 | EINA_LOG_ERR("Can not create a module log domain."); | ||
902 | return 0; | ||
903 | } | ||
904 | /* store it for later use */ | ||
905 | func = pfunc; | ||
906 | /* now to override methods */ | ||
907 | #define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_) | ||
908 | ORD(info); | ||
909 | ORD(info_free); | ||
910 | ORD(setup); | ||
911 | ORD(canvas_alpha_get); | ||
912 | ORD(output_free); | ||
913 | ORD(output_resize); | ||
914 | ORD(output_tile_size_set); | ||
915 | ORD(output_redraws_rect_add); | ||
916 | ORD(output_redraws_rect_del); | ||
917 | ORD(output_redraws_clear); | ||
918 | ORD(output_redraws_next_update_get); | ||
919 | ORD(output_redraws_next_update_push); | ||
920 | ORD(context_cutout_add); | ||
921 | ORD(context_cutout_clear); | ||
922 | ORD(output_flush); | ||
923 | ORD(output_idle_flush); | ||
924 | ORD(output_dump); | ||
925 | ORD(rectangle_draw); | ||
926 | ORD(line_draw); | ||
927 | ORD(polygon_point_add); | ||
928 | ORD(polygon_points_clear); | ||
929 | ORD(polygon_draw); | ||
930 | |||
931 | ORD(image_load); | ||
932 | ORD(image_new_from_data); | ||
933 | ORD(image_new_from_copied_data); | ||
934 | ORD(image_free); | ||
935 | ORD(image_size_get); | ||
936 | ORD(image_size_set); | ||
937 | ORD(image_dirty_region); | ||
938 | ORD(image_data_get); | ||
939 | ORD(image_data_put); | ||
940 | ORD(image_data_preload_request); | ||
941 | ORD(image_data_preload_cancel); | ||
942 | ORD(image_alpha_set); | ||
943 | ORD(image_alpha_get); | ||
944 | ORD(image_border_set); | ||
945 | ORD(image_border_get); | ||
946 | ORD(image_draw); | ||
947 | ORD(image_comment_get); | ||
948 | ORD(image_format_get); | ||
949 | ORD(image_colorspace_set); | ||
950 | ORD(image_colorspace_get); | ||
951 | ORD(image_native_set); | ||
952 | ORD(image_native_get); | ||
953 | #if 0 // filtering disabled | ||
954 | // ORD(image_draw_filtered); | ||
955 | // ORD(image_filtered_get); | ||
956 | // ORD(image_filtered_save); | ||
957 | // ORD(image_filtered_free); | ||
958 | #endif | ||
959 | ORD(font_draw); | ||
960 | |||
961 | ORD(image_scale_hint_set); | ||
962 | ORD(image_scale_hint_get); | ||
963 | |||
964 | ORD(image_map_draw); | ||
965 | ORD(image_map_surface_new); | ||
966 | ORD(image_map_surface_free); | ||
967 | |||
968 | // ORD(image_content_hint_set); | ||
969 | // ORD(image_content_hint_get); | ||
970 | |||
971 | // ORD(image_cache_flush); | ||
972 | // ORD(image_cache_set); | ||
973 | // ORD(image_cache_get); | ||
974 | |||
975 | // ORD(gl_surface_create); | ||
976 | // ORD(gl_surface_destroy); | ||
977 | // ORD(gl_context_create); | ||
978 | // ORD(gl_context_destroy); | ||
979 | // ORD(gl_make_current); | ||
980 | // ORD(gl_proc_address_get); | ||
981 | // ORD(gl_native_surface_get); | ||
982 | |||
983 | // ORD(gl_api_get); | ||
984 | |||
985 | ORD(image_load_error_get); | ||
986 | |||
987 | /* now advertise out own api */ | ||
988 | em->functions = (void *)(&func); | ||
989 | return 1; | ||
990 | } | ||
991 | |||
992 | static void | ||
993 | module_close(Evas_Module *em) | ||
994 | { | ||
995 | eina_log_domain_unregister(_evas_engine_GL_SDL_log_dom); | ||
996 | evas_gl_common_module_close(); | ||
997 | } | ||
998 | |||
999 | static Evas_Module_Api evas_modapi = | ||
1000 | { | ||
1001 | EVAS_MODULE_API_VERSION, | ||
1002 | "gl_sdl", | ||
1003 | "none", | ||
1004 | { | ||
1005 | module_open, | ||
1006 | module_close | ||
1007 | } | ||
1008 | }; | ||
1009 | |||
1010 | EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_ENGINE, engine, gl_sdl); | ||
1011 | |||
1012 | #ifndef EVAS_STATIC_BUILD_GL_SDL | ||
1013 | EVAS_EINA_MODULE_DEFINE(engine, gl_sdl); | ||
1014 | #endif | ||
1015 | |||
1016 | static void* | ||
1017 | _sdl_output_setup (int w, int h, int fullscreen, int noframe) | ||
1018 | { | ||
1019 | Render_Engine *re = calloc(1, sizeof(Render_Engine)); | ||
1020 | SDL_Surface *surface; | ||
1021 | int context_attrs[3]; | ||
1022 | int config_attrs[20]; | ||
1023 | int major_version, minor_version; | ||
1024 | int num_config; | ||
1025 | |||
1026 | /* if we haven't initialized - init (automatic abort if already done) */ | ||
1027 | evas_common_cpu_init(); | ||
1028 | evas_common_blend_init(); | ||
1029 | evas_common_image_init(); | ||
1030 | evas_common_convert_init(); | ||
1031 | evas_common_scale_init(); | ||
1032 | evas_common_rectangle_init(); | ||
1033 | evas_common_polygon_init(); | ||
1034 | evas_common_line_init(); | ||
1035 | evas_common_font_init(); | ||
1036 | evas_common_draw_init(); | ||
1037 | evas_common_tilebuf_init(); | ||
1038 | |||
1039 | if (w <= 0) w = 640; | ||
1040 | if (h <= 0) h = 480; | ||
1041 | |||
1042 | /* GL Initialization */ | ||
1043 | #ifdef HAVE_SDL_GL_CONTEXT_VERSION | ||
1044 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); | ||
1045 | SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); | ||
1046 | #endif | ||
1047 | SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); | ||
1048 | SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); | ||
1049 | SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); | ||
1050 | SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); | ||
1051 | SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); | ||
1052 | SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0); | ||
1053 | |||
1054 | surface = SDL_SetVideoMode(w, h, 32, EVAS_SDL_GL_FLAG | ||
1055 | | (fullscreen ? SDL_FULLSCREEN : 0) | ||
1056 | | (noframe ? SDL_NOFRAME : 0)); | ||
1057 | |||
1058 | if (!surface) | ||
1059 | { | ||
1060 | CRIT("SDL_SetVideoMode [ %i x %i x 32 ] failed. %s", w, h, SDL_GetError()); | ||
1061 | SDL_Quit(); | ||
1062 | exit(-1); | ||
1063 | } | ||
1064 | |||
1065 | INF("Screen Depth: %d, Vendor: '%s', Renderer: '%s', Version: '%s'", SDL_GetVideoSurface()->format->BitsPerPixel, glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION)); | ||
1066 | |||
1067 | re->gl_context = evas_gl_common_context_new(); | ||
1068 | if (!re->gl_context) | ||
1069 | { | ||
1070 | free(re); | ||
1071 | return NULL; | ||
1072 | } | ||
1073 | evas_gl_common_context_use(re->gl_context); | ||
1074 | evas_gl_common_context_resize(re->gl_context, w, h, re->gl_context->rot); | ||
1075 | |||
1076 | /* End GL Initialization */ | ||
1077 | re->w = w; | ||
1078 | re->h = h; | ||
1079 | return re; | ||
1080 | } | ||
1081 | |||