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