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 // create the yuv textures
176 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
177 (this->*m_textureCreate)(i);
185 bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
187 m_sourceWidth = width;
188 m_sourceHeight = height;
189 m_renderOrientation = orientation;
195 // Calculate the input frame aspect ratio.
196 CalculateFrameAspectRatio(d_width, d_height);
197 ChooseBestResolution(fps);
198 SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
201 m_bConfigured = true;
202 m_bImageReady = false;
203 m_scalingMethodGui = (ESCALINGMETHOD)-1;
205 // Ensure that textures are recreated and rendering starts only after the 1st
206 // frame is loaded after every call to Configure().
207 m_bValidated = false;
209 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
210 m_buffers[i].image.flags = 0;
212 m_iLastRenderBuffer = -1;
214 m_RenderUpdateCallBackFn = NULL;
215 m_RenderUpdateCallBackCtx = NULL;
216 if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer())
218 m_renderFeatures.clear();
219 m_scalingMethods.clear();
220 m_deinterlaceModes.clear();
221 m_deinterlaceMethods.clear();
223 if (m_RenderFeaturesCallBackFn)
225 (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures);
226 // after setting up m_renderFeatures, we are done with the callback
227 m_RenderFeaturesCallBackFn = NULL;
228 m_RenderFeaturesCallBackCtx = NULL;
230 g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures);
231 g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods);
232 g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes);
233 g_application.m_pPlayer->GetScalingMethods(m_scalingMethods);
239 int CLinuxRendererGLES::NextYV12Texture()
241 return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
244 int CLinuxRendererGLES::GetImage(YV12Image *image, int source, bool readonly)
246 if (!image) return -1;
247 if (!m_bValidated) return -1;
249 /* take next available buffer */
250 if( source == AUTOSOURCE )
251 source = NextYV12Texture();
253 if ( m_renderMethod & RENDER_OMXEGL )
257 #ifdef HAS_LIBSTAGEFRIGHT
258 if ( m_renderMethod & RENDER_EGLIMG )
263 #ifdef HAVE_VIDEOTOOLBOXDECODER
264 if (m_renderMethod & RENDER_CVREF )
270 YV12Image &im = m_buffers[source].image;
272 if ((im.flags&(~IMAGE_FLAG_READY)) != 0)
274 CLog::Log(LOGDEBUG, "CLinuxRenderer::GetImage - request image but none to give");
279 im.flags |= IMAGE_FLAG_READING;
281 im.flags |= IMAGE_FLAG_WRITING;
283 // copy the image - should be operator of YV12Image
284 for (int p=0;p<MAX_PLANES;p++)
286 image->plane[p] = im.plane[p];
287 image->stride[p] = im.stride[p];
289 image->width = im.width;
290 image->height = im.height;
291 image->flags = im.flags;
292 image->cshift_x = im.cshift_x;
293 image->cshift_y = im.cshift_y;
299 void CLinuxRendererGLES::ReleaseImage(int source, bool preserve)
301 YV12Image &im = m_buffers[source].image;
303 im.flags &= ~IMAGE_FLAG_INUSE;
304 im.flags |= IMAGE_FLAG_READY;
305 /* if image should be preserved reserve it so it's not auto seleceted */
308 im.flags |= IMAGE_FLAG_RESERVED;
310 m_bImageReady = true;
313 void CLinuxRendererGLES::CalculateTextureSourceRects(int source, int num_planes)
315 YUVBUFFER& buf = m_buffers[source];
316 YV12Image* im = &buf.image;
317 YUVFIELDS& fields = buf.fields;
319 // calculate the source rectangle
320 for(int field = 0; field < 3; field++)
322 for(int plane = 0; plane < num_planes; plane++)
324 YUVPLANE& p = fields[field][plane];
326 p.rect = m_sourceRect;
328 p.height = im->height;
330 if(field != FIELD_FULL)
332 /* correct for field offsets and chroma offsets */
333 float offset_y = 0.5;
336 if(field == FIELD_BOT)
339 p.rect.y1 += offset_y;
340 p.rect.y2 += offset_y;
342 /* half the height if this is a field */
350 p.width /= 1 << im->cshift_x;
351 p.height /= 1 << im->cshift_y;
353 p.rect.x1 /= 1 << im->cshift_x;
354 p.rect.x2 /= 1 << im->cshift_x;
355 p.rect.y1 /= 1 << im->cshift_y;
356 p.rect.y2 /= 1 << im->cshift_y;
359 if (m_textureTarget == GL_TEXTURE_2D)
361 p.height /= p.texheight;
362 p.rect.y1 /= p.texheight;
363 p.rect.y2 /= p.texheight;
364 p.width /= p.texwidth;
365 p.rect.x1 /= p.texwidth;
366 p.rect.x2 /= p.texwidth;
372 void CLinuxRendererGLES::LoadPlane( YUVPLANE& plane, int type, unsigned flipindex
373 , unsigned width, unsigned height
374 , unsigned int stride, void* data )
376 if(plane.flipindex == flipindex)
379 const GLvoid *pixelData = data;
381 int bps = glFormatElementByteCount(type);
383 glBindTexture(m_textureTarget, plane.id);
385 // OpenGL ES does not support strided texture input.
386 if(stride != width * bps)
388 unsigned char* src = (unsigned char*)data;
389 for (unsigned int y = 0; y < height;++y, src += stride)
390 glTexSubImage2D(m_textureTarget, 0, 0, y, width, 1, type, GL_UNSIGNED_BYTE, src);
392 glTexSubImage2D(m_textureTarget, 0, 0, 0, width, height, type, GL_UNSIGNED_BYTE, pixelData);
395 /* check if we need to load any border pixels */
396 if(height < plane.texheight)
397 glTexSubImage2D( m_textureTarget, 0
398 , 0, height, width, 1
399 , type, GL_UNSIGNED_BYTE
400 , (unsigned char*)pixelData + stride * (height-1));
402 if(width < plane.texwidth)
403 glTexSubImage2D( m_textureTarget, 0
404 , width, 0, 1, height
405 , type, GL_UNSIGNED_BYTE
406 , (unsigned char*)pixelData + bps * (width-1));
408 glBindTexture(m_textureTarget, 0);
410 plane.flipindex = flipindex;
413 void CLinuxRendererGLES::Reset()
415 for(int i=0; i<m_NumYV12Buffers; i++)
417 /* reset all image flags, this will cleanup textures later */
418 m_buffers[i].image.flags = 0;
422 void CLinuxRendererGLES::Flush()
429 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
430 (this->*m_textureDelete)(i);
433 m_bValidated = false;
435 m_iYV12RenderBuffer = 0;
438 void CLinuxRendererGLES::Update()
440 if (!m_bConfigured) return;
444 void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
446 if (!m_bConfigured) return;
448 // if its first pass, just init textures and return
449 if (ValidateRenderTarget())
452 if (m_renderMethod & RENDER_BYPASS)
455 // if running bypass, then the player might need the src/dst rects
456 // for sizing video playback on a layer other than the gles layer.
457 if (m_RenderUpdateCallBackFn)
458 (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect);
460 CRect old = g_graphicsContext.GetScissors();
462 g_graphicsContext.BeginPaint();
463 g_graphicsContext.SetScissors(m_destRect);
466 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
467 glClearColor(0, 0, 0, 0);
468 glClear(GL_COLOR_BUFFER_BIT);
470 g_graphicsContext.SetScissors(old);
471 g_graphicsContext.EndPaint();
475 // this needs to be checked after texture validation
476 if (!m_bImageReady) return;
478 int index = m_iYV12RenderBuffer;
479 YUVBUFFER& buf = m_buffers[index];
481 if (m_format != RENDER_FMT_OMXEGL && m_format != RENDER_FMT_EGLIMG)
483 if (!buf.fields[FIELD_FULL][0].id) return;
485 if (buf.image.flags==0)
490 g_graphicsContext.BeginPaint();
492 m_iLastRenderBuffer = index;
496 glClearColor(m_clearColour, m_clearColour, m_clearColour, 0);
497 glClear(GL_COLOR_BUFFER_BIT);
498 glClearColor(0,0,0,0);
504 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
506 m_pYUVShader->SetAlpha(alpha / 255.0f);
512 m_pYUVShader->SetAlpha(1.0f);
515 if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT))
516 CLog::Log(LOGERROR, "GLES: Cannot render stipple!");
518 Render(flags, index);
523 g_graphicsContext.EndPaint();
526 void CLinuxRendererGLES::FlipPage(int source)
528 if( source >= 0 && source < m_NumYV12Buffers )
529 m_iYV12RenderBuffer = source;
531 m_iYV12RenderBuffer = NextYV12Texture();
533 m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
538 unsigned int CLinuxRendererGLES::PreInit()
540 CSingleLock lock(g_graphicsContext);
541 m_bConfigured = false;
542 m_bValidated = false;
544 m_resolution = CDisplaySettings::Get().GetCurrentResolution();
545 if ( m_resolution == RES_WINDOW )
546 m_resolution = RES_DESKTOP;
548 m_iYV12RenderBuffer = 0;
549 m_NumYV12Buffers = 2;
551 m_formats.push_back(RENDER_FMT_YUV420P);
552 m_formats.push_back(RENDER_FMT_BYPASS);
553 #if defined(HAVE_LIBOPENMAX)
554 m_formats.push_back(RENDER_FMT_OMXEGL);
556 #ifdef HAVE_VIDEOTOOLBOXDECODER
557 m_formats.push_back(RENDER_FMT_CVBREF);
559 #ifdef HAS_LIBSTAGEFRIGHT
560 m_formats.push_back(RENDER_FMT_EGLIMG);
563 // setup the background colour
564 m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
566 if (!m_dllSwScale->Load())
567 CLog::Log(LOGERROR,"CLinuxRendererGL::PreInit - failed to load rescale libraries!");
572 void CLinuxRendererGLES::UpdateVideoFilter()
574 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod)
576 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
577 m_scalingMethod = m_scalingMethodGui;
579 if(!Supports(m_scalingMethod))
581 CLog::Log(LOGWARNING, "CLinuxRendererGLES::UpdateVideoFilter - choosen scaling method %d, is not supported by renderer", (int)m_scalingMethod);
582 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
585 if (m_pVideoFilterShader)
587 m_pVideoFilterShader->Free();
588 delete m_pVideoFilterShader;
589 m_pVideoFilterShader = NULL;
595 switch (m_scalingMethod)
597 case VS_SCALINGMETHOD_NEAREST:
598 SetTextureFilter(GL_NEAREST);
599 m_renderQuality = RQ_SINGLEPASS;
602 case VS_SCALINGMETHOD_LINEAR:
603 SetTextureFilter(GL_LINEAR);
604 m_renderQuality = RQ_SINGLEPASS;
607 case VS_SCALINGMETHOD_CUBIC:
608 CLog::Log(LOGERROR, "GLES: CUBIC not supported!");
611 case VS_SCALINGMETHOD_LANCZOS2:
612 case VS_SCALINGMETHOD_LANCZOS3:
613 case VS_SCALINGMETHOD_SINC8:
614 case VS_SCALINGMETHOD_NEDI:
615 CLog::Log(LOGERROR, "GL: TODO: This scaler has not yet been implemented");
622 CGUIDialogKaiToast::QueueNotification("Video Renderering", "Failed to init video filters/scalers, falling back to bilinear scaling");
623 CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler");
624 if (m_pVideoFilterShader)
626 m_pVideoFilterShader->Free();
627 delete m_pVideoFilterShader;
628 m_pVideoFilterShader = NULL;
632 SetTextureFilter(GL_LINEAR);
633 m_renderQuality = RQ_SINGLEPASS;
636 void CLinuxRendererGLES::LoadShaders(int field)
638 #ifdef TARGET_DARWIN_IOS
639 float ios_version = GetIOSVersion();
641 int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
642 CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod);
646 m_pYUVShader->Free();
651 switch(requestedMethod)
653 case RENDER_METHOD_AUTO:
654 case RENDER_METHOD_GLSL:
655 if (m_format == RENDER_FMT_OMXEGL)
657 CLog::Log(LOGNOTICE, "GL: Using OMXEGL RGBA render method");
658 m_renderMethod = RENDER_OMXEGL;
661 else if (m_format == RENDER_FMT_EGLIMG)
663 CLog::Log(LOGNOTICE, "GL: Using EGL Image render method");
664 m_renderMethod = RENDER_EGLIMG;
667 else if (m_format == RENDER_FMT_BYPASS)
669 CLog::Log(LOGNOTICE, "GL: Using BYPASS render method");
670 m_renderMethod = RENDER_BYPASS;
673 else if (m_format == RENDER_FMT_CVBREF)
675 CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef RGBA render method");
676 m_renderMethod = RENDER_CVREF;
679 #if defined(TARGET_DARWIN_IOS)
680 else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P)
682 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA render method");
683 m_renderMethod = RENDER_SW;
687 // Try GLSL shaders if supported and user requested auto or GLSL.
690 // create regular progressive scan shader
691 m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format);
692 CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
694 if (m_pYUVShader && m_pYUVShader->CompileAndLink())
696 m_renderMethod = RENDER_GLSL;
700 else if (m_pYUVShader)
702 m_pYUVShader->Free();
705 CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader");
706 // drop through and try SW
709 case RENDER_METHOD_SOFTWARE:
712 // Use software YUV 2 RGB conversion if user requested it or GLSL failed
713 m_renderMethod = RENDER_SW ;
714 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA rendering");
718 // determine whether GPU supports NPOT textures
719 if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
721 CLog::Log(LOGNOTICE, "GL: GL_ARB_texture_rectangle not supported and OpenGL version is not 2.x");
722 CLog::Log(LOGNOTICE, "GL: Reverting to POT textures");
723 m_renderMethod |= RENDER_POT;
726 CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
728 // Now that we now the render method, setup texture function handlers
729 if (m_format == RENDER_FMT_CVBREF)
731 m_textureUpload = &CLinuxRendererGLES::UploadCVRefTexture;
732 m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
733 m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
735 else if (m_format == RENDER_FMT_BYPASS)
737 m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
738 m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
739 m_textureDelete = &CLinuxRendererGLES::DeleteBYPASSTexture;
741 else if (m_format == RENDER_FMT_EGLIMG)
743 m_textureUpload = &CLinuxRendererGLES::UploadEGLIMGTexture;
744 m_textureCreate = &CLinuxRendererGLES::CreateEGLIMGTexture;
745 m_textureDelete = &CLinuxRendererGLES::DeleteEGLIMGTexture;
749 // default to YV12 texture handlers
750 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
751 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
752 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
755 if (m_oldRenderMethod != m_renderMethod)
757 CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod);
759 m_oldRenderMethod = m_renderMethod;
763 void CLinuxRendererGLES::UnInit()
765 CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources");
766 CSingleLock lock(g_graphicsContext);
768 if (m_rgbBuffer != NULL)
770 delete [] m_rgbBuffer;
776 for (int i = 0; i < NUM_BUFFERS; ++i)
777 (this->*m_textureDelete)(i);
779 if (m_dllSwScale && m_sw_context)
781 m_dllSwScale->sws_freeContext(m_sw_context);
785 // cleanup framebuffer object if it was in use
787 m_bValidated = false;
788 m_bImageReady = false;
789 m_bConfigured = false;
790 m_RenderUpdateCallBackFn = NULL;
791 m_RenderUpdateCallBackCtx = NULL;
792 m_RenderFeaturesCallBackFn = NULL;
793 m_RenderFeaturesCallBackCtx = NULL;
796 inline void CLinuxRendererGLES::ReorderDrawPoints()
799 CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points
801 //corevideo and EGL are flipped in y
802 if(m_renderMethod & RENDER_CVREF)
805 tmp = m_rotatedDestCoords[0];
806 m_rotatedDestCoords[0] = m_rotatedDestCoords[3];
807 m_rotatedDestCoords[3] = tmp;
808 tmp = m_rotatedDestCoords[1];
809 m_rotatedDestCoords[1] = m_rotatedDestCoords[2];
810 m_rotatedDestCoords[2] = tmp;
814 void CLinuxRendererGLES::ReleaseBuffer(int idx)
816 #ifdef HAVE_VIDEOTOOLBOXDECODER
817 YUVBUFFER &buf = m_buffers[idx];
820 CVBufferRelease(buf.cvBufferRef);
821 buf.cvBufferRef = NULL;
825 void CLinuxRendererGLES::Render(DWORD flags, int index)
827 // If rendered directly by the hardware
828 if (m_renderMethod & RENDER_BYPASS)
831 // obtain current field, if interlaced
832 if( flags & RENDER_FLAG_TOP)
833 m_currentField = FIELD_TOP;
835 else if (flags & RENDER_FLAG_BOT)
836 m_currentField = FIELD_BOT;
839 m_currentField = FIELD_FULL;
841 (this->*m_textureUpload)(index);
843 if (m_renderMethod & RENDER_GLSL)
846 switch(m_renderQuality)
850 RenderSinglePass(index, m_currentField);
855 RenderMultiPass(index, m_currentField);
860 RenderSoftware(index, m_currentField);
865 else if (m_renderMethod & RENDER_OMXEGL)
867 RenderOpenMax(index, m_currentField);
870 else if (m_renderMethod & RENDER_EGLIMG)
872 RenderEglImage(index, m_currentField);
875 else if (m_renderMethod & RENDER_CVREF)
877 RenderCoreVideoRef(index, m_currentField);
882 RenderSoftware(index, m_currentField);
887 void CLinuxRendererGLES::RenderSinglePass(int index, int field)
889 YV12Image &im = m_buffers[index].image;
890 YUVFIELDS &fields = m_buffers[index].fields;
891 YUVPLANES &planes = fields[field];
899 glDisable(GL_DEPTH_TEST);
902 glActiveTexture(GL_TEXTURE0);
903 glEnable(m_textureTarget);
904 glBindTexture(m_textureTarget, planes[0].id);
907 glActiveTexture(GL_TEXTURE1);
908 glEnable(m_textureTarget);
909 glBindTexture(m_textureTarget, planes[1].id);
912 glActiveTexture(GL_TEXTURE2);
913 glEnable(m_textureTarget);
914 glBindTexture(m_textureTarget, planes[2].id);
916 glActiveTexture(GL_TEXTURE0);
919 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
920 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
921 m_pYUVShader->SetWidth(im.width);
922 m_pYUVShader->SetHeight(im.height);
923 if (field == FIELD_TOP)
924 m_pYUVShader->SetField(1);
925 else if(field == FIELD_BOT)
926 m_pYUVShader->SetField(0);
928 m_pYUVShader->SetMatrices(g_matrices.GetMatrix(MM_PROJECTION), g_matrices.GetMatrix(MM_MODELVIEW));
929 m_pYUVShader->Enable();
931 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
932 GLfloat m_vert[4][3];
933 GLfloat m_tex[3][4][2];
935 GLint vertLoc = m_pYUVShader->GetVertexLoc();
936 GLint Yloc = m_pYUVShader->GetYcoordLoc();
937 GLint Uloc = m_pYUVShader->GetUcoordLoc();
938 GLint Vloc = m_pYUVShader->GetVcoordLoc();
940 glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert);
941 glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]);
942 glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, m_tex[1]);
943 glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, m_tex[2]);
945 glEnableVertexAttribArray(vertLoc);
946 glEnableVertexAttribArray(Yloc);
947 glEnableVertexAttribArray(Uloc);
948 glEnableVertexAttribArray(Vloc);
950 // Setup vertex position values
951 for(int i = 0; i < 4; i++)
953 m_vert[i][0] = m_rotatedDestCoords[i].x;
954 m_vert[i][1] = m_rotatedDestCoords[i].y;
955 m_vert[i][2] = 0.0f;// set z to 0
958 // Setup texture coordinates
959 for (int i=0; i<3; i++)
961 m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1;
962 m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1;
963 m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2;
964 m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2;
967 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
971 m_pYUVShader->Disable();
974 glDisableVertexAttribArray(vertLoc);
975 glDisableVertexAttribArray(Yloc);
976 glDisableVertexAttribArray(Uloc);
977 glDisableVertexAttribArray(Vloc);
979 glActiveTexture(GL_TEXTURE1);
980 glDisable(m_textureTarget);
982 glActiveTexture(GL_TEXTURE2);
983 glDisable(m_textureTarget);
985 glActiveTexture(GL_TEXTURE0);
986 glDisable(m_textureTarget);
988 g_matrices.MatrixMode(MM_MODELVIEW);
993 void CLinuxRendererGLES::RenderMultiPass(int index, int field)
995 // TODO: Multipass rendering does not currently work! FIX!
996 CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!");
999 YV12Image &im = m_buffers[index].image;
1000 YUVPLANES &planes = m_buffers[index].fields[field];
1002 if (m_reloadShaders)
1004 m_reloadShaders = 0;
1005 LoadShaders(m_currentField);
1008 glDisable(GL_DEPTH_TEST);
1011 glEnable(m_textureTarget);
1012 glActiveTexture(GL_TEXTURE0);
1013 glBindTexture(m_textureTarget, planes[0].id);
1017 glActiveTexture(GL_TEXTURE1);
1018 glEnable(m_textureTarget);
1019 glBindTexture(m_textureTarget, planes[1].id);
1023 glActiveTexture(GL_TEXTURE2);
1024 glEnable(m_textureTarget);
1025 glBindTexture(m_textureTarget, planes[2].id);
1028 glActiveTexture(GL_TEXTURE0);
1031 // make sure the yuv shader is loaded and ready to go
1032 if (!m_pYUVShader || (!m_pYUVShader->OK()))
1034 CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render");
1038 m_fbo.BeginRender();
1041 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
1042 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1043 m_pYUVShader->SetWidth(im.width);
1044 m_pYUVShader->SetHeight(im.height);
1045 if (field == FIELD_TOP)
1046 m_pYUVShader->SetField(1);
1047 else if(field == FIELD_BOT)
1048 m_pYUVShader->SetField(0);
1052 // glPushAttrib(GL_VIEWPORT_BIT);
1053 // glPushAttrib(GL_SCISSOR_BIT);
1054 g_matrices.MatrixMode(MM_MODELVIEW);
1055 g_matrices.PushMatrix();
1056 g_matrices.LoadIdentity();
1059 g_matrices.MatrixMode(MM_PROJECTION);
1060 g_matrices.PushMatrix();
1061 g_matrices.LoadIdentity();
1063 g_matrices.Ortho2D(0, m_sourceWidth, 0, m_sourceHeight);
1064 glViewport(0, 0, m_sourceWidth, m_sourceHeight);
1065 glScissor(0, 0, m_sourceWidth, m_sourceHeight);
1066 g_matrices.MatrixMode(MM_MODELVIEW);
1070 if (!m_pYUVShader->Enable())
1072 CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
1075 // 1st Pass to video frame size
1077 // float imgwidth = planes[0].rect.x2 - planes[0].rect.x1;
1078 // float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
1079 // if (m_textureTarget == GL_TEXTURE_2D)
1081 // imgwidth *= planes[0].texwidth;
1082 // imgheight *= planes[0].texheight;
1085 // glBegin(GL_QUADS);
1087 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
1088 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
1089 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
1090 // glVertex2f(0.0f , 0.0f);
1092 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
1093 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
1094 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
1095 // glVertex2f(imgwidth, 0.0f);
1097 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
1098 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
1099 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
1100 // glVertex2f(imgwidth, imgheight);
1102 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
1103 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
1104 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
1105 // glVertex2f(0.0f , imgheight);
1110 m_pYUVShader->Disable();
1112 g_matrices.MatrixMode(MM_MODELVIEW);
1113 g_matrices.PopMatrix(); // pop modelview
1114 g_matrices.MatrixMode(MM_PROJECTION);
1115 g_matrices.PopMatrix(); // pop projection
1117 // glPopAttrib(); // pop scissor
1118 // glPopAttrib(); // pop viewport
1119 g_matrices.MatrixMode(MM_MODELVIEW);
1124 glActiveTexture(GL_TEXTURE1);
1125 glDisable(m_textureTarget);
1126 glActiveTexture(GL_TEXTURE2);
1127 glDisable(m_textureTarget);
1128 glActiveTexture(GL_TEXTURE0);
1129 glDisable(m_textureTarget);
1131 glEnable(GL_TEXTURE_2D);
1132 glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
1135 // Use regular normalized texture coordinates
1137 // 2nd Pass to screen size with optional video filter
1139 if (m_pVideoFilterShader)
1141 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_NEAREST);
1142 m_pVideoFilterShader->SetSourceTexture(0);
1143 m_pVideoFilterShader->SetWidth(m_sourceWidth);
1144 m_pVideoFilterShader->SetHeight(m_sourceHeight);
1145 m_pVideoFilterShader->Enable();
1148 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_LINEAR);
1153 // imgwidth /= m_sourceWidth;
1154 // imgheight /= m_sourceHeight;
1156 // glBegin(GL_QUADS);
1158 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f);
1159 // glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
1161 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
1162 // glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
1164 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
1165 // glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
1167 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight);
1168 // glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
1174 if (m_pVideoFilterShader)
1175 m_pVideoFilterShader->Disable();
1179 glDisable(m_textureTarget);
1183 void CLinuxRendererGLES::RenderSoftware(int index, int field)
1185 YUVPLANES &planes = m_buffers[index].fields[field];
1187 glDisable(GL_DEPTH_TEST);
1190 glEnable(m_textureTarget);
1191 glActiveTexture(GL_TEXTURE0);
1192 glBindTexture(m_textureTarget, planes[0].id);
1194 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1196 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1199 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1201 GLint posLoc = g_Windowing.GUIShaderGetPos();
1202 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1203 GLint colLoc = g_Windowing.GUIShaderGetCol();
1205 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1206 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1207 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1209 glEnableVertexAttribArray(posLoc);
1210 glEnableVertexAttribArray(texLoc);
1211 glEnableVertexAttribArray(colLoc);
1213 // Set vertex coordinates
1214 for(int i = 0; i < 4; i++)
1216 ver[i][0] = m_rotatedDestCoords[i].x;
1217 ver[i][1] = m_rotatedDestCoords[i].y;
1218 ver[i][2] = 0.0f;// set z to 0
1222 // Set texture coordinates
1223 tex[0][0] = tex[3][0] = planes[0].rect.x1;
1224 tex[0][1] = tex[1][1] = planes[0].rect.y1;
1225 tex[1][0] = tex[2][0] = planes[0].rect.x2;
1226 tex[2][1] = tex[3][1] = planes[0].rect.y2;
1228 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1230 glDisableVertexAttribArray(posLoc);
1231 glDisableVertexAttribArray(texLoc);
1232 glDisableVertexAttribArray(colLoc);
1234 g_Windowing.DisableGUIShader();
1238 glDisable(m_textureTarget);
1242 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1244 #if defined(HAVE_LIBOPENMAX)
1245 GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1247 glDisable(GL_DEPTH_TEST);
1250 glEnable(m_textureTarget);
1251 glActiveTexture(GL_TEXTURE0);
1252 glBindTexture(m_textureTarget, textureId);
1254 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1256 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1259 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1261 GLint posLoc = g_Windowing.GUIShaderGetPos();
1262 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1263 GLint colLoc = g_Windowing.GUIShaderGetCol();
1265 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1266 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1267 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1269 glEnableVertexAttribArray(posLoc);
1270 glEnableVertexAttribArray(texLoc);
1271 glEnableVertexAttribArray(colLoc);
1273 // Set vertex coordinates
1274 for(int i = 0; i < 4; i++)
1276 ver[i][0] = m_rotatedDestCoords[i].x;
1277 ver[i][1] = m_rotatedDestCoords[i].y;
1278 ver[i][2] = 0.0f;// set z to 0
1282 // Set texture coordinates
1283 tex[0][0] = tex[3][0] = 0;
1284 tex[0][1] = tex[1][1] = 0;
1285 tex[1][0] = tex[2][0] = 1;
1286 tex[2][1] = tex[3][1] = 1;
1288 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1290 glDisableVertexAttribArray(posLoc);
1291 glDisableVertexAttribArray(texLoc);
1292 glDisableVertexAttribArray(colLoc);
1294 g_Windowing.DisableGUIShader();
1298 glDisable(m_textureTarget);
1303 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1305 #if defined(HAS_LIBSTAGEFRIGHT)
1306 #ifdef DEBUG_VERBOSE
1307 unsigned int time = XbmcThreads::SystemClockMillis();
1310 YUVPLANE &plane = m_buffers[index].fields[field][0];
1312 glDisable(GL_DEPTH_TEST);
1314 glActiveTexture(GL_TEXTURE0);
1315 glBindTexture(m_textureTarget, plane.id);
1317 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1319 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1322 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1324 GLint posLoc = g_Windowing.GUIShaderGetPos();
1325 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1326 GLint colLoc = g_Windowing.GUIShaderGetCol();
1328 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1329 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1330 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1332 glEnableVertexAttribArray(posLoc);
1333 glEnableVertexAttribArray(texLoc);
1334 glEnableVertexAttribArray(colLoc);
1336 // Set vertex coordinates
1337 for(int i = 0; i < 4; i++)
1339 ver[i][0] = m_rotatedDestCoords[i].x;
1340 ver[i][1] = m_rotatedDestCoords[i].y;
1341 ver[i][2] = 0.0f;// set z to 0
1345 // Set texture coordinates (is flipped in y)
1346 tex[0][0] = tex[3][0] = 0;
1347 tex[0][1] = tex[1][1] = 1;
1348 tex[1][0] = tex[2][0] = 1;
1349 tex[2][1] = tex[3][1] = 0;
1351 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1353 glDisableVertexAttribArray(posLoc);
1354 glDisableVertexAttribArray(texLoc);
1355 glDisableVertexAttribArray(colLoc);
1357 g_Windowing.DisableGUIShader();
1360 glBindTexture(m_textureTarget, 0);
1363 #ifdef DEBUG_VERBOSE
1364 CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1369 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1371 #ifdef HAVE_VIDEOTOOLBOXDECODER
1372 YUVPLANE &plane = m_buffers[index].fields[field][0];
1374 glDisable(GL_DEPTH_TEST);
1376 glEnable(m_textureTarget);
1377 glActiveTexture(GL_TEXTURE0);
1378 glBindTexture(m_textureTarget, plane.id);
1380 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1382 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1385 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1387 GLint posLoc = g_Windowing.GUIShaderGetPos();
1388 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1389 GLint colLoc = g_Windowing.GUIShaderGetCol();
1391 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1392 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1393 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1395 glEnableVertexAttribArray(posLoc);
1396 glEnableVertexAttribArray(texLoc);
1397 glEnableVertexAttribArray(colLoc);
1399 // Set vertex coordinates
1400 for(int i = 0; i < 4; i++)
1402 ver[i][0] = m_rotatedDestCoords[i].x;
1403 ver[i][1] = m_rotatedDestCoords[i].y;
1404 ver[i][2] = 0.0f;// set z to 0
1408 // Set texture coordinates (corevideo is flipped in y)
1409 tex[0][0] = tex[3][0] = 0;
1410 tex[0][1] = tex[1][1] = 1;
1411 tex[1][0] = tex[2][0] = 1;
1412 tex[2][1] = tex[3][1] = 0;
1414 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1416 glDisableVertexAttribArray(posLoc);
1417 glDisableVertexAttribArray(texLoc);
1418 glDisableVertexAttribArray(colLoc);
1420 g_Windowing.DisableGUIShader();
1423 glDisable(m_textureTarget);
1428 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1433 // If rendered directly by the hardware
1434 if (m_renderMethod & RENDER_BYPASS)
1436 capture->BeginRender();
1437 capture->EndRender();
1441 // save current video rect
1442 CRect saveSize = m_destRect;
1443 saveRotatedCoords();//backup current m_rotatedDestCoords
1445 // new video rect is thumbnail size
1446 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1448 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1449 // clear framebuffer and invert Y axis to get non-inverted image
1450 glDisable(GL_BLEND);
1452 g_matrices.MatrixMode(MM_MODELVIEW);
1453 g_matrices.PushMatrix();
1454 // fixme - we know that cvref & eglimg are already flipped in y direction
1455 // but somehow this also effects the rendercapture here
1456 // therefore we have to skip the flip here or we get upside down
1458 if (m_renderMethod != RENDER_CVREF)
1460 g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1461 g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1464 capture->BeginRender();
1466 Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1468 glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1469 GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1471 // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1472 // XOR Swap RGBA -> BGRA
1473 unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1474 for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1476 std::swap(pixels[0], pixels[2]);
1479 capture->EndRender();
1481 // revert model view matrix
1482 g_matrices.MatrixMode(MM_MODELVIEW);
1483 g_matrices.PopMatrix();
1485 // restore original video rect
1486 m_destRect = saveSize;
1487 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1492 //********************************************************************************************************
1493 // YV12 Texture creation, deletion, copying + clearing
1494 //********************************************************************************************************
1495 void CLinuxRendererGLES::UploadYV12Texture(int source)
1497 YUVBUFFER& buf = m_buffers[source];
1498 YV12Image* im = &buf.image;
1499 YUVFIELDS& fields = buf.fields;
1502 #if defined(HAVE_LIBOPENMAX)
1503 if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1505 if (!(im->flags&IMAGE_FLAG_READY))
1511 // if we don't have a shader, fallback to SW YUV2RGB for now
1512 if (m_renderMethod & RENDER_SW)
1514 if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1516 delete [] m_rgbBuffer;
1517 m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1518 m_rgbBuffer = new BYTE[m_rgbBufferSize];
1521 #if defined(__ARM_NEON__)
1522 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1524 yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1525 m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1530 m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1531 im->width, im->height, PIX_FMT_YUV420P,
1532 im->width, im->height, PIX_FMT_RGBA,
1533 SWS_FAST_BILINEAR, NULL, NULL, NULL);
1535 uint8_t *src[] = { im->plane[0], im->plane[1], im->plane[2], 0 };
1536 int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1537 uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 };
1538 int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1539 m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1544 if (m_currentField == FIELD_FULL)
1545 deinterlacing = false;
1547 deinterlacing = true;
1549 glEnable(m_textureTarget);
1552 if (m_renderMethod & RENDER_SW)
1557 LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1558 , im->width, im->height >> 1
1559 , m_sourceWidth*8, m_rgbBuffer );
1561 LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1562 , im->width, im->height >> 1
1563 , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4);
1567 LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1568 , im->width, im->height
1569 , m_sourceWidth*4, m_rgbBuffer );
1574 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1579 LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1580 , im->width, im->height >> 1
1581 , im->stride[0]*2, im->plane[0] );
1583 LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1584 , im->width, im->height >> 1
1585 , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
1590 LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1591 , im->width, im->height
1592 , im->stride[0], im->plane[0] );
1598 if (!(m_renderMethod & RENDER_SW))
1600 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1604 // Load Even U & V Fields
1605 LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1606 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1607 , im->stride[1]*2, im->plane[1] );
1609 LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
1610 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1611 , im->stride[2]*2, im->plane[2] );
1613 // Load Odd U & V Fields
1614 LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1615 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1616 , im->stride[1]*2, im->plane[1] + im->stride[1] );
1618 LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
1619 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1620 , im->stride[2]*2, im->plane[2] + im->stride[2] );
1625 LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1626 , im->width >> im->cshift_x, im->height >> im->cshift_y
1627 , im->stride[1], im->plane[1] );
1629 LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
1630 , im->width >> im->cshift_x, im->height >> im->cshift_y
1631 , im->stride[2], im->plane[2] );
1634 CalculateTextureSourceRects(source, 3);
1636 glDisable(m_textureTarget);
1639 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1641 YV12Image &im = m_buffers[index].image;
1642 YUVFIELDS &fields = m_buffers[index].fields;
1644 if( fields[FIELD_FULL][0].id == 0 ) return;
1646 /* finish up all textures, and delete them */
1647 g_graphicsContext.BeginPaint(); //FIXME
1648 for(int f = 0;f<MAX_FIELDS;f++)
1650 for(int p = 0;p<MAX_PLANES;p++)
1652 if( fields[f][p].id )
1654 if (glIsTexture(fields[f][p].id))
1655 glDeleteTextures(1, &fields[f][p].id);
1656 fields[f][p].id = 0;
1660 g_graphicsContext.EndPaint();
1662 for(int p = 0;p<MAX_PLANES;p++)
1666 delete[] im.plane[p];
1672 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1674 /* since we also want the field textures, pitch must be texture aligned */
1675 YV12Image &im = m_buffers[index].image;
1676 YUVFIELDS &fields = m_buffers[index].fields;
1678 DeleteYV12Texture(index);
1680 im.height = m_sourceHeight;
1681 im.width = m_sourceWidth;
1685 im.stride[0] = im.width;
1686 im.stride[1] = im.width >> im.cshift_x;
1687 im.stride[2] = im.width >> im.cshift_x;
1689 im.planesize[0] = im.stride[0] * im.height;
1690 im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1691 im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1693 for (int i = 0; i < 3; i++)
1694 im.plane[i] = new BYTE[im.planesize[i]];
1696 glEnable(m_textureTarget);
1697 for(int f = 0;f<MAX_FIELDS;f++)
1699 for(int p = 0;p<MAX_PLANES;p++)
1701 if (!glIsTexture(fields[f][p].id))
1703 glGenTextures(1, &fields[f][p].id);
1710 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1712 int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1713 YUVPLANES &planes = fields[f];
1715 planes[0].texwidth = im.width;
1716 planes[0].texheight = im.height >> fieldshift;
1718 if (m_renderMethod & RENDER_SW)
1720 planes[1].texwidth = 0;
1721 planes[1].texheight = 0;
1722 planes[2].texwidth = 0;
1723 planes[2].texheight = 0;
1727 planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
1728 planes[1].texheight = planes[0].texheight >> im.cshift_y;
1729 planes[2].texwidth = planes[0].texwidth >> im.cshift_x;
1730 planes[2].texheight = planes[0].texheight >> im.cshift_y;
1733 if(m_renderMethod & RENDER_POT)
1735 for(int p = 0; p < 3; p++)
1737 planes[p].texwidth = NP2(planes[p].texwidth);
1738 planes[p].texheight = NP2(planes[p].texheight);
1742 for(int p = 0; p < 3; p++)
1744 YUVPLANE &plane = planes[p];
1745 if (plane.texwidth * plane.texheight == 0)
1748 glBindTexture(m_textureTarget, plane.id);
1749 if (m_renderMethod & RENDER_SW)
1751 if(m_renderMethod & RENDER_POT)
1752 CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d", plane.texwidth, plane.texheight);
1754 CLog::Log(LOGDEBUG, "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1756 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1757 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1761 if(m_renderMethod & RENDER_POT)
1762 CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d", plane.texwidth, plane.texheight);
1764 CLog::Log(LOGDEBUG, "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1766 glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
1769 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1770 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1771 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1772 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1776 glDisable(m_textureTarget);
1780 //********************************************************************************************************
1781 // CoreVideoRef Texture creation, deletion, copying + clearing
1782 //********************************************************************************************************
1783 void CLinuxRendererGLES::UploadCVRefTexture(int index)
1785 #ifdef HAVE_VIDEOTOOLBOXDECODER
1786 CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
1790 YUVPLANE &plane = m_buffers[index].fields[0][0];
1792 CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1793 #if !TARGET_OS_IPHONE
1794 int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
1796 int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
1797 int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
1798 unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
1800 glEnable(m_textureTarget);
1803 glBindTexture(m_textureTarget, plane.id);
1804 #if !TARGET_OS_IPHONE
1805 #ifdef GL_UNPACK_ROW_LENGTH
1807 glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
1809 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1810 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1811 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1815 // Using BGRA extension to pull in video frame data directly
1816 glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
1818 #if !TARGET_OS_IPHONE
1819 #ifdef GL_UNPACK_ROW_LENGTH
1821 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1824 glBindTexture(m_textureTarget, 0);
1826 glDisable(m_textureTarget);
1829 CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1830 CVBufferRelease(m_buffers[index].cvBufferRef);
1831 m_buffers[index].cvBufferRef = NULL;
1833 plane.flipindex = m_buffers[index].flipindex;
1837 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
1839 #ifdef HAVE_VIDEOTOOLBOXDECODER
1840 YUVPLANE &plane = m_buffers[index].fields[0][0];
1842 if (m_buffers[index].cvBufferRef)
1843 CVBufferRelease(m_buffers[index].cvBufferRef);
1844 m_buffers[index].cvBufferRef = NULL;
1846 if(plane.id && glIsTexture(plane.id))
1847 glDeleteTextures(1, &plane.id);
1851 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
1853 #ifdef HAVE_VIDEOTOOLBOXDECODER
1854 YV12Image &im = m_buffers[index].image;
1855 YUVFIELDS &fields = m_buffers[index].fields;
1856 YUVPLANE &plane = fields[0][0];
1858 DeleteCVRefTexture(index);
1860 memset(&im , 0, sizeof(im));
1861 memset(&fields, 0, sizeof(fields));
1863 im.height = m_sourceHeight;
1864 im.width = m_sourceWidth;
1866 plane.texwidth = im.width;
1867 plane.texheight = im.height;
1869 if(m_renderMethod & RENDER_POT)
1871 plane.texwidth = NP2(plane.texwidth);
1872 plane.texheight = NP2(plane.texheight);
1874 glEnable(m_textureTarget);
1875 glGenTextures(1, &plane.id);
1878 glBindTexture(m_textureTarget, plane.id);
1879 #if !TARGET_OS_IPHONE
1880 #ifdef GL_UNPACK_ROW_LENGTH
1882 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
1884 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1885 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1886 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1887 // Set client storage
1889 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
1892 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1893 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1894 // This is necessary for non-power-of-two textures
1895 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1896 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1897 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1898 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
1900 #if !TARGET_OS_IPHONE
1901 // turn off client storage so it doesn't get picked up for the next texture
1902 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
1904 glBindTexture(m_textureTarget, 0);
1905 glDisable(m_textureTarget);
1910 //********************************************************************************************************
1911 // BYPASS creation, deletion, copying + clearing
1912 //********************************************************************************************************
1913 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
1916 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
1919 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
1924 //********************************************************************************************************
1925 // EGLIMG creation, deletion, copying + clearing
1926 //********************************************************************************************************
1927 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
1929 #ifdef HAS_LIBSTAGEFRIGHT
1930 #ifdef DEBUG_VERBOSE
1931 unsigned int time = XbmcThreads::SystemClockMillis();
1934 if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
1936 YUVPLANE &plane = m_buffers[index].fields[0][0];
1938 glActiveTexture(GL_TEXTURE0);
1939 glBindTexture(m_textureTarget, plane.id);
1940 glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
1941 glBindTexture(m_textureTarget, 0);
1943 plane.flipindex = m_buffers[index].flipindex;
1946 #ifdef DEBUG_VERBOSE
1947 CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
1951 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
1953 #ifdef HAS_LIBSTAGEFRIGHT
1954 YUVPLANE &plane = m_buffers[index].fields[0][0];
1956 if(plane.id && glIsTexture(plane.id))
1957 glDeleteTextures(1, &plane.id);
1961 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
1963 #ifdef HAS_LIBSTAGEFRIGHT
1964 YV12Image &im = m_buffers[index].image;
1965 YUVFIELDS &fields = m_buffers[index].fields;
1966 YUVPLANE &plane = fields[0][0];
1968 DeleteEGLIMGTexture(index);
1970 memset(&im , 0, sizeof(im));
1971 memset(&fields, 0, sizeof(fields));
1973 im.height = m_sourceHeight;
1974 im.width = m_sourceWidth;
1976 plane.texwidth = im.width;
1977 plane.texheight = im.height;
1979 if(m_renderMethod & RENDER_POT)
1981 plane.texwidth = NP2(plane.texwidth);
1982 plane.texheight = NP2(plane.texheight);
1984 glEnable(m_textureTarget);
1985 glGenTextures(1, &plane.id);
1988 glBindTexture(m_textureTarget, plane.id);
1990 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1991 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1992 // This is necessary for non-power-of-two textures
1993 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1994 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1996 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1998 glDisable(m_textureTarget);
2003 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
2005 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
2007 YUVFIELDS &fields = m_buffers[i].fields;
2009 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2011 glBindTexture(m_textureTarget, fields[f][0].id);
2012 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2013 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2016 if (!(m_renderMethod & RENDER_SW))
2018 glBindTexture(m_textureTarget, fields[f][1].id);
2019 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2020 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2023 glBindTexture(m_textureTarget, fields[f][2].id);
2024 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2025 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2032 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2034 // Player controls render, let it dictate available render features
2035 if((m_renderMethod & RENDER_BYPASS))
2037 Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2038 return itr != m_renderFeatures.end();
2041 if(feature == RENDERFEATURE_BRIGHTNESS)
2044 if(feature == RENDERFEATURE_CONTRAST)
2047 if(feature == RENDERFEATURE_GAMMA)
2050 if(feature == RENDERFEATURE_NOISE)
2053 if(feature == RENDERFEATURE_SHARPNESS)
2056 if (feature == RENDERFEATURE_NONLINSTRETCH)
2059 if (feature == RENDERFEATURE_STRETCH ||
2060 feature == RENDERFEATURE_CROP ||
2061 feature == RENDERFEATURE_ZOOM ||
2062 feature == RENDERFEATURE_VERTICAL_SHIFT ||
2063 feature == RENDERFEATURE_PIXEL_RATIO ||
2064 feature == RENDERFEATURE_POSTPROCESS ||
2065 feature == RENDERFEATURE_ROTATION)
2072 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2077 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2079 // Player controls render, let it dictate available deinterlace modes
2080 if((m_renderMethod & RENDER_BYPASS))
2082 Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2083 return itr != m_deinterlaceModes.end();
2086 if (mode == VS_DEINTERLACEMODE_OFF)
2089 if(m_renderMethod & RENDER_OMXEGL)
2092 if(m_renderMethod & RENDER_EGLIMG)
2095 if(m_renderMethod & RENDER_CVREF)
2098 if(mode == VS_DEINTERLACEMODE_AUTO
2099 || mode == VS_DEINTERLACEMODE_FORCE)
2105 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2107 // Player controls render, let it dictate available deinterlace methods
2108 if((m_renderMethod & RENDER_BYPASS))
2110 Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2111 return itr != m_deinterlaceMethods.end();
2114 if(m_renderMethod & RENDER_OMXEGL)
2117 if(m_renderMethod & RENDER_EGLIMG)
2120 if(m_renderMethod & RENDER_CVREF)
2123 if(method == VS_INTERLACEMETHOD_AUTO)
2126 #if defined(__i386__) || defined(__x86_64__)
2127 if(method == VS_INTERLACEMETHOD_DEINTERLACE
2128 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2129 || method == VS_INTERLACEMETHOD_SW_BLEND)
2131 if(method == VS_INTERLACEMETHOD_SW_BLEND)
2138 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2140 // Player controls render, let it dictate available scaling methods
2141 if((m_renderMethod & RENDER_BYPASS))
2143 Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2144 return itr != m_scalingMethods.end();
2147 if(method == VS_SCALINGMETHOD_NEAREST
2148 || method == VS_SCALINGMETHOD_LINEAR)
2154 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2156 // Player controls render, let it pick the auto-deinterlace method
2157 if((m_renderMethod & RENDER_BYPASS))
2159 if (!m_deinterlaceMethods.empty())
2160 return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2162 return VS_INTERLACEMETHOD_NONE;
2165 if(m_renderMethod & RENDER_OMXEGL)
2166 return VS_INTERLACEMETHOD_NONE;
2168 if(m_renderMethod & RENDER_EGLIMG)
2169 return VS_INTERLACEMETHOD_NONE;
2171 if(m_renderMethod & RENDER_CVREF)
2172 return VS_INTERLACEMETHOD_NONE;
2174 #if defined(__i386__) || defined(__x86_64__)
2175 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2177 return VS_INTERLACEMETHOD_SW_BLEND;
2181 unsigned int CLinuxRendererGLES::GetProcessorSize()
2183 if(m_format == RENDER_FMT_OMXEGL
2184 || m_format == RENDER_FMT_CVBREF
2185 || m_format == RENDER_FMT_EGLIMG)
2191 #ifdef HAVE_LIBOPENMAX
2192 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2194 YUVBUFFER &buf = m_buffers[index];
2195 buf.openMaxBuffer = picture->openMaxBuffer;
2198 #ifdef HAVE_VIDEOTOOLBOXDECODER
2199 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2201 YUVBUFFER &buf = m_buffers[index];
2202 if (buf.cvBufferRef)
2203 CVBufferRelease(buf.cvBufferRef);
2204 buf.cvBufferRef = cvBufferRef;
2205 // retain another reference, this way dvdplayer and renderer can issue releases.
2206 CVBufferRetain(buf.cvBufferRef);
2209 #ifdef HAS_LIBSTAGEFRIGHT
2210 void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
2212 #ifdef DEBUG_VERBOSE
2213 unsigned int time = XbmcThreads::SystemClockMillis();
2216 YUVBUFFER &buf = m_buffers[index];
2217 if (buf.eglimg != EGL_NO_IMAGE_KHR)
2218 stf->ReleaseBuffer(buf.eglimg);
2219 stf->LockBuffer(eglimg);
2222 buf.eglimg = eglimg;
2224 #ifdef DEBUG_VERBOSE
2225 CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);