Merge pull request #3274 from FernetMenta/aefixes
[vuplus_xbmc] / xbmc / cores / VideoRenderers / LinuxRendererGLES.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20 //#define DEBUG_VERBOSE 1
21
22 #include "system.h"
23 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
24   #include "config.h"
25 #endif
26
27 #if HAS_GLES == 2
28 #include "system_gl.h"
29
30 #include <locale.h>
31 #include "guilib/MatrixGLES.h"
32 #include "LinuxRendererGLES.h"
33 #include "utils/fastmemcpy.h"
34 #include "utils/MathUtils.h"
35 #include "utils/GLUtils.h"
36 #include "settings/AdvancedSettings.h"
37 #include "settings/DisplaySettings.h"
38 #include "settings/MediaSettings.h"
39 #include "settings/Settings.h"
40 #include "guilib/FrameBufferObject.h"
41 #include "VideoShaders/YUV2RGBShader.h"
42 #include "VideoShaders/VideoFilterShader.h"
43 #include "windowing/WindowingFactory.h"
44 #include "dialogs/GUIDialogKaiToast.h"
45 #include "guilib/Texture.h"
46 #include "lib/DllSwScale.h"
47 #include "../dvdplayer/DVDCodecs/Video/OpenMaxVideo.h"
48 #include "threads/SingleLock.h"
49 #include "RenderCapture.h"
50 #include "RenderFormats.h"
51 #include "xbmc/Application.h"
52 #include "cores/IPlayer.h"
53
54 #if defined(__ARM_NEON__)
55 #include "yuv2rgb.neon.h"
56 #include "utils/CPUInfo.h"
57 #endif
58 #ifdef HAVE_VIDEOTOOLBOXDECODER
59 #include "DVDCodecs/Video/DVDVideoCodecVideoToolBox.h"
60 #include <CoreVideo/CoreVideo.h>
61 #endif
62 #ifdef TARGET_DARWIN_IOS
63 #include "osx/DarwinUtils.h"
64 #endif
65 #if defined(HAS_LIBSTAGEFRIGHT)
66 #include <EGL/egl.h>
67 #include <EGL/eglext.h>
68 #include "windowing/egl/EGLWrapper.h"
69 #include "android/activity/XBMCApp.h"
70 #include "DVDCodecs/Video/StageFrightVideo.h"
71
72 // EGL extension functions
73 static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
74 static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
75 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
76 #endif
77
78 using namespace Shaders;
79
80 CLinuxRendererGLES::YUVBUFFER::YUVBUFFER()
81 {
82   memset(&fields, 0, sizeof(fields));
83   memset(&image , 0, sizeof(image));
84   flipindex = 0;
85 #ifdef HAVE_LIBOPENMAX
86   openMaxBuffer = NULL;
87 #endif
88 #ifdef HAVE_VIDEOTOOLBOXDECODER
89   cvBufferRef = NULL;
90 #endif
91 #ifdef HAS_LIBSTAGEFRIGHT
92   stf = NULL;
93   eglimg = EGL_NO_IMAGE_KHR;
94 #endif
95 }
96
97 CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER()
98 {
99 }
100
101 CLinuxRendererGLES::CLinuxRendererGLES()
102 {
103   m_textureTarget = GL_TEXTURE_2D;
104
105   m_renderMethod = RENDER_GLSL;
106   m_oldRenderMethod = m_renderMethod;
107   m_renderQuality = RQ_SINGLEPASS;
108   m_iFlags = 0;
109   m_format = RENDER_FMT_NONE;
110
111   m_iYV12RenderBuffer = 0;
112   m_flipindex = 0;
113   m_currentField = FIELD_FULL;
114   m_reloadShaders = 0;
115   m_pYUVShader = NULL;
116   m_pVideoFilterShader = NULL;
117   m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
118   m_scalingMethodGui = (ESCALINGMETHOD)-1;
119
120   // default texture handlers to YUV
121   m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
122   m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
123   m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
124
125   m_rgbBuffer = NULL;
126   m_rgbBufferSize = 0;
127
128   m_dllSwScale = new DllSwScale;
129   m_sw_context = NULL;
130   m_NumYV12Buffers = 0;
131   m_iLastRenderBuffer = 0;
132   m_bConfigured = false;
133   m_bValidated = false;
134   m_bImageReady = false;
135   m_StrictBinding = false;
136   m_clearColour = 0.0f;
137
138 #ifdef HAS_LIBSTAGEFRIGHT
139   if (!eglCreateImageKHR)
140     eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglCreateImageKHR");
141   if (!eglDestroyImageKHR)
142     eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglDestroyImageKHR");
143   if (!glEGLImageTargetTexture2DOES)
144     glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES");
145 #endif
146 }
147
148 CLinuxRendererGLES::~CLinuxRendererGLES()
149 {
150   UnInit();
151
152   if (m_rgbBuffer != NULL) {
153     delete [] m_rgbBuffer;
154     m_rgbBuffer = NULL;
155   }
156
157   if (m_pYUVShader)
158   {
159     m_pYUVShader->Free();
160     delete m_pYUVShader;
161     m_pYUVShader = NULL;
162   }
163
164   delete m_dllSwScale;
165 }
166
167 bool CLinuxRendererGLES::ValidateRenderTarget()
168 {
169   if (!m_bValidated)
170   {
171     CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
172
173      // create the yuv textures
174     LoadShaders();
175
176     for (int i = 0 ; i < m_NumYV12Buffers ; i++)
177       (this->*m_textureCreate)(i);
178
179     m_bValidated = true;
180     return true;
181   }
182   return false;
183 }
184
185 bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
186 {
187   m_sourceWidth = width;
188   m_sourceHeight = height;
189   m_renderOrientation = orientation;
190
191   // Save the flags.
192   m_iFlags = flags;
193   m_format = format;
194
195   // Calculate the input frame aspect ratio.
196   CalculateFrameAspectRatio(d_width, d_height);
197   ChooseBestResolution(fps);
198   SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
199   ManageDisplay();
200
201   m_bConfigured = true;
202   m_bImageReady = false;
203   m_scalingMethodGui = (ESCALINGMETHOD)-1;
204
205   // Ensure that textures are recreated and rendering starts only after the 1st
206   // frame is loaded after every call to Configure().
207   m_bValidated = false;
208
209   for (int i = 0 ; i<m_NumYV12Buffers ; i++)
210     m_buffers[i].image.flags = 0;
211
212   m_iLastRenderBuffer = -1;
213
214   m_RenderUpdateCallBackFn = NULL;
215   m_RenderUpdateCallBackCtx = NULL;
216   if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer())
217   {
218     m_renderFeatures.clear();
219     m_scalingMethods.clear();
220     m_deinterlaceModes.clear();
221     m_deinterlaceMethods.clear();
222
223     if (m_RenderFeaturesCallBackFn)
224     {
225       (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures);
226       // after setting up m_renderFeatures, we are done with the callback
227       m_RenderFeaturesCallBackFn = NULL;
228       m_RenderFeaturesCallBackCtx = NULL;
229     }
230     g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures);
231     g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods);
232     g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes);
233     g_application.m_pPlayer->GetScalingMethods(m_scalingMethods);
234   }
235
236   return true;
237 }
238
239 int CLinuxRendererGLES::NextYV12Texture()
240 {
241   return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
242 }
243
244 int CLinuxRendererGLES::GetImage(YV12Image *image, int source, bool readonly)
245 {
246   if (!image) return -1;
247   if (!m_bValidated) return -1;
248
249   /* take next available buffer */
250   if( source == AUTOSOURCE )
251    source = NextYV12Texture();
252
253   if ( m_renderMethod & RENDER_OMXEGL )
254   {
255     return source;
256   }
257 #ifdef HAS_LIBSTAGEFRIGHT
258   if ( m_renderMethod & RENDER_EGLIMG )
259   {
260     return source;
261   }
262 #endif
263 #ifdef HAVE_VIDEOTOOLBOXDECODER
264   if (m_renderMethod & RENDER_CVREF )
265   {
266     return source;
267   }
268 #endif
269
270   YV12Image &im = m_buffers[source].image;
271
272   if ((im.flags&(~IMAGE_FLAG_READY)) != 0)
273   {
274      CLog::Log(LOGDEBUG, "CLinuxRenderer::GetImage - request image but none to give");
275      return -1;
276   }
277
278   if( readonly )
279     im.flags |= IMAGE_FLAG_READING;
280   else
281     im.flags |= IMAGE_FLAG_WRITING;
282
283   // copy the image - should be operator of YV12Image
284   for (int p=0;p<MAX_PLANES;p++)
285   {
286     image->plane[p]  = im.plane[p];
287     image->stride[p] = im.stride[p];
288   }
289   image->width    = im.width;
290   image->height   = im.height;
291   image->flags    = im.flags;
292   image->cshift_x = im.cshift_x;
293   image->cshift_y = im.cshift_y;
294   image->bpp      = 1;
295
296   return source;
297 }
298
299 void CLinuxRendererGLES::ReleaseImage(int source, bool preserve)
300 {
301   YV12Image &im = m_buffers[source].image;
302
303   im.flags &= ~IMAGE_FLAG_INUSE;
304   im.flags |= IMAGE_FLAG_READY;
305   /* if image should be preserved reserve it so it's not auto seleceted */
306
307   if( preserve )
308     im.flags |= IMAGE_FLAG_RESERVED;
309
310   m_bImageReady = true;
311 }
312
313 void CLinuxRendererGLES::CalculateTextureSourceRects(int source, int num_planes)
314 {
315   YUVBUFFER& buf    =  m_buffers[source];
316   YV12Image* im     = &buf.image;
317   YUVFIELDS& fields =  buf.fields;
318
319   // calculate the source rectangle
320   for(int field = 0; field < 3; field++)
321   {
322     for(int plane = 0; plane < num_planes; plane++)
323     {
324       YUVPLANE& p = fields[field][plane];
325
326       p.rect = m_sourceRect;
327       p.width  = im->width;
328       p.height = im->height;
329
330       if(field != FIELD_FULL)
331       {
332         /* correct for field offsets and chroma offsets */
333         float offset_y = 0.5;
334         if(plane != 0)
335           offset_y += 0.5;
336         if(field == FIELD_BOT)
337           offset_y *= -1;
338
339         p.rect.y1 += offset_y;
340         p.rect.y2 += offset_y;
341
342         /* half the height if this is a field */
343         p.height  *= 0.5f;
344         p.rect.y1 *= 0.5f;
345         p.rect.y2 *= 0.5f;
346       }
347
348       if(plane != 0)
349       {
350         p.width   /= 1 << im->cshift_x;
351         p.height  /= 1 << im->cshift_y;
352
353         p.rect.x1 /= 1 << im->cshift_x;
354         p.rect.x2 /= 1 << im->cshift_x;
355         p.rect.y1 /= 1 << im->cshift_y;
356         p.rect.y2 /= 1 << im->cshift_y;
357       }
358
359       if (m_textureTarget == GL_TEXTURE_2D)
360       {
361         p.height  /= p.texheight;
362         p.rect.y1 /= p.texheight;
363         p.rect.y2 /= p.texheight;
364         p.width   /= p.texwidth;
365         p.rect.x1 /= p.texwidth;
366         p.rect.x2 /= p.texwidth;
367       }
368     }
369   }
370 }
371
372 void CLinuxRendererGLES::LoadPlane( YUVPLANE& plane, int type, unsigned flipindex
373                                 , unsigned width, unsigned height
374                                 , unsigned int stride, void* data )
375 {
376   if(plane.flipindex == flipindex)
377     return;
378
379   const GLvoid *pixelData = data;
380
381   int bps = glFormatElementByteCount(type);
382
383   glBindTexture(m_textureTarget, plane.id);
384
385   // OpenGL ES does not support strided texture input.
386   if(stride != width * bps)
387   {
388     unsigned char* src = (unsigned char*)data;
389     for (unsigned int y = 0; y < height;++y, src += stride)
390       glTexSubImage2D(m_textureTarget, 0, 0, y, width, 1, type, GL_UNSIGNED_BYTE, src);
391   } else {
392     glTexSubImage2D(m_textureTarget, 0, 0, 0, width, height, type, GL_UNSIGNED_BYTE, pixelData);
393   }
394
395   /* check if we need to load any border pixels */
396   if(height < plane.texheight)
397     glTexSubImage2D( m_textureTarget, 0
398                    , 0, height, width, 1
399                    , type, GL_UNSIGNED_BYTE
400                    , (unsigned char*)pixelData + stride * (height-1));
401
402   if(width  < plane.texwidth)
403     glTexSubImage2D( m_textureTarget, 0
404                    , width, 0, 1, height
405                    , type, GL_UNSIGNED_BYTE
406                    , (unsigned char*)pixelData + bps * (width-1));
407
408   glBindTexture(m_textureTarget, 0);
409
410   plane.flipindex = flipindex;
411 }
412
413 void CLinuxRendererGLES::Reset()
414 {
415   for(int i=0; i<m_NumYV12Buffers; i++)
416   {
417     /* reset all image flags, this will cleanup textures later */
418     m_buffers[i].image.flags = 0;
419   }
420 }
421
422 void CLinuxRendererGLES::Update()
423 {
424   if (!m_bConfigured) return;
425   ManageDisplay();
426 }
427
428 void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
429 {
430   if (!m_bConfigured) return;
431
432   // if its first pass, just init textures and return
433   if (ValidateRenderTarget())
434     return;
435
436   if (m_renderMethod & RENDER_BYPASS)
437   {
438     ManageDisplay();
439     // if running bypass, then the player might need the src/dst rects
440     // for sizing video playback on a layer other than the gles layer.
441     if (m_RenderUpdateCallBackFn)
442       (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect);
443
444     CRect old = g_graphicsContext.GetScissors();
445
446     g_graphicsContext.BeginPaint();
447     g_graphicsContext.SetScissors(m_destRect);
448
449     glEnable(GL_BLEND);
450     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
451     glClearColor(0, 0, 0, 0);
452     glClear(GL_COLOR_BUFFER_BIT);
453
454     g_graphicsContext.SetScissors(old);
455     g_graphicsContext.EndPaint();
456     return;
457   }
458
459   // this needs to be checked after texture validation
460   if (!m_bImageReady) return;
461
462   int index = m_iYV12RenderBuffer;
463   YUVBUFFER& buf =  m_buffers[index];
464
465   if (m_format != RENDER_FMT_OMXEGL && m_format != RENDER_FMT_EGLIMG)
466   {
467     if (!buf.fields[FIELD_FULL][0].id) return;
468   }
469   if (buf.image.flags==0)
470     return;
471
472   ManageDisplay();
473
474   g_graphicsContext.BeginPaint();
475
476   m_iLastRenderBuffer = index;
477
478   if (clear)
479   {
480     glClearColor(m_clearColour, m_clearColour, m_clearColour, 0);
481     glClear(GL_COLOR_BUFFER_BIT);
482     glClearColor(0,0,0,0);
483   }
484
485   if (alpha<255)
486   {
487     glEnable(GL_BLEND);
488     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
489     if (m_pYUVShader)
490       m_pYUVShader->SetAlpha(alpha / 255.0f);
491   }
492   else
493   {
494     glDisable(GL_BLEND);
495     if (m_pYUVShader)
496       m_pYUVShader->SetAlpha(1.0f);
497   }
498
499   if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT))
500     CLog::Log(LOGERROR, "GLES: Cannot render stipple!");
501   else
502     Render(flags, index);
503
504   VerifyGLState();
505   glEnable(GL_BLEND);
506
507   g_graphicsContext.EndPaint();
508 }
509
510 void CLinuxRendererGLES::FlipPage(int source)
511 {
512   if( source >= 0 && source < m_NumYV12Buffers )
513     m_iYV12RenderBuffer = source;
514   else
515     m_iYV12RenderBuffer = NextYV12Texture();
516
517   m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
518
519   return;
520 }
521
522 unsigned int CLinuxRendererGLES::PreInit()
523 {
524   CSingleLock lock(g_graphicsContext);
525   m_bConfigured = false;
526   m_bValidated = false;
527   UnInit();
528   m_resolution = CDisplaySettings::Get().GetCurrentResolution();
529   if ( m_resolution == RES_WINDOW )
530     m_resolution = RES_DESKTOP;
531
532   m_iYV12RenderBuffer = 0;
533   m_NumYV12Buffers = 2;
534
535   m_formats.push_back(RENDER_FMT_YUV420P);
536   m_formats.push_back(RENDER_FMT_BYPASS);
537 #if defined(HAVE_LIBOPENMAX)
538   m_formats.push_back(RENDER_FMT_OMXEGL);
539 #endif
540 #ifdef HAVE_VIDEOTOOLBOXDECODER
541   m_formats.push_back(RENDER_FMT_CVBREF);
542 #endif
543 #ifdef HAS_LIBSTAGEFRIGHT
544   m_formats.push_back(RENDER_FMT_EGLIMG);
545 #endif
546
547   // setup the background colour
548   m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
549
550   if (!m_dllSwScale->Load())
551     CLog::Log(LOGERROR,"CLinuxRendererGL::PreInit - failed to load rescale libraries!");
552
553   return true;
554 }
555
556 void CLinuxRendererGLES::UpdateVideoFilter()
557 {
558   if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod)
559     return;
560   m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
561   m_scalingMethod    = m_scalingMethodGui;
562
563   if(!Supports(m_scalingMethod))
564   {
565     CLog::Log(LOGWARNING, "CLinuxRendererGLES::UpdateVideoFilter - choosen scaling method %d, is not supported by renderer", (int)m_scalingMethod);
566     m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
567   }
568
569   if (m_pVideoFilterShader)
570   {
571     m_pVideoFilterShader->Free();
572     delete m_pVideoFilterShader;
573     m_pVideoFilterShader = NULL;
574   }
575   m_fbo.Cleanup();
576
577   VerifyGLState();
578
579   switch (m_scalingMethod)
580   {
581   case VS_SCALINGMETHOD_NEAREST:
582     SetTextureFilter(GL_NEAREST);
583     m_renderQuality = RQ_SINGLEPASS;
584     return;
585
586   case VS_SCALINGMETHOD_LINEAR:
587     SetTextureFilter(GL_LINEAR);
588     m_renderQuality = RQ_SINGLEPASS;
589     return;
590
591   case VS_SCALINGMETHOD_CUBIC:
592     CLog::Log(LOGERROR, "GLES: CUBIC not supported!");
593     break;
594
595   case VS_SCALINGMETHOD_LANCZOS2:
596   case VS_SCALINGMETHOD_LANCZOS3:
597   case VS_SCALINGMETHOD_SINC8:
598   case VS_SCALINGMETHOD_NEDI:
599     CLog::Log(LOGERROR, "GL: TODO: This scaler has not yet been implemented");
600     break;
601
602   default:
603     break;
604   }
605
606   CGUIDialogKaiToast::QueueNotification("Video Renderering", "Failed to init video filters/scalers, falling back to bilinear scaling");
607   CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler");
608   if (m_pVideoFilterShader)
609   {
610     m_pVideoFilterShader->Free();
611     delete m_pVideoFilterShader;
612     m_pVideoFilterShader = NULL;
613   }
614   m_fbo.Cleanup();
615
616   SetTextureFilter(GL_LINEAR);
617   m_renderQuality = RQ_SINGLEPASS;
618 }
619
620 void CLinuxRendererGLES::LoadShaders(int field)
621 {
622 #ifdef TARGET_DARWIN_IOS
623   float ios_version = GetIOSVersion();
624 #endif
625   int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
626   CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod);
627
628   if (m_pYUVShader)
629   {
630     m_pYUVShader->Free();
631     delete m_pYUVShader;
632     m_pYUVShader = NULL;
633   }
634
635   switch(requestedMethod)
636   {
637     case RENDER_METHOD_AUTO:
638     case RENDER_METHOD_GLSL:
639       if (m_format == RENDER_FMT_OMXEGL)
640       {
641         CLog::Log(LOGNOTICE, "GL: Using OMXEGL RGBA render method");
642         m_renderMethod = RENDER_OMXEGL;
643         break;
644       }
645       else if (m_format == RENDER_FMT_EGLIMG)
646       {
647         CLog::Log(LOGNOTICE, "GL: Using EGL Image render method");
648         m_renderMethod = RENDER_EGLIMG;
649         break;
650       }
651       else if (m_format == RENDER_FMT_BYPASS)
652       {
653         CLog::Log(LOGNOTICE, "GL: Using BYPASS render method");
654         m_renderMethod = RENDER_BYPASS;
655         break;
656       }
657       else if (m_format == RENDER_FMT_CVBREF)
658       {
659         CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef RGBA render method");
660         m_renderMethod = RENDER_CVREF;
661         break;
662       }
663       #if defined(TARGET_DARWIN_IOS)
664       else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P)
665       {
666         CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA render method");
667         m_renderMethod = RENDER_SW;
668         break;
669       }
670       #endif
671       // Try GLSL shaders if supported and user requested auto or GLSL.
672       if (glCreateProgram)
673       {
674         // create regular progressive scan shader
675         m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format);
676         CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
677
678         if (m_pYUVShader && m_pYUVShader->CompileAndLink())
679         {
680           m_renderMethod = RENDER_GLSL;
681           UpdateVideoFilter();
682           break;
683         }
684         else if (m_pYUVShader)
685         {
686           m_pYUVShader->Free();
687           delete m_pYUVShader;
688           m_pYUVShader = NULL;
689           CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader");
690           // drop through and try SW
691         }
692       }
693     case RENDER_METHOD_SOFTWARE:
694     default:
695       {
696         // Use software YUV 2 RGB conversion if user requested it or GLSL failed
697         m_renderMethod = RENDER_SW ;
698         CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA rendering");
699       }
700   }
701
702   // determine whether GPU supports NPOT textures
703   if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
704   {
705     CLog::Log(LOGNOTICE, "GL: GL_ARB_texture_rectangle not supported and OpenGL version is not 2.x");
706     CLog::Log(LOGNOTICE, "GL: Reverting to POT textures");
707     m_renderMethod |= RENDER_POT;
708   }
709   else
710     CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
711
712   // Now that we now the render method, setup texture function handlers
713   if (m_format == RENDER_FMT_CVBREF)
714   {
715     m_textureUpload = &CLinuxRendererGLES::UploadCVRefTexture;
716     m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
717     m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
718   }
719   else if (m_format == RENDER_FMT_BYPASS)
720   {
721     m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
722     m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
723     m_textureDelete = &CLinuxRendererGLES::DeleteBYPASSTexture;
724   }
725   else if (m_format == RENDER_FMT_EGLIMG)
726   {
727     m_textureUpload = &CLinuxRendererGLES::UploadEGLIMGTexture;
728     m_textureCreate = &CLinuxRendererGLES::CreateEGLIMGTexture;
729     m_textureDelete = &CLinuxRendererGLES::DeleteEGLIMGTexture;
730   }
731   else
732   {
733     // default to YV12 texture handlers
734     m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
735     m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
736     m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
737   }
738
739   if (m_oldRenderMethod != m_renderMethod)
740   {
741     CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod);
742     ReorderDrawPoints();
743     m_oldRenderMethod = m_renderMethod;
744   }
745 }
746
747 void CLinuxRendererGLES::UnInit()
748 {
749   CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources");
750   CSingleLock lock(g_graphicsContext);
751
752   if (m_rgbBuffer != NULL)
753   {
754     delete [] m_rgbBuffer;
755     m_rgbBuffer = NULL;
756   }
757   m_rgbBufferSize = 0;
758
759   // YV12 textures
760   for (int i = 0; i < NUM_BUFFERS; ++i)
761     (this->*m_textureDelete)(i);
762
763   if (m_dllSwScale && m_sw_context)
764   {
765     m_dllSwScale->sws_freeContext(m_sw_context);
766     m_sw_context = NULL;
767   }
768
769   // cleanup framebuffer object if it was in use
770   m_fbo.Cleanup();
771   m_bValidated = false;
772   m_bImageReady = false;
773   m_bConfigured = false;
774   m_RenderUpdateCallBackFn = NULL;
775   m_RenderUpdateCallBackCtx = NULL;
776   m_RenderFeaturesCallBackFn = NULL;
777   m_RenderFeaturesCallBackCtx = NULL;
778 }
779
780 inline void CLinuxRendererGLES::ReorderDrawPoints()
781 {
782
783   CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points
784
785   //corevideo and EGL are flipped in y
786   if(m_renderMethod & RENDER_CVREF)
787   {
788     CPoint tmp;
789     tmp = m_rotatedDestCoords[0];
790     m_rotatedDestCoords[0] = m_rotatedDestCoords[3];
791     m_rotatedDestCoords[3] = tmp;
792     tmp = m_rotatedDestCoords[1];
793     m_rotatedDestCoords[1] = m_rotatedDestCoords[2];
794     m_rotatedDestCoords[2] = tmp;
795   }
796 }
797
798 void CLinuxRendererGLES::Render(DWORD flags, int index)
799 {
800   // If rendered directly by the hardware
801   if (m_renderMethod & RENDER_BYPASS)
802     return;
803
804   // obtain current field, if interlaced
805   if( flags & RENDER_FLAG_TOP)
806     m_currentField = FIELD_TOP;
807
808   else if (flags & RENDER_FLAG_BOT)
809     m_currentField = FIELD_BOT;
810
811   else
812     m_currentField = FIELD_FULL;
813
814   (this->*m_textureUpload)(index);
815
816   if (m_renderMethod & RENDER_GLSL)
817   {
818     UpdateVideoFilter();
819     switch(m_renderQuality)
820     {
821     case RQ_LOW:
822     case RQ_SINGLEPASS:
823       RenderSinglePass(index, m_currentField);
824       VerifyGLState();
825       break;
826
827     case RQ_MULTIPASS:
828       RenderMultiPass(index, m_currentField);
829       VerifyGLState();
830       break;
831
832     case RQ_SOFTWARE:
833       RenderSoftware(index, m_currentField);
834       VerifyGLState();
835       break;
836     }
837   }
838   else if (m_renderMethod & RENDER_OMXEGL)
839   {
840     RenderOpenMax(index, m_currentField);
841     VerifyGLState();
842   }
843   else if (m_renderMethod & RENDER_EGLIMG)
844   {
845     RenderEglImage(index, m_currentField);
846     VerifyGLState();
847   }
848   else if (m_renderMethod & RENDER_CVREF)
849   {
850     RenderCoreVideoRef(index, m_currentField);
851     VerifyGLState();
852   }
853   else
854   {
855     RenderSoftware(index, m_currentField);
856     VerifyGLState();
857   }
858 }
859
860 void CLinuxRendererGLES::RenderSinglePass(int index, int field)
861 {
862   YV12Image &im     = m_buffers[index].image;
863   YUVFIELDS &fields = m_buffers[index].fields;
864   YUVPLANES &planes = fields[field];
865
866   if (m_reloadShaders)
867   {
868     m_reloadShaders = 0;
869     LoadShaders(field);
870   }
871
872   glDisable(GL_DEPTH_TEST);
873
874   // Y
875   glActiveTexture(GL_TEXTURE0);
876   glEnable(m_textureTarget);
877   glBindTexture(m_textureTarget, planes[0].id);
878
879   // U
880   glActiveTexture(GL_TEXTURE1);
881   glEnable(m_textureTarget);
882   glBindTexture(m_textureTarget, planes[1].id);
883
884   // V
885   glActiveTexture(GL_TEXTURE2);
886   glEnable(m_textureTarget);
887   glBindTexture(m_textureTarget, planes[2].id);
888
889   glActiveTexture(GL_TEXTURE0);
890   VerifyGLState();
891
892   m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
893   m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
894   m_pYUVShader->SetWidth(im.width);
895   m_pYUVShader->SetHeight(im.height);
896   if     (field == FIELD_TOP)
897     m_pYUVShader->SetField(1);
898   else if(field == FIELD_BOT)
899     m_pYUVShader->SetField(0);
900
901   m_pYUVShader->SetMatrices(g_matrices.GetMatrix(MM_PROJECTION), g_matrices.GetMatrix(MM_MODELVIEW));
902   m_pYUVShader->Enable();
903
904   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
905   GLfloat m_vert[4][3];
906   GLfloat m_tex[3][4][2];
907
908   GLint vertLoc = m_pYUVShader->GetVertexLoc();
909   GLint Yloc    = m_pYUVShader->GetYcoordLoc();
910   GLint Uloc    = m_pYUVShader->GetUcoordLoc();
911   GLint Vloc    = m_pYUVShader->GetVcoordLoc();
912
913   glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert);
914   glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]);
915   glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, m_tex[1]);
916   glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, m_tex[2]);
917
918   glEnableVertexAttribArray(vertLoc);
919   glEnableVertexAttribArray(Yloc);
920   glEnableVertexAttribArray(Uloc);
921   glEnableVertexAttribArray(Vloc);
922
923   // Setup vertex position values
924   for(int i = 0; i < 4; i++)
925   {
926     m_vert[i][0] = m_rotatedDestCoords[i].x;
927     m_vert[i][1] = m_rotatedDestCoords[i].y;
928     m_vert[i][2] = 0.0f;// set z to 0
929   }
930
931   // Setup texture coordinates
932   for (int i=0; i<3; i++)
933   {
934     m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1;
935     m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1;
936     m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2;
937     m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2;
938   }
939
940   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
941
942   VerifyGLState();
943
944   m_pYUVShader->Disable();
945   VerifyGLState();
946
947   glDisableVertexAttribArray(vertLoc);
948   glDisableVertexAttribArray(Yloc);
949   glDisableVertexAttribArray(Uloc);
950   glDisableVertexAttribArray(Vloc);
951
952   glActiveTexture(GL_TEXTURE1);
953   glDisable(m_textureTarget);
954
955   glActiveTexture(GL_TEXTURE2);
956   glDisable(m_textureTarget);
957
958   glActiveTexture(GL_TEXTURE0);
959   glDisable(m_textureTarget);
960
961   g_matrices.MatrixMode(MM_MODELVIEW);
962
963   VerifyGLState();
964 }
965
966 void CLinuxRendererGLES::RenderMultiPass(int index, int field)
967 {
968   // TODO: Multipass rendering does not currently work! FIX!
969   CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!");
970   return;
971
972   YV12Image &im     = m_buffers[index].image;
973   YUVPLANES &planes = m_buffers[index].fields[field];
974
975   if (m_reloadShaders)
976   {
977     m_reloadShaders = 0;
978     LoadShaders(m_currentField);
979   }
980
981   glDisable(GL_DEPTH_TEST);
982
983   // Y
984   glEnable(m_textureTarget);
985   glActiveTexture(GL_TEXTURE0);
986   glBindTexture(m_textureTarget, planes[0].id);
987   VerifyGLState();
988
989   // U
990   glActiveTexture(GL_TEXTURE1);
991   glEnable(m_textureTarget);
992   glBindTexture(m_textureTarget, planes[1].id);
993   VerifyGLState();
994
995   // V
996   glActiveTexture(GL_TEXTURE2);
997   glEnable(m_textureTarget);
998   glBindTexture(m_textureTarget, planes[2].id);
999   VerifyGLState();
1000
1001   glActiveTexture(GL_TEXTURE0);
1002   VerifyGLState();
1003
1004   // make sure the yuv shader is loaded and ready to go
1005   if (!m_pYUVShader || (!m_pYUVShader->OK()))
1006   {
1007     CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render");
1008     return;
1009   }
1010
1011   m_fbo.BeginRender();
1012   VerifyGLState();
1013
1014   m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
1015   m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1016   m_pYUVShader->SetWidth(im.width);
1017   m_pYUVShader->SetHeight(im.height);
1018   if     (field == FIELD_TOP)
1019     m_pYUVShader->SetField(1);
1020   else if(field == FIELD_BOT)
1021     m_pYUVShader->SetField(0);
1022
1023   VerifyGLState();
1024 //TODO
1025 //  glPushAttrib(GL_VIEWPORT_BIT);
1026 //  glPushAttrib(GL_SCISSOR_BIT);
1027   g_matrices.MatrixMode(MM_MODELVIEW);
1028   g_matrices.PushMatrix();
1029   g_matrices.LoadIdentity();
1030   VerifyGLState();
1031
1032   g_matrices.MatrixMode(MM_PROJECTION);
1033   g_matrices.PushMatrix();
1034   g_matrices.LoadIdentity();
1035   VerifyGLState();
1036   g_matrices.Ortho2D(0, m_sourceWidth, 0, m_sourceHeight);
1037   glViewport(0, 0, m_sourceWidth, m_sourceHeight);
1038   glScissor(0, 0, m_sourceWidth, m_sourceHeight);
1039   g_matrices.MatrixMode(MM_MODELVIEW);
1040   VerifyGLState();
1041
1042
1043   if (!m_pYUVShader->Enable())
1044   {
1045     CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
1046   }
1047
1048 // 1st Pass to video frame size
1049 //TODO
1050 //  float imgwidth  = planes[0].rect.x2 - planes[0].rect.x1;
1051 //  float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
1052 //  if (m_textureTarget == GL_TEXTURE_2D)
1053 //  {
1054 //    imgwidth  *= planes[0].texwidth;
1055 //    imgheight *= planes[0].texheight;
1056 //  }
1057 //  
1058 //  glBegin(GL_QUADS);
1059 //
1060 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
1061 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
1062 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
1063 //  glVertex2f(0.0f    , 0.0f);
1064 //
1065 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
1066 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
1067 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
1068 //  glVertex2f(imgwidth, 0.0f);
1069 //
1070 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
1071 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
1072 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
1073 //  glVertex2f(imgwidth, imgheight);
1074 //
1075 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
1076 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
1077 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
1078 //  glVertex2f(0.0f    , imgheight);
1079 //
1080 //  glEnd();
1081 //  VerifyGLState();
1082
1083   m_pYUVShader->Disable();
1084
1085   g_matrices.MatrixMode(MM_MODELVIEW);
1086   g_matrices.PopMatrix(); // pop modelview
1087   g_matrices.MatrixMode(MM_PROJECTION);
1088   g_matrices.PopMatrix(); // pop projection
1089 //TODO
1090 //  glPopAttrib(); // pop scissor
1091 //  glPopAttrib(); // pop viewport
1092   g_matrices.MatrixMode(MM_MODELVIEW);
1093   VerifyGLState();
1094
1095   m_fbo.EndRender();
1096
1097   glActiveTexture(GL_TEXTURE1);
1098   glDisable(m_textureTarget);
1099   glActiveTexture(GL_TEXTURE2);
1100   glDisable(m_textureTarget);
1101   glActiveTexture(GL_TEXTURE0);
1102   glDisable(m_textureTarget);
1103
1104   glEnable(GL_TEXTURE_2D);
1105   glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
1106   VerifyGLState();
1107
1108   // Use regular normalized texture coordinates
1109
1110   // 2nd Pass to screen size with optional video filter
1111
1112   if (m_pVideoFilterShader)
1113   {
1114     m_fbo.SetFiltering(GL_TEXTURE_2D, GL_NEAREST);
1115     m_pVideoFilterShader->SetSourceTexture(0);
1116     m_pVideoFilterShader->SetWidth(m_sourceWidth);
1117     m_pVideoFilterShader->SetHeight(m_sourceHeight);
1118     m_pVideoFilterShader->Enable();
1119   }
1120   else
1121     m_fbo.SetFiltering(GL_TEXTURE_2D, GL_LINEAR);
1122
1123   VerifyGLState();
1124
1125 //TODO
1126 //  imgwidth  /= m_sourceWidth;
1127 //  imgheight /= m_sourceHeight;
1128 //
1129 //  glBegin(GL_QUADS);
1130 //
1131 //  glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f    , 0.0f);
1132 //  glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
1133 //
1134 //  glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
1135 //  glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
1136 //
1137 //  glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
1138 //  glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
1139 //
1140 //  glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f    , imgheight);
1141 //  glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
1142 //
1143 //  glEnd();
1144
1145   VerifyGLState();
1146
1147   if (m_pVideoFilterShader)
1148     m_pVideoFilterShader->Disable();
1149
1150   VerifyGLState();
1151
1152   glDisable(m_textureTarget);
1153   VerifyGLState();
1154 }
1155
1156 void CLinuxRendererGLES::RenderSoftware(int index, int field)
1157 {
1158   YUVPLANES &planes = m_buffers[index].fields[field];
1159
1160   glDisable(GL_DEPTH_TEST);
1161
1162   // Y
1163   glEnable(m_textureTarget);
1164   glActiveTexture(GL_TEXTURE0);
1165   glBindTexture(m_textureTarget, planes[0].id);
1166
1167   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1168
1169   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1170   GLfloat ver[4][4];
1171   GLfloat tex[4][2];
1172   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1173
1174   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1175   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1176   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1177
1178   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1179   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1180   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1181
1182   glEnableVertexAttribArray(posLoc);
1183   glEnableVertexAttribArray(texLoc);
1184   glEnableVertexAttribArray(colLoc);
1185
1186   // Set vertex coordinates
1187   for(int i = 0; i < 4; i++)
1188   {
1189     ver[i][0] = m_rotatedDestCoords[i].x;
1190     ver[i][1] = m_rotatedDestCoords[i].y;
1191     ver[i][2] = 0.0f;// set z to 0
1192     ver[i][3] = 1.0f;
1193   }
1194
1195   // Set texture coordinates
1196   tex[0][0] = tex[3][0] = planes[0].rect.x1;
1197   tex[0][1] = tex[1][1] = planes[0].rect.y1;
1198   tex[1][0] = tex[2][0] = planes[0].rect.x2;
1199   tex[2][1] = tex[3][1] = planes[0].rect.y2;
1200
1201   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1202
1203   glDisableVertexAttribArray(posLoc);
1204   glDisableVertexAttribArray(texLoc);
1205   glDisableVertexAttribArray(colLoc);
1206
1207   g_Windowing.DisableGUIShader();
1208
1209   VerifyGLState();
1210
1211   glDisable(m_textureTarget);
1212   VerifyGLState();
1213 }
1214
1215 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1216 {
1217 #if defined(HAVE_LIBOPENMAX)
1218   GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1219
1220   glDisable(GL_DEPTH_TEST);
1221
1222   // Y
1223   glEnable(m_textureTarget);
1224   glActiveTexture(GL_TEXTURE0);
1225   glBindTexture(m_textureTarget, textureId);
1226
1227   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1228
1229   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1230   GLfloat ver[4][4];
1231   GLfloat tex[4][2];
1232   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1233
1234   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1235   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1236   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1237
1238   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1239   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1240   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1241
1242   glEnableVertexAttribArray(posLoc);
1243   glEnableVertexAttribArray(texLoc);
1244   glEnableVertexAttribArray(colLoc);
1245
1246   // Set vertex coordinates
1247   for(int i = 0; i < 4; i++)
1248   {
1249     ver[i][0] = m_rotatedDestCoords[i].x;
1250     ver[i][1] = m_rotatedDestCoords[i].y;
1251     ver[i][2] = 0.0f;// set z to 0
1252     ver[i][3] = 1.0f;
1253   }
1254
1255   // Set texture coordinates
1256   tex[0][0] = tex[3][0] = 0;
1257   tex[0][1] = tex[1][1] = 0;
1258   tex[1][0] = tex[2][0] = 1;
1259   tex[2][1] = tex[3][1] = 1;
1260
1261   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1262
1263   glDisableVertexAttribArray(posLoc);
1264   glDisableVertexAttribArray(texLoc);
1265   glDisableVertexAttribArray(colLoc);
1266
1267   g_Windowing.DisableGUIShader();
1268
1269   VerifyGLState();
1270
1271   glDisable(m_textureTarget);
1272   VerifyGLState();
1273 #endif
1274 }
1275
1276 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1277 {
1278 #if defined(HAS_LIBSTAGEFRIGHT)
1279 #ifdef DEBUG_VERBOSE
1280   unsigned int time = XbmcThreads::SystemClockMillis();
1281 #endif
1282
1283   YUVPLANE &plane = m_buffers[index].fields[field][0];
1284
1285   glDisable(GL_DEPTH_TEST);
1286
1287   glActiveTexture(GL_TEXTURE0);
1288   glBindTexture(m_textureTarget, plane.id);
1289
1290   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1291
1292   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1293   GLfloat ver[4][4];
1294   GLfloat tex[4][2];
1295   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1296
1297   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1298   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1299   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1300
1301   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1302   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1303   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1304
1305   glEnableVertexAttribArray(posLoc);
1306   glEnableVertexAttribArray(texLoc);
1307   glEnableVertexAttribArray(colLoc);
1308
1309   // Set vertex coordinates
1310   for(int i = 0; i < 4; i++)
1311   {
1312     ver[i][0] = m_rotatedDestCoords[i].x;
1313     ver[i][1] = m_rotatedDestCoords[i].y;
1314     ver[i][2] = 0.0f;// set z to 0
1315     ver[i][3] = 1.0f;
1316   }
1317
1318   // Set texture coordinates (is flipped in y)
1319   tex[0][0] = tex[3][0] = 0;
1320   tex[0][1] = tex[1][1] = 1;
1321   tex[1][0] = tex[2][0] = 1;
1322   tex[2][1] = tex[3][1] = 0;
1323
1324   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1325
1326   glDisableVertexAttribArray(posLoc);
1327   glDisableVertexAttribArray(texLoc);
1328   glDisableVertexAttribArray(colLoc);
1329
1330   g_Windowing.DisableGUIShader();
1331   VerifyGLState();
1332
1333   glBindTexture(m_textureTarget, 0);
1334   VerifyGLState();
1335
1336 #ifdef DEBUG_VERBOSE
1337   CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1338 #endif
1339 #endif
1340 }
1341
1342 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1343 {
1344 #ifdef HAVE_VIDEOTOOLBOXDECODER
1345   YUVPLANE &plane = m_buffers[index].fields[field][0];
1346
1347   glDisable(GL_DEPTH_TEST);
1348
1349   glEnable(m_textureTarget);
1350   glActiveTexture(GL_TEXTURE0);
1351   glBindTexture(m_textureTarget, plane.id);
1352
1353   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1354
1355   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1356   GLfloat ver[4][4];
1357   GLfloat tex[4][2];
1358   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1359
1360   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1361   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1362   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1363
1364   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1365   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1366   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1367
1368   glEnableVertexAttribArray(posLoc);
1369   glEnableVertexAttribArray(texLoc);
1370   glEnableVertexAttribArray(colLoc);
1371
1372   // Set vertex coordinates
1373   for(int i = 0; i < 4; i++)
1374   {
1375     ver[i][0] = m_rotatedDestCoords[i].x;
1376     ver[i][1] = m_rotatedDestCoords[i].y;
1377     ver[i][2] = 0.0f;// set z to 0
1378     ver[i][3] = 1.0f;
1379   }
1380
1381   // Set texture coordinates (corevideo is flipped in y)
1382   tex[0][0] = tex[3][0] = 0;
1383   tex[0][1] = tex[1][1] = 1;
1384   tex[1][0] = tex[2][0] = 1;
1385   tex[2][1] = tex[3][1] = 0;
1386
1387   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1388
1389   glDisableVertexAttribArray(posLoc);
1390   glDisableVertexAttribArray(texLoc);
1391   glDisableVertexAttribArray(colLoc);
1392
1393   g_Windowing.DisableGUIShader();
1394   VerifyGLState();
1395
1396   glDisable(m_textureTarget);
1397   VerifyGLState();
1398 #endif
1399 }
1400
1401 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1402 {
1403   if (!m_bValidated)
1404     return false;
1405
1406   // If rendered directly by the hardware
1407   if (m_renderMethod & RENDER_BYPASS)
1408   {
1409     capture->BeginRender();
1410     capture->EndRender();
1411     return true;
1412   }
1413
1414   // save current video rect
1415   CRect saveSize = m_destRect;
1416   saveRotatedCoords();//backup current m_rotatedDestCoords
1417
1418   // new video rect is thumbnail size
1419   m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1420   MarkDirty();
1421   syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1422   // clear framebuffer and invert Y axis to get non-inverted image
1423   glDisable(GL_BLEND);
1424
1425   g_matrices.MatrixMode(MM_MODELVIEW);
1426   g_matrices.PushMatrix();
1427   // fixme - we know that cvref  & eglimg are already flipped in y direction
1428   // but somehow this also effects the rendercapture here
1429   // therefore we have to skip the flip here or we get upside down
1430   // images
1431   if (m_renderMethod != RENDER_CVREF)
1432   {
1433     g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1434     g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1435   }
1436
1437   capture->BeginRender();
1438
1439   Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1440   // read pixels
1441   glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1442                GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1443
1444   // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1445   // XOR Swap RGBA -> BGRA
1446   unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1447   for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1448   {
1449     std::swap(pixels[0], pixels[2]);
1450   }
1451
1452   capture->EndRender();
1453
1454   // revert model view matrix
1455   g_matrices.MatrixMode(MM_MODELVIEW);
1456   g_matrices.PopMatrix();
1457
1458   // restore original video rect
1459   m_destRect = saveSize;
1460   restoreRotatedCoords();//restores the previous state of the rotated dest coords
1461
1462   return true;
1463 }
1464
1465 //********************************************************************************************************
1466 // YV12 Texture creation, deletion, copying + clearing
1467 //********************************************************************************************************
1468 void CLinuxRendererGLES::UploadYV12Texture(int source)
1469 {
1470   YUVBUFFER& buf    =  m_buffers[source];
1471   YV12Image* im     = &buf.image;
1472   YUVFIELDS& fields =  buf.fields;
1473
1474
1475 #if defined(HAVE_LIBOPENMAX)
1476   if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1477 #else
1478   if (!(im->flags&IMAGE_FLAG_READY))
1479 #endif
1480   {
1481     return;
1482   }
1483
1484   // if we don't have a shader, fallback to SW YUV2RGB for now
1485   if (m_renderMethod & RENDER_SW)
1486   {
1487     if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1488     {
1489       delete [] m_rgbBuffer;
1490       m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1491       m_rgbBuffer = new BYTE[m_rgbBufferSize];
1492     }
1493
1494 #if defined(__ARM_NEON__)
1495     if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1496     {
1497       yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1498         m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1499     }
1500     else
1501 #endif
1502     {
1503       m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1504         im->width, im->height, PIX_FMT_YUV420P,
1505         im->width, im->height, PIX_FMT_RGBA,
1506         SWS_FAST_BILINEAR, NULL, NULL, NULL);
1507
1508       uint8_t *src[]  = { im->plane[0], im->plane[1], im->plane[2], 0 };
1509       int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1510       uint8_t *dst[]  = { m_rgbBuffer, 0, 0, 0 };
1511       int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1512       m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1513     }
1514   }
1515
1516   bool deinterlacing;
1517   if (m_currentField == FIELD_FULL)
1518     deinterlacing = false;
1519   else
1520     deinterlacing = true;
1521
1522   glEnable(m_textureTarget);
1523   VerifyGLState();
1524
1525   if (m_renderMethod & RENDER_SW)
1526   {
1527     // Load RGB image
1528     if (deinterlacing)
1529     {
1530       LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1531                , im->width, im->height >> 1
1532                , m_sourceWidth*8, m_rgbBuffer );
1533
1534       LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1535                , im->width, im->height >> 1
1536                , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4);
1537     }
1538     else
1539     {
1540       LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1541                , im->width, im->height
1542                , m_sourceWidth*4, m_rgbBuffer );
1543     }
1544   }
1545   else
1546   {
1547     glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1548
1549     if (deinterlacing)
1550     {
1551       // Load Y fields
1552       LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1553                , im->width, im->height >> 1
1554                , im->stride[0]*2, im->plane[0] );
1555
1556       LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1557                , im->width, im->height >> 1
1558                , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
1559     }
1560     else
1561     {
1562       // Load Y plane
1563       LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1564                , im->width, im->height
1565                , im->stride[0], im->plane[0] );
1566     }
1567   }
1568
1569   VerifyGLState();
1570
1571   if (!(m_renderMethod & RENDER_SW))
1572   {
1573     glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1574
1575     if (deinterlacing)
1576     {
1577       // Load Even U & V Fields
1578       LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1579                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1580                , im->stride[1]*2, im->plane[1] );
1581
1582       LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
1583                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1584                , im->stride[2]*2, im->plane[2] );
1585
1586       // Load Odd U & V Fields
1587       LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1588                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1589                , im->stride[1]*2, im->plane[1] + im->stride[1] );
1590
1591       LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
1592                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1593                , im->stride[2]*2, im->plane[2] + im->stride[2] );
1594
1595     }
1596     else
1597     {
1598       LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1599                , im->width >> im->cshift_x, im->height >> im->cshift_y
1600                , im->stride[1], im->plane[1] );
1601
1602       LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
1603                , im->width >> im->cshift_x, im->height >> im->cshift_y
1604                , im->stride[2], im->plane[2] );
1605     }
1606   }
1607   CalculateTextureSourceRects(source, 3);
1608
1609   glDisable(m_textureTarget);
1610 }
1611
1612 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1613 {
1614   YV12Image &im     = m_buffers[index].image;
1615   YUVFIELDS &fields = m_buffers[index].fields;
1616
1617   if( fields[FIELD_FULL][0].id == 0 ) return;
1618
1619   /* finish up all textures, and delete them */
1620   g_graphicsContext.BeginPaint();  //FIXME
1621   for(int f = 0;f<MAX_FIELDS;f++)
1622   {
1623     for(int p = 0;p<MAX_PLANES;p++)
1624     {
1625       if( fields[f][p].id )
1626       {
1627         if (glIsTexture(fields[f][p].id))
1628           glDeleteTextures(1, &fields[f][p].id);
1629         fields[f][p].id = 0;
1630       }
1631     }
1632   }
1633   g_graphicsContext.EndPaint();
1634
1635   for(int p = 0;p<MAX_PLANES;p++)
1636   {
1637     if (im.plane[p])
1638     {
1639       delete[] im.plane[p];
1640       im.plane[p] = NULL;
1641     }
1642   }
1643 }
1644
1645 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1646 {
1647   /* since we also want the field textures, pitch must be texture aligned */
1648   YV12Image &im     = m_buffers[index].image;
1649   YUVFIELDS &fields = m_buffers[index].fields;
1650
1651   DeleteYV12Texture(index);
1652
1653   im.height = m_sourceHeight;
1654   im.width  = m_sourceWidth;
1655   im.cshift_x = 1;
1656   im.cshift_y = 1;
1657
1658   im.stride[0] = im.width;
1659   im.stride[1] = im.width >> im.cshift_x;
1660   im.stride[2] = im.width >> im.cshift_x;
1661
1662   im.planesize[0] = im.stride[0] * im.height;
1663   im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1664   im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1665
1666   for (int i = 0; i < 3; i++)
1667     im.plane[i] = new BYTE[im.planesize[i]];
1668
1669   glEnable(m_textureTarget);
1670   for(int f = 0;f<MAX_FIELDS;f++)
1671   {
1672     for(int p = 0;p<MAX_PLANES;p++)
1673     {
1674       if (!glIsTexture(fields[f][p].id))
1675       {
1676         glGenTextures(1, &fields[f][p].id);
1677         VerifyGLState();
1678       }
1679     }
1680   }
1681
1682   // YUV
1683   for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1684   {
1685     int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1686     YUVPLANES &planes = fields[f];
1687
1688     planes[0].texwidth  = im.width;
1689     planes[0].texheight = im.height >> fieldshift;
1690
1691     if (m_renderMethod & RENDER_SW)
1692     {
1693       planes[1].texwidth  = 0;
1694       planes[1].texheight = 0;
1695       planes[2].texwidth  = 0;
1696       planes[2].texheight = 0;
1697     }
1698     else
1699     {
1700       planes[1].texwidth  = planes[0].texwidth  >> im.cshift_x;
1701       planes[1].texheight = planes[0].texheight >> im.cshift_y;
1702       planes[2].texwidth  = planes[0].texwidth  >> im.cshift_x;
1703       planes[2].texheight = planes[0].texheight >> im.cshift_y;
1704     }
1705
1706     if(m_renderMethod & RENDER_POT)
1707     {
1708       for(int p = 0; p < 3; p++)
1709       {
1710         planes[p].texwidth  = NP2(planes[p].texwidth);
1711         planes[p].texheight = NP2(planes[p].texheight);
1712       }
1713     }
1714
1715     for(int p = 0; p < 3; p++)
1716     {
1717       YUVPLANE &plane = planes[p];
1718       if (plane.texwidth * plane.texheight == 0)
1719         continue;
1720
1721       glBindTexture(m_textureTarget, plane.id);
1722       if (m_renderMethod & RENDER_SW)
1723       {
1724         if(m_renderMethod & RENDER_POT)
1725           CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d",  plane.texwidth, plane.texheight);
1726         else
1727           CLog::Log(LOGDEBUG,  "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1728
1729         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1730         glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1731       }
1732       else
1733       {
1734         if(m_renderMethod & RENDER_POT)
1735           CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d",  plane.texwidth, plane.texheight);
1736         else
1737           CLog::Log(LOGDEBUG,  "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1738
1739         glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
1740       }
1741
1742       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1743       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1744       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1745       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1746       VerifyGLState();
1747     }
1748   }
1749   glDisable(m_textureTarget);
1750   return true;
1751 }
1752
1753 //********************************************************************************************************
1754 // CoreVideoRef Texture creation, deletion, copying + clearing
1755 //********************************************************************************************************
1756 void CLinuxRendererGLES::UploadCVRefTexture(int index)
1757 {
1758 #ifdef HAVE_VIDEOTOOLBOXDECODER
1759   CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
1760
1761   if (cvBufferRef)
1762   {
1763     YUVPLANE &plane = m_buffers[index].fields[0][0];
1764
1765     CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1766     #if !TARGET_OS_IPHONE
1767       int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
1768     #endif
1769     int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
1770     int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
1771     unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
1772
1773     glEnable(m_textureTarget);
1774     VerifyGLState();
1775
1776     glBindTexture(m_textureTarget, plane.id);
1777     #if !TARGET_OS_IPHONE
1778       #ifdef GL_UNPACK_ROW_LENGTH
1779         // Set row pixels
1780         glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
1781       #endif
1782       #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1783         // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1784         glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1785       #endif
1786     #endif
1787
1788     // Using BGRA extension to pull in video frame data directly
1789     glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
1790
1791     #if !TARGET_OS_IPHONE
1792       #ifdef GL_UNPACK_ROW_LENGTH
1793         // Unset row pixels
1794         glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1795       #endif
1796     #endif
1797     glBindTexture(m_textureTarget, 0);
1798
1799     glDisable(m_textureTarget);
1800     VerifyGLState();
1801
1802     CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1803     CVBufferRelease(m_buffers[index].cvBufferRef);
1804     m_buffers[index].cvBufferRef = NULL;
1805
1806     plane.flipindex = m_buffers[index].flipindex;
1807   }
1808 #endif
1809 }
1810 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
1811 {
1812 #ifdef HAVE_VIDEOTOOLBOXDECODER
1813   YUVPLANE &plane = m_buffers[index].fields[0][0];
1814
1815   if (m_buffers[index].cvBufferRef)
1816     CVBufferRelease(m_buffers[index].cvBufferRef);
1817   m_buffers[index].cvBufferRef = NULL;
1818
1819   if(plane.id && glIsTexture(plane.id))
1820     glDeleteTextures(1, &plane.id);
1821   plane.id = 0;
1822 #endif
1823 }
1824 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
1825 {
1826 #ifdef HAVE_VIDEOTOOLBOXDECODER
1827   YV12Image &im     = m_buffers[index].image;
1828   YUVFIELDS &fields = m_buffers[index].fields;
1829   YUVPLANE  &plane  = fields[0][0];
1830
1831   DeleteCVRefTexture(index);
1832
1833   memset(&im    , 0, sizeof(im));
1834   memset(&fields, 0, sizeof(fields));
1835
1836   im.height = m_sourceHeight;
1837   im.width  = m_sourceWidth;
1838
1839   plane.texwidth  = im.width;
1840   plane.texheight = im.height;
1841
1842   if(m_renderMethod & RENDER_POT)
1843   {
1844     plane.texwidth  = NP2(plane.texwidth);
1845     plane.texheight = NP2(plane.texheight);
1846   }
1847   glEnable(m_textureTarget);
1848   glGenTextures(1, &plane.id);
1849   VerifyGLState();
1850
1851   glBindTexture(m_textureTarget, plane.id);
1852   #if !TARGET_OS_IPHONE
1853     #ifdef GL_UNPACK_ROW_LENGTH
1854       // Set row pixels
1855       glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
1856     #endif
1857     #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1858       // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1859       glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1860       // Set client storage
1861     #endif
1862     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1863   #endif
1864
1865   glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1866   glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1867         // This is necessary for non-power-of-two textures
1868   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1869   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1870   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1871   glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1872
1873   #if !TARGET_OS_IPHONE
1874     // turn off client storage so it doesn't get picked up for the next texture
1875     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
1876   #endif
1877   glBindTexture(m_textureTarget, 0);
1878   glDisable(m_textureTarget);
1879 #endif
1880   return true;
1881 }
1882
1883 //********************************************************************************************************
1884 // BYPASS creation, deletion, copying + clearing
1885 //********************************************************************************************************
1886 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
1887 {
1888 }
1889 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
1890 {
1891 }
1892 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
1893 {
1894   return true;
1895 }
1896
1897 //********************************************************************************************************
1898 // EGLIMG creation, deletion, copying + clearing
1899 //********************************************************************************************************
1900 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
1901 {
1902 #ifdef HAS_LIBSTAGEFRIGHT
1903 #ifdef DEBUG_VERBOSE
1904   unsigned int time = XbmcThreads::SystemClockMillis();
1905 #endif
1906
1907   if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
1908   {
1909     YUVPLANE &plane = m_buffers[index].fields[0][0];
1910
1911     glActiveTexture(GL_TEXTURE0);
1912     glBindTexture(m_textureTarget, plane.id);
1913     glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
1914     glBindTexture(m_textureTarget, 0);
1915
1916     plane.flipindex = m_buffers[index].flipindex;
1917   }
1918
1919 #ifdef DEBUG_VERBOSE
1920   CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
1921 #endif
1922 #endif
1923 }
1924 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
1925 {
1926 #ifdef HAS_LIBSTAGEFRIGHT
1927   YUVPLANE &plane = m_buffers[index].fields[0][0];
1928
1929   if(plane.id && glIsTexture(plane.id))
1930     glDeleteTextures(1, &plane.id);
1931   plane.id = 0;
1932 #endif
1933 }
1934 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
1935 {
1936 #ifdef HAS_LIBSTAGEFRIGHT
1937   YV12Image &im     = m_buffers[index].image;
1938   YUVFIELDS &fields = m_buffers[index].fields;
1939   YUVPLANE  &plane  = fields[0][0];
1940
1941   DeleteEGLIMGTexture(index);
1942
1943   memset(&im    , 0, sizeof(im));
1944   memset(&fields, 0, sizeof(fields));
1945
1946   im.height = m_sourceHeight;
1947   im.width  = m_sourceWidth;
1948
1949   plane.texwidth  = im.width;
1950   plane.texheight = im.height;
1951
1952   if(m_renderMethod & RENDER_POT)
1953   {
1954     plane.texwidth  = NP2(plane.texwidth);
1955     plane.texheight = NP2(plane.texheight);
1956   }
1957   glEnable(m_textureTarget);
1958   glGenTextures(1, &plane.id);
1959   VerifyGLState();
1960
1961   glBindTexture(m_textureTarget, plane.id);
1962
1963   glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1964   glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1965         // This is necessary for non-power-of-two textures
1966   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1967   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1968
1969   glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1970
1971   glDisable(m_textureTarget);
1972 #endif
1973   return true;
1974 }
1975
1976 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
1977 {
1978   for (int i = 0 ; i<m_NumYV12Buffers ; i++)
1979   {
1980     YUVFIELDS &fields = m_buffers[i].fields;
1981
1982     for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1983     {
1984       glBindTexture(m_textureTarget, fields[f][0].id);
1985       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
1986       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
1987       VerifyGLState();
1988
1989       if (!(m_renderMethod & RENDER_SW))
1990       {
1991         glBindTexture(m_textureTarget, fields[f][1].id);
1992         glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
1993         glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
1994         VerifyGLState();
1995
1996         glBindTexture(m_textureTarget, fields[f][2].id);
1997         glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
1998         glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
1999         VerifyGLState();
2000       }
2001     }
2002   }
2003 }
2004
2005 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2006 {
2007   // Player controls render, let it dictate available render features
2008   if((m_renderMethod & RENDER_BYPASS))
2009   {
2010     Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2011     return itr != m_renderFeatures.end();
2012   }
2013
2014   if(feature == RENDERFEATURE_BRIGHTNESS)
2015     return false;
2016
2017   if(feature == RENDERFEATURE_CONTRAST)
2018     return false;
2019
2020   if(feature == RENDERFEATURE_GAMMA)
2021     return false;
2022
2023   if(feature == RENDERFEATURE_NOISE)
2024     return false;
2025
2026   if(feature == RENDERFEATURE_SHARPNESS)
2027     return false;
2028
2029   if (feature == RENDERFEATURE_NONLINSTRETCH)
2030     return false;
2031
2032   if (feature == RENDERFEATURE_STRETCH         ||
2033       feature == RENDERFEATURE_CROP            ||
2034       feature == RENDERFEATURE_ZOOM            ||
2035       feature == RENDERFEATURE_VERTICAL_SHIFT  ||
2036       feature == RENDERFEATURE_PIXEL_RATIO     ||
2037       feature == RENDERFEATURE_POSTPROCESS     ||
2038       feature == RENDERFEATURE_ROTATION)
2039     return true;
2040
2041
2042   return false;
2043 }
2044
2045 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2046 {
2047   return false;
2048 }
2049
2050 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2051 {
2052   // Player controls render, let it dictate available deinterlace modes
2053   if((m_renderMethod & RENDER_BYPASS))
2054   {
2055     Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2056     return itr != m_deinterlaceModes.end();
2057   }
2058
2059   if (mode == VS_DEINTERLACEMODE_OFF)
2060     return true;
2061
2062   if(m_renderMethod & RENDER_OMXEGL)
2063     return false;
2064
2065   if(m_renderMethod & RENDER_EGLIMG)
2066     return false;
2067
2068   if(m_renderMethod & RENDER_CVREF)
2069     return false;
2070
2071   if(mode == VS_DEINTERLACEMODE_AUTO
2072   || mode == VS_DEINTERLACEMODE_FORCE)
2073     return true;
2074
2075   return false;
2076 }
2077
2078 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2079 {
2080   // Player controls render, let it dictate available deinterlace methods
2081   if((m_renderMethod & RENDER_BYPASS))
2082   {
2083     Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2084     return itr != m_deinterlaceMethods.end();
2085   }
2086
2087   if(m_renderMethod & RENDER_OMXEGL)
2088     return false;
2089
2090   if(m_renderMethod & RENDER_EGLIMG)
2091     return false;
2092
2093   if(m_renderMethod & RENDER_CVREF)
2094     return false;
2095
2096   if(method == VS_INTERLACEMETHOD_AUTO)
2097     return true;
2098
2099 #if defined(__i386__) || defined(__x86_64__)
2100   if(method == VS_INTERLACEMETHOD_DEINTERLACE
2101   || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2102   || method == VS_INTERLACEMETHOD_SW_BLEND)
2103 #else
2104   if(method == VS_INTERLACEMETHOD_SW_BLEND)
2105 #endif
2106     return true;
2107
2108   return false;
2109 }
2110
2111 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2112 {
2113   // Player controls render, let it dictate available scaling methods
2114   if((m_renderMethod & RENDER_BYPASS))
2115   {
2116     Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2117     return itr != m_scalingMethods.end();
2118   }
2119
2120   if(method == VS_SCALINGMETHOD_NEAREST
2121   || method == VS_SCALINGMETHOD_LINEAR)
2122     return true;
2123
2124   return false;
2125 }
2126
2127 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2128 {
2129   // Player controls render, let it pick the auto-deinterlace method
2130   if((m_renderMethod & RENDER_BYPASS))
2131   {
2132     if (!m_deinterlaceMethods.empty())
2133       return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2134     else
2135       return VS_INTERLACEMETHOD_NONE;
2136   }
2137
2138   if(m_renderMethod & RENDER_OMXEGL)
2139     return VS_INTERLACEMETHOD_NONE;
2140
2141   if(m_renderMethod & RENDER_EGLIMG)
2142     return VS_INTERLACEMETHOD_NONE;
2143
2144   if(m_renderMethod & RENDER_CVREF)
2145     return VS_INTERLACEMETHOD_NONE;
2146
2147 #if defined(__i386__) || defined(__x86_64__)
2148   return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2149 #else
2150   return VS_INTERLACEMETHOD_SW_BLEND;
2151 #endif
2152 }
2153
2154 unsigned int CLinuxRendererGLES::GetProcessorSize()
2155 {
2156   if(m_format == RENDER_FMT_OMXEGL
2157   || m_format == RENDER_FMT_CVBREF
2158   || m_format == RENDER_FMT_EGLIMG)
2159     return 1;
2160   else
2161     return 0;
2162 }
2163
2164 #ifdef HAVE_LIBOPENMAX
2165 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2166 {
2167   YUVBUFFER &buf = m_buffers[index];
2168   buf.openMaxBuffer = picture->openMaxBuffer;
2169 }
2170 #endif
2171 #ifdef HAVE_VIDEOTOOLBOXDECODER
2172 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2173 {
2174   YUVBUFFER &buf = m_buffers[index];
2175   if (buf.cvBufferRef)
2176     CVBufferRelease(buf.cvBufferRef);
2177   buf.cvBufferRef = cvBufferRef;
2178   // retain another reference, this way dvdplayer and renderer can issue releases.
2179   CVBufferRetain(buf.cvBufferRef);
2180 }
2181 #endif
2182 #ifdef HAS_LIBSTAGEFRIGHT
2183 void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
2184 {
2185 #ifdef DEBUG_VERBOSE
2186   unsigned int time = XbmcThreads::SystemClockMillis();
2187 #endif
2188
2189   YUVBUFFER &buf = m_buffers[index];
2190   if (buf.eglimg != EGL_NO_IMAGE_KHR)
2191     stf->ReleaseBuffer(buf.eglimg);
2192   stf->LockBuffer(eglimg);
2193
2194   buf.stf = stf;
2195   buf.eglimg = eglimg;
2196
2197 #ifdef DEBUG_VERBOSE
2198   CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);
2199 #endif
2200 }
2201 #endif
2202
2203 #endif
2204