2 * Copyright (C) 2010-2013 Team XBMC
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)
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.
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/>.
20 //#define DEBUG_VERBOSE 1
23 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
28 #include "system_gl.h"
31 #include "guilib/MatrixGLES.h"
32 #include "LinuxRendererGLES.h"
33 #include "utils/fastmemcpy.h"
34 #include "utils/MathUtils.h"
35 #include "utils/GLUtils.h"
36 #include "settings/AdvancedSettings.h"
37 #include "settings/DisplaySettings.h"
38 #include "settings/MediaSettings.h"
39 #include "settings/Settings.h"
40 #include "guilib/FrameBufferObject.h"
41 #include "VideoShaders/YUV2RGBShader.h"
42 #include "VideoShaders/VideoFilterShader.h"
43 #include "windowing/WindowingFactory.h"
44 #include "dialogs/GUIDialogKaiToast.h"
45 #include "guilib/Texture.h"
46 #include "lib/DllSwScale.h"
47 #include "../dvdplayer/DVDCodecs/Video/OpenMaxVideo.h"
48 #include "threads/SingleLock.h"
49 #include "RenderCapture.h"
50 #include "RenderFormats.h"
51 #include "xbmc/Application.h"
52 #include "cores/IPlayer.h"
54 #if defined(__ARM_NEON__)
55 #include "yuv2rgb.neon.h"
56 #include "utils/CPUInfo.h"
58 #ifdef HAVE_VIDEOTOOLBOXDECODER
59 #include "DVDCodecs/Video/DVDVideoCodecVideoToolBox.h"
60 #include <CoreVideo/CoreVideo.h>
62 #ifdef TARGET_DARWIN_IOS
63 #include "osx/DarwinUtils.h"
65 #if defined(HAS_LIBSTAGEFRIGHT)
67 #include <EGL/eglext.h>
68 #include "windowing/egl/EGLWrapper.h"
69 #include "android/activity/XBMCApp.h"
70 #include "DVDCodecs/Video/StageFrightVideo.h"
72 // EGL extension functions
73 static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
74 static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
75 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
78 using namespace Shaders;
80 CLinuxRendererGLES::YUVBUFFER::YUVBUFFER()
82 memset(&fields, 0, sizeof(fields));
83 memset(&image , 0, sizeof(image));
85 #ifdef HAVE_LIBOPENMAX
88 #ifdef HAVE_VIDEOTOOLBOXDECODER
91 #ifdef HAS_LIBSTAGEFRIGHT
93 eglimg = EGL_NO_IMAGE_KHR;
97 CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER()
101 CLinuxRendererGLES::CLinuxRendererGLES()
103 m_textureTarget = GL_TEXTURE_2D;
105 m_renderMethod = RENDER_GLSL;
106 m_oldRenderMethod = m_renderMethod;
107 m_renderQuality = RQ_SINGLEPASS;
109 m_format = RENDER_FMT_NONE;
111 m_iYV12RenderBuffer = 0;
113 m_currentField = FIELD_FULL;
116 m_pVideoFilterShader = NULL;
117 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
118 m_scalingMethodGui = (ESCALINGMETHOD)-1;
120 // default texture handlers to YUV
121 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
122 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
123 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
128 m_dllSwScale = new DllSwScale;
130 m_NumYV12Buffers = 0;
131 m_iLastRenderBuffer = 0;
132 m_bConfigured = false;
133 m_bValidated = false;
134 m_bImageReady = false;
135 m_StrictBinding = false;
136 m_clearColour = 0.0f;
138 #ifdef HAS_LIBSTAGEFRIGHT
139 if (!eglCreateImageKHR)
140 eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglCreateImageKHR");
141 if (!eglDestroyImageKHR)
142 eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglDestroyImageKHR");
143 if (!glEGLImageTargetTexture2DOES)
144 glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES");
148 CLinuxRendererGLES::~CLinuxRendererGLES()
152 if (m_rgbBuffer != NULL) {
153 delete [] m_rgbBuffer;
159 m_pYUVShader->Free();
167 bool CLinuxRendererGLES::ValidateRenderTarget()
171 CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
173 // function pointer for texture might change in
174 // call to LoadShaders
176 for (int i = 0 ; i < NUM_BUFFERS ; i++)
177 (this->*m_textureDelete)(i);
179 // create the yuv textures
182 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
183 (this->*m_textureCreate)(i);
191 bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
193 m_sourceWidth = width;
194 m_sourceHeight = height;
195 m_renderOrientation = orientation;
201 // Calculate the input frame aspect ratio.
202 CalculateFrameAspectRatio(d_width, d_height);
203 ChooseBestResolution(fps);
204 SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
207 m_bConfigured = true;
208 m_bImageReady = false;
209 m_scalingMethodGui = (ESCALINGMETHOD)-1;
211 // Ensure that textures are recreated and rendering starts only after the 1st
212 // frame is loaded after every call to Configure().
213 m_bValidated = false;
215 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
216 m_buffers[i].image.flags = 0;
218 m_iLastRenderBuffer = -1;
220 m_RenderUpdateCallBackFn = NULL;
221 m_RenderUpdateCallBackCtx = NULL;
222 if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer())
224 m_renderFeatures.clear();
225 m_scalingMethods.clear();
226 m_deinterlaceModes.clear();
227 m_deinterlaceMethods.clear();
229 if (m_RenderFeaturesCallBackFn)
231 (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures);
232 // after setting up m_renderFeatures, we are done with the callback
233 m_RenderFeaturesCallBackFn = NULL;
234 m_RenderFeaturesCallBackCtx = NULL;
236 g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures);
237 g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods);
238 g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes);
239 g_application.m_pPlayer->GetScalingMethods(m_scalingMethods);
245 int CLinuxRendererGLES::NextYV12Texture()
247 return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
250 int CLinuxRendererGLES::GetImage(YV12Image *image, int source, bool readonly)
252 if (!image) return -1;
253 if (!m_bValidated) return -1;
255 /* take next available buffer */
256 if( source == AUTOSOURCE )
257 source = NextYV12Texture();
259 if ( m_renderMethod & RENDER_OMXEGL )
263 #ifdef HAS_LIBSTAGEFRIGHT
264 if ( m_renderMethod & RENDER_EGLIMG )
269 #ifdef HAVE_VIDEOTOOLBOXDECODER
270 if (m_renderMethod & RENDER_CVREF )
276 YV12Image &im = m_buffers[source].image;
278 if ((im.flags&(~IMAGE_FLAG_READY)) != 0)
280 CLog::Log(LOGDEBUG, "CLinuxRenderer::GetImage - request image but none to give");
285 im.flags |= IMAGE_FLAG_READING;
287 im.flags |= IMAGE_FLAG_WRITING;
289 // copy the image - should be operator of YV12Image
290 for (int p=0;p<MAX_PLANES;p++)
292 image->plane[p] = im.plane[p];
293 image->stride[p] = im.stride[p];
295 image->width = im.width;
296 image->height = im.height;
297 image->flags = im.flags;
298 image->cshift_x = im.cshift_x;
299 image->cshift_y = im.cshift_y;
305 void CLinuxRendererGLES::ReleaseImage(int source, bool preserve)
307 YV12Image &im = m_buffers[source].image;
309 im.flags &= ~IMAGE_FLAG_INUSE;
310 im.flags |= IMAGE_FLAG_READY;
311 /* if image should be preserved reserve it so it's not auto seleceted */
314 im.flags |= IMAGE_FLAG_RESERVED;
316 m_bImageReady = true;
319 void CLinuxRendererGLES::CalculateTextureSourceRects(int source, int num_planes)
321 YUVBUFFER& buf = m_buffers[source];
322 YV12Image* im = &buf.image;
323 YUVFIELDS& fields = buf.fields;
325 // calculate the source rectangle
326 for(int field = 0; field < 3; field++)
328 for(int plane = 0; plane < num_planes; plane++)
330 YUVPLANE& p = fields[field][plane];
332 p.rect = m_sourceRect;
334 p.height = im->height;
336 if(field != FIELD_FULL)
338 /* correct for field offsets and chroma offsets */
339 float offset_y = 0.5;
342 if(field == FIELD_BOT)
345 p.rect.y1 += offset_y;
346 p.rect.y2 += offset_y;
348 /* half the height if this is a field */
356 p.width /= 1 << im->cshift_x;
357 p.height /= 1 << im->cshift_y;
359 p.rect.x1 /= 1 << im->cshift_x;
360 p.rect.x2 /= 1 << im->cshift_x;
361 p.rect.y1 /= 1 << im->cshift_y;
362 p.rect.y2 /= 1 << im->cshift_y;
365 if (m_textureTarget == GL_TEXTURE_2D)
367 p.height /= p.texheight;
368 p.rect.y1 /= p.texheight;
369 p.rect.y2 /= p.texheight;
370 p.width /= p.texwidth;
371 p.rect.x1 /= p.texwidth;
372 p.rect.x2 /= p.texwidth;
378 void CLinuxRendererGLES::LoadPlane( YUVPLANE& plane, int type, unsigned flipindex
379 , unsigned width, unsigned height
380 , unsigned int stride, void* data )
382 if(plane.flipindex == flipindex)
385 const GLvoid *pixelData = data;
387 int bps = glFormatElementByteCount(type);
389 glBindTexture(m_textureTarget, plane.id);
391 // OpenGL ES does not support strided texture input.
392 if(stride != width * bps)
394 unsigned char* src = (unsigned char*)data;
395 for (unsigned int y = 0; y < height;++y, src += stride)
396 glTexSubImage2D(m_textureTarget, 0, 0, y, width, 1, type, GL_UNSIGNED_BYTE, src);
398 glTexSubImage2D(m_textureTarget, 0, 0, 0, width, height, type, GL_UNSIGNED_BYTE, pixelData);
401 /* check if we need to load any border pixels */
402 if(height < plane.texheight)
403 glTexSubImage2D( m_textureTarget, 0
404 , 0, height, width, 1
405 , type, GL_UNSIGNED_BYTE
406 , (unsigned char*)pixelData + stride * (height-1));
408 if(width < plane.texwidth)
409 glTexSubImage2D( m_textureTarget, 0
410 , width, 0, 1, height
411 , type, GL_UNSIGNED_BYTE
412 , (unsigned char*)pixelData + bps * (width-1));
414 glBindTexture(m_textureTarget, 0);
416 plane.flipindex = flipindex;
419 void CLinuxRendererGLES::Reset()
421 for(int i=0; i<m_NumYV12Buffers; i++)
423 /* reset all image flags, this will cleanup textures later */
424 m_buffers[i].image.flags = 0;
428 void CLinuxRendererGLES::Flush()
435 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
436 (this->*m_textureDelete)(i);
439 m_bValidated = false;
441 m_iYV12RenderBuffer = 0;
444 void CLinuxRendererGLES::Update()
446 if (!m_bConfigured) return;
450 void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
452 if (!m_bConfigured) return;
454 // if its first pass, just init textures and return
455 if (ValidateRenderTarget())
458 if (m_renderMethod & RENDER_BYPASS)
461 // if running bypass, then the player might need the src/dst rects
462 // for sizing video playback on a layer other than the gles layer.
463 if (m_RenderUpdateCallBackFn)
464 (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect);
466 CRect old = g_graphicsContext.GetScissors();
468 g_graphicsContext.BeginPaint();
469 g_graphicsContext.SetScissors(m_destRect);
472 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
473 glClearColor(0, 0, 0, 0);
474 glClear(GL_COLOR_BUFFER_BIT);
476 g_graphicsContext.SetScissors(old);
477 g_graphicsContext.EndPaint();
481 // this needs to be checked after texture validation
482 if (!m_bImageReady) return;
484 int index = m_iYV12RenderBuffer;
485 YUVBUFFER& buf = m_buffers[index];
487 if (m_format != RENDER_FMT_OMXEGL && m_format != RENDER_FMT_EGLIMG)
489 if (!buf.fields[FIELD_FULL][0].id) return;
491 if (buf.image.flags==0)
496 g_graphicsContext.BeginPaint();
498 m_iLastRenderBuffer = index;
502 glClearColor(m_clearColour, m_clearColour, m_clearColour, 0);
503 glClear(GL_COLOR_BUFFER_BIT);
504 glClearColor(0,0,0,0);
510 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
512 m_pYUVShader->SetAlpha(alpha / 255.0f);
518 m_pYUVShader->SetAlpha(1.0f);
521 if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT))
522 CLog::Log(LOGERROR, "GLES: Cannot render stipple!");
524 Render(flags, index);
529 g_graphicsContext.EndPaint();
532 void CLinuxRendererGLES::FlipPage(int source)
534 if( source >= 0 && source < m_NumYV12Buffers )
535 m_iYV12RenderBuffer = source;
537 m_iYV12RenderBuffer = NextYV12Texture();
539 m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
544 unsigned int CLinuxRendererGLES::PreInit()
546 CSingleLock lock(g_graphicsContext);
547 m_bConfigured = false;
548 m_bValidated = false;
550 m_resolution = CDisplaySettings::Get().GetCurrentResolution();
551 if ( m_resolution == RES_WINDOW )
552 m_resolution = RES_DESKTOP;
554 m_iYV12RenderBuffer = 0;
555 m_NumYV12Buffers = 2;
557 m_formats.push_back(RENDER_FMT_YUV420P);
558 m_formats.push_back(RENDER_FMT_BYPASS);
559 #if defined(HAVE_LIBOPENMAX)
560 m_formats.push_back(RENDER_FMT_OMXEGL);
562 #ifdef HAVE_VIDEOTOOLBOXDECODER
563 m_formats.push_back(RENDER_FMT_CVBREF);
565 #ifdef HAS_LIBSTAGEFRIGHT
566 m_formats.push_back(RENDER_FMT_EGLIMG);
569 // setup the background colour
570 m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
572 if (!m_dllSwScale->Load())
573 CLog::Log(LOGERROR,"CLinuxRendererGL::PreInit - failed to load rescale libraries!");
578 void CLinuxRendererGLES::UpdateVideoFilter()
580 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod)
582 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
583 m_scalingMethod = m_scalingMethodGui;
585 if(!Supports(m_scalingMethod))
587 CLog::Log(LOGWARNING, "CLinuxRendererGLES::UpdateVideoFilter - choosen scaling method %d, is not supported by renderer", (int)m_scalingMethod);
588 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
591 if (m_pVideoFilterShader)
593 m_pVideoFilterShader->Free();
594 delete m_pVideoFilterShader;
595 m_pVideoFilterShader = NULL;
601 switch (m_scalingMethod)
603 case VS_SCALINGMETHOD_NEAREST:
604 SetTextureFilter(GL_NEAREST);
605 m_renderQuality = RQ_SINGLEPASS;
608 case VS_SCALINGMETHOD_LINEAR:
609 SetTextureFilter(GL_LINEAR);
610 m_renderQuality = RQ_SINGLEPASS;
613 case VS_SCALINGMETHOD_CUBIC:
614 CLog::Log(LOGERROR, "GLES: CUBIC not supported!");
617 case VS_SCALINGMETHOD_LANCZOS2:
618 case VS_SCALINGMETHOD_LANCZOS3:
619 case VS_SCALINGMETHOD_SINC8:
620 case VS_SCALINGMETHOD_NEDI:
621 CLog::Log(LOGERROR, "GL: TODO: This scaler has not yet been implemented");
628 CGUIDialogKaiToast::QueueNotification("Video Renderering", "Failed to init video filters/scalers, falling back to bilinear scaling");
629 CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler");
630 if (m_pVideoFilterShader)
632 m_pVideoFilterShader->Free();
633 delete m_pVideoFilterShader;
634 m_pVideoFilterShader = NULL;
638 SetTextureFilter(GL_LINEAR);
639 m_renderQuality = RQ_SINGLEPASS;
642 void CLinuxRendererGLES::LoadShaders(int field)
644 #ifdef TARGET_DARWIN_IOS
645 float ios_version = GetIOSVersion();
647 int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
648 CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod);
652 m_pYUVShader->Free();
657 switch(requestedMethod)
659 case RENDER_METHOD_AUTO:
660 case RENDER_METHOD_GLSL:
661 if (m_format == RENDER_FMT_OMXEGL)
663 CLog::Log(LOGNOTICE, "GL: Using OMXEGL RGBA render method");
664 m_renderMethod = RENDER_OMXEGL;
667 else if (m_format == RENDER_FMT_EGLIMG)
669 CLog::Log(LOGNOTICE, "GL: Using EGL Image render method");
670 m_renderMethod = RENDER_EGLIMG;
673 else if (m_format == RENDER_FMT_BYPASS)
675 CLog::Log(LOGNOTICE, "GL: Using BYPASS render method");
676 m_renderMethod = RENDER_BYPASS;
679 else if (m_format == RENDER_FMT_CVBREF)
681 CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef RGBA render method");
682 m_renderMethod = RENDER_CVREF;
685 #if defined(TARGET_DARWIN_IOS)
686 else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P)
688 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA render method");
689 m_renderMethod = RENDER_SW;
693 // Try GLSL shaders if supported and user requested auto or GLSL.
696 // create regular progressive scan shader
697 m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format);
698 CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
700 if (m_pYUVShader && m_pYUVShader->CompileAndLink())
702 m_renderMethod = RENDER_GLSL;
706 else if (m_pYUVShader)
708 m_pYUVShader->Free();
711 CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader");
712 // drop through and try SW
715 case RENDER_METHOD_SOFTWARE:
718 // Use software YUV 2 RGB conversion if user requested it or GLSL failed
719 m_renderMethod = RENDER_SW ;
720 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA rendering");
724 // determine whether GPU supports NPOT textures
725 if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
727 CLog::Log(LOGNOTICE, "GL: GL_ARB_texture_rectangle not supported and OpenGL version is not 2.x");
728 CLog::Log(LOGNOTICE, "GL: Reverting to POT textures");
729 m_renderMethod |= RENDER_POT;
732 CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
734 // Now that we now the render method, setup texture function handlers
735 if (m_format == RENDER_FMT_CVBREF)
737 m_textureUpload = &CLinuxRendererGLES::UploadCVRefTexture;
738 m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
739 m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
741 else if (m_format == RENDER_FMT_BYPASS)
743 m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
744 m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
745 m_textureDelete = &CLinuxRendererGLES::DeleteBYPASSTexture;
747 else if (m_format == RENDER_FMT_EGLIMG)
749 m_textureUpload = &CLinuxRendererGLES::UploadEGLIMGTexture;
750 m_textureCreate = &CLinuxRendererGLES::CreateEGLIMGTexture;
751 m_textureDelete = &CLinuxRendererGLES::DeleteEGLIMGTexture;
755 // default to YV12 texture handlers
756 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
757 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
758 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
761 if (m_oldRenderMethod != m_renderMethod)
763 CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod);
765 m_oldRenderMethod = m_renderMethod;
769 void CLinuxRendererGLES::UnInit()
771 CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources");
772 CSingleLock lock(g_graphicsContext);
774 if (m_rgbBuffer != NULL)
776 delete [] m_rgbBuffer;
782 for (int i = 0; i < NUM_BUFFERS; ++i)
783 (this->*m_textureDelete)(i);
785 if (m_dllSwScale && m_sw_context)
787 m_dllSwScale->sws_freeContext(m_sw_context);
791 // cleanup framebuffer object if it was in use
793 m_bValidated = false;
794 m_bImageReady = false;
795 m_bConfigured = false;
796 m_RenderUpdateCallBackFn = NULL;
797 m_RenderUpdateCallBackCtx = NULL;
798 m_RenderFeaturesCallBackFn = NULL;
799 m_RenderFeaturesCallBackCtx = NULL;
802 inline void CLinuxRendererGLES::ReorderDrawPoints()
805 CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points
807 //corevideo and EGL are flipped in y
808 if(m_renderMethod & RENDER_CVREF)
811 tmp = m_rotatedDestCoords[0];
812 m_rotatedDestCoords[0] = m_rotatedDestCoords[3];
813 m_rotatedDestCoords[3] = tmp;
814 tmp = m_rotatedDestCoords[1];
815 m_rotatedDestCoords[1] = m_rotatedDestCoords[2];
816 m_rotatedDestCoords[2] = tmp;
820 void CLinuxRendererGLES::ReleaseBuffer(int idx)
822 #ifdef HAVE_VIDEOTOOLBOXDECODER
823 YUVBUFFER &buf = m_buffers[idx];
826 CVBufferRelease(buf.cvBufferRef);
827 buf.cvBufferRef = NULL;
831 void CLinuxRendererGLES::Render(DWORD flags, int index)
833 // If rendered directly by the hardware
834 if (m_renderMethod & RENDER_BYPASS)
837 // obtain current field, if interlaced
838 if( flags & RENDER_FLAG_TOP)
839 m_currentField = FIELD_TOP;
841 else if (flags & RENDER_FLAG_BOT)
842 m_currentField = FIELD_BOT;
845 m_currentField = FIELD_FULL;
847 (this->*m_textureUpload)(index);
849 if (m_renderMethod & RENDER_GLSL)
852 switch(m_renderQuality)
856 RenderSinglePass(index, m_currentField);
861 RenderMultiPass(index, m_currentField);
866 RenderSoftware(index, m_currentField);
871 else if (m_renderMethod & RENDER_OMXEGL)
873 RenderOpenMax(index, m_currentField);
876 else if (m_renderMethod & RENDER_EGLIMG)
878 RenderEglImage(index, m_currentField);
881 else if (m_renderMethod & RENDER_CVREF)
883 RenderCoreVideoRef(index, m_currentField);
888 RenderSoftware(index, m_currentField);
893 void CLinuxRendererGLES::RenderSinglePass(int index, int field)
895 YV12Image &im = m_buffers[index].image;
896 YUVFIELDS &fields = m_buffers[index].fields;
897 YUVPLANES &planes = fields[field];
905 glDisable(GL_DEPTH_TEST);
908 glActiveTexture(GL_TEXTURE0);
909 glEnable(m_textureTarget);
910 glBindTexture(m_textureTarget, planes[0].id);
913 glActiveTexture(GL_TEXTURE1);
914 glEnable(m_textureTarget);
915 glBindTexture(m_textureTarget, planes[1].id);
918 glActiveTexture(GL_TEXTURE2);
919 glEnable(m_textureTarget);
920 glBindTexture(m_textureTarget, planes[2].id);
922 glActiveTexture(GL_TEXTURE0);
925 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
926 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
927 m_pYUVShader->SetWidth(im.width);
928 m_pYUVShader->SetHeight(im.height);
929 if (field == FIELD_TOP)
930 m_pYUVShader->SetField(1);
931 else if(field == FIELD_BOT)
932 m_pYUVShader->SetField(0);
934 m_pYUVShader->SetMatrices(g_matrices.GetMatrix(MM_PROJECTION), g_matrices.GetMatrix(MM_MODELVIEW));
935 m_pYUVShader->Enable();
937 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
938 GLfloat m_vert[4][3];
939 GLfloat m_tex[3][4][2];
941 GLint vertLoc = m_pYUVShader->GetVertexLoc();
942 GLint Yloc = m_pYUVShader->GetYcoordLoc();
943 GLint Uloc = m_pYUVShader->GetUcoordLoc();
944 GLint Vloc = m_pYUVShader->GetVcoordLoc();
946 glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert);
947 glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]);
948 glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, m_tex[1]);
949 glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, m_tex[2]);
951 glEnableVertexAttribArray(vertLoc);
952 glEnableVertexAttribArray(Yloc);
953 glEnableVertexAttribArray(Uloc);
954 glEnableVertexAttribArray(Vloc);
956 // Setup vertex position values
957 for(int i = 0; i < 4; i++)
959 m_vert[i][0] = m_rotatedDestCoords[i].x;
960 m_vert[i][1] = m_rotatedDestCoords[i].y;
961 m_vert[i][2] = 0.0f;// set z to 0
964 // Setup texture coordinates
965 for (int i=0; i<3; i++)
967 m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1;
968 m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1;
969 m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2;
970 m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2;
973 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
977 m_pYUVShader->Disable();
980 glDisableVertexAttribArray(vertLoc);
981 glDisableVertexAttribArray(Yloc);
982 glDisableVertexAttribArray(Uloc);
983 glDisableVertexAttribArray(Vloc);
985 glActiveTexture(GL_TEXTURE1);
986 glDisable(m_textureTarget);
988 glActiveTexture(GL_TEXTURE2);
989 glDisable(m_textureTarget);
991 glActiveTexture(GL_TEXTURE0);
992 glDisable(m_textureTarget);
994 g_matrices.MatrixMode(MM_MODELVIEW);
999 void CLinuxRendererGLES::RenderMultiPass(int index, int field)
1001 // TODO: Multipass rendering does not currently work! FIX!
1002 CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!");
1005 YV12Image &im = m_buffers[index].image;
1006 YUVPLANES &planes = m_buffers[index].fields[field];
1008 if (m_reloadShaders)
1010 m_reloadShaders = 0;
1011 LoadShaders(m_currentField);
1014 glDisable(GL_DEPTH_TEST);
1017 glEnable(m_textureTarget);
1018 glActiveTexture(GL_TEXTURE0);
1019 glBindTexture(m_textureTarget, planes[0].id);
1023 glActiveTexture(GL_TEXTURE1);
1024 glEnable(m_textureTarget);
1025 glBindTexture(m_textureTarget, planes[1].id);
1029 glActiveTexture(GL_TEXTURE2);
1030 glEnable(m_textureTarget);
1031 glBindTexture(m_textureTarget, planes[2].id);
1034 glActiveTexture(GL_TEXTURE0);
1037 // make sure the yuv shader is loaded and ready to go
1038 if (!m_pYUVShader || (!m_pYUVShader->OK()))
1040 CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render");
1044 m_fbo.BeginRender();
1047 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
1048 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1049 m_pYUVShader->SetWidth(im.width);
1050 m_pYUVShader->SetHeight(im.height);
1051 if (field == FIELD_TOP)
1052 m_pYUVShader->SetField(1);
1053 else if(field == FIELD_BOT)
1054 m_pYUVShader->SetField(0);
1058 // glPushAttrib(GL_VIEWPORT_BIT);
1059 // glPushAttrib(GL_SCISSOR_BIT);
1060 g_matrices.MatrixMode(MM_MODELVIEW);
1061 g_matrices.PushMatrix();
1062 g_matrices.LoadIdentity();
1065 g_matrices.MatrixMode(MM_PROJECTION);
1066 g_matrices.PushMatrix();
1067 g_matrices.LoadIdentity();
1069 g_matrices.Ortho2D(0, m_sourceWidth, 0, m_sourceHeight);
1070 glViewport(0, 0, m_sourceWidth, m_sourceHeight);
1071 glScissor(0, 0, m_sourceWidth, m_sourceHeight);
1072 g_matrices.MatrixMode(MM_MODELVIEW);
1076 if (!m_pYUVShader->Enable())
1078 CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
1081 // 1st Pass to video frame size
1083 // float imgwidth = planes[0].rect.x2 - planes[0].rect.x1;
1084 // float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
1085 // if (m_textureTarget == GL_TEXTURE_2D)
1087 // imgwidth *= planes[0].texwidth;
1088 // imgheight *= planes[0].texheight;
1091 // glBegin(GL_QUADS);
1093 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
1094 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
1095 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
1096 // glVertex2f(0.0f , 0.0f);
1098 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
1099 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
1100 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
1101 // glVertex2f(imgwidth, 0.0f);
1103 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
1104 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
1105 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
1106 // glVertex2f(imgwidth, imgheight);
1108 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
1109 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
1110 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
1111 // glVertex2f(0.0f , imgheight);
1116 m_pYUVShader->Disable();
1118 g_matrices.MatrixMode(MM_MODELVIEW);
1119 g_matrices.PopMatrix(); // pop modelview
1120 g_matrices.MatrixMode(MM_PROJECTION);
1121 g_matrices.PopMatrix(); // pop projection
1123 // glPopAttrib(); // pop scissor
1124 // glPopAttrib(); // pop viewport
1125 g_matrices.MatrixMode(MM_MODELVIEW);
1130 glActiveTexture(GL_TEXTURE1);
1131 glDisable(m_textureTarget);
1132 glActiveTexture(GL_TEXTURE2);
1133 glDisable(m_textureTarget);
1134 glActiveTexture(GL_TEXTURE0);
1135 glDisable(m_textureTarget);
1137 glEnable(GL_TEXTURE_2D);
1138 glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
1141 // Use regular normalized texture coordinates
1143 // 2nd Pass to screen size with optional video filter
1145 if (m_pVideoFilterShader)
1147 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_NEAREST);
1148 m_pVideoFilterShader->SetSourceTexture(0);
1149 m_pVideoFilterShader->SetWidth(m_sourceWidth);
1150 m_pVideoFilterShader->SetHeight(m_sourceHeight);
1151 m_pVideoFilterShader->Enable();
1154 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_LINEAR);
1159 // imgwidth /= m_sourceWidth;
1160 // imgheight /= m_sourceHeight;
1162 // glBegin(GL_QUADS);
1164 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f);
1165 // glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
1167 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
1168 // glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
1170 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
1171 // glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
1173 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight);
1174 // glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
1180 if (m_pVideoFilterShader)
1181 m_pVideoFilterShader->Disable();
1185 glDisable(m_textureTarget);
1189 void CLinuxRendererGLES::RenderSoftware(int index, int field)
1191 YUVPLANES &planes = m_buffers[index].fields[field];
1193 glDisable(GL_DEPTH_TEST);
1196 glEnable(m_textureTarget);
1197 glActiveTexture(GL_TEXTURE0);
1198 glBindTexture(m_textureTarget, planes[0].id);
1200 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1202 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1205 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1207 GLint posLoc = g_Windowing.GUIShaderGetPos();
1208 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1209 GLint colLoc = g_Windowing.GUIShaderGetCol();
1211 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1212 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1213 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1215 glEnableVertexAttribArray(posLoc);
1216 glEnableVertexAttribArray(texLoc);
1217 glEnableVertexAttribArray(colLoc);
1219 // Set vertex coordinates
1220 for(int i = 0; i < 4; i++)
1222 ver[i][0] = m_rotatedDestCoords[i].x;
1223 ver[i][1] = m_rotatedDestCoords[i].y;
1224 ver[i][2] = 0.0f;// set z to 0
1228 // Set texture coordinates
1229 tex[0][0] = tex[3][0] = planes[0].rect.x1;
1230 tex[0][1] = tex[1][1] = planes[0].rect.y1;
1231 tex[1][0] = tex[2][0] = planes[0].rect.x2;
1232 tex[2][1] = tex[3][1] = planes[0].rect.y2;
1234 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1236 glDisableVertexAttribArray(posLoc);
1237 glDisableVertexAttribArray(texLoc);
1238 glDisableVertexAttribArray(colLoc);
1240 g_Windowing.DisableGUIShader();
1244 glDisable(m_textureTarget);
1248 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1250 #if defined(HAVE_LIBOPENMAX)
1251 GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1253 glDisable(GL_DEPTH_TEST);
1256 glEnable(m_textureTarget);
1257 glActiveTexture(GL_TEXTURE0);
1258 glBindTexture(m_textureTarget, textureId);
1260 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1262 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1265 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1267 GLint posLoc = g_Windowing.GUIShaderGetPos();
1268 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1269 GLint colLoc = g_Windowing.GUIShaderGetCol();
1271 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1272 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1273 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1275 glEnableVertexAttribArray(posLoc);
1276 glEnableVertexAttribArray(texLoc);
1277 glEnableVertexAttribArray(colLoc);
1279 // Set vertex coordinates
1280 for(int i = 0; i < 4; i++)
1282 ver[i][0] = m_rotatedDestCoords[i].x;
1283 ver[i][1] = m_rotatedDestCoords[i].y;
1284 ver[i][2] = 0.0f;// set z to 0
1288 // Set texture coordinates
1289 tex[0][0] = tex[3][0] = 0;
1290 tex[0][1] = tex[1][1] = 0;
1291 tex[1][0] = tex[2][0] = 1;
1292 tex[2][1] = tex[3][1] = 1;
1294 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1296 glDisableVertexAttribArray(posLoc);
1297 glDisableVertexAttribArray(texLoc);
1298 glDisableVertexAttribArray(colLoc);
1300 g_Windowing.DisableGUIShader();
1304 glDisable(m_textureTarget);
1309 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1311 #if defined(HAS_LIBSTAGEFRIGHT)
1312 #ifdef DEBUG_VERBOSE
1313 unsigned int time = XbmcThreads::SystemClockMillis();
1316 YUVPLANE &plane = m_buffers[index].fields[field][0];
1318 glDisable(GL_DEPTH_TEST);
1320 glActiveTexture(GL_TEXTURE0);
1321 glBindTexture(m_textureTarget, plane.id);
1323 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1325 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1328 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1330 GLint posLoc = g_Windowing.GUIShaderGetPos();
1331 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1332 GLint colLoc = g_Windowing.GUIShaderGetCol();
1334 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1335 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1336 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1338 glEnableVertexAttribArray(posLoc);
1339 glEnableVertexAttribArray(texLoc);
1340 glEnableVertexAttribArray(colLoc);
1342 // Set vertex coordinates
1343 for(int i = 0; i < 4; i++)
1345 ver[i][0] = m_rotatedDestCoords[i].x;
1346 ver[i][1] = m_rotatedDestCoords[i].y;
1347 ver[i][2] = 0.0f;// set z to 0
1351 // Set texture coordinates (is flipped in y)
1352 tex[0][0] = tex[3][0] = 0;
1353 tex[0][1] = tex[1][1] = 1;
1354 tex[1][0] = tex[2][0] = 1;
1355 tex[2][1] = tex[3][1] = 0;
1357 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1359 glDisableVertexAttribArray(posLoc);
1360 glDisableVertexAttribArray(texLoc);
1361 glDisableVertexAttribArray(colLoc);
1363 g_Windowing.DisableGUIShader();
1366 glBindTexture(m_textureTarget, 0);
1369 #ifdef DEBUG_VERBOSE
1370 CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1375 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1377 #ifdef HAVE_VIDEOTOOLBOXDECODER
1378 YUVPLANE &plane = m_buffers[index].fields[field][0];
1380 glDisable(GL_DEPTH_TEST);
1382 glEnable(m_textureTarget);
1383 glActiveTexture(GL_TEXTURE0);
1384 glBindTexture(m_textureTarget, plane.id);
1386 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1388 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1391 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1393 GLint posLoc = g_Windowing.GUIShaderGetPos();
1394 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1395 GLint colLoc = g_Windowing.GUIShaderGetCol();
1397 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1398 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1399 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1401 glEnableVertexAttribArray(posLoc);
1402 glEnableVertexAttribArray(texLoc);
1403 glEnableVertexAttribArray(colLoc);
1405 // Set vertex coordinates
1406 for(int i = 0; i < 4; i++)
1408 ver[i][0] = m_rotatedDestCoords[i].x;
1409 ver[i][1] = m_rotatedDestCoords[i].y;
1410 ver[i][2] = 0.0f;// set z to 0
1414 // Set texture coordinates (corevideo is flipped in y)
1415 tex[0][0] = tex[3][0] = 0;
1416 tex[0][1] = tex[1][1] = 1;
1417 tex[1][0] = tex[2][0] = 1;
1418 tex[2][1] = tex[3][1] = 0;
1420 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1422 glDisableVertexAttribArray(posLoc);
1423 glDisableVertexAttribArray(texLoc);
1424 glDisableVertexAttribArray(colLoc);
1426 g_Windowing.DisableGUIShader();
1429 glDisable(m_textureTarget);
1434 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1439 // If rendered directly by the hardware
1440 if (m_renderMethod & RENDER_BYPASS)
1442 capture->BeginRender();
1443 capture->EndRender();
1447 // save current video rect
1448 CRect saveSize = m_destRect;
1449 saveRotatedCoords();//backup current m_rotatedDestCoords
1451 // new video rect is thumbnail size
1452 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1454 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1455 // clear framebuffer and invert Y axis to get non-inverted image
1456 glDisable(GL_BLEND);
1458 g_matrices.MatrixMode(MM_MODELVIEW);
1459 g_matrices.PushMatrix();
1460 // fixme - we know that cvref & eglimg are already flipped in y direction
1461 // but somehow this also effects the rendercapture here
1462 // therefore we have to skip the flip here or we get upside down
1464 if (m_renderMethod != RENDER_CVREF)
1466 g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1467 g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1470 capture->BeginRender();
1472 Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1474 glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1475 GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1477 // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1478 // XOR Swap RGBA -> BGRA
1479 unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1480 for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1482 std::swap(pixels[0], pixels[2]);
1485 capture->EndRender();
1487 // revert model view matrix
1488 g_matrices.MatrixMode(MM_MODELVIEW);
1489 g_matrices.PopMatrix();
1491 // restore original video rect
1492 m_destRect = saveSize;
1493 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1498 //********************************************************************************************************
1499 // YV12 Texture creation, deletion, copying + clearing
1500 //********************************************************************************************************
1501 void CLinuxRendererGLES::UploadYV12Texture(int source)
1503 YUVBUFFER& buf = m_buffers[source];
1504 YV12Image* im = &buf.image;
1505 YUVFIELDS& fields = buf.fields;
1508 #if defined(HAVE_LIBOPENMAX)
1509 if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1511 if (!(im->flags&IMAGE_FLAG_READY))
1517 // if we don't have a shader, fallback to SW YUV2RGB for now
1518 if (m_renderMethod & RENDER_SW)
1520 if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1522 delete [] m_rgbBuffer;
1523 m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1524 m_rgbBuffer = new BYTE[m_rgbBufferSize];
1527 #if defined(__ARM_NEON__)
1528 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1530 yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1531 m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1536 m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1537 im->width, im->height, PIX_FMT_YUV420P,
1538 im->width, im->height, PIX_FMT_RGBA,
1539 SWS_FAST_BILINEAR, NULL, NULL, NULL);
1541 uint8_t *src[] = { im->plane[0], im->plane[1], im->plane[2], 0 };
1542 int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1543 uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 };
1544 int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1545 m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1550 if (m_currentField == FIELD_FULL)
1551 deinterlacing = false;
1553 deinterlacing = true;
1555 glEnable(m_textureTarget);
1558 if (m_renderMethod & RENDER_SW)
1563 LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1564 , im->width, im->height >> 1
1565 , m_sourceWidth*8, m_rgbBuffer );
1567 LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1568 , im->width, im->height >> 1
1569 , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4);
1573 LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1574 , im->width, im->height
1575 , m_sourceWidth*4, m_rgbBuffer );
1580 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1585 LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1586 , im->width, im->height >> 1
1587 , im->stride[0]*2, im->plane[0] );
1589 LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1590 , im->width, im->height >> 1
1591 , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
1596 LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1597 , im->width, im->height
1598 , im->stride[0], im->plane[0] );
1604 if (!(m_renderMethod & RENDER_SW))
1606 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1610 // Load Even U & V Fields
1611 LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1612 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1613 , im->stride[1]*2, im->plane[1] );
1615 LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
1616 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1617 , im->stride[2]*2, im->plane[2] );
1619 // Load Odd U & V Fields
1620 LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1621 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1622 , im->stride[1]*2, im->plane[1] + im->stride[1] );
1624 LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
1625 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1626 , im->stride[2]*2, im->plane[2] + im->stride[2] );
1631 LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1632 , im->width >> im->cshift_x, im->height >> im->cshift_y
1633 , im->stride[1], im->plane[1] );
1635 LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
1636 , im->width >> im->cshift_x, im->height >> im->cshift_y
1637 , im->stride[2], im->plane[2] );
1640 CalculateTextureSourceRects(source, 3);
1642 glDisable(m_textureTarget);
1645 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1647 YV12Image &im = m_buffers[index].image;
1648 YUVFIELDS &fields = m_buffers[index].fields;
1650 if( fields[FIELD_FULL][0].id == 0 ) return;
1652 /* finish up all textures, and delete them */
1653 g_graphicsContext.BeginPaint(); //FIXME
1654 for(int f = 0;f<MAX_FIELDS;f++)
1656 for(int p = 0;p<MAX_PLANES;p++)
1658 if( fields[f][p].id )
1660 if (glIsTexture(fields[f][p].id))
1661 glDeleteTextures(1, &fields[f][p].id);
1662 fields[f][p].id = 0;
1666 g_graphicsContext.EndPaint();
1668 for(int p = 0;p<MAX_PLANES;p++)
1672 delete[] im.plane[p];
1678 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1680 /* since we also want the field textures, pitch must be texture aligned */
1681 YV12Image &im = m_buffers[index].image;
1682 YUVFIELDS &fields = m_buffers[index].fields;
1684 DeleteYV12Texture(index);
1686 im.height = m_sourceHeight;
1687 im.width = m_sourceWidth;
1691 im.stride[0] = im.width;
1692 im.stride[1] = im.width >> im.cshift_x;
1693 im.stride[2] = im.width >> im.cshift_x;
1695 im.planesize[0] = im.stride[0] * im.height;
1696 im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1697 im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1699 for (int i = 0; i < 3; i++)
1700 im.plane[i] = new BYTE[im.planesize[i]];
1702 glEnable(m_textureTarget);
1703 for(int f = 0;f<MAX_FIELDS;f++)
1705 for(int p = 0;p<MAX_PLANES;p++)
1707 if (!glIsTexture(fields[f][p].id))
1709 glGenTextures(1, &fields[f][p].id);
1716 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1718 int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1719 YUVPLANES &planes = fields[f];
1721 planes[0].texwidth = im.width;
1722 planes[0].texheight = im.height >> fieldshift;
1724 if (m_renderMethod & RENDER_SW)
1726 planes[1].texwidth = 0;
1727 planes[1].texheight = 0;
1728 planes[2].texwidth = 0;
1729 planes[2].texheight = 0;
1733 planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
1734 planes[1].texheight = planes[0].texheight >> im.cshift_y;
1735 planes[2].texwidth = planes[0].texwidth >> im.cshift_x;
1736 planes[2].texheight = planes[0].texheight >> im.cshift_y;
1739 if(m_renderMethod & RENDER_POT)
1741 for(int p = 0; p < 3; p++)
1743 planes[p].texwidth = NP2(planes[p].texwidth);
1744 planes[p].texheight = NP2(planes[p].texheight);
1748 for(int p = 0; p < 3; p++)
1750 YUVPLANE &plane = planes[p];
1751 if (plane.texwidth * plane.texheight == 0)
1754 glBindTexture(m_textureTarget, plane.id);
1755 if (m_renderMethod & RENDER_SW)
1757 if(m_renderMethod & RENDER_POT)
1758 CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d", plane.texwidth, plane.texheight);
1760 CLog::Log(LOGDEBUG, "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1762 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1763 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1767 if(m_renderMethod & RENDER_POT)
1768 CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d", plane.texwidth, plane.texheight);
1770 CLog::Log(LOGDEBUG, "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1772 glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
1775 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1776 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1777 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1778 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1782 glDisable(m_textureTarget);
1786 //********************************************************************************************************
1787 // CoreVideoRef Texture creation, deletion, copying + clearing
1788 //********************************************************************************************************
1789 void CLinuxRendererGLES::UploadCVRefTexture(int index)
1791 #ifdef HAVE_VIDEOTOOLBOXDECODER
1792 CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
1796 YUVPLANE &plane = m_buffers[index].fields[0][0];
1798 CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1799 #if !TARGET_OS_IPHONE
1800 int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
1802 int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
1803 int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
1804 unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
1806 glEnable(m_textureTarget);
1809 glBindTexture(m_textureTarget, plane.id);
1810 #if !TARGET_OS_IPHONE
1811 #ifdef GL_UNPACK_ROW_LENGTH
1813 glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
1815 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1816 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1817 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1821 // Using BGRA extension to pull in video frame data directly
1822 glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
1824 #if !TARGET_OS_IPHONE
1825 #ifdef GL_UNPACK_ROW_LENGTH
1827 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1830 glBindTexture(m_textureTarget, 0);
1832 glDisable(m_textureTarget);
1835 CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1836 CVBufferRelease(m_buffers[index].cvBufferRef);
1837 m_buffers[index].cvBufferRef = NULL;
1839 plane.flipindex = m_buffers[index].flipindex;
1843 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
1845 #ifdef HAVE_VIDEOTOOLBOXDECODER
1846 YUVPLANE &plane = m_buffers[index].fields[0][0];
1848 if (m_buffers[index].cvBufferRef)
1849 CVBufferRelease(m_buffers[index].cvBufferRef);
1850 m_buffers[index].cvBufferRef = NULL;
1852 if(plane.id && glIsTexture(plane.id))
1853 glDeleteTextures(1, &plane.id);
1857 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
1859 #ifdef HAVE_VIDEOTOOLBOXDECODER
1860 YV12Image &im = m_buffers[index].image;
1861 YUVFIELDS &fields = m_buffers[index].fields;
1862 YUVPLANE &plane = fields[0][0];
1864 DeleteCVRefTexture(index);
1866 memset(&im , 0, sizeof(im));
1867 memset(&fields, 0, sizeof(fields));
1869 im.height = m_sourceHeight;
1870 im.width = m_sourceWidth;
1872 plane.texwidth = im.width;
1873 plane.texheight = im.height;
1875 if(m_renderMethod & RENDER_POT)
1877 plane.texwidth = NP2(plane.texwidth);
1878 plane.texheight = NP2(plane.texheight);
1880 glEnable(m_textureTarget);
1881 glGenTextures(1, &plane.id);
1884 glBindTexture(m_textureTarget, plane.id);
1885 #if !TARGET_OS_IPHONE
1886 #ifdef GL_UNPACK_ROW_LENGTH
1888 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
1890 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1891 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1892 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1893 // Set client storage
1895 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1898 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1899 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1900 // This is necessary for non-power-of-two textures
1901 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1902 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1903 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1904 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1906 #if !TARGET_OS_IPHONE
1907 // turn off client storage so it doesn't get picked up for the next texture
1908 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
1910 glBindTexture(m_textureTarget, 0);
1911 glDisable(m_textureTarget);
1916 //********************************************************************************************************
1917 // BYPASS creation, deletion, copying + clearing
1918 //********************************************************************************************************
1919 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
1922 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
1925 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
1930 //********************************************************************************************************
1931 // EGLIMG creation, deletion, copying + clearing
1932 //********************************************************************************************************
1933 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
1935 #ifdef HAS_LIBSTAGEFRIGHT
1936 #ifdef DEBUG_VERBOSE
1937 unsigned int time = XbmcThreads::SystemClockMillis();
1940 if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
1942 YUVPLANE &plane = m_buffers[index].fields[0][0];
1944 glActiveTexture(GL_TEXTURE0);
1945 glBindTexture(m_textureTarget, plane.id);
1946 glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
1947 glBindTexture(m_textureTarget, 0);
1949 plane.flipindex = m_buffers[index].flipindex;
1952 #ifdef DEBUG_VERBOSE
1953 CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
1957 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
1959 #ifdef HAS_LIBSTAGEFRIGHT
1960 YUVPLANE &plane = m_buffers[index].fields[0][0];
1962 if(plane.id && glIsTexture(plane.id))
1963 glDeleteTextures(1, &plane.id);
1967 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
1969 #ifdef HAS_LIBSTAGEFRIGHT
1970 YV12Image &im = m_buffers[index].image;
1971 YUVFIELDS &fields = m_buffers[index].fields;
1972 YUVPLANE &plane = fields[0][0];
1974 DeleteEGLIMGTexture(index);
1976 memset(&im , 0, sizeof(im));
1977 memset(&fields, 0, sizeof(fields));
1979 im.height = m_sourceHeight;
1980 im.width = m_sourceWidth;
1982 plane.texwidth = im.width;
1983 plane.texheight = im.height;
1985 if(m_renderMethod & RENDER_POT)
1987 plane.texwidth = NP2(plane.texwidth);
1988 plane.texheight = NP2(plane.texheight);
1990 glEnable(m_textureTarget);
1991 glGenTextures(1, &plane.id);
1994 glBindTexture(m_textureTarget, plane.id);
1996 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1997 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1998 // This is necessary for non-power-of-two textures
1999 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2000 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2002 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2004 glDisable(m_textureTarget);
2009 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
2011 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
2013 YUVFIELDS &fields = m_buffers[i].fields;
2015 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2017 glBindTexture(m_textureTarget, fields[f][0].id);
2018 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2019 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2022 if (!(m_renderMethod & RENDER_SW))
2024 glBindTexture(m_textureTarget, fields[f][1].id);
2025 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2026 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2029 glBindTexture(m_textureTarget, fields[f][2].id);
2030 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2031 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2038 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2040 // Player controls render, let it dictate available render features
2041 if((m_renderMethod & RENDER_BYPASS))
2043 Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2044 return itr != m_renderFeatures.end();
2047 if(feature == RENDERFEATURE_BRIGHTNESS)
2050 if(feature == RENDERFEATURE_CONTRAST)
2053 if(feature == RENDERFEATURE_GAMMA)
2056 if(feature == RENDERFEATURE_NOISE)
2059 if(feature == RENDERFEATURE_SHARPNESS)
2062 if (feature == RENDERFEATURE_NONLINSTRETCH)
2065 if (feature == RENDERFEATURE_STRETCH ||
2066 feature == RENDERFEATURE_CROP ||
2067 feature == RENDERFEATURE_ZOOM ||
2068 feature == RENDERFEATURE_VERTICAL_SHIFT ||
2069 feature == RENDERFEATURE_PIXEL_RATIO ||
2070 feature == RENDERFEATURE_POSTPROCESS ||
2071 feature == RENDERFEATURE_ROTATION)
2078 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2083 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2085 // Player controls render, let it dictate available deinterlace modes
2086 if((m_renderMethod & RENDER_BYPASS))
2088 Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2089 return itr != m_deinterlaceModes.end();
2092 if (mode == VS_DEINTERLACEMODE_OFF)
2095 if(m_renderMethod & RENDER_OMXEGL)
2098 if(m_renderMethod & RENDER_EGLIMG)
2101 if(m_renderMethod & RENDER_CVREF)
2104 if(mode == VS_DEINTERLACEMODE_AUTO
2105 || mode == VS_DEINTERLACEMODE_FORCE)
2111 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2113 // Player controls render, let it dictate available deinterlace methods
2114 if((m_renderMethod & RENDER_BYPASS))
2116 Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2117 return itr != m_deinterlaceMethods.end();
2120 if(m_renderMethod & RENDER_OMXEGL)
2123 if(m_renderMethod & RENDER_EGLIMG)
2126 if(m_renderMethod & RENDER_CVREF)
2129 if(method == VS_INTERLACEMETHOD_AUTO)
2132 #if defined(__i386__) || defined(__x86_64__)
2133 if(method == VS_INTERLACEMETHOD_DEINTERLACE
2134 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2135 || method == VS_INTERLACEMETHOD_SW_BLEND)
2137 if(method == VS_INTERLACEMETHOD_SW_BLEND)
2144 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2146 // Player controls render, let it dictate available scaling methods
2147 if((m_renderMethod & RENDER_BYPASS))
2149 Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2150 return itr != m_scalingMethods.end();
2153 if(method == VS_SCALINGMETHOD_NEAREST
2154 || method == VS_SCALINGMETHOD_LINEAR)
2160 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2162 // Player controls render, let it pick the auto-deinterlace method
2163 if((m_renderMethod & RENDER_BYPASS))
2165 if (!m_deinterlaceMethods.empty())
2166 return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2168 return VS_INTERLACEMETHOD_NONE;
2171 if(m_renderMethod & RENDER_OMXEGL)
2172 return VS_INTERLACEMETHOD_NONE;
2174 if(m_renderMethod & RENDER_EGLIMG)
2175 return VS_INTERLACEMETHOD_NONE;
2177 if(m_renderMethod & RENDER_CVREF)
2178 return VS_INTERLACEMETHOD_NONE;
2180 #if defined(__i386__) || defined(__x86_64__)
2181 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2183 return VS_INTERLACEMETHOD_SW_BLEND;
2187 unsigned int CLinuxRendererGLES::GetProcessorSize()
2189 if(m_format == RENDER_FMT_OMXEGL
2190 || m_format == RENDER_FMT_CVBREF
2191 || m_format == RENDER_FMT_EGLIMG)
2197 #ifdef HAVE_LIBOPENMAX
2198 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2200 YUVBUFFER &buf = m_buffers[index];
2201 buf.openMaxBuffer = picture->openMaxBuffer;
2204 #ifdef HAVE_VIDEOTOOLBOXDECODER
2205 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2207 YUVBUFFER &buf = m_buffers[index];
2208 if (buf.cvBufferRef)
2209 CVBufferRelease(buf.cvBufferRef);
2210 buf.cvBufferRef = cvBufferRef;
2211 // retain another reference, this way dvdplayer and renderer can issue releases.
2212 CVBufferRetain(buf.cvBufferRef);
2215 #ifdef HAS_LIBSTAGEFRIGHT
2216 void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
2218 #ifdef DEBUG_VERBOSE
2219 unsigned int time = XbmcThreads::SystemClockMillis();
2222 YUVBUFFER &buf = m_buffers[index];
2223 if (buf.eglimg != EGL_NO_IMAGE_KHR)
2224 stf->ReleaseBuffer(buf.eglimg);
2225 stf->LockBuffer(eglimg);
2228 buf.eglimg = eglimg;
2230 #ifdef DEBUG_VERBOSE
2231 CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);