1 /***************************************************************************
2                           gui_render.cpp  -  description
3 
4 	The final render a frame. The external interface is the same
5 	whatever the mean (RGB/YUV/Xv)
6                              -------------------
7     begin                : Thu Jan 3 2002
8     copyright            : (C) 2002 by mean
9     email                : fixounet@free.fr
10  ***************************************************************************/
11 
12 /***************************************************************************
13  *                                                                         *
14  *   This program is free software; you can redistribute it and/or modify  *
15  *   it under the terms of the GNU General Public License as published by  *
16  *   the Free Software Foundation; either version 2 of the License, or     *
17  *   (at your option) any later version.                                   *
18  *                                                                         *
19  ***************************************************************************/
20 
21 #include "config.h"
22 #include "ADM_default.h"
23 #include "DIA_coreToolkit.h"
24 #include "GUI_render.h"
25 #include "GUI_renderInternal.h"
26 #include "GUI_accelRender.h"
27 #include "GUI_nullRender.h"
28 #include "prefs.h"
29 
30 
31 extern VideoRenderBase *spawnSimpleRender();
32 
33 #ifdef USE_XV
34 extern VideoRenderBase *spawnXvRender();
35 #endif
36 
37 #ifdef USE_SDL
38 extern VideoRenderBase *spawnSdlRender();
39 #endif
40 
41 #ifdef USE_VDPAU
42 extern VideoRenderBase *spawnVDPAURender();
43 #endif
44 
45 #ifdef USE_LIBVA
46 extern VideoRenderBase *spawnLIBVARender();
47 #endif
48 
49 #if defined (USE_OPENGL)
50 extern VideoRenderBase *RenderSpawnQtGl(void);
51 #endif
52 #if defined (USE_DXVA2)
53 extern VideoRenderBase *RenderSpawnDxva2(void);
54 #endif
55 #include "ADM_colorspace.h"
56 #include "DIA_uiTypes.h"
57 
58 //_____________________________________
59 //_____________________________________
60 static VideoRenderBase *renderer=NULL;
61 static uint8_t         *accelSurface=NULL;
62 static bool             spawnRenderer(void);
63 //_______________________________________
64 
65 static void         *draw=NULL;
66 static uint32_t     phyW=0,phyH=0; /* physical window size */
67 static float        lastZoom=ZOOM_1_1;
68 static uint8_t      _lock=0;
69 
70 static const UI_FUNCTIONS_T *HookFunc=NULL;
71 static bool  enableDraw=true;
72 
73 refreshSB refreshCallback=NULL;
74 /**
75  * \fn renderGetName
76  * @param name
77  */
renderGetName(std::string & name)78 void renderGetName(std::string &name)
79 {
80     if(!renderer) name=std::string("None");
81     else name=std::string(renderer->getName());
82 }
83 
84 /**
85     \fn renderHookRefreshRequest
86     \brief Hook the callback when a renderer requests a full redraw
87 */
renderHookRefreshRequest(refreshSB cb)88 bool renderHookRefreshRequest(refreshSB cb)
89 {
90     refreshCallback=cb;
91     return true;
92 }
93 /**
94  *      \fn ADM_renderLibInit
95  *      \brief Initialize the renderlib with the needed external functions
96  *
97  */
ADM_renderLibInit(const UI_FUNCTIONS_T * funcs)98 uint8_t ADM_renderLibInit(const UI_FUNCTIONS_T *funcs)
99   {
100     HookFunc=funcs;
101     ADM_assert(funcs->apiVersion==ADM_RENDER_API_VERSION_NUMBER);
102     return 1;
103   }
104 //**************************************
105 //**************************************
106 //**************************************
107 #define RENDER_CHECK(x) {ADM_assert(HookFunc);ADM_assert(HookFunc->x);}
MUI_getWindowInfo(void * draw,GUI_WindowInfo * xinfo)108 void MUI_getWindowInfo(void *draw, GUI_WindowInfo *xinfo)
109 {
110   RENDER_CHECK(UI_getWindowInfo);
111   HookFunc->UI_getWindowInfo(draw, xinfo);
112 }
MUI_updateDrawWindowSize(void * win,uint32_t w,uint32_t h)113 static void MUI_updateDrawWindowSize(void *win,uint32_t w,uint32_t h)
114 {
115    RENDER_CHECK(UI_updateDrawWindowSize);
116    HookFunc->UI_updateDrawWindowSize(win,w,h);
117 }
MUI_getPreferredRender(void)118 static   ADM_RENDER_TYPE MUI_getPreferredRender(void)
119 {
120   RENDER_CHECK(UI_getPreferredRender);
121   return HookFunc->UI_getPreferredRender();
122 }
MUI_getDrawWidget(void)123 void *MUI_getDrawWidget(void)
124 {
125   RENDER_CHECK(UI_getDrawWidget);
126   return HookFunc->UI_getDrawWidget();
127 }
128 
129 //**************************************
130 //**************************************
131 //**************************************
132 
133 /**
134 	Render init, initialize internals. Constuctor like function
135 
136 */
renderInit(void)137 uint8_t renderInit( void )
138 {
139     draw=MUI_getDrawWidget(  );
140     enableDraw=false;
141     return 1;
142 }
143 
renderDestroy(void)144 void renderDestroy(void)
145 {
146     ADM_info("Cleaning up Render\n");
147     if(renderer)
148     {
149         renderer->stop();
150         delete renderer;
151         renderer=NULL;
152     }
153     enableDraw=false;
154 }
155 
156 /**
157     \fn renderLock
158     \brief Take the weak lock (i.e. not threadsafe)
159 */
renderLock(void)160 uint8_t renderLock(void)
161 {
162   ADM_assert(!_lock);
163   _lock=1;
164   return 1;
165 }
renderUnlock(void)166 uint8_t renderUnlock(void)
167 {
168   ADM_assert(_lock);
169   _lock=0;
170   return 1;
171 }
172 
173 /**
174 	Warn the renderer that the display size is changing
175 
176 */
177 //----------------------------------------
renderDisplayResize(uint32_t w,uint32_t h,float zoom)178 uint8_t renderDisplayResize(uint32_t w, uint32_t h, float zoom)
179 {
180         bool create=false;
181         enableDraw=false;
182         ADM_info("Render to %" PRIu32"x%" PRIu32" zoom=%.4f, old one =%d x %d, zoom=%.4f, renderer=%p\n",w,h,zoom,phyW,phyH,lastZoom,renderer);
183         // Check if something has changed...
184 
185 
186         if(renderer && w==phyW && h==phyH && zoom==lastZoom)
187         {
188             ADM_info("          No change, nothing to do\n");
189             return true;
190         }
191 
192         if(!renderer || (w!=phyW || h!=phyH))
193         {
194             if(renderer)
195             {
196                 renderer->stop();
197                 delete renderer;
198                 renderer=NULL;
199             }
200             phyW=w;
201             phyH=h;
202             lastZoom=zoom;
203             if(w && h)
204                 spawnRenderer();
205         }else // only zoom changed
206         {
207               renderer->changeZoom(zoom);
208         }
209          // Resize widget to be the same as input after zoom
210          lastZoom=zoom;
211         MUI_updateDrawWindowSize(draw,(uint32_t)((float)w*zoom),(uint32_t)((float)h*zoom));
212         if(w && h)
213             renderCompleteRedrawRequest();
214         UI_purge();
215         return 1;
216 }
217 /**
218 	Update the image and render it
219 	The width and hiehgt must NOT have changed
220 
221 */
222 //----------------------------------------
renderUpdateImage(ADMImage * image)223 uint8_t renderUpdateImage(ADMImage *image)
224 {
225     if(!renderer)
226     {
227         ADM_warning("Render update image without renderer\n");
228         return 0;
229     }
230     ADM_assert(!_lock);
231     enableDraw=true;
232     if(renderer->getPreferedImage()!=image->refType)
233             image->hwDownloadFromRef();
234 
235     renderer->displayImage(image);
236     return 1;
237 }
238 /**
239 	Refresh the image from internal buffer / last image
240 	Used for example as call back for X11 events
241 
242 */
243 //_______________________________________________
renderRefresh(void)244 uint8_t renderRefresh(void)
245 {
246       if(_lock) return 1;
247       if(enableDraw==false) return true;
248       if(renderer)
249         renderer->refresh();
250       return 1;
251 }
252 /**
253     \fn renderCompleteRedrawRequest
254     \brief ask the *caller* to redraw, whereas expose/refresh asks the renderer to refresh
255 */
renderCompleteRedrawRequest(void)256 bool renderCompleteRedrawRequest(void)
257 {
258     ADM_info("RedrawRequest\n");
259     if(enableDraw==false) return true;
260     if(refreshCallback)
261         refreshCallback();
262     return true;
263 }
264 /**
265     \fn renderExpose
266 */
renderExpose(void)267 uint8_t renderExpose(void)
268 {
269     if(enableDraw==false) return true;
270     renderRefresh();
271     return 1;
272 }
273 /**
274     \fn spawnRenderer
275     \brief Create renderer according to prefs
276 */
277 #if ADM_UI_TYPE_BUILD == ADM_UI_CLI
278 
spawnRenderer(void)279 bool spawnRenderer(void)
280 {
281     renderer=new nullRender();
282     return true;
283 }
284 #else
285 
286 #define TRY_RENDERER_INTERNAL(clss,create,name) \
287                 renderer=create clss(); \
288                 r=renderer->init(&xinfo,phyW,phyH,lastZoom); \
289                 if(!r) \
290                 { \
291                     delete renderer; \
292                     renderer=NULL; \
293                     ADM_warning(name" init failed\n"); \
294                 }\
295                 else \
296                 { \
297                     ADM_info(name" init ok\n"); \
298                 }
299 //#define TRY_RENDERER_CLASS(clss,name) TRY_RENDERER_INTERNAL(clss,new,name)
300 //#define TRY_RENDERER_FUNC(func,name) TRY_RENDERER_INTERNAL(func,,name)
301 #define TRY_RENDERER_SPAWN(spawn,name)  TRY_RENDERER_INTERNAL(spawn,,name)
302 /**
303  *
304  * @param renderName
305  * @return
306  */
spawnRenderer(void)307 bool spawnRenderer(void)
308 {
309         int prefRenderer=MUI_getPreferredRender();
310         bool r=false;
311 
312         GUI_WindowInfo xinfo;
313         MUI_getWindowInfo(draw, &xinfo);
314         switch(prefRenderer)
315         {
316 #if defined(USE_DXVA2)
317        case RENDER_DXVA2:
318             {
319                 TRY_RENDERER_SPAWN(RenderSpawnDxva2,"Dxva2");
320                 break;
321             }
322 #endif
323 #if defined(USE_OPENGL)
324        case RENDER_QTOPENGL:
325             {
326                 bool hasOpenGl=false;
327                 prefs->get(FEATURES_ENABLE_OPENGL,&hasOpenGl);
328                 if(!hasOpenGl)
329                 {
330                     ADM_warning("OpenGl is disabled\n");
331                     renderer=NULL;
332                 }else
333                 {
334                     TRY_RENDERER_SPAWN(RenderSpawnQtGl,"QtGl");
335                 }
336                 break;
337             }
338 #endif
339 
340 #if defined(USE_VDPAU)
341        case RENDER_VDPAU:
342                 TRY_RENDERER_SPAWN(spawnVDPAURender,"VDPAU")
343                 break;
344 #endif
345 #if defined(USE_LIBVA)
346        case RENDER_LIBVA:
347                 TRY_RENDERER_SPAWN(spawnLIBVARender,"LIBVA")
348                 break;
349 #endif
350 
351 #if defined(USE_XV)
352        case RENDER_XV:
353                 TRY_RENDERER_SPAWN(spawnXvRender,"Xv")
354                 break;
355 #endif
356 
357 #if  defined(USE_SDL)
358     case RENDER_SDL:
359                 TRY_RENDERER_SPAWN(spawnSdlRender,"SDL")
360                 break;
361 #endif
362         }
363         if(!renderer)
364         {
365             TRY_RENDERER_SPAWN(spawnSimpleRender,"simpleRenderer");
366             ADM_assert(renderer);
367         }
368         return true;
369 }
370 #endif
371 
372 /**
373     \fn
374 */
renderStartPlaying(void)375 uint8_t renderStartPlaying( void )
376 {
377 
378 	return 1;
379 }
380 
381 /**
382     \fn renderStopPlaying
383 */
renderStopPlaying(void)384 uint8_t renderStopPlaying( void )
385 {
386 
387       return true;
388 }
389 /**
390     \fn renderExposeEventFromUI
391     \brief retrurn true if UI(gtk/qt) should handle redraw
392 */
renderExposeEventFromUI(void)393 bool    renderExposeEventFromUI(void)
394 {
395     if(!renderer) return true;
396     if(renderer->usingUIRedraw()==true) return true;
397     renderer->refresh();
398     return false;
399 
400 }
401 /**
402     \fn renderGetPreferedImageFormat
403     \brief get the prefered hw accelerated image format (NONE,VDPAU,...)
404 */
renderGetPreferedImageFormat(void)405 ADM_HW_IMAGE renderGetPreferedImageFormat(void)
406 {
407     if(!renderer) return ADM_HW_NONE;
408     return renderer->getPreferedImage();
409 }
410 
411 //***************************************
412 /**
413     \fn calcDisplayFromZoom
414 */
calcDisplayFromZoom(float zoom)415 bool VideoRenderBase::calcDisplayFromZoom(float zoom)
416 {
417     displayWidth=(uint32_t)((float)imageWidth * zoom);
418     displayHeight=(uint32_t)((float)imageHeight * zoom);
419     return true;
420 }
421 
422 /**
423     \fn baseInit
424 */
baseInit(uint32_t w,uint32_t h,float zoom)425 bool VideoRenderBase::baseInit(uint32_t w, uint32_t h, float zoom)
426 {
427         imageWidth=w;
428         imageHeight=h;
429         currentZoom=zoom;
430         calcDisplayFromZoom(zoom);
431         return true;
432 }
433 
434 /**
435  * \fn renderClearInstance
436  * \brief warn render that the renderer has been deleted by low level (window manager)
437  * Would be prettier to do it with refCounting
438  * @return
439  */
renderClearInstance(void)440 bool renderClearInstance(void)
441 {
442     renderer=NULL;
443     return true;
444 }
445 
446 //EOF
447