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