Merge pull request #4539 from Matricom/amcodec
[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
21 //#define DEBUG_VERBOSE 1
22
23 #include "system.h"
24 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
25   #include "config.h"
26 #endif
27
28 #if HAS_GLES == 2
29 #include "system_gl.h"
30
31 #include <locale.h>
32 #include "guilib/MatrixGLES.h"
33 #include "LinuxRendererGLES.h"
34 #include "utils/fastmemcpy.h"
35 #include "utils/MathUtils.h"
36 #include "utils/GLUtils.h"
37 #include "settings/AdvancedSettings.h"
38 #include "settings/DisplaySettings.h"
39 #include "settings/MediaSettings.h"
40 #include "settings/Settings.h"
41 #include "guilib/FrameBufferObject.h"
42 #include "VideoShaders/YUV2RGBShader.h"
43 #include "VideoShaders/VideoFilterShader.h"
44 #include "windowing/WindowingFactory.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/DVDVideoCodecStageFright.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       // protect against division by zero
379       if (p.texheight == 0 || p.texwidth == 0 ||
380           p.pixpertex_x == 0 || p.pixpertex_y == 0)
381       {
382         continue;
383       }
384
385       p.height  /= p.pixpertex_y;
386       p.rect.y1 /= p.pixpertex_y;
387       p.rect.y2 /= p.pixpertex_y;
388       p.width   /= p.pixpertex_x;
389       p.rect.x1 /= p.pixpertex_x;
390       p.rect.x2 /= p.pixpertex_x;
391
392       if (m_textureTarget == GL_TEXTURE_2D)
393       {
394         p.height  /= p.texheight;
395         p.rect.y1 /= p.texheight;
396         p.rect.y2 /= p.texheight;
397         p.width   /= p.texwidth;
398         p.rect.x1 /= p.texwidth;
399         p.rect.x2 /= p.texwidth;
400       }
401     }
402   }
403 }
404
405 void CLinuxRendererGLES::LoadPlane( YUVPLANE& plane, int type, unsigned flipindex
406                                 , unsigned width, unsigned height
407                                 , unsigned int stride, int bpp, void* data )
408 {
409   if(plane.flipindex == flipindex)
410     return;
411
412   const GLvoid *pixelData = data;
413
414   int bps = bpp * glFormatElementByteCount(type);
415
416   unsigned datatype;
417   if(bpp == 2)
418     datatype = GL_UNSIGNED_SHORT;
419   else
420     datatype = GL_UNSIGNED_BYTE;
421
422   glBindTexture(m_textureTarget, plane.id);
423
424   // OpenGL ES does not support strided texture input.
425   if(stride != width * bps)
426   {
427     unsigned char* src = (unsigned char*)data;
428     for (unsigned int y = 0; y < height;++y, src += stride)
429       glTexSubImage2D(m_textureTarget, 0, 0, y, width, 1, type, datatype, src);
430   } else {
431     glTexSubImage2D(m_textureTarget, 0, 0, 0, width, height, type, datatype, pixelData);
432   }
433
434   /* check if we need to load any border pixels */
435   if(height < plane.texheight)
436     glTexSubImage2D( m_textureTarget, 0
437                    , 0, height, width, 1
438                    , type, datatype
439                    , (unsigned char*)pixelData + stride * (height-1));
440
441   if(width  < plane.texwidth)
442     glTexSubImage2D( m_textureTarget, 0
443                    , width, 0, 1, height
444                    , type, datatype
445                    , (unsigned char*)pixelData + bps * (width-1));
446
447   glBindTexture(m_textureTarget, 0);
448
449   plane.flipindex = flipindex;
450 }
451
452 void CLinuxRendererGLES::Reset()
453 {
454   for(int i=0; i<m_NumYV12Buffers; i++)
455   {
456     /* reset all image flags, this will cleanup textures later */
457     m_buffers[i].image.flags = 0;
458   }
459 }
460
461 void CLinuxRendererGLES::Flush()
462 {
463   if (!m_bValidated)
464     return;
465
466   glFinish();
467
468   for (int i = 0 ; i < m_NumYV12Buffers ; i++)
469     (this->*m_textureDelete)(i);
470
471   glFinish();
472   m_bValidated = false;
473   m_fbo.Cleanup();
474   m_iYV12RenderBuffer = 0;
475 }
476
477 void CLinuxRendererGLES::Update()
478 {
479   if (!m_bConfigured) return;
480   ManageDisplay();
481 }
482
483 void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
484 {
485   if (!m_bConfigured) return;
486
487   // if its first pass, just init textures and return
488   if (ValidateRenderTarget())
489     return;
490
491   if (m_renderMethod & RENDER_BYPASS)
492   {
493     ManageDisplay();
494     // if running bypass, then the player might need the src/dst rects
495     // for sizing video playback on a layer other than the gles layer.
496     if (m_RenderUpdateCallBackFn)
497       (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect);
498
499     CRect old = g_graphicsContext.GetScissors();
500
501     g_graphicsContext.BeginPaint();
502     g_graphicsContext.SetScissors(m_destRect);
503
504     glEnable(GL_BLEND);
505     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
506     glClearColor(0, 0, 0, 0);
507     glClear(GL_COLOR_BUFFER_BIT);
508
509     g_graphicsContext.SetScissors(old);
510     g_graphicsContext.EndPaint();
511     return;
512   }
513
514   // this needs to be checked after texture validation
515   if (!m_bImageReady) return;
516
517   int index = m_iYV12RenderBuffer;
518   YUVBUFFER& buf =  m_buffers[index];
519
520   if (m_format != RENDER_FMT_OMXEGL && m_format != RENDER_FMT_EGLIMG && m_format != RENDER_FMT_MEDIACODEC)
521   {
522     if (!buf.fields[FIELD_FULL][0].id) return;
523   }
524   if (buf.image.flags==0)
525     return;
526
527   ManageDisplay();
528
529   g_graphicsContext.BeginPaint();
530
531   m_iLastRenderBuffer = index;
532
533   if (clear)
534   {
535     glClearColor(m_clearColour, m_clearColour, m_clearColour, 0);
536     glClear(GL_COLOR_BUFFER_BIT);
537     glClearColor(0,0,0,0);
538   }
539
540   if (alpha<255)
541   {
542     glEnable(GL_BLEND);
543     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
544     if (m_pYUVShader)
545       m_pYUVShader->SetAlpha(alpha / 255.0f);
546   }
547   else
548   {
549     glDisable(GL_BLEND);
550     if (m_pYUVShader)
551       m_pYUVShader->SetAlpha(1.0f);
552   }
553
554   if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT))
555     CLog::Log(LOGERROR, "GLES: Cannot render stipple!");
556   else
557     Render(flags, index);
558
559   VerifyGLState();
560   glEnable(GL_BLEND);
561
562   g_graphicsContext.EndPaint();
563 }
564
565 void CLinuxRendererGLES::FlipPage(int source)
566 {
567   if( source >= 0 && source < m_NumYV12Buffers )
568     m_iYV12RenderBuffer = source;
569   else
570     m_iYV12RenderBuffer = NextYV12Texture();
571
572   m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
573
574   return;
575 }
576
577 unsigned int CLinuxRendererGLES::PreInit()
578 {
579   CSingleLock lock(g_graphicsContext);
580   m_bConfigured = false;
581   m_bValidated = false;
582   UnInit();
583   m_resolution = CDisplaySettings::Get().GetCurrentResolution();
584   if ( m_resolution == RES_WINDOW )
585     m_resolution = RES_DESKTOP;
586
587   m_iYV12RenderBuffer = 0;
588   m_NumYV12Buffers = 2;
589
590   m_formats.clear();
591   m_formats.push_back(RENDER_FMT_YUV420P);
592   m_formats.push_back(RENDER_FMT_NV12);
593   m_formats.push_back(RENDER_FMT_BYPASS);
594 #if defined(HAVE_LIBOPENMAX)
595   m_formats.push_back(RENDER_FMT_OMXEGL);
596 #endif
597 #ifdef HAVE_VIDEOTOOLBOXDECODER
598   m_formats.push_back(RENDER_FMT_CVBREF);
599 #endif
600 #ifdef HAS_LIBSTAGEFRIGHT
601   m_formats.push_back(RENDER_FMT_EGLIMG);
602 #endif
603 #if defined(TARGET_ANDROID)
604   m_formats.push_back(RENDER_FMT_MEDIACODEC);
605 #endif
606
607   // setup the background colour
608   m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
609
610   if (!m_dllSwScale->Load())
611     CLog::Log(LOGERROR,"CLinuxRendererGL::PreInit - failed to load rescale libraries!");
612
613   return true;
614 }
615
616 void CLinuxRendererGLES::UpdateVideoFilter()
617 {
618   if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod)
619     return;
620   m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
621   m_scalingMethod    = m_scalingMethodGui;
622
623   if(!Supports(m_scalingMethod))
624   {
625     CLog::Log(LOGWARNING, "CLinuxRendererGLES::UpdateVideoFilter - choosen scaling method %d, is not supported by renderer", (int)m_scalingMethod);
626     m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
627   }
628
629   if (m_pVideoFilterShader)
630   {
631     m_pVideoFilterShader->Free();
632     delete m_pVideoFilterShader;
633     m_pVideoFilterShader = NULL;
634   }
635   m_fbo.Cleanup();
636
637   VerifyGLState();
638
639   switch (m_scalingMethod)
640   {
641   case VS_SCALINGMETHOD_NEAREST:
642     SetTextureFilter(GL_NEAREST);
643     m_renderQuality = RQ_SINGLEPASS;
644     return;
645
646   case VS_SCALINGMETHOD_LINEAR:
647     SetTextureFilter(GL_LINEAR);
648     m_renderQuality = RQ_SINGLEPASS;
649     return;
650
651   case VS_SCALINGMETHOD_CUBIC:
652     CLog::Log(LOGERROR, "GLES: CUBIC not supported!");
653     break;
654
655   case VS_SCALINGMETHOD_LANCZOS2:
656   case VS_SCALINGMETHOD_LANCZOS3:
657   case VS_SCALINGMETHOD_SINC8:
658   case VS_SCALINGMETHOD_NEDI:
659     CLog::Log(LOGERROR, "GL: TODO: This scaler has not yet been implemented");
660     break;
661
662   default:
663     break;
664   }
665
666   CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler");
667   if (m_pVideoFilterShader)
668   {
669     m_pVideoFilterShader->Free();
670     delete m_pVideoFilterShader;
671     m_pVideoFilterShader = NULL;
672   }
673   m_fbo.Cleanup();
674
675   SetTextureFilter(GL_LINEAR);
676   m_renderQuality = RQ_SINGLEPASS;
677 }
678
679 void CLinuxRendererGLES::LoadShaders(int field)
680 {
681 #ifdef TARGET_DARWIN_IOS
682   float ios_version = GetIOSVersion();
683 #endif
684   int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
685   CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod);
686
687   if (m_pYUVShader)
688   {
689     m_pYUVShader->Free();
690     delete m_pYUVShader;
691     m_pYUVShader = NULL;
692   }
693
694   switch(requestedMethod)
695   {
696     case RENDER_METHOD_AUTO:
697     case RENDER_METHOD_GLSL:
698       if (m_format == RENDER_FMT_OMXEGL)
699       {
700         CLog::Log(LOGNOTICE, "GL: Using OMXEGL RGBA render method");
701         m_renderMethod = RENDER_OMXEGL;
702         break;
703       }
704       else if (m_format == RENDER_FMT_EGLIMG)
705       {
706         CLog::Log(LOGNOTICE, "GL: Using EGL Image render method");
707         m_renderMethod = RENDER_EGLIMG;
708         break;
709       }
710       else if (m_format == RENDER_FMT_MEDIACODEC)
711       {
712         CLog::Log(LOGNOTICE, "GL: Using MediaCodec render method");
713         m_renderMethod = RENDER_MEDIACODEC;
714         break;
715       }
716       else if (m_format == RENDER_FMT_BYPASS)
717       {
718         CLog::Log(LOGNOTICE, "GL: Using BYPASS render method");
719         m_renderMethod = RENDER_BYPASS;
720         break;
721       }
722       else if (m_format == RENDER_FMT_CVBREF)
723       {
724         CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef RGBA render method");
725         m_renderMethod = RENDER_CVREF;
726         break;
727       }
728       #if defined(TARGET_DARWIN_IOS)
729       else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P)
730       {
731         CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA render method");
732         m_renderMethod = RENDER_SW;
733         break;
734       }
735       #endif
736       // Try GLSL shaders if supported and user requested auto or GLSL.
737       if (glCreateProgram)
738       {
739         // create regular progressive scan shader
740         m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format);
741         CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
742
743         if (m_pYUVShader && m_pYUVShader->CompileAndLink())
744         {
745           m_renderMethod = RENDER_GLSL;
746           UpdateVideoFilter();
747           break;
748         }
749         else if (m_pYUVShader)
750         {
751           m_pYUVShader->Free();
752           delete m_pYUVShader;
753           m_pYUVShader = NULL;
754           CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader");
755           // drop through and try SW
756         }
757       }
758     case RENDER_METHOD_SOFTWARE:
759     default:
760       {
761         // Use software YUV 2 RGB conversion if user requested it or GLSL failed
762         m_renderMethod = RENDER_SW ;
763         CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA rendering");
764       }
765   }
766
767   // determine whether GPU supports NPOT textures
768   if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
769   {
770     CLog::Log(LOGNOTICE, "GL: GL_ARB_texture_rectangle not supported and OpenGL version is not 2.x");
771     CLog::Log(LOGNOTICE, "GL: Reverting to POT textures");
772     m_renderMethod |= RENDER_POT;
773   }
774   else
775     CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
776
777   // Now that we now the render method, setup texture function handlers
778   if (m_format == RENDER_FMT_CVBREF)
779   {
780     m_textureUpload = &CLinuxRendererGLES::UploadCVRefTexture;
781     m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
782     m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
783   }
784   else if (m_format == RENDER_FMT_BYPASS)
785   {
786     m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
787     m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
788     m_textureDelete = &CLinuxRendererGLES::DeleteBYPASSTexture;
789   }
790   else if (m_format == RENDER_FMT_EGLIMG)
791   {
792     m_textureUpload = &CLinuxRendererGLES::UploadEGLIMGTexture;
793     m_textureCreate = &CLinuxRendererGLES::CreateEGLIMGTexture;
794     m_textureDelete = &CLinuxRendererGLES::DeleteEGLIMGTexture;
795   }
796   else if (m_format == RENDER_FMT_MEDIACODEC)
797   {
798     m_textureUpload = &CLinuxRendererGLES::UploadSurfaceTexture;
799     m_textureCreate = &CLinuxRendererGLES::CreateSurfaceTexture;
800     m_textureDelete = &CLinuxRendererGLES::DeleteSurfaceTexture;
801   }
802   else if (m_format == RENDER_FMT_NV12)
803   {
804     m_textureUpload = &CLinuxRendererGLES::UploadNV12Texture;
805     m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture;
806     m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture;
807   }
808   else
809   {
810     // default to YV12 texture handlers
811     m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
812     m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
813     m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
814   }
815
816   if (m_oldRenderMethod != m_renderMethod)
817   {
818     CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod);
819     ReorderDrawPoints();
820     m_oldRenderMethod = m_renderMethod;
821   }
822 }
823
824 void CLinuxRendererGLES::UnInit()
825 {
826   CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources");
827   CSingleLock lock(g_graphicsContext);
828
829   if (m_rgbBuffer != NULL)
830   {
831     delete [] m_rgbBuffer;
832     m_rgbBuffer = NULL;
833   }
834   m_rgbBufferSize = 0;
835
836   // YV12 textures
837   for (int i = 0; i < NUM_BUFFERS; ++i)
838     (this->*m_textureDelete)(i);
839
840   if (m_dllSwScale && m_sw_context)
841   {
842     m_dllSwScale->sws_freeContext(m_sw_context);
843     m_sw_context = NULL;
844   }
845
846   // cleanup framebuffer object if it was in use
847   m_fbo.Cleanup();
848   m_bValidated = false;
849   m_bImageReady = false;
850   m_bConfigured = false;
851   m_RenderUpdateCallBackFn = NULL;
852   m_RenderUpdateCallBackCtx = NULL;
853   m_RenderFeaturesCallBackFn = NULL;
854   m_RenderFeaturesCallBackCtx = NULL;
855 }
856
857 inline void CLinuxRendererGLES::ReorderDrawPoints()
858 {
859
860   CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points
861
862   //corevideo and EGL are flipped in y
863   if(m_renderMethod & RENDER_CVREF)
864   {
865     CPoint tmp;
866     tmp = m_rotatedDestCoords[0];
867     m_rotatedDestCoords[0] = m_rotatedDestCoords[3];
868     m_rotatedDestCoords[3] = tmp;
869     tmp = m_rotatedDestCoords[1];
870     m_rotatedDestCoords[1] = m_rotatedDestCoords[2];
871     m_rotatedDestCoords[2] = tmp;
872   }
873 }
874
875 void CLinuxRendererGLES::ReleaseBuffer(int idx)
876 {
877   YUVBUFFER &buf = m_buffers[idx];
878 #ifdef HAVE_VIDEOTOOLBOXDECODER
879   if (m_renderMethod & RENDER_CVREF )
880   {
881     if (buf.cvBufferRef)
882       CVBufferRelease(buf.cvBufferRef);
883     buf.cvBufferRef = NULL;
884   }
885 #endif
886 #if defined(TARGET_ANDROID)
887   if ( m_renderMethod & RENDER_MEDIACODEC )
888   {
889     if (buf.mediacodec)
890     {
891       // The media buffer has been queued to the SurfaceView but we didn't render it
892       // We have to do to the updateTexImage or it will get stuck
893       buf.mediacodec->UpdateTexImage();
894       SAFE_RELEASE(buf.mediacodec);
895     }
896   }
897 #endif
898 }
899
900 void CLinuxRendererGLES::Render(DWORD flags, int index)
901 {
902   // If rendered directly by the hardware
903   if (m_renderMethod & RENDER_BYPASS)
904     return;
905
906   // obtain current field, if interlaced
907   if( flags & RENDER_FLAG_TOP)
908     m_currentField = FIELD_TOP;
909
910   else if (flags & RENDER_FLAG_BOT)
911     m_currentField = FIELD_BOT;
912
913   else
914     m_currentField = FIELD_FULL;
915
916   (this->*m_textureUpload)(index);
917
918   if (m_renderMethod & RENDER_GLSL)
919   {
920     UpdateVideoFilter();
921     switch(m_renderQuality)
922     {
923     case RQ_LOW:
924     case RQ_SINGLEPASS:
925       RenderSinglePass(index, m_currentField);
926       VerifyGLState();
927       break;
928
929     case RQ_MULTIPASS:
930       RenderMultiPass(index, m_currentField);
931       VerifyGLState();
932       break;
933
934     case RQ_SOFTWARE:
935       RenderSoftware(index, m_currentField);
936       VerifyGLState();
937       break;
938     }
939   }
940   else if (m_renderMethod & RENDER_OMXEGL)
941   {
942     RenderOpenMax(index, m_currentField);
943     VerifyGLState();
944   }
945   else if (m_renderMethod & RENDER_EGLIMG)
946   {
947     RenderEglImage(index, m_currentField);
948     VerifyGLState();
949   }
950   else if (m_renderMethod & RENDER_CVREF)
951   {
952     RenderCoreVideoRef(index, m_currentField);
953     VerifyGLState();
954   }
955   else if (m_renderMethod & RENDER_MEDIACODEC)
956   {
957     RenderSurfaceTexture(index, m_currentField);
958   }
959   else
960   {
961     RenderSoftware(index, m_currentField);
962     VerifyGLState();
963   }
964 }
965
966 void CLinuxRendererGLES::RenderSinglePass(int index, int field)
967 {
968   YV12Image &im     = m_buffers[index].image;
969   YUVFIELDS &fields = m_buffers[index].fields;
970   YUVPLANES &planes = fields[field];
971
972   if (m_reloadShaders)
973   {
974     m_reloadShaders = 0;
975     LoadShaders(field);
976   }
977
978   glDisable(GL_DEPTH_TEST);
979
980   // Y
981   glActiveTexture(GL_TEXTURE0);
982   glEnable(m_textureTarget);
983   glBindTexture(m_textureTarget, planes[0].id);
984
985   // U
986   glActiveTexture(GL_TEXTURE1);
987   glEnable(m_textureTarget);
988   glBindTexture(m_textureTarget, planes[1].id);
989
990   // V
991   glActiveTexture(GL_TEXTURE2);
992   glEnable(m_textureTarget);
993   glBindTexture(m_textureTarget, planes[2].id);
994
995   glActiveTexture(GL_TEXTURE0);
996   VerifyGLState();
997
998   m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
999   m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1000   m_pYUVShader->SetWidth(im.width);
1001   m_pYUVShader->SetHeight(im.height);
1002   if     (field == FIELD_TOP)
1003     m_pYUVShader->SetField(1);
1004   else if(field == FIELD_BOT)
1005     m_pYUVShader->SetField(0);
1006
1007   m_pYUVShader->SetMatrices(g_matrices.GetMatrix(MM_PROJECTION), g_matrices.GetMatrix(MM_MODELVIEW));
1008   m_pYUVShader->Enable();
1009
1010   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1011   GLfloat m_vert[4][3];
1012   GLfloat m_tex[3][4][2];
1013
1014   GLint vertLoc = m_pYUVShader->GetVertexLoc();
1015   GLint Yloc    = m_pYUVShader->GetYcoordLoc();
1016   GLint Uloc    = m_pYUVShader->GetUcoordLoc();
1017   GLint Vloc    = m_pYUVShader->GetVcoordLoc();
1018
1019   glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert);
1020   glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]);
1021   glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, m_tex[1]);
1022   glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, m_tex[2]);
1023
1024   glEnableVertexAttribArray(vertLoc);
1025   glEnableVertexAttribArray(Yloc);
1026   glEnableVertexAttribArray(Uloc);
1027   glEnableVertexAttribArray(Vloc);
1028
1029   // Setup vertex position values
1030   for(int i = 0; i < 4; i++)
1031   {
1032     m_vert[i][0] = m_rotatedDestCoords[i].x;
1033     m_vert[i][1] = m_rotatedDestCoords[i].y;
1034     m_vert[i][2] = 0.0f;// set z to 0
1035   }
1036
1037   // Setup texture coordinates
1038   for (int i=0; i<3; i++)
1039   {
1040     m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1;
1041     m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1;
1042     m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2;
1043     m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2;
1044   }
1045
1046   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1047
1048   VerifyGLState();
1049
1050   m_pYUVShader->Disable();
1051   VerifyGLState();
1052
1053   glDisableVertexAttribArray(vertLoc);
1054   glDisableVertexAttribArray(Yloc);
1055   glDisableVertexAttribArray(Uloc);
1056   glDisableVertexAttribArray(Vloc);
1057
1058   glActiveTexture(GL_TEXTURE1);
1059   glDisable(m_textureTarget);
1060
1061   glActiveTexture(GL_TEXTURE2);
1062   glDisable(m_textureTarget);
1063
1064   glActiveTexture(GL_TEXTURE0);
1065   glDisable(m_textureTarget);
1066
1067   g_matrices.MatrixMode(MM_MODELVIEW);
1068
1069   VerifyGLState();
1070 }
1071
1072 void CLinuxRendererGLES::RenderMultiPass(int index, int field)
1073 {
1074   // TODO: Multipass rendering does not currently work! FIX!
1075   CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!");
1076   return;
1077
1078   YV12Image &im     = m_buffers[index].image;
1079   YUVPLANES &planes = m_buffers[index].fields[field];
1080
1081   if (m_reloadShaders)
1082   {
1083     m_reloadShaders = 0;
1084     LoadShaders(m_currentField);
1085   }
1086
1087   glDisable(GL_DEPTH_TEST);
1088
1089   // Y
1090   glEnable(m_textureTarget);
1091   glActiveTexture(GL_TEXTURE0);
1092   glBindTexture(m_textureTarget, planes[0].id);
1093   VerifyGLState();
1094
1095   // U
1096   glActiveTexture(GL_TEXTURE1);
1097   glEnable(m_textureTarget);
1098   glBindTexture(m_textureTarget, planes[1].id);
1099   VerifyGLState();
1100
1101   // V
1102   glActiveTexture(GL_TEXTURE2);
1103   glEnable(m_textureTarget);
1104   glBindTexture(m_textureTarget, planes[2].id);
1105   VerifyGLState();
1106
1107   glActiveTexture(GL_TEXTURE0);
1108   VerifyGLState();
1109
1110   // make sure the yuv shader is loaded and ready to go
1111   if (!m_pYUVShader || (!m_pYUVShader->OK()))
1112   {
1113     CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render");
1114     return;
1115   }
1116
1117   m_fbo.BeginRender();
1118   VerifyGLState();
1119
1120   m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
1121   m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1122   m_pYUVShader->SetWidth(im.width);
1123   m_pYUVShader->SetHeight(im.height);
1124   if     (field == FIELD_TOP)
1125     m_pYUVShader->SetField(1);
1126   else if(field == FIELD_BOT)
1127     m_pYUVShader->SetField(0);
1128
1129   VerifyGLState();
1130 //TODO
1131 //  glPushAttrib(GL_VIEWPORT_BIT);
1132 //  glPushAttrib(GL_SCISSOR_BIT);
1133   g_matrices.MatrixMode(MM_MODELVIEW);
1134   g_matrices.PushMatrix();
1135   g_matrices.LoadIdentity();
1136   VerifyGLState();
1137
1138   g_matrices.MatrixMode(MM_PROJECTION);
1139   g_matrices.PushMatrix();
1140   g_matrices.LoadIdentity();
1141   VerifyGLState();
1142   g_matrices.Ortho2D(0, m_sourceWidth, 0, m_sourceHeight);
1143   CRect viewport(0, 0, m_sourceWidth, m_sourceHeight);
1144   g_Windowing.SetViewPort(viewport);
1145   g_matrices.MatrixMode(MM_MODELVIEW);
1146   VerifyGLState();
1147
1148
1149   if (!m_pYUVShader->Enable())
1150   {
1151     CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
1152   }
1153
1154 // 1st Pass to video frame size
1155 //TODO
1156 //  float imgwidth  = planes[0].rect.x2 - planes[0].rect.x1;
1157 //  float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
1158 //  if (m_textureTarget == GL_TEXTURE_2D)
1159 //  {
1160 //    imgwidth  *= planes[0].pixpertex_x;
1161 //    imgheight *= planes[0].pixpertex_y;
1162 //  }
1163 //  
1164 //  glBegin(GL_QUADS);
1165 //
1166 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
1167 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
1168 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
1169 //  glVertex2f(0.0f    , 0.0f);
1170 //
1171 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
1172 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
1173 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
1174 //  glVertex2f(imgwidth, 0.0f);
1175 //
1176 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
1177 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
1178 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
1179 //  glVertex2f(imgwidth, imgheight);
1180 //
1181 //  glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
1182 //  glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
1183 //  glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
1184 //  glVertex2f(0.0f    , imgheight);
1185 //
1186 //  glEnd();
1187 //  VerifyGLState();
1188
1189   m_pYUVShader->Disable();
1190
1191   g_matrices.MatrixMode(MM_MODELVIEW);
1192   g_matrices.PopMatrix(); // pop modelview
1193   g_matrices.MatrixMode(MM_PROJECTION);
1194   g_matrices.PopMatrix(); // pop projection
1195 //TODO
1196 //  glPopAttrib(); // pop scissor
1197 //  glPopAttrib(); // pop viewport
1198   g_matrices.MatrixMode(MM_MODELVIEW);
1199   VerifyGLState();
1200
1201   m_fbo.EndRender();
1202
1203   glActiveTexture(GL_TEXTURE1);
1204   glDisable(m_textureTarget);
1205   glActiveTexture(GL_TEXTURE2);
1206   glDisable(m_textureTarget);
1207   glActiveTexture(GL_TEXTURE0);
1208   glDisable(m_textureTarget);
1209
1210   glEnable(GL_TEXTURE_2D);
1211   glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
1212   VerifyGLState();
1213
1214   // Use regular normalized texture coordinates
1215
1216   // 2nd Pass to screen size with optional video filter
1217
1218   if (m_pVideoFilterShader)
1219   {
1220     m_fbo.SetFiltering(GL_TEXTURE_2D, GL_NEAREST);
1221     m_pVideoFilterShader->SetSourceTexture(0);
1222     m_pVideoFilterShader->SetWidth(m_sourceWidth);
1223     m_pVideoFilterShader->SetHeight(m_sourceHeight);
1224     m_pVideoFilterShader->Enable();
1225   }
1226   else
1227     m_fbo.SetFiltering(GL_TEXTURE_2D, GL_LINEAR);
1228
1229   VerifyGLState();
1230
1231 //TODO
1232 //  imgwidth  /= m_sourceWidth;
1233 //  imgheight /= m_sourceHeight;
1234 //
1235 //  glBegin(GL_QUADS);
1236 //
1237 //  glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f    , 0.0f);
1238 //  glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
1239 //
1240 //  glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
1241 //  glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
1242 //
1243 //  glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
1244 //  glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
1245 //
1246 //  glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f    , imgheight);
1247 //  glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
1248 //
1249 //  glEnd();
1250
1251   VerifyGLState();
1252
1253   if (m_pVideoFilterShader)
1254     m_pVideoFilterShader->Disable();
1255
1256   VerifyGLState();
1257
1258   glDisable(m_textureTarget);
1259   VerifyGLState();
1260 }
1261
1262 void CLinuxRendererGLES::RenderSoftware(int index, int field)
1263 {
1264   YUVPLANES &planes = m_buffers[index].fields[field];
1265
1266   glDisable(GL_DEPTH_TEST);
1267
1268   // Y
1269   glEnable(m_textureTarget);
1270   glActiveTexture(GL_TEXTURE0);
1271   glBindTexture(m_textureTarget, planes[0].id);
1272
1273   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1274
1275   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1276   GLfloat ver[4][4];
1277   GLfloat tex[4][2];
1278   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1279
1280   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1281   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1282   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1283
1284   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1285   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1286   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1287
1288   glEnableVertexAttribArray(posLoc);
1289   glEnableVertexAttribArray(texLoc);
1290   glEnableVertexAttribArray(colLoc);
1291
1292   // Set vertex coordinates
1293   for(int i = 0; i < 4; i++)
1294   {
1295     ver[i][0] = m_rotatedDestCoords[i].x;
1296     ver[i][1] = m_rotatedDestCoords[i].y;
1297     ver[i][2] = 0.0f;// set z to 0
1298     ver[i][3] = 1.0f;
1299   }
1300
1301   // Set texture coordinates
1302   tex[0][0] = tex[3][0] = planes[0].rect.x1;
1303   tex[0][1] = tex[1][1] = planes[0].rect.y1;
1304   tex[1][0] = tex[2][0] = planes[0].rect.x2;
1305   tex[2][1] = tex[3][1] = planes[0].rect.y2;
1306
1307   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1308
1309   glDisableVertexAttribArray(posLoc);
1310   glDisableVertexAttribArray(texLoc);
1311   glDisableVertexAttribArray(colLoc);
1312
1313   g_Windowing.DisableGUIShader();
1314
1315   VerifyGLState();
1316
1317   glDisable(m_textureTarget);
1318   VerifyGLState();
1319 }
1320
1321 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1322 {
1323 #if defined(HAVE_LIBOPENMAX)
1324   GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1325
1326   glDisable(GL_DEPTH_TEST);
1327
1328   // Y
1329   glEnable(m_textureTarget);
1330   glActiveTexture(GL_TEXTURE0);
1331   glBindTexture(m_textureTarget, textureId);
1332
1333   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1334
1335   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1336   GLfloat ver[4][4];
1337   GLfloat tex[4][2];
1338   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1339
1340   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1341   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1342   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1343
1344   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1345   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1346   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1347
1348   glEnableVertexAttribArray(posLoc);
1349   glEnableVertexAttribArray(texLoc);
1350   glEnableVertexAttribArray(colLoc);
1351
1352   // Set vertex coordinates
1353   for(int i = 0; i < 4; i++)
1354   {
1355     ver[i][0] = m_rotatedDestCoords[i].x;
1356     ver[i][1] = m_rotatedDestCoords[i].y;
1357     ver[i][2] = 0.0f;// set z to 0
1358     ver[i][3] = 1.0f;
1359   }
1360
1361   // Set texture coordinates
1362   tex[0][0] = tex[3][0] = 0;
1363   tex[0][1] = tex[1][1] = 0;
1364   tex[1][0] = tex[2][0] = 1;
1365   tex[2][1] = tex[3][1] = 1;
1366
1367   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1368
1369   glDisableVertexAttribArray(posLoc);
1370   glDisableVertexAttribArray(texLoc);
1371   glDisableVertexAttribArray(colLoc);
1372
1373   g_Windowing.DisableGUIShader();
1374
1375   VerifyGLState();
1376
1377   glDisable(m_textureTarget);
1378   VerifyGLState();
1379 #endif
1380 }
1381
1382 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1383 {
1384 #if defined(HAS_LIBSTAGEFRIGHT)
1385 #ifdef DEBUG_VERBOSE
1386   unsigned int time = XbmcThreads::SystemClockMillis();
1387 #endif
1388
1389   YUVPLANE &plane = m_buffers[index].fields[field][0];
1390
1391   glDisable(GL_DEPTH_TEST);
1392
1393   glActiveTexture(GL_TEXTURE0);
1394   glBindTexture(m_textureTarget, plane.id);
1395
1396   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1397
1398   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1399   GLfloat ver[4][4];
1400   GLfloat tex[4][2];
1401   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1402
1403   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1404   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1405   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1406
1407   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1408   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1409   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1410
1411   glEnableVertexAttribArray(posLoc);
1412   glEnableVertexAttribArray(texLoc);
1413   glEnableVertexAttribArray(colLoc);
1414
1415   // Set vertex coordinates
1416   for(int i = 0; i < 4; i++)
1417   {
1418     ver[i][0] = m_rotatedDestCoords[i].x;
1419     ver[i][1] = m_rotatedDestCoords[i].y;
1420     ver[i][2] = 0.0f;// set z to 0
1421     ver[i][3] = 1.0f;
1422   }
1423
1424   // Set texture coordinates (is flipped in y)
1425   tex[0][0] = tex[3][0] = plane.rect.x1;
1426   tex[0][1] = tex[1][1] = plane.rect.y2;
1427   tex[1][0] = tex[2][0] = plane.rect.x2;
1428   tex[2][1] = tex[3][1] = plane.rect.y1;
1429
1430   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1431
1432   glDisableVertexAttribArray(posLoc);
1433   glDisableVertexAttribArray(texLoc);
1434   glDisableVertexAttribArray(colLoc);
1435
1436   g_Windowing.DisableGUIShader();
1437   VerifyGLState();
1438
1439   glBindTexture(m_textureTarget, 0);
1440   VerifyGLState();
1441
1442 #ifdef DEBUG_VERBOSE
1443   CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1444 #endif
1445 #endif
1446 }
1447
1448 void CLinuxRendererGLES::RenderSurfaceTexture(int index, int field)
1449 {
1450 #if defined(TARGET_ANDROID)
1451   #ifdef DEBUG_VERBOSE
1452     unsigned int time = XbmcThreads::SystemClockMillis();
1453   #endif
1454
1455   YUVPLANE &plane = m_buffers[index].fields[0][0];
1456
1457   glDisable(GL_DEPTH_TEST);
1458
1459   glActiveTexture(GL_TEXTURE0);
1460   glBindTexture(GL_TEXTURE_EXTERNAL_OES, plane.id);
1461
1462   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA_OES);
1463
1464   glUniformMatrix4fv(g_Windowing.GUIShaderGetCoord0Matrix(), 1, GL_FALSE, m_textureMatrix);
1465
1466   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1467   GLfloat ver[4][4];
1468   GLfloat tex[4][4];
1469
1470   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1471   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1472
1473
1474   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1475   glVertexAttribPointer(texLoc, 4, GL_FLOAT, 0, 0, tex);
1476
1477   glEnableVertexAttribArray(posLoc);
1478   glEnableVertexAttribArray(texLoc);
1479
1480   // Set vertex coordinates
1481   for(int i = 0; i < 4; i++)
1482   {
1483     ver[i][0] = m_rotatedDestCoords[i].x;
1484     ver[i][1] = m_rotatedDestCoords[i].y;
1485     ver[i][2] = 0.0f;        // set z to 0
1486     ver[i][3] = 1.0f;
1487   }
1488
1489   // Set texture coordinates (MediaCodec is flipped in y)
1490   tex[0][0] = tex[3][0] = plane.rect.x1;
1491   tex[0][1] = tex[1][1] = plane.rect.y2;
1492   tex[1][0] = tex[2][0] = plane.rect.x2;
1493   tex[2][1] = tex[3][1] = plane.rect.y1;
1494
1495   for(int i = 0; i < 4; i++)
1496   {
1497     tex[i][2] = 0.0f;
1498     tex[i][3] = 1.0f;
1499   }
1500
1501   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1502
1503   glDisableVertexAttribArray(posLoc);
1504   glDisableVertexAttribArray(texLoc);
1505
1506   const float identity[16] = {
1507       1.0f, 0.0f, 0.0f, 0.0f,
1508       0.0f, 1.0f, 0.0f, 0.0f,
1509       0.0f, 0.0f, 1.0f, 0.0f,
1510       0.0f, 0.0f, 0.0f, 1.0f
1511   };
1512   glUniformMatrix4fv(g_Windowing.GUIShaderGetCoord0Matrix(),  1, GL_FALSE, identity);
1513
1514   g_Windowing.DisableGUIShader();
1515   VerifyGLState();
1516
1517   glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
1518   VerifyGLState();
1519
1520   #ifdef DEBUG_VERBOSE
1521     CLog::Log(LOGDEBUG, "RenderMediaCodecImage %d: tm:%d", index, XbmcThreads::SystemClockMillis() - time);
1522   #endif
1523 #endif
1524 }
1525
1526 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1527 {
1528 #ifdef HAVE_VIDEOTOOLBOXDECODER
1529   YUVPLANE &plane = m_buffers[index].fields[field][0];
1530
1531   glDisable(GL_DEPTH_TEST);
1532
1533   glEnable(m_textureTarget);
1534   glActiveTexture(GL_TEXTURE0);
1535   glBindTexture(m_textureTarget, plane.id);
1536
1537   g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1538
1539   GLubyte idx[4] = {0, 1, 3, 2};        //determines order of triangle strip
1540   GLfloat ver[4][4];
1541   GLfloat tex[4][2];
1542   GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1543
1544   GLint   posLoc = g_Windowing.GUIShaderGetPos();
1545   GLint   texLoc = g_Windowing.GUIShaderGetCoord0();
1546   GLint   colLoc = g_Windowing.GUIShaderGetCol();
1547
1548   glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1549   glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1550   glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1551
1552   glEnableVertexAttribArray(posLoc);
1553   glEnableVertexAttribArray(texLoc);
1554   glEnableVertexAttribArray(colLoc);
1555
1556   // Set vertex coordinates
1557   for(int i = 0; i < 4; i++)
1558   {
1559     ver[i][0] = m_rotatedDestCoords[i].x;
1560     ver[i][1] = m_rotatedDestCoords[i].y;
1561     ver[i][2] = 0.0f;// set z to 0
1562     ver[i][3] = 1.0f;
1563   }
1564
1565   // Set texture coordinates (corevideo is flipped in y)
1566   tex[0][0] = tex[3][0] = plane.rect.x1;
1567   tex[0][1] = tex[1][1] = plane.rect.y2;
1568   tex[1][0] = tex[2][0] = plane.rect.x2;
1569   tex[2][1] = tex[3][1] = plane.rect.y1;
1570
1571   glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1572
1573   glDisableVertexAttribArray(posLoc);
1574   glDisableVertexAttribArray(texLoc);
1575   glDisableVertexAttribArray(colLoc);
1576
1577   g_Windowing.DisableGUIShader();
1578   VerifyGLState();
1579
1580   glDisable(m_textureTarget);
1581   VerifyGLState();
1582 #endif
1583 }
1584
1585 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1586 {
1587   if (!m_bValidated)
1588     return false;
1589
1590   // If rendered directly by the hardware
1591   if (m_renderMethod & RENDER_BYPASS)
1592   {
1593     capture->BeginRender();
1594     capture->EndRender();
1595     return true;
1596   }
1597
1598   // save current video rect
1599   CRect saveSize = m_destRect;
1600   saveRotatedCoords();//backup current m_rotatedDestCoords
1601
1602   // new video rect is thumbnail size
1603   m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1604   MarkDirty();
1605   syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1606   // clear framebuffer and invert Y axis to get non-inverted image
1607   glDisable(GL_BLEND);
1608
1609   g_matrices.MatrixMode(MM_MODELVIEW);
1610   g_matrices.PushMatrix();
1611   // fixme - we know that cvref  & eglimg are already flipped in y direction
1612   // but somehow this also effects the rendercapture here
1613   // therefore we have to skip the flip here or we get upside down
1614   // images
1615   if (m_renderMethod != RENDER_CVREF)
1616   {
1617     g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1618     g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1619   }
1620
1621   capture->BeginRender();
1622
1623   Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1624   // read pixels
1625   glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1626                GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1627
1628   // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1629   // XOR Swap RGBA -> BGRA
1630   unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1631   for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1632   {
1633     std::swap(pixels[0], pixels[2]);
1634   }
1635
1636   capture->EndRender();
1637
1638   // revert model view matrix
1639   g_matrices.MatrixMode(MM_MODELVIEW);
1640   g_matrices.PopMatrix();
1641
1642   // restore original video rect
1643   m_destRect = saveSize;
1644   restoreRotatedCoords();//restores the previous state of the rotated dest coords
1645
1646   return true;
1647 }
1648
1649 //********************************************************************************************************
1650 // YV12 Texture creation, deletion, copying + clearing
1651 //********************************************************************************************************
1652 void CLinuxRendererGLES::UploadYV12Texture(int source)
1653 {
1654   YUVBUFFER& buf    =  m_buffers[source];
1655   YV12Image* im     = &buf.image;
1656   YUVFIELDS& fields =  buf.fields;
1657
1658
1659 #if defined(HAVE_LIBOPENMAX)
1660   if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1661 #else
1662   if (!(im->flags&IMAGE_FLAG_READY))
1663 #endif
1664   {
1665     return;
1666   }
1667
1668   // if we don't have a shader, fallback to SW YUV2RGB for now
1669   if (m_renderMethod & RENDER_SW)
1670   {
1671     if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1672     {
1673       delete [] m_rgbBuffer;
1674       m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1675       m_rgbBuffer = new BYTE[m_rgbBufferSize];
1676     }
1677
1678 #if defined(__ARM_NEON__)
1679     if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1680     {
1681       yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1682         m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1683     }
1684     else
1685 #endif
1686     {
1687       m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1688         im->width, im->height, PIX_FMT_YUV420P,
1689         im->width, im->height, PIX_FMT_RGBA,
1690         SWS_FAST_BILINEAR, NULL, NULL, NULL);
1691
1692       uint8_t *src[]  = { im->plane[0], im->plane[1], im->plane[2], 0 };
1693       int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1694       uint8_t *dst[]  = { m_rgbBuffer, 0, 0, 0 };
1695       int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1696       m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1697     }
1698   }
1699
1700   bool deinterlacing;
1701   if (m_currentField == FIELD_FULL)
1702     deinterlacing = false;
1703   else
1704     deinterlacing = true;
1705
1706   glEnable(m_textureTarget);
1707   VerifyGLState();
1708
1709   if (m_renderMethod & RENDER_SW)
1710   {
1711     // Load RGB image
1712     if (deinterlacing)
1713     {
1714       LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1715                , im->width, im->height >> 1
1716                , m_sourceWidth*8, im->bpp, m_rgbBuffer );
1717
1718       LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1719                , im->width, im->height >> 1
1720                , m_sourceWidth*8, im->bpp, m_rgbBuffer + m_sourceWidth*4);
1721     }
1722     else
1723     {
1724       LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1725                , im->width, im->height
1726                , m_sourceWidth*4, im->bpp, m_rgbBuffer );
1727     }
1728   }
1729   else
1730   {
1731     glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1732
1733     if (deinterlacing)
1734     {
1735       // Load Even Y Field
1736       LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1737                , im->width, im->height >> 1
1738                , im->stride[0]*2, im->bpp, im->plane[0] );
1739
1740       // Load Odd Y fields
1741       LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1742                , im->width, im->height >> 1
1743                , im->stride[0]*2, im->bpp, im->plane[0] + im->stride[0]) ;
1744
1745       // Load Even U & V Fields
1746       LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1747                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1748                , im->stride[1]*2, im->bpp, im->plane[1] );
1749
1750       LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex
1751                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1752                , im->stride[2]*2, im->bpp, im->plane[2] );
1753
1754       // Load Odd U & V Fields
1755       LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1756                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1757                , im->stride[1]*2, im->bpp, im->plane[1] + im->stride[1] );
1758
1759       LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex
1760                , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1761                , im->stride[2]*2, im->bpp, im->plane[2] + im->stride[2] );
1762     }
1763     else
1764     {
1765       // Load Y plane
1766       LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1767                , im->width, im->height
1768                , im->stride[0], im->bpp, im->plane[0] );
1769
1770       //load U plane
1771       LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1772                , im->width >> im->cshift_x, im->height >> im->cshift_y
1773                , im->stride[1], im->bpp, im->plane[1] );
1774
1775       //load V plane
1776       LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex
1777                , im->width >> im->cshift_x, im->height >> im->cshift_y
1778                , im->stride[2], im->bpp, im->plane[2] );
1779     }
1780   }
1781
1782   VerifyGLState();
1783
1784   CalculateTextureSourceRects(source, 3);
1785
1786   glDisable(m_textureTarget);
1787 }
1788
1789 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1790 {
1791   YV12Image &im     = m_buffers[index].image;
1792   YUVFIELDS &fields = m_buffers[index].fields;
1793
1794   if( fields[FIELD_FULL][0].id == 0 ) return;
1795
1796   /* finish up all textures, and delete them */
1797   g_graphicsContext.BeginPaint();  //FIXME
1798   for(int f = 0;f<MAX_FIELDS;f++)
1799   {
1800     for(int p = 0;p<MAX_PLANES;p++)
1801     {
1802       if( fields[f][p].id )
1803       {
1804         if (glIsTexture(fields[f][p].id))
1805           glDeleteTextures(1, &fields[f][p].id);
1806         fields[f][p].id = 0;
1807       }
1808     }
1809   }
1810   g_graphicsContext.EndPaint();
1811
1812   for(int p = 0;p<MAX_PLANES;p++)
1813   {
1814     if (im.plane[p])
1815     {
1816       delete[] im.plane[p];
1817       im.plane[p] = NULL;
1818     }
1819   }
1820 }
1821
1822 static GLint GetInternalFormat(GLint format, int bpp)
1823 {
1824   if(bpp == 2)
1825   {
1826     switch (format)
1827     {
1828 #ifdef GL_ALPHA16
1829       case GL_ALPHA:     return GL_ALPHA16;
1830 #endif
1831 #ifdef GL_LUMINANCE16
1832       case GL_LUMINANCE: return GL_LUMINANCE16;
1833 #endif
1834       default:           return format;
1835     }
1836   }
1837   else
1838     return format;
1839 }
1840
1841 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1842 {
1843   /* since we also want the field textures, pitch must be texture aligned */
1844   YV12Image &im     = m_buffers[index].image;
1845   YUVFIELDS &fields = m_buffers[index].fields;
1846
1847   DeleteYV12Texture(index);
1848
1849   im.height = m_sourceHeight;
1850   im.width  = m_sourceWidth;
1851   im.cshift_x = 1;
1852   im.cshift_y = 1;
1853
1854
1855   if(m_format == RENDER_FMT_YUV420P16
1856   || m_format == RENDER_FMT_YUV420P10)
1857     im.bpp = 2;
1858   else
1859     im.bpp = 1;
1860
1861   im.stride[0] = im.bpp *   im.width;
1862   im.stride[1] = im.bpp * ( im.width >> im.cshift_x );
1863   im.stride[2] = im.bpp * ( im.width >> im.cshift_x );
1864
1865   im.planesize[0] = im.stride[0] *   im.height;
1866   im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1867   im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1868
1869   for (int i = 0; i < 3; i++)
1870     im.plane[i] = new BYTE[im.planesize[i]];
1871
1872   glEnable(m_textureTarget);
1873   for(int f = 0;f<MAX_FIELDS;f++)
1874   {
1875     for(int p = 0;p<MAX_PLANES;p++)
1876     {
1877       if (!glIsTexture(fields[f][p].id))
1878       {
1879         glGenTextures(1, &fields[f][p].id);
1880         VerifyGLState();
1881       }
1882     }
1883   }
1884
1885   // YUV
1886   for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1887   {
1888     int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1889     YUVPLANES &planes = fields[f];
1890
1891     planes[0].texwidth  = im.width;
1892     planes[0].texheight = im.height >> fieldshift;
1893
1894     if (m_renderMethod & RENDER_SW)
1895     {
1896       planes[1].texwidth  = 0;
1897       planes[1].texheight = 0;
1898       planes[2].texwidth  = 0;
1899       planes[2].texheight = 0;
1900     }
1901     else
1902     {
1903       planes[1].texwidth  = planes[0].texwidth  >> im.cshift_x;
1904       planes[1].texheight = planes[0].texheight >> im.cshift_y;
1905       planes[2].texwidth  = planes[0].texwidth  >> im.cshift_x;
1906       planes[2].texheight = planes[0].texheight >> im.cshift_y;
1907     }
1908
1909     for (int p = 0; p < 3; p++)
1910     {
1911       planes[p].pixpertex_x = 1;
1912       planes[p].pixpertex_y = 1;
1913     }
1914
1915     if(m_renderMethod & RENDER_POT)
1916     {
1917       for(int p = 0; p < 3; p++)
1918       {
1919         planes[p].texwidth  = NP2(planes[p].texwidth);
1920         planes[p].texheight = NP2(planes[p].texheight);
1921       }
1922     }
1923
1924     for(int p = 0; p < 3; p++)
1925     {
1926       YUVPLANE &plane = planes[p];
1927       if (plane.texwidth * plane.texheight == 0)
1928         continue;
1929
1930       glBindTexture(m_textureTarget, plane.id);
1931       if (m_renderMethod & RENDER_SW)
1932       {
1933         if(m_renderMethod & RENDER_POT)
1934           CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d",  plane.texwidth, plane.texheight);
1935         else
1936           CLog::Log(LOGDEBUG,  "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1937
1938         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1939         glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1940       }
1941       else
1942       {
1943         GLenum format;
1944         GLint internalformat;
1945         if (p == 2) //V plane needs an alpha texture
1946           format = GL_ALPHA;
1947         else
1948           format = GL_LUMINANCE;
1949         internalformat = GetInternalFormat(format, im.bpp);
1950
1951         if(m_renderMethod & RENDER_POT)
1952           CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d",  plane.texwidth, plane.texheight);
1953         else
1954           CLog::Log(LOGDEBUG,  "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1955
1956         glTexImage2D(m_textureTarget, 0, internalformat, plane.texwidth, plane.texheight, 0, format, GL_UNSIGNED_BYTE, NULL);
1957       }
1958
1959       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1960       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1961       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1962       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1963       VerifyGLState();
1964     }
1965   }
1966   glDisable(m_textureTarget);
1967   return true;
1968 }
1969
1970 //********************************************************************************************************
1971 // NV12 Texture loading, creation and deletion
1972 //********************************************************************************************************
1973 void CLinuxRendererGLES::UploadNV12Texture(int source)
1974 {
1975   YUVBUFFER& buf    =  m_buffers[source];
1976   YV12Image* im     = &buf.image;
1977   YUVFIELDS& fields =  buf.fields;
1978
1979   if (!(im->flags & IMAGE_FLAG_READY))
1980     return;
1981   bool deinterlacing;
1982   if (m_currentField == FIELD_FULL)
1983     deinterlacing = false;
1984   else
1985     deinterlacing = true;
1986
1987   glEnable(m_textureTarget);
1988   VerifyGLState();
1989
1990   glPixelStorei(GL_UNPACK_ALIGNMENT, im->bpp);
1991
1992   if (deinterlacing)
1993   {
1994     // Load Odd Y field
1995     LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1996              , im->width, im->height >> 1
1997              , im->stride[0]*2, im->bpp, im->plane[0] );
1998
1999     // Load Even Y field
2000     LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
2001              , im->width, im->height >> 1
2002              , im->stride[0]*2, im->bpp, im->plane[0] + im->stride[0]) ;
2003
2004     // Load Odd UV Fields
2005     LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE_ALPHA, buf.flipindex
2006              , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
2007              , im->stride[1]*2, im->bpp, im->plane[1] );
2008
2009     // Load Even UV Fields
2010     LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE_ALPHA, buf.flipindex
2011              , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
2012              , im->stride[1]*2, im->bpp, im->plane[1] + im->stride[1] );
2013
2014   }
2015   else
2016   {
2017     // Load Y plane
2018     LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
2019              , im->width, im->height
2020              , im->stride[0], im->bpp, im->plane[0] );
2021
2022     // Load UV plane
2023     LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE_ALPHA, buf.flipindex
2024              , im->width >> im->cshift_x, im->height >> im->cshift_y
2025              , im->stride[1], im->bpp, im->plane[1] );
2026   }
2027
2028   VerifyGLState();
2029
2030   CalculateTextureSourceRects(source, 3);
2031
2032   glDisable(m_textureTarget);
2033   return;
2034 }
2035
2036 bool CLinuxRendererGLES::CreateNV12Texture(int index)
2037 {
2038   // since we also want the field textures, pitch must be texture aligned
2039   YV12Image &im     = m_buffers[index].image;
2040   YUVFIELDS &fields = m_buffers[index].fields;
2041
2042   // Delete any old texture
2043   DeleteNV12Texture(index);
2044
2045   im.height = m_sourceHeight;
2046   im.width  = m_sourceWidth;
2047   im.cshift_x = 1;
2048   im.cshift_y = 1;
2049   im.bpp = 1;
2050
2051   im.stride[0] = im.width;
2052   im.stride[1] = im.width;
2053   im.stride[2] = 0;
2054
2055   im.plane[0] = NULL;
2056   im.plane[1] = NULL;
2057   im.plane[2] = NULL;
2058
2059   // Y plane
2060   im.planesize[0] = im.stride[0] * im.height;
2061   // packed UV plane
2062   im.planesize[1] = im.stride[1] * im.height / 2;
2063   // third plane is not used
2064   im.planesize[2] = 0;
2065
2066   for (int i = 0; i < 2; i++)
2067     im.plane[i] = new BYTE[im.planesize[i]];
2068
2069   glEnable(m_textureTarget);
2070   for(int f = 0;f<MAX_FIELDS;f++)
2071   {
2072     for(int p = 0;p<2;p++)
2073     {
2074       if (!glIsTexture(fields[f][p].id))
2075       {
2076         glGenTextures(1, &fields[f][p].id);
2077         VerifyGLState();
2078       }
2079     }
2080     fields[f][2].id = fields[f][1].id;
2081   }
2082
2083   // YUV
2084   for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2085   {
2086     int fieldshift = (f==FIELD_FULL) ? 0 : 1;
2087     YUVPLANES &planes = fields[f];
2088
2089     planes[0].texwidth  = im.width;
2090     planes[0].texheight = im.height >> fieldshift;
2091
2092     if (m_renderMethod & RENDER_SW)
2093     {
2094       planes[1].texwidth  = 0;
2095       planes[1].texheight = 0;
2096       planes[2].texwidth  = 0;
2097       planes[2].texheight = 0;
2098     }
2099     else
2100     {
2101       planes[1].texwidth  = planes[0].texwidth  >> im.cshift_x;
2102       planes[1].texheight = planes[0].texheight >> im.cshift_y;
2103       planes[2].texwidth  = planes[1].texwidth;
2104       planes[2].texheight = planes[1].texheight;
2105     }
2106
2107     for (int p = 0; p < 3; p++)
2108     {
2109       planes[p].pixpertex_x = 1;
2110       planes[p].pixpertex_y = 1;
2111     }
2112
2113     if(m_renderMethod & RENDER_POT)
2114     {
2115       for(int p = 0; p < 3; p++)
2116       {
2117         planes[p].texwidth  = NP2(planes[p].texwidth);
2118         planes[p].texheight = NP2(planes[p].texheight);
2119       }
2120     }
2121
2122     for(int p = 0; p < 2; p++)
2123     {
2124       YUVPLANE &plane = planes[p];
2125       if (plane.texwidth * plane.texheight == 0)
2126         continue;
2127
2128       glBindTexture(m_textureTarget, plane.id);
2129       if (m_renderMethod & RENDER_SW)
2130       {
2131         glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
2132       }
2133       else
2134       {
2135         if (p == 1)
2136           glTexImage2D(m_textureTarget, 0, GL_LUMINANCE_ALPHA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
2137         else
2138           glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
2139       }
2140
2141       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2142       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2143       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2144       glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2145       VerifyGLState();
2146     }
2147   }
2148   glDisable(m_textureTarget);
2149
2150   return true;
2151 }
2152 void CLinuxRendererGLES::DeleteNV12Texture(int index)
2153 {
2154   YV12Image &im     = m_buffers[index].image;
2155   YUVFIELDS &fields = m_buffers[index].fields;
2156
2157   if( fields[FIELD_FULL][0].id == 0 ) return;
2158
2159   // finish up all textures, and delete them
2160   g_graphicsContext.BeginPaint();  //FIXME
2161   for(int f = 0;f<MAX_FIELDS;f++)
2162   {
2163     for(int p = 0;p<2;p++)
2164     {
2165       if( fields[f][p].id )
2166       {
2167         if (glIsTexture(fields[f][p].id))
2168         {
2169           glDeleteTextures(1, &fields[f][p].id);
2170         }
2171         fields[f][p].id = 0;
2172       }
2173     }
2174     fields[f][2].id = 0;
2175   }
2176   g_graphicsContext.EndPaint();
2177
2178   for(int p = 0;p<2;p++)
2179   {
2180     if (im.plane[p])
2181     {
2182       delete[] im.plane[p];
2183       im.plane[p] = NULL;
2184     }
2185   }
2186 }
2187
2188 //********************************************************************************************************
2189 // CoreVideoRef Texture creation, deletion, copying + clearing
2190 //********************************************************************************************************
2191 void CLinuxRendererGLES::UploadCVRefTexture(int index)
2192 {
2193 #ifdef HAVE_VIDEOTOOLBOXDECODER
2194   CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
2195
2196   if (cvBufferRef)
2197   {
2198     YUVPLANE &plane = m_buffers[index].fields[0][0];
2199
2200     CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
2201     #if !TARGET_OS_IPHONE
2202       int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
2203     #endif
2204     int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
2205     int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
2206     unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
2207
2208     glEnable(m_textureTarget);
2209     VerifyGLState();
2210
2211     glBindTexture(m_textureTarget, plane.id);
2212     #if !TARGET_OS_IPHONE
2213       #ifdef GL_UNPACK_ROW_LENGTH
2214         // Set row pixels
2215         glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
2216       #endif
2217       #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
2218         // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
2219         glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
2220       #endif
2221     #endif
2222
2223     // Using BGRA extension to pull in video frame data directly
2224     glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
2225
2226     #if !TARGET_OS_IPHONE
2227       #ifdef GL_UNPACK_ROW_LENGTH
2228         // Unset row pixels
2229         glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
2230       #endif
2231     #endif
2232     glBindTexture(m_textureTarget, 0);
2233
2234     glDisable(m_textureTarget);
2235     VerifyGLState();
2236
2237     CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
2238     CVBufferRelease(m_buffers[index].cvBufferRef);
2239     m_buffers[index].cvBufferRef = NULL;
2240
2241     plane.flipindex = m_buffers[index].flipindex;
2242   }
2243
2244   CalculateTextureSourceRects(index, 1);
2245 #endif
2246 }
2247 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
2248 {
2249 #ifdef HAVE_VIDEOTOOLBOXDECODER
2250   YUVPLANE &plane = m_buffers[index].fields[0][0];
2251
2252   if (m_buffers[index].cvBufferRef)
2253     CVBufferRelease(m_buffers[index].cvBufferRef);
2254   m_buffers[index].cvBufferRef = NULL;
2255
2256   if(plane.id && glIsTexture(plane.id))
2257     glDeleteTextures(1, &plane.id);
2258   plane.id = 0;
2259 #endif
2260 }
2261 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
2262 {
2263 #ifdef HAVE_VIDEOTOOLBOXDECODER
2264   YV12Image &im     = m_buffers[index].image;
2265   YUVFIELDS &fields = m_buffers[index].fields;
2266   YUVPLANE  &plane  = fields[0][0];
2267
2268   DeleteCVRefTexture(index);
2269
2270   memset(&im    , 0, sizeof(im));
2271   memset(&fields, 0, sizeof(fields));
2272
2273   im.height = m_sourceHeight;
2274   im.width  = m_sourceWidth;
2275
2276   plane.texwidth  = im.width;
2277   plane.texheight = im.height;
2278   plane.pixpertex_x = 1;
2279   plane.pixpertex_y = 1;
2280
2281   if(m_renderMethod & RENDER_POT)
2282   {
2283     plane.texwidth  = NP2(plane.texwidth);
2284     plane.texheight = NP2(plane.texheight);
2285   }
2286   glEnable(m_textureTarget);
2287   glGenTextures(1, &plane.id);
2288   VerifyGLState();
2289
2290   glBindTexture(m_textureTarget, plane.id);
2291   #if !TARGET_OS_IPHONE
2292     #ifdef GL_UNPACK_ROW_LENGTH
2293       // Set row pixels
2294       glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
2295     #endif
2296     #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
2297       // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
2298       glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
2299       // Set client storage
2300     #endif
2301     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
2302   #endif
2303
2304   glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2305   glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2306         // This is necessary for non-power-of-two textures
2307   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2308   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2309   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2310   glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
2311
2312   #if !TARGET_OS_IPHONE
2313     // turn off client storage so it doesn't get picked up for the next texture
2314     glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
2315   #endif
2316   glBindTexture(m_textureTarget, 0);
2317   glDisable(m_textureTarget);
2318 #endif
2319   return true;
2320 }
2321
2322 //********************************************************************************************************
2323 // BYPASS creation, deletion, copying + clearing
2324 //********************************************************************************************************
2325 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
2326 {
2327 }
2328 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
2329 {
2330 }
2331 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
2332 {
2333   return true;
2334 }
2335
2336 //********************************************************************************************************
2337 // EGLIMG creation, deletion, copying + clearing
2338 //********************************************************************************************************
2339 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
2340 {
2341 #ifdef HAS_LIBSTAGEFRIGHT
2342 #ifdef DEBUG_VERBOSE
2343   unsigned int time = XbmcThreads::SystemClockMillis();
2344 #endif
2345
2346   if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
2347   {
2348     YUVPLANE &plane = m_buffers[index].fields[0][0];
2349
2350     glActiveTexture(GL_TEXTURE0);
2351     glBindTexture(m_textureTarget, plane.id);
2352     glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
2353     glBindTexture(m_textureTarget, 0);
2354
2355     plane.flipindex = m_buffers[index].flipindex;
2356   }
2357
2358   CalculateTextureSourceRects(index, 1);
2359
2360 #ifdef DEBUG_VERBOSE
2361   CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
2362 #endif
2363 #endif
2364 }
2365 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
2366 {
2367 #ifdef HAS_LIBSTAGEFRIGHT
2368   YUVBUFFER &buf = m_buffers[index];
2369   YUVPLANE &plane = buf.fields[0][0];
2370
2371   if(plane.id && glIsTexture(plane.id))
2372     glDeleteTextures(1, &plane.id);
2373   plane.id = 0;
2374
2375   buf.stf = NULL;
2376   buf.eglimg = EGL_NO_IMAGE_KHR;
2377 #endif
2378 }
2379 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
2380 {
2381 #ifdef HAS_LIBSTAGEFRIGHT
2382   YV12Image &im     = m_buffers[index].image;
2383   YUVFIELDS &fields = m_buffers[index].fields;
2384   YUVPLANE  &plane  = fields[0][0];
2385
2386   DeleteEGLIMGTexture(index);
2387
2388   memset(&im    , 0, sizeof(im));
2389   memset(&fields, 0, sizeof(fields));
2390
2391   im.height = m_sourceHeight;
2392   im.width  = m_sourceWidth;
2393
2394   plane.texwidth  = im.width;
2395   plane.texheight = im.height;
2396   plane.pixpertex_x = 1;
2397   plane.pixpertex_y = 1;
2398
2399   if(m_renderMethod & RENDER_POT)
2400   {
2401     plane.texwidth  = NP2(plane.texwidth);
2402     plane.texheight = NP2(plane.texheight);
2403   }
2404   glEnable(m_textureTarget);
2405   glGenTextures(1, &plane.id);
2406   VerifyGLState();
2407
2408   glBindTexture(m_textureTarget, plane.id);
2409
2410   glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2411   glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2412         // This is necessary for non-power-of-two textures
2413   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2414   glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2415
2416   glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2417
2418   glDisable(m_textureTarget);
2419 #endif
2420   return true;
2421 }
2422
2423 //********************************************************************************************************
2424 // SurfaceTexture creation, deletion, copying + clearing
2425 //********************************************************************************************************
2426 void CLinuxRendererGLES::UploadSurfaceTexture(int index)
2427 {
2428 #if defined(TARGET_ANDROID)
2429 #ifdef DEBUG_VERBOSE
2430   unsigned int time = XbmcThreads::SystemClockMillis();
2431   int mindex = -1;
2432 #endif
2433
2434   YUVBUFFER &buf = m_buffers[index];
2435
2436   if (buf.mediacodec)
2437   {
2438 #ifdef DEBUG_VERBOSE
2439     mindex = buf.mediacodec->GetIndex();
2440 #endif
2441     buf.fields[0][0].id = buf.mediacodec->GetTextureID();
2442     buf.mediacodec->UpdateTexImage();
2443     buf.mediacodec->GetTransformMatrix(m_textureMatrix);
2444     SAFE_RELEASE(buf.mediacodec);
2445   }
2446
2447   CalculateTextureSourceRects(index, 1);
2448
2449 #ifdef DEBUG_VERBOSE
2450   CLog::Log(LOGDEBUG, "UploadSurfaceTexture %d: img: %d tm:%d", index, mindex, XbmcThreads::SystemClockMillis() - time);
2451 #endif
2452 #endif
2453 }
2454 void CLinuxRendererGLES::DeleteSurfaceTexture(int index)
2455 {
2456 #if defined(TARGET_ANDROID)
2457   SAFE_RELEASE(m_buffers[index].mediacodec);
2458 #endif
2459 }
2460 bool CLinuxRendererGLES::CreateSurfaceTexture(int index)
2461 {
2462   YV12Image &im     = m_buffers[index].image;
2463   YUVFIELDS &fields = m_buffers[index].fields;
2464   YUVPLANE  &plane  = fields[0][0];
2465
2466   memset(&im    , 0, sizeof(im));
2467   memset(&fields, 0, sizeof(fields));
2468
2469   im.height = m_sourceHeight;
2470   im.width  = m_sourceWidth;
2471
2472   plane.texwidth  = im.width;
2473   plane.texheight = im.height;
2474   plane.pixpertex_x = 1;
2475   plane.pixpertex_y = 1;
2476
2477   if(m_renderMethod & RENDER_POT)
2478   {
2479     plane.texwidth  = NP2(plane.texwidth);
2480     plane.texheight = NP2(plane.texheight);
2481   }
2482
2483   return true;
2484 }
2485
2486 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
2487 {
2488   for (int i = 0 ; i<m_NumYV12Buffers ; i++)
2489   {
2490     YUVFIELDS &fields = m_buffers[i].fields;
2491
2492     for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2493     {
2494       glBindTexture(m_textureTarget, fields[f][0].id);
2495       glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2496       glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2497       VerifyGLState();
2498
2499       if (!(m_renderMethod & RENDER_SW))
2500       {
2501         glBindTexture(m_textureTarget, fields[f][1].id);
2502         glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2503         glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2504         VerifyGLState();
2505
2506         glBindTexture(m_textureTarget, fields[f][2].id);
2507         glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2508         glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2509         VerifyGLState();
2510       }
2511     }
2512   }
2513 }
2514
2515 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2516 {
2517   // Player controls render, let it dictate available render features
2518   if((m_renderMethod & RENDER_BYPASS))
2519   {
2520     Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2521     return itr != m_renderFeatures.end();
2522   }
2523
2524   if(feature == RENDERFEATURE_BRIGHTNESS)
2525     return false;
2526
2527   if(feature == RENDERFEATURE_CONTRAST)
2528     return false;
2529
2530   if(feature == RENDERFEATURE_GAMMA)
2531     return false;
2532
2533   if(feature == RENDERFEATURE_NOISE)
2534     return false;
2535
2536   if(feature == RENDERFEATURE_SHARPNESS)
2537     return false;
2538
2539   if (feature == RENDERFEATURE_NONLINSTRETCH)
2540     return false;
2541
2542   if (feature == RENDERFEATURE_STRETCH         ||
2543       feature == RENDERFEATURE_CROP            ||
2544       feature == RENDERFEATURE_ZOOM            ||
2545       feature == RENDERFEATURE_VERTICAL_SHIFT  ||
2546       feature == RENDERFEATURE_PIXEL_RATIO     ||
2547       feature == RENDERFEATURE_POSTPROCESS     ||
2548       feature == RENDERFEATURE_ROTATION)
2549     return true;
2550
2551
2552   return false;
2553 }
2554
2555 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2556 {
2557   return false;
2558 }
2559
2560 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2561 {
2562   // Player controls render, let it dictate available deinterlace modes
2563   if((m_renderMethod & RENDER_BYPASS))
2564   {
2565     Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2566     return itr != m_deinterlaceModes.end();
2567   }
2568
2569   if (mode == VS_DEINTERLACEMODE_OFF)
2570     return true;
2571
2572   if(m_renderMethod & RENDER_OMXEGL)
2573     return false;
2574
2575   if(m_renderMethod & RENDER_EGLIMG)
2576     return false;
2577
2578   if(m_renderMethod & RENDER_CVREF)
2579     return false;
2580
2581   if(mode == VS_DEINTERLACEMODE_AUTO
2582   || mode == VS_DEINTERLACEMODE_FORCE)
2583     return true;
2584
2585   return false;
2586 }
2587
2588 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2589 {
2590   // Player controls render, let it dictate available deinterlace methods
2591   if((m_renderMethod & RENDER_BYPASS))
2592   {
2593     Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2594     return itr != m_deinterlaceMethods.end();
2595   }
2596
2597   if(m_renderMethod & RENDER_OMXEGL)
2598     return false;
2599
2600   if(m_renderMethod & RENDER_EGLIMG)
2601     return false;
2602
2603   if(m_renderMethod & RENDER_MEDIACODEC)
2604     return false;
2605
2606   if(m_renderMethod & RENDER_CVREF)
2607     return false;
2608
2609   if(method == VS_INTERLACEMETHOD_AUTO)
2610     return true;
2611
2612 #if defined(__i386__) || defined(__x86_64__)
2613   if(method == VS_INTERLACEMETHOD_DEINTERLACE
2614   || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2615   || method == VS_INTERLACEMETHOD_SW_BLEND)
2616 #else
2617   if(method == VS_INTERLACEMETHOD_SW_BLEND)
2618 #endif
2619     return true;
2620
2621   return false;
2622 }
2623
2624 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2625 {
2626   // Player controls render, let it dictate available scaling methods
2627   if((m_renderMethod & RENDER_BYPASS))
2628   {
2629     Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2630     return itr != m_scalingMethods.end();
2631   }
2632
2633   if(method == VS_SCALINGMETHOD_NEAREST
2634   || method == VS_SCALINGMETHOD_LINEAR)
2635     return true;
2636
2637   return false;
2638 }
2639
2640 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2641 {
2642   // Player controls render, let it pick the auto-deinterlace method
2643   if((m_renderMethod & RENDER_BYPASS))
2644   {
2645     if (!m_deinterlaceMethods.empty())
2646       return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2647     else
2648       return VS_INTERLACEMETHOD_NONE;
2649   }
2650
2651   if(m_renderMethod & RENDER_OMXEGL)
2652     return VS_INTERLACEMETHOD_NONE;
2653
2654   if(m_renderMethod & RENDER_EGLIMG)
2655     return VS_INTERLACEMETHOD_NONE;
2656
2657   if(m_renderMethod & RENDER_CVREF)
2658     return VS_INTERLACEMETHOD_NONE;
2659
2660 #if defined(__i386__) || defined(__x86_64__)
2661   return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2662 #else
2663   return VS_INTERLACEMETHOD_SW_BLEND;
2664 #endif
2665 }
2666
2667 unsigned int CLinuxRendererGLES::GetProcessorSize()
2668 {
2669   if(m_format == RENDER_FMT_OMXEGL
2670   || m_format == RENDER_FMT_CVBREF
2671   || m_format == RENDER_FMT_EGLIMG
2672   || m_format == RENDER_FMT_MEDIACODEC)
2673     return 1;
2674   else
2675     return 0;
2676 }
2677
2678 #ifdef HAVE_LIBOPENMAX
2679 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2680 {
2681   YUVBUFFER &buf = m_buffers[index];
2682   buf.openMaxBuffer = picture->openMaxBuffer;
2683 }
2684 #endif
2685 #ifdef HAVE_VIDEOTOOLBOXDECODER
2686 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2687 {
2688   YUVBUFFER &buf = m_buffers[index];
2689   if (buf.cvBufferRef)
2690     CVBufferRelease(buf.cvBufferRef);
2691   buf.cvBufferRef = cvBufferRef;
2692   // retain another reference, this way dvdplayer and renderer can issue releases.
2693   CVBufferRetain(buf.cvBufferRef);
2694 }
2695 #endif
2696 #ifdef HAS_LIBSTAGEFRIGHT
2697 void CLinuxRendererGLES::AddProcessor(CDVDVideoCodecStageFright* stf, EGLImageKHR eglimg, int index)
2698 {
2699 #ifdef DEBUG_VERBOSE
2700   unsigned int time = XbmcThreads::SystemClockMillis();
2701 #endif
2702
2703   YUVBUFFER &buf = m_buffers[index];
2704   if (buf.eglimg != EGL_NO_IMAGE_KHR)
2705     stf->ReleaseBuffer(buf.eglimg);
2706   stf->LockBuffer(eglimg);
2707
2708   buf.stf = stf;
2709   buf.eglimg = eglimg;
2710
2711 #ifdef DEBUG_VERBOSE
2712   CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);
2713 #endif
2714 }
2715 #endif
2716
2717 #if defined(TARGET_ANDROID)
2718 void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index)
2719 {
2720 #ifdef DEBUG_VERBOSE
2721   unsigned int time = XbmcThreads::SystemClockMillis();
2722   int mindex = -1;
2723 #endif
2724
2725   YUVBUFFER &buf = m_buffers[index];
2726   if (mediacodec)
2727   {
2728     buf.mediacodec = mediacodec->Retain();
2729 #ifdef DEBUG_VERBOSE
2730     mindex = buf.mediacodec->GetIndex();
2731 #endif
2732     // releaseOutputBuffer must be in same thread as
2733     // dequeueOutputBuffer. We are in DVDPlayerVideo
2734     // thread here, so we are safe.
2735     buf.mediacodec->ReleaseOutputBuffer(true);
2736   }
2737
2738 #ifdef DEBUG_VERBOSE
2739   CLog::Log(LOGDEBUG, "AddProcessor %d: img:%d tm:%d", index, mindex, XbmcThreads::SystemClockMillis() - time);
2740 #endif
2741 }
2742 #endif
2743
2744 #endif
2745