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