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