Merge pull request #3222 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   float col[4][3];
1173
1174   for (int index = 0;index < 4;++index)
1175     col[index][0] = col[index][1] = col[index][2] = 1.0;
1176
1177   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1178   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1179   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1180
1181   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1182   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1183   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1184
1185   glEnableVertexAttribArray(posLoc);
1186   glEnableVertexAttribArray(texLoc);
1187   glEnableVertexAttribArray(colLoc);
1188
1189   // Set vertex coordinates
1190   for(int i = 0; i < 4; i++)
1191   {
1192     ver[i][0] = m_rotatedDestCoords[i].x;
1193     ver[i][1] = m_rotatedDestCoords[i].y;
1194     ver[i][2] = 0.0f;// set z to 0
1195     ver[i][3] = 1.0f;
1196   }
1197
1198   // Set texture coordinates
1199   tex[0][0] = tex[3][0] = planes[0].rect.x1;
1200   tex[0][1] = tex[1][1] = planes[0].rect.y1;
1201   tex[1][0] = tex[2][0] = planes[0].rect.x2;
1202   tex[2][1] = tex[3][1] = planes[0].rect.y2;
1203
1204   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1205
1206   glDisableVertexAttribArray(posLoc);
1207   glDisableVertexAttribArray(texLoc);
1208   glDisableVertexAttribArray(colLoc);
1209
1210   g_Windowing.DisableGUIShader();
1211
1212   VerifyGLState();
1213
1214   glDisable(m_textureTarget);
1215   VerifyGLState();
1216 }
1217
1218 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1219 {
1220 #if defined(HAVE_LIBOPENMAX)
1221   GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1222
1223   glDisable(GL_DEPTH_TEST);
1224
1225   // Y
1226   glEnable(m_textureTarget);
1227   glActiveTexture(GL_TEXTURE0);
1228   glBindTexture(m_textureTarget, textureId);
1229
1230   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1231
1232   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1233   GLfloat ver[4][4];
1234   GLfloat tex[4][2];
1235   float col[4][3];
1236
1237   for (int index = 0;index < 4;++index)
1238   {
1239     col[index][0] = col[index][1] = col[index][2] = 1.0;
1240   }
1241
1242   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1243   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1244   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1245
1246   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1247   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1248   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1249
1250   glEnableVertexAttribArray(posLoc);
1251   glEnableVertexAttribArray(texLoc);
1252   glEnableVertexAttribArray(colLoc);
1253
1254   // Set vertex coordinates
1255   for(int i = 0; i < 4; i++)
1256   {
1257     ver[i][0] = m_rotatedDestCoords[i].x;
1258     ver[i][1] = m_rotatedDestCoords[i].y;
1259     ver[i][2] = 0.0f;// set z to 0
1260     ver[i][3] = 1.0f;
1261   }
1262
1263   // Set texture coordinates
1264   tex[0][0] = tex[3][0] = 0;
1265   tex[0][1] = tex[1][1] = 0;
1266   tex[1][0] = tex[2][0] = 1;
1267   tex[2][1] = tex[3][1] = 1;
1268
1269   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1270
1271   glDisableVertexAttribArray(posLoc);
1272   glDisableVertexAttribArray(texLoc);
1273   glDisableVertexAttribArray(colLoc);
1274
1275   g_Windowing.DisableGUIShader();
1276
1277   VerifyGLState();
1278
1279   glDisable(m_textureTarget);
1280   VerifyGLState();
1281 #endif
1282 }
1283
1284 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1285 {
1286 #if defined(HAS_LIBSTAGEFRIGHT)
1287 #ifdef DEBUG_VERBOSE
1288   unsigned int time = XbmcThreads::SystemClockMillis();
1289 #endif
1290
1291   YUVPLANE &plane = m_buffers[index].fields[field][0];
1292
1293   glDisable(GL_DEPTH_TEST);
1294
1295   glActiveTexture(GL_TEXTURE0);
1296   glBindTexture(m_textureTarget, plane.id);
1297
1298   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1299
1300   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1301   GLfloat ver[4][4];
1302   GLfloat tex[4][2];
1303   float col[4][3];
1304
1305   for (int i = 0;i < 4;++i)
1306   {
1307     col[i][0] = col[i][1] = col[i][2] = 1.0;
1308   }
1309
1310   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1311   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1312   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1313
1314   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1315   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1316   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1317
1318   glEnableVertexAttribArray(posLoc);
1319   glEnableVertexAttribArray(texLoc);
1320   glEnableVertexAttribArray(colLoc);
1321
1322   // Set vertex coordinates
1323   for(int i = 0; i < 4; i++)
1324   {
1325     ver[i][0] = m_rotatedDestCoords[i].x;
1326     ver[i][1] = m_rotatedDestCoords[i].y;
1327     ver[i][2] = 0.0f;// set z to 0
1328     ver[i][3] = 1.0f;
1329   }
1330
1331   // Set texture coordinates (is flipped in y)
1332   tex[0][0] = tex[3][0] = 0;
1333   tex[0][1] = tex[1][1] = 1;
1334   tex[1][0] = tex[2][0] = 1;
1335   tex[2][1] = tex[3][1] = 0;
1336
1337   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1338
1339   glDisableVertexAttribArray(posLoc);
1340   glDisableVertexAttribArray(texLoc);
1341   glDisableVertexAttribArray(colLoc);
1342
1343   g_Windowing.DisableGUIShader();
1344   VerifyGLState();
1345
1346   glBindTexture(m_textureTarget, 0);
1347   VerifyGLState();
1348
1349 #ifdef DEBUG_VERBOSE
1350   CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1351 #endif
1352 #endif
1353 }
1354
1355 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1356 {
1357 #ifdef HAVE_VIDEOTOOLBOXDECODER
1358   YUVPLANE &plane = m_buffers[index].fields[field][0];
1359
1360   glDisable(GL_DEPTH_TEST);
1361
1362   glEnable(m_textureTarget);
1363   glActiveTexture(GL_TEXTURE0);
1364   glBindTexture(m_textureTarget, plane.id);
1365
1366   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1367
1368   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1369   GLfloat ver[4][4];
1370   GLfloat tex[4][2];
1371   float col[4][3];
1372
1373   for (int index = 0;index < 4;++index)
1374   {
1375     col[index][0] = col[index][1] = col[index][2] = 1.0;
1376   }
1377
1378   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1379   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1380   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1381
1382   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1383   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1384   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1385
1386   glEnableVertexAttribArray(posLoc);
1387   glEnableVertexAttribArray(texLoc);
1388   glEnableVertexAttribArray(colLoc);
1389
1390   // Set vertex coordinates
1391   for(int i = 0; i < 4; i++)
1392   {
1393     ver[i][0] = m_rotatedDestCoords[i].x;
1394     ver[i][1] = m_rotatedDestCoords[i].y;
1395     ver[i][2] = 0.0f;// set z to 0
1396     ver[i][3] = 1.0f;
1397   }
1398
1399   // Set texture coordinates (corevideo is flipped in y)
1400   tex[0][0] = tex[3][0] = 0;
1401   tex[0][1] = tex[1][1] = 1;
1402   tex[1][0] = tex[2][0] = 1;
1403   tex[2][1] = tex[3][1] = 0;
1404
1405   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1406
1407   glDisableVertexAttribArray(posLoc);
1408   glDisableVertexAttribArray(texLoc);
1409   glDisableVertexAttribArray(colLoc);
1410
1411   g_Windowing.DisableGUIShader();
1412   VerifyGLState();
1413
1414   glDisable(m_textureTarget);
1415   VerifyGLState();
1416 #endif
1417 }
1418
1419 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1420 {
1421   if (!m_bValidated)
1422     return false;
1423
1424   // If rendered directly by the hardware
1425   if (m_renderMethod & RENDER_BYPASS)
1426   {
1427     capture->BeginRender();
1428     capture->EndRender();
1429     return true;
1430   }
1431
1432   // save current video rect
1433   CRect saveSize = m_destRect;
1434   saveRotatedCoords();//backup current m_rotatedDestCoords
1435
1436   // new video rect is thumbnail size
1437   m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1438   MarkDirty();
1439   syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1440   // clear framebuffer and invert Y axis to get non-inverted image
1441   glDisable(GL_BLEND);
1442
1443   g_matrices.MatrixMode(MM_MODELVIEW);
1444   g_matrices.PushMatrix();
1445   // fixme - we know that cvref  & eglimg are already flipped in y direction
1446   // but somehow this also effects the rendercapture here
1447   // therefore we have to skip the flip here or we get upside down
1448   // images
1449   if (m_renderMethod != RENDER_CVREF)
1450   {
1451     g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1452     g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1453   }
1454
1455   capture->BeginRender();
1456
1457   Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1458   // read pixels
1459   glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1460                GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1461
1462   // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1463   // XOR Swap RGBA -> BGRA
1464   unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1465   for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1466   {
1467     std::swap(pixels[0], pixels[2]);
1468   }
1469
1470   capture->EndRender();
1471
1472   // revert model view matrix
1473   g_matrices.MatrixMode(MM_MODELVIEW);
1474   g_matrices.PopMatrix();
1475
1476   // restore original video rect
1477   m_destRect = saveSize;
1478   restoreRotatedCoords();//restores the previous state of the rotated dest coords
1479
1480   return true;
1481 }
1482
1483 //********************************************************************************************************
1484 // YV12 Texture creation, deletion, copying + clearing
1485 //********************************************************************************************************
1486 void CLinuxRendererGLES::UploadYV12Texture(int source)
1487 {
1488   YUVBUFFER& buf    =  m_buffers[source];
1489   YV12Image* im     = &buf.image;
1490   YUVFIELDS& fields =  buf.fields;
1491
1492
1493 #if defined(HAVE_LIBOPENMAX)
1494   if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1495 #else
1496   if (!(im->flags&IMAGE_FLAG_READY))
1497 #endif
1498   {
1499     return;
1500   }
1501
1502   // if we don't have a shader, fallback to SW YUV2RGB for now
1503   if (m_renderMethod & RENDER_SW)
1504   {
1505     if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1506     {
1507       delete [] m_rgbBuffer;
1508       m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1509       m_rgbBuffer = new BYTE[m_rgbBufferSize];
1510     }
1511
1512 #if defined(__ARM_NEON__)
1513     if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1514     {
1515       yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1516         m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1517     }
1518     else
1519 #endif
1520     {
1521       m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1522         im->width, im->height, PIX_FMT_YUV420P,
1523         im->width, im->height, PIX_FMT_RGBA,
1524         SWS_FAST_BILINEAR, NULL, NULL, NULL);
1525
1526       uint8_t *src[]  = { im->plane[0], im->plane[1], im->plane[2], 0 };
1527       int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1528       uint8_t *dst[]  = { m_rgbBuffer, 0, 0, 0 };
1529       int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1530       m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1531     }
1532   }
1533
1534   bool deinterlacing;
1535   if (m_currentField == FIELD_FULL)
1536     deinterlacing = false;
1537   else
1538     deinterlacing = true;
1539
1540   glEnable(m_textureTarget);
1541   VerifyGLState();
1542
1543   if (m_renderMethod & RENDER_SW)
1544   {
1545     // Load RGB image
1546     if (deinterlacing)
1547     {
1548       LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1549                , im->width, im->height >> 1
1550                , m_sourceWidth*8, m_rgbBuffer );
1551
1552       LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1553                , im->width, im->height >> 1
1554                , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4);
1555     }
1556     else
1557     {
1558       LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1559                , im->width, im->height
1560                , m_sourceWidth*4, m_rgbBuffer );
1561     }
1562   }
1563   else
1564   {
1565     glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1566
1567     if (deinterlacing)
1568     {
1569       // Load Y fields
1570       LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1571                , im->width, im->height >> 1
1572                , im->stride[0]*2, im->plane[0] );
1573
1574       LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1575                , im->width, im->height >> 1
1576                , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
1577     }
1578     else
1579     {
1580       // Load Y plane
1581       LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1582                , im->width, im->height
1583                , im->stride[0], im->plane[0] );
1584     }
1585   }
1586
1587   VerifyGLState();
1588
1589   if (!(m_renderMethod & RENDER_SW))
1590   {
1591     glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1592
1593     if (deinterlacing)
1594     {
1595       // Load Even U & V Fields
1596       LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1597                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1598                , im->stride[1]*2, im->plane[1] );
1599
1600       LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
1601                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1602                , im->stride[2]*2, im->plane[2] );
1603
1604       // Load Odd U & V Fields
1605       LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1606                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1607                , im->stride[1]*2, im->plane[1] + im->stride[1] );
1608
1609       LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
1610                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1611                , im->stride[2]*2, im->plane[2] + im->stride[2] );
1612
1613     }
1614     else
1615     {
1616       LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1617                , im->width >> im->cshift_x, im->height >> im->cshift_y
1618                , im->stride[1], im->plane[1] );
1619
1620       LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
1621                , im->width >> im->cshift_x, im->height >> im->cshift_y
1622                , im->stride[2], im->plane[2] );
1623     }
1624   }
1625   CalculateTextureSourceRects(source, 3);
1626
1627   glDisable(m_textureTarget);
1628 }
1629
1630 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1631 {
1632   YV12Image &im     = m_buffers[index].image;
1633   YUVFIELDS &fields = m_buffers[index].fields;
1634
1635   if( fields[FIELD_FULL][0].id == 0 ) return;
1636
1637   /* finish up all textures, and delete them */
1638   g_graphicsContext.BeginPaint();  //FIXME
1639   for(int f = 0;f<MAX_FIELDS;f++)
1640   {
1641     for(int p = 0;p<MAX_PLANES;p++)
1642     {
1643       if( fields[f][p].id )
1644       {
1645         if (glIsTexture(fields[f][p].id))
1646           glDeleteTextures(1, &fields[f][p].id);
1647         fields[f][p].id = 0;
1648       }
1649     }
1650   }
1651   g_graphicsContext.EndPaint();
1652
1653   for(int p = 0;p<MAX_PLANES;p++)
1654   {
1655     if (im.plane[p])
1656     {
1657       delete[] im.plane[p];
1658       im.plane[p] = NULL;
1659     }
1660   }
1661 }
1662
1663 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1664 {
1665   /* since we also want the field textures, pitch must be texture aligned */
1666   YV12Image &im     = m_buffers[index].image;
1667   YUVFIELDS &fields = m_buffers[index].fields;
1668
1669   DeleteYV12Texture(index);
1670
1671   im.height = m_sourceHeight;
1672   im.width  = m_sourceWidth;
1673   im.cshift_x = 1;
1674   im.cshift_y = 1;
1675
1676   im.stride[0] = im.width;
1677   im.stride[1] = im.width >> im.cshift_x;
1678   im.stride[2] = im.width >> im.cshift_x;
1679
1680   im.planesize[0] = im.stride[0] * im.height;
1681   im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1682   im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1683
1684   for (int i = 0; i < 3; i++)
1685     im.plane[i] = new BYTE[im.planesize[i]];
1686
1687   glEnable(m_textureTarget);
1688   for(int f = 0;f<MAX_FIELDS;f++)
1689   {
1690     for(int p = 0;p<MAX_PLANES;p++)
1691     {
1692       if (!glIsTexture(fields[f][p].id))
1693       {
1694         glGenTextures(1, &fields[f][p].id);
1695         VerifyGLState();
1696       }
1697     }
1698   }
1699
1700   // YUV
1701   for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1702   {
1703     int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1704     YUVPLANES &planes = fields[f];
1705
1706     planes[0].texwidth  = im.width;
1707     planes[0].texheight = im.height >> fieldshift;
1708
1709     if (m_renderMethod & RENDER_SW)
1710     {
1711       planes[1].texwidth  = 0;
1712       planes[1].texheight = 0;
1713       planes[2].texwidth  = 0;
1714       planes[2].texheight = 0;
1715     }
1716     else
1717     {
1718       planes[1].texwidth  = planes[0].texwidth  >> im.cshift_x;
1719       planes[1].texheight = planes[0].texheight >> im.cshift_y;
1720       planes[2].texwidth  = planes[0].texwidth  >> im.cshift_x;
1721       planes[2].texheight = planes[0].texheight >> im.cshift_y;
1722     }
1723
1724     if(m_renderMethod & RENDER_POT)
1725     {
1726       for(int p = 0; p < 3; p++)
1727       {
1728         planes[p].texwidth  = NP2(planes[p].texwidth);
1729         planes[p].texheight = NP2(planes[p].texheight);
1730       }
1731     }
1732
1733     for(int p = 0; p < 3; p++)
1734     {
1735       YUVPLANE &plane = planes[p];
1736       if (plane.texwidth * plane.texheight == 0)
1737         continue;
1738
1739       glBindTexture(m_textureTarget, plane.id);
1740       if (m_renderMethod & RENDER_SW)
1741       {
1742         if(m_renderMethod & RENDER_POT)
1743           CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d",  plane.texwidth, plane.texheight);
1744         else
1745           CLog::Log(LOGDEBUG,  "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1746
1747         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1748         glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1749       }
1750       else
1751       {
1752         if(m_renderMethod & RENDER_POT)
1753           CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d",  plane.texwidth, plane.texheight);
1754         else
1755           CLog::Log(LOGDEBUG,  "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1756
1757         glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
1758       }
1759
1760       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1761       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1762       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1763       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1764       VerifyGLState();
1765     }
1766   }
1767   glDisable(m_textureTarget);
1768   return true;
1769 }
1770
1771 //********************************************************************************************************
1772 // CoreVideoRef Texture creation, deletion, copying + clearing
1773 //********************************************************************************************************
1774 void CLinuxRendererGLES::UploadCVRefTexture(int index)
1775 {
1776 #ifdef HAVE_VIDEOTOOLBOXDECODER
1777   CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
1778
1779   if (cvBufferRef)
1780   {
1781     YUVPLANE &plane = m_buffers[index].fields[0][0];
1782
1783     CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1784     #if !TARGET_OS_IPHONE
1785       int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
1786     #endif
1787     int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
1788     int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
1789     unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
1790
1791     glEnable(m_textureTarget);
1792     VerifyGLState();
1793
1794     glBindTexture(m_textureTarget, plane.id);
1795     #if !TARGET_OS_IPHONE
1796       #ifdef GL_UNPACK_ROW_LENGTH
1797         // Set row pixels
1798         glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
1799       #endif
1800       #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1801         // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1802         glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1803       #endif
1804     #endif
1805
1806     // Using BGRA extension to pull in video frame data directly
1807     glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
1808
1809     #if !TARGET_OS_IPHONE
1810       #ifdef GL_UNPACK_ROW_LENGTH
1811         // Unset row pixels
1812         glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1813       #endif
1814     #endif
1815     glBindTexture(m_textureTarget, 0);
1816
1817     glDisable(m_textureTarget);
1818     VerifyGLState();
1819
1820     CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1821     CVBufferRelease(m_buffers[index].cvBufferRef);
1822     m_buffers[index].cvBufferRef = NULL;
1823
1824     plane.flipindex = m_buffers[index].flipindex;
1825   }
1826 #endif
1827 }
1828 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
1829 {
1830 #ifdef HAVE_VIDEOTOOLBOXDECODER
1831   YUVPLANE &plane = m_buffers[index].fields[0][0];
1832
1833   if (m_buffers[index].cvBufferRef)
1834     CVBufferRelease(m_buffers[index].cvBufferRef);
1835   m_buffers[index].cvBufferRef = NULL;
1836
1837   if(plane.id && glIsTexture(plane.id))
1838     glDeleteTextures(1, &plane.id);
1839   plane.id = 0;
1840 #endif
1841 }
1842 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
1843 {
1844 #ifdef HAVE_VIDEOTOOLBOXDECODER
1845   YV12Image &im     = m_buffers[index].image;
1846   YUVFIELDS &fields = m_buffers[index].fields;
1847   YUVPLANE  &plane  = fields[0][0];
1848
1849   DeleteCVRefTexture(index);
1850
1851   memset(&im    , 0, sizeof(im));
1852   memset(&fields, 0, sizeof(fields));
1853
1854   im.height = m_sourceHeight;
1855   im.width  = m_sourceWidth;
1856
1857   plane.texwidth  = im.width;
1858   plane.texheight = im.height;
1859
1860   if(m_renderMethod & RENDER_POT)
1861   {
1862     plane.texwidth  = NP2(plane.texwidth);
1863     plane.texheight = NP2(plane.texheight);
1864   }
1865   glEnable(m_textureTarget);
1866   glGenTextures(1, &plane.id);
1867   VerifyGLState();
1868
1869   glBindTexture(m_textureTarget, plane.id);
1870   #if !TARGET_OS_IPHONE
1871     #ifdef GL_UNPACK_ROW_LENGTH
1872       // Set row pixels
1873       glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
1874     #endif
1875     #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1876       // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1877       glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1878       // Set client storage
1879     #endif
1880     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1881   #endif
1882
1883   glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1884   glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1885         // This is necessary for non-power-of-two textures
1886   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1887   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1888   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1889   glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1890
1891   #if !TARGET_OS_IPHONE
1892     // turn off client storage so it doesn't get picked up for the next texture
1893     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
1894   #endif
1895   glBindTexture(m_textureTarget, 0);
1896   glDisable(m_textureTarget);
1897 #endif
1898   return true;
1899 }
1900
1901 //********************************************************************************************************
1902 // BYPASS creation, deletion, copying + clearing
1903 //********************************************************************************************************
1904 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
1905 {
1906 }
1907 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
1908 {
1909 }
1910 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
1911 {
1912   return true;
1913 }
1914
1915 //********************************************************************************************************
1916 // EGLIMG creation, deletion, copying + clearing
1917 //********************************************************************************************************
1918 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
1919 {
1920 #ifdef HAS_LIBSTAGEFRIGHT
1921 #ifdef DEBUG_VERBOSE
1922   unsigned int time = XbmcThreads::SystemClockMillis();
1923 #endif
1924
1925   if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
1926   {
1927     YUVPLANE &plane = m_buffers[index].fields[0][0];
1928
1929     glActiveTexture(GL_TEXTURE0);
1930     glBindTexture(m_textureTarget, plane.id);
1931     glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
1932     glBindTexture(m_textureTarget, 0);
1933
1934     plane.flipindex = m_buffers[index].flipindex;
1935   }
1936
1937 #ifdef DEBUG_VERBOSE
1938   CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
1939 #endif
1940 #endif
1941 }
1942 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
1943 {
1944 #ifdef HAS_LIBSTAGEFRIGHT
1945   YUVPLANE &plane = m_buffers[index].fields[0][0];
1946
1947   if(plane.id && glIsTexture(plane.id))
1948     glDeleteTextures(1, &plane.id);
1949   plane.id = 0;
1950 #endif
1951 }
1952 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
1953 {
1954 #ifdef HAS_LIBSTAGEFRIGHT
1955   YV12Image &im     = m_buffers[index].image;
1956   YUVFIELDS &fields = m_buffers[index].fields;
1957   YUVPLANE  &plane  = fields[0][0];
1958
1959   DeleteEGLIMGTexture(index);
1960
1961   memset(&im    , 0, sizeof(im));
1962   memset(&fields, 0, sizeof(fields));
1963
1964   im.height = m_sourceHeight;
1965   im.width  = m_sourceWidth;
1966
1967   plane.texwidth  = im.width;
1968   plane.texheight = im.height;
1969
1970   if(m_renderMethod & RENDER_POT)
1971   {
1972     plane.texwidth  = NP2(plane.texwidth);
1973     plane.texheight = NP2(plane.texheight);
1974   }
1975   glEnable(m_textureTarget);
1976   glGenTextures(1, &plane.id);
1977   VerifyGLState();
1978
1979   glBindTexture(m_textureTarget, plane.id);
1980
1981   glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1982   glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1983         // This is necessary for non-power-of-two textures
1984   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1985   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1986
1987   glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1988
1989   glDisable(m_textureTarget);
1990 #endif
1991   return true;
1992 }
1993
1994 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
1995 {
1996   for (int i = 0 ; i<m_NumYV12Buffers ; i++)
1997   {
1998     YUVFIELDS &fields = m_buffers[i].fields;
1999
2000     for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2001     {
2002       glBindTexture(m_textureTarget, fields[f][0].id);
2003       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2004       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2005       VerifyGLState();
2006
2007       if (!(m_renderMethod & RENDER_SW))
2008       {
2009         glBindTexture(m_textureTarget, fields[f][1].id);
2010         glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2011         glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2012         VerifyGLState();
2013
2014         glBindTexture(m_textureTarget, fields[f][2].id);
2015         glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2016         glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2017         VerifyGLState();
2018       }
2019     }
2020   }
2021 }
2022
2023 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2024 {
2025   // Player controls render, let it dictate available render features
2026   if((m_renderMethod & RENDER_BYPASS))
2027   {
2028     Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2029     return itr != m_renderFeatures.end();
2030   }
2031
2032   if(feature == RENDERFEATURE_BRIGHTNESS)
2033     return false;
2034
2035   if(feature == RENDERFEATURE_CONTRAST)
2036     return false;
2037
2038   if(feature == RENDERFEATURE_GAMMA)
2039     return false;
2040
2041   if(feature == RENDERFEATURE_NOISE)
2042     return false;
2043
2044   if(feature == RENDERFEATURE_SHARPNESS)
2045     return false;
2046
2047   if (feature == RENDERFEATURE_NONLINSTRETCH)
2048     return false;
2049
2050   if (feature == RENDERFEATURE_STRETCH         ||
2051       feature == RENDERFEATURE_CROP            ||
2052       feature == RENDERFEATURE_ZOOM            ||
2053       feature == RENDERFEATURE_VERTICAL_SHIFT  ||
2054       feature == RENDERFEATURE_PIXEL_RATIO     ||
2055       feature == RENDERFEATURE_POSTPROCESS     ||
2056       feature == RENDERFEATURE_ROTATION)
2057     return true;
2058
2059
2060   return false;
2061 }
2062
2063 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2064 {
2065   return false;
2066 }
2067
2068 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2069 {
2070   // Player controls render, let it dictate available deinterlace modes
2071   if((m_renderMethod & RENDER_BYPASS))
2072   {
2073     Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2074     return itr != m_deinterlaceModes.end();
2075   }
2076
2077   if (mode == VS_DEINTERLACEMODE_OFF)
2078     return true;
2079
2080   if(m_renderMethod & RENDER_OMXEGL)
2081     return false;
2082
2083   if(m_renderMethod & RENDER_EGLIMG)
2084     return false;
2085
2086   if(m_renderMethod & RENDER_CVREF)
2087     return false;
2088
2089   if(mode == VS_DEINTERLACEMODE_AUTO
2090   || mode == VS_DEINTERLACEMODE_FORCE)
2091     return true;
2092
2093   return false;
2094 }
2095
2096 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2097 {
2098   // Player controls render, let it dictate available deinterlace methods
2099   if((m_renderMethod & RENDER_BYPASS))
2100   {
2101     Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2102     return itr != m_deinterlaceMethods.end();
2103   }
2104
2105   if(m_renderMethod & RENDER_OMXEGL)
2106     return false;
2107
2108   if(m_renderMethod & RENDER_EGLIMG)
2109     return false;
2110
2111   if(m_renderMethod & RENDER_CVREF)
2112     return false;
2113
2114   if(method == VS_INTERLACEMETHOD_AUTO)
2115     return true;
2116
2117 #if defined(__i386__) || defined(__x86_64__)
2118   if(method == VS_INTERLACEMETHOD_DEINTERLACE
2119   || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2120   || method == VS_INTERLACEMETHOD_SW_BLEND)
2121 #else
2122   if(method == VS_INTERLACEMETHOD_SW_BLEND)
2123 #endif
2124     return true;
2125
2126   return false;
2127 }
2128
2129 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2130 {
2131   // Player controls render, let it dictate available scaling methods
2132   if((m_renderMethod & RENDER_BYPASS))
2133   {
2134     Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2135     return itr != m_scalingMethods.end();
2136   }
2137
2138   if(method == VS_SCALINGMETHOD_NEAREST
2139   || method == VS_SCALINGMETHOD_LINEAR)
2140     return true;
2141
2142   return false;
2143 }
2144
2145 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2146 {
2147   // Player controls render, let it pick the auto-deinterlace method
2148   if((m_renderMethod & RENDER_BYPASS))
2149   {
2150     if (!m_deinterlaceMethods.empty())
2151       return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2152     else
2153       return VS_INTERLACEMETHOD_NONE;
2154   }
2155
2156   if(m_renderMethod & RENDER_OMXEGL)
2157     return VS_INTERLACEMETHOD_NONE;
2158
2159   if(m_renderMethod & RENDER_EGLIMG)
2160     return VS_INTERLACEMETHOD_NONE;
2161
2162   if(m_renderMethod & RENDER_CVREF)
2163     return VS_INTERLACEMETHOD_NONE;
2164
2165 #if defined(__i386__) || defined(__x86_64__)
2166   return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2167 #else
2168   return VS_INTERLACEMETHOD_SW_BLEND;
2169 #endif
2170 }
2171
2172 unsigned int CLinuxRendererGLES::GetProcessorSize()
2173 {
2174   if(m_format == RENDER_FMT_OMXEGL
2175   || m_format == RENDER_FMT_CVBREF
2176   || m_format == RENDER_FMT_EGLIMG)
2177     return 1;
2178   else
2179     return 0;
2180 }
2181
2182 #ifdef HAVE_LIBOPENMAX
2183 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2184 {
2185   YUVBUFFER &buf = m_buffers[index];
2186   buf.openMaxBuffer = picture->openMaxBuffer;
2187 }
2188 #endif
2189 #ifdef HAVE_VIDEOTOOLBOXDECODER
2190 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2191 {
2192   YUVBUFFER &buf = m_buffers[index];
2193   if (buf.cvBufferRef)
2194     CVBufferRelease(buf.cvBufferRef);
2195   buf.cvBufferRef = cvBufferRef;
2196   // retain another reference, this way dvdplayer and renderer can issue releases.
2197   CVBufferRetain(buf.cvBufferRef);
2198 }
2199 #endif
2200 #ifdef HAS_LIBSTAGEFRIGHT
2201 void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
2202 {
2203 #ifdef DEBUG_VERBOSE
2204   unsigned int time = XbmcThreads::SystemClockMillis();
2205 #endif
2206
2207   YUVBUFFER &buf = m_buffers[index];
2208   if (buf.eglimg != EGL_NO_IMAGE_KHR)
2209     stf->ReleaseBuffer(buf.eglimg);
2210   stf->LockBuffer(eglimg);
2211
2212   buf.stf = stf;
2213   buf.eglimg = eglimg;
2214
2215 #ifdef DEBUG_VERBOSE
2216   CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);
2217 #endif
2218 }
2219 #endif
2220
2221 #endif
2222