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/>.
21 //#define DEBUG_VERBOSE 1
24 #if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
29 #include "system_gl.h"
32 #include "guilib/MatrixGLES.h"
33 #include "LinuxRendererGLES.h"
34 #include "utils/fastmemcpy.h"
35 #include "utils/MathUtils.h"
36 #include "utils/GLUtils.h"
37 #include "settings/AdvancedSettings.h"
38 #include "settings/DisplaySettings.h"
39 #include "settings/MediaSettings.h"
40 #include "settings/Settings.h"
41 #include "guilib/FrameBufferObject.h"
42 #include "VideoShaders/YUV2RGBShader.h"
43 #include "VideoShaders/VideoFilterShader.h"
44 #include "windowing/WindowingFactory.h"
45 #include "dialogs/GUIDialogKaiToast.h"
46 #include "guilib/Texture.h"
47 #include "lib/DllSwScale.h"
48 #include "../dvdplayer/DVDCodecs/Video/OpenMaxVideo.h"
49 #include "threads/SingleLock.h"
50 #include "RenderCapture.h"
51 #include "RenderFormats.h"
52 #include "xbmc/Application.h"
53 #include "cores/IPlayer.h"
55 #if defined(__ARM_NEON__)
56 #include "yuv2rgb.neon.h"
57 #include "utils/CPUInfo.h"
59 #ifdef HAVE_VIDEOTOOLBOXDECODER
60 #include "DVDCodecs/Video/DVDVideoCodecVideoToolBox.h"
61 #include <CoreVideo/CoreVideo.h>
63 #ifdef TARGET_DARWIN_IOS
64 #include "osx/DarwinUtils.h"
66 #if defined(HAS_LIBSTAGEFRIGHT)
68 #include <EGL/eglext.h>
69 #include "windowing/egl/EGLWrapper.h"
70 #include "android/activity/XBMCApp.h"
71 #include "DVDCodecs/Video/StageFrightVideo.h"
73 // EGL extension functions
74 static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
75 static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
76 static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
79 #if defined(TARGET_ANDROID)
80 #include "DVDCodecs/Video/DVDVideoCodecAndroidMediaCodec.h"
83 using namespace Shaders;
85 CLinuxRendererGLES::YUVBUFFER::YUVBUFFER()
87 memset(&fields, 0, sizeof(fields));
88 memset(&image , 0, sizeof(image));
90 #ifdef HAVE_LIBOPENMAX
93 #ifdef HAVE_VIDEOTOOLBOXDECODER
96 #ifdef HAS_LIBSTAGEFRIGHT
98 eglimg = EGL_NO_IMAGE_KHR;
100 #if defined(TARGET_ANDROID)
105 CLinuxRendererGLES::YUVBUFFER::~YUVBUFFER()
109 CLinuxRendererGLES::CLinuxRendererGLES()
111 m_textureTarget = GL_TEXTURE_2D;
113 m_renderMethod = RENDER_GLSL;
114 m_oldRenderMethod = m_renderMethod;
115 m_renderQuality = RQ_SINGLEPASS;
117 m_format = RENDER_FMT_NONE;
119 m_iYV12RenderBuffer = 0;
121 m_currentField = FIELD_FULL;
124 m_pVideoFilterShader = NULL;
125 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
126 m_scalingMethodGui = (ESCALINGMETHOD)-1;
128 // default texture handlers to YUV
129 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
130 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
131 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
136 m_dllSwScale = new DllSwScale;
138 m_NumYV12Buffers = 0;
139 m_iLastRenderBuffer = 0;
140 m_bConfigured = false;
141 m_bValidated = false;
142 m_bImageReady = false;
143 m_StrictBinding = false;
144 m_clearColour = 0.0f;
146 #ifdef HAS_LIBSTAGEFRIGHT
147 if (!eglCreateImageKHR)
148 eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglCreateImageKHR");
149 if (!eglDestroyImageKHR)
150 eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) CEGLWrapper::GetProcAddress("eglDestroyImageKHR");
151 if (!glEGLImageTargetTexture2DOES)
152 glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) CEGLWrapper::GetProcAddress("glEGLImageTargetTexture2DOES");
156 CLinuxRendererGLES::~CLinuxRendererGLES()
160 if (m_rgbBuffer != NULL) {
161 delete [] m_rgbBuffer;
167 m_pYUVShader->Free();
175 bool CLinuxRendererGLES::ValidateRenderTarget()
179 CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
181 // function pointer for texture might change in
182 // call to LoadShaders
184 for (int i = 0 ; i < NUM_BUFFERS ; i++)
185 (this->*m_textureDelete)(i);
187 // create the yuv textures
190 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
191 (this->*m_textureCreate)(i);
199 bool CLinuxRendererGLES::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
201 m_sourceWidth = width;
202 m_sourceHeight = height;
203 m_renderOrientation = orientation;
209 // Calculate the input frame aspect ratio.
210 CalculateFrameAspectRatio(d_width, d_height);
211 ChooseBestResolution(fps);
212 SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
215 m_bConfigured = true;
216 m_bImageReady = false;
217 m_scalingMethodGui = (ESCALINGMETHOD)-1;
219 // Ensure that textures are recreated and rendering starts only after the 1st
220 // frame is loaded after every call to Configure().
221 m_bValidated = false;
223 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
224 m_buffers[i].image.flags = 0;
226 m_iLastRenderBuffer = -1;
228 m_RenderUpdateCallBackFn = NULL;
229 m_RenderUpdateCallBackCtx = NULL;
230 if ((m_format == RENDER_FMT_BYPASS) && g_application.GetCurrentPlayer())
232 m_renderFeatures.clear();
233 m_scalingMethods.clear();
234 m_deinterlaceModes.clear();
235 m_deinterlaceMethods.clear();
237 if (m_RenderFeaturesCallBackFn)
239 (*m_RenderFeaturesCallBackFn)(m_RenderFeaturesCallBackCtx, m_renderFeatures);
240 // after setting up m_renderFeatures, we are done with the callback
241 m_RenderFeaturesCallBackFn = NULL;
242 m_RenderFeaturesCallBackCtx = NULL;
244 g_application.m_pPlayer->GetRenderFeatures(m_renderFeatures);
245 g_application.m_pPlayer->GetDeinterlaceMethods(m_deinterlaceMethods);
246 g_application.m_pPlayer->GetDeinterlaceModes(m_deinterlaceModes);
247 g_application.m_pPlayer->GetScalingMethods(m_scalingMethods);
253 int CLinuxRendererGLES::NextYV12Texture()
255 return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
258 int CLinuxRendererGLES::GetImage(YV12Image *image, int source, bool readonly)
260 if (!image) return -1;
261 if (!m_bValidated) return -1;
263 /* take next available buffer */
264 if( source == AUTOSOURCE )
265 source = NextYV12Texture();
267 if ( m_renderMethod & RENDER_OMXEGL )
271 #ifdef HAS_LIBSTAGEFRIGHT
272 if ( m_renderMethod & RENDER_EGLIMG )
278 if ( m_renderMethod & RENDER_MEDIACODEC )
283 #ifdef HAVE_VIDEOTOOLBOXDECODER
284 if (m_renderMethod & RENDER_CVREF )
290 YV12Image &im = m_buffers[source].image;
292 if ((im.flags&(~IMAGE_FLAG_READY)) != 0)
294 CLog::Log(LOGDEBUG, "CLinuxRenderer::GetImage - request image but none to give");
299 im.flags |= IMAGE_FLAG_READING;
301 im.flags |= IMAGE_FLAG_WRITING;
303 // copy the image - should be operator of YV12Image
304 for (int p=0;p<MAX_PLANES;p++)
306 image->plane[p] = im.plane[p];
307 image->stride[p] = im.stride[p];
309 image->width = im.width;
310 image->height = im.height;
311 image->flags = im.flags;
312 image->cshift_x = im.cshift_x;
313 image->cshift_y = im.cshift_y;
319 void CLinuxRendererGLES::ReleaseImage(int source, bool preserve)
321 YV12Image &im = m_buffers[source].image;
323 im.flags &= ~IMAGE_FLAG_INUSE;
324 im.flags |= IMAGE_FLAG_READY;
325 /* if image should be preserved reserve it so it's not auto seleceted */
328 im.flags |= IMAGE_FLAG_RESERVED;
330 m_bImageReady = true;
333 void CLinuxRendererGLES::CalculateTextureSourceRects(int source, int num_planes)
335 YUVBUFFER& buf = m_buffers[source];
336 YV12Image* im = &buf.image;
337 YUVFIELDS& fields = buf.fields;
339 // calculate the source rectangle
340 for(int field = 0; field < 3; field++)
342 for(int plane = 0; plane < num_planes; plane++)
344 YUVPLANE& p = fields[field][plane];
346 p.rect = m_sourceRect;
348 p.height = im->height;
350 if(field != FIELD_FULL)
352 /* correct for field offsets and chroma offsets */
353 float offset_y = 0.5;
356 if(field == FIELD_BOT)
359 p.rect.y1 += offset_y;
360 p.rect.y2 += offset_y;
362 /* half the height if this is a field */
370 p.width /= 1 << im->cshift_x;
371 p.height /= 1 << im->cshift_y;
373 p.rect.x1 /= 1 << im->cshift_x;
374 p.rect.x2 /= 1 << im->cshift_x;
375 p.rect.y1 /= 1 << im->cshift_y;
376 p.rect.y2 /= 1 << im->cshift_y;
379 if (m_textureTarget == GL_TEXTURE_2D)
381 p.height /= p.texheight;
382 p.rect.y1 /= p.texheight;
383 p.rect.y2 /= p.texheight;
384 p.width /= p.texwidth;
385 p.rect.x1 /= p.texwidth;
386 p.rect.x2 /= p.texwidth;
392 void CLinuxRendererGLES::LoadPlane( YUVPLANE& plane, int type, unsigned flipindex
393 , unsigned width, unsigned height
394 , unsigned int stride, void* data )
396 if(plane.flipindex == flipindex)
399 const GLvoid *pixelData = data;
401 int bps = glFormatElementByteCount(type);
403 glBindTexture(m_textureTarget, plane.id);
405 // OpenGL ES does not support strided texture input.
406 if(stride != width * bps)
408 unsigned char* src = (unsigned char*)data;
409 for (unsigned int y = 0; y < height;++y, src += stride)
410 glTexSubImage2D(m_textureTarget, 0, 0, y, width, 1, type, GL_UNSIGNED_BYTE, src);
412 glTexSubImage2D(m_textureTarget, 0, 0, 0, width, height, type, GL_UNSIGNED_BYTE, pixelData);
415 /* check if we need to load any border pixels */
416 if(height < plane.texheight)
417 glTexSubImage2D( m_textureTarget, 0
418 , 0, height, width, 1
419 , type, GL_UNSIGNED_BYTE
420 , (unsigned char*)pixelData + stride * (height-1));
422 if(width < plane.texwidth)
423 glTexSubImage2D( m_textureTarget, 0
424 , width, 0, 1, height
425 , type, GL_UNSIGNED_BYTE
426 , (unsigned char*)pixelData + bps * (width-1));
428 glBindTexture(m_textureTarget, 0);
430 plane.flipindex = flipindex;
433 void CLinuxRendererGLES::Reset()
435 for(int i=0; i<m_NumYV12Buffers; i++)
437 /* reset all image flags, this will cleanup textures later */
438 m_buffers[i].image.flags = 0;
442 void CLinuxRendererGLES::Flush()
449 for (int i = 0 ; i < m_NumYV12Buffers ; i++)
450 (this->*m_textureDelete)(i);
453 m_bValidated = false;
455 m_iYV12RenderBuffer = 0;
458 void CLinuxRendererGLES::Update()
460 if (!m_bConfigured) return;
464 void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
466 if (!m_bConfigured) return;
468 // if its first pass, just init textures and return
469 if (ValidateRenderTarget())
472 if (m_renderMethod & RENDER_BYPASS)
475 // if running bypass, then the player might need the src/dst rects
476 // for sizing video playback on a layer other than the gles layer.
477 if (m_RenderUpdateCallBackFn)
478 (*m_RenderUpdateCallBackFn)(m_RenderUpdateCallBackCtx, m_sourceRect, m_destRect);
480 CRect old = g_graphicsContext.GetScissors();
482 g_graphicsContext.BeginPaint();
483 g_graphicsContext.SetScissors(m_destRect);
486 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
487 glClearColor(0, 0, 0, 0);
488 glClear(GL_COLOR_BUFFER_BIT);
490 g_graphicsContext.SetScissors(old);
491 g_graphicsContext.EndPaint();
495 // this needs to be checked after texture validation
496 if (!m_bImageReady) return;
498 int index = m_iYV12RenderBuffer;
499 YUVBUFFER& buf = m_buffers[index];
501 if (m_format != RENDER_FMT_OMXEGL && m_format != RENDER_FMT_EGLIMG && m_format != RENDER_FMT_MEDIACODEC)
503 if (!buf.fields[FIELD_FULL][0].id) return;
505 if (buf.image.flags==0)
510 g_graphicsContext.BeginPaint();
512 m_iLastRenderBuffer = index;
516 glClearColor(m_clearColour, m_clearColour, m_clearColour, 0);
517 glClear(GL_COLOR_BUFFER_BIT);
518 glClearColor(0,0,0,0);
524 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
526 m_pYUVShader->SetAlpha(alpha / 255.0f);
532 m_pYUVShader->SetAlpha(1.0f);
535 if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT))
536 CLog::Log(LOGERROR, "GLES: Cannot render stipple!");
538 Render(flags, index);
543 g_graphicsContext.EndPaint();
546 void CLinuxRendererGLES::FlipPage(int source)
548 if( source >= 0 && source < m_NumYV12Buffers )
549 m_iYV12RenderBuffer = source;
551 m_iYV12RenderBuffer = NextYV12Texture();
553 m_buffers[m_iYV12RenderBuffer].flipindex = ++m_flipindex;
558 unsigned int CLinuxRendererGLES::PreInit()
560 CSingleLock lock(g_graphicsContext);
561 m_bConfigured = false;
562 m_bValidated = false;
564 m_resolution = CDisplaySettings::Get().GetCurrentResolution();
565 if ( m_resolution == RES_WINDOW )
566 m_resolution = RES_DESKTOP;
568 m_iYV12RenderBuffer = 0;
569 m_NumYV12Buffers = 2;
571 m_formats.push_back(RENDER_FMT_YUV420P);
572 m_formats.push_back(RENDER_FMT_BYPASS);
573 #if defined(HAVE_LIBOPENMAX)
574 m_formats.push_back(RENDER_FMT_OMXEGL);
576 #ifdef HAVE_VIDEOTOOLBOXDECODER
577 m_formats.push_back(RENDER_FMT_CVBREF);
579 #ifdef HAS_LIBSTAGEFRIGHT
580 m_formats.push_back(RENDER_FMT_EGLIMG);
582 #if defined(TARGET_ANDROID)
583 m_formats.push_back(RENDER_FMT_MEDIACODEC);
586 // setup the background colour
587 m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
589 if (!m_dllSwScale->Load())
590 CLog::Log(LOGERROR,"CLinuxRendererGL::PreInit - failed to load rescale libraries!");
595 void CLinuxRendererGLES::UpdateVideoFilter()
597 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod)
599 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
600 m_scalingMethod = m_scalingMethodGui;
602 if(!Supports(m_scalingMethod))
604 CLog::Log(LOGWARNING, "CLinuxRendererGLES::UpdateVideoFilter - choosen scaling method %d, is not supported by renderer", (int)m_scalingMethod);
605 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
608 if (m_pVideoFilterShader)
610 m_pVideoFilterShader->Free();
611 delete m_pVideoFilterShader;
612 m_pVideoFilterShader = NULL;
618 switch (m_scalingMethod)
620 case VS_SCALINGMETHOD_NEAREST:
621 SetTextureFilter(GL_NEAREST);
622 m_renderQuality = RQ_SINGLEPASS;
625 case VS_SCALINGMETHOD_LINEAR:
626 SetTextureFilter(GL_LINEAR);
627 m_renderQuality = RQ_SINGLEPASS;
630 case VS_SCALINGMETHOD_CUBIC:
631 CLog::Log(LOGERROR, "GLES: CUBIC not supported!");
634 case VS_SCALINGMETHOD_LANCZOS2:
635 case VS_SCALINGMETHOD_LANCZOS3:
636 case VS_SCALINGMETHOD_SINC8:
637 case VS_SCALINGMETHOD_NEDI:
638 CLog::Log(LOGERROR, "GL: TODO: This scaler has not yet been implemented");
645 CGUIDialogKaiToast::QueueNotification("Video Renderering", "Failed to init video filters/scalers, falling back to bilinear scaling");
646 CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler");
647 if (m_pVideoFilterShader)
649 m_pVideoFilterShader->Free();
650 delete m_pVideoFilterShader;
651 m_pVideoFilterShader = NULL;
655 SetTextureFilter(GL_LINEAR);
656 m_renderQuality = RQ_SINGLEPASS;
659 void CLinuxRendererGLES::LoadShaders(int field)
661 #ifdef TARGET_DARWIN_IOS
662 float ios_version = GetIOSVersion();
664 int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
665 CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod);
669 m_pYUVShader->Free();
674 switch(requestedMethod)
676 case RENDER_METHOD_AUTO:
677 case RENDER_METHOD_GLSL:
678 if (m_format == RENDER_FMT_OMXEGL)
680 CLog::Log(LOGNOTICE, "GL: Using OMXEGL RGBA render method");
681 m_renderMethod = RENDER_OMXEGL;
684 else if (m_format == RENDER_FMT_EGLIMG)
686 CLog::Log(LOGNOTICE, "GL: Using EGL Image render method");
687 m_renderMethod = RENDER_EGLIMG;
690 else if (m_format == RENDER_FMT_MEDIACODEC)
692 CLog::Log(LOGNOTICE, "GL: Using MediaCodec render method");
693 m_renderMethod = RENDER_MEDIACODEC;
696 else if (m_format == RENDER_FMT_BYPASS)
698 CLog::Log(LOGNOTICE, "GL: Using BYPASS render method");
699 m_renderMethod = RENDER_BYPASS;
702 else if (m_format == RENDER_FMT_CVBREF)
704 CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef RGBA render method");
705 m_renderMethod = RENDER_CVREF;
708 #if defined(TARGET_DARWIN_IOS)
709 else if (ios_version < 5.0 && m_format == RENDER_FMT_YUV420P)
711 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA render method");
712 m_renderMethod = RENDER_SW;
716 // Try GLSL shaders if supported and user requested auto or GLSL.
719 // create regular progressive scan shader
720 m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format);
721 CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader");
723 if (m_pYUVShader && m_pYUVShader->CompileAndLink())
725 m_renderMethod = RENDER_GLSL;
729 else if (m_pYUVShader)
731 m_pYUVShader->Free();
734 CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader");
735 // drop through and try SW
738 case RENDER_METHOD_SOFTWARE:
741 // Use software YUV 2 RGB conversion if user requested it or GLSL failed
742 m_renderMethod = RENDER_SW ;
743 CLog::Log(LOGNOTICE, "GL: Using software color conversion/RGBA rendering");
747 // determine whether GPU supports NPOT textures
748 if (!g_Windowing.IsExtSupported("GL_TEXTURE_NPOT"))
750 CLog::Log(LOGNOTICE, "GL: GL_ARB_texture_rectangle not supported and OpenGL version is not 2.x");
751 CLog::Log(LOGNOTICE, "GL: Reverting to POT textures");
752 m_renderMethod |= RENDER_POT;
755 CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
757 // Now that we now the render method, setup texture function handlers
758 if (m_format == RENDER_FMT_CVBREF)
760 m_textureUpload = &CLinuxRendererGLES::UploadCVRefTexture;
761 m_textureCreate = &CLinuxRendererGLES::CreateCVRefTexture;
762 m_textureDelete = &CLinuxRendererGLES::DeleteCVRefTexture;
764 else if (m_format == RENDER_FMT_BYPASS)
766 m_textureUpload = &CLinuxRendererGLES::UploadBYPASSTexture;
767 m_textureCreate = &CLinuxRendererGLES::CreateBYPASSTexture;
768 m_textureDelete = &CLinuxRendererGLES::DeleteBYPASSTexture;
770 else if (m_format == RENDER_FMT_EGLIMG)
772 m_textureUpload = &CLinuxRendererGLES::UploadEGLIMGTexture;
773 m_textureCreate = &CLinuxRendererGLES::CreateEGLIMGTexture;
774 m_textureDelete = &CLinuxRendererGLES::DeleteEGLIMGTexture;
776 else if (m_format == RENDER_FMT_MEDIACODEC)
778 m_textureUpload = &CLinuxRendererGLES::UploadSurfaceTexture;
779 m_textureCreate = &CLinuxRendererGLES::CreateSurfaceTexture;
780 m_textureDelete = &CLinuxRendererGLES::DeleteSurfaceTexture;
785 // default to YV12 texture handlers
786 m_textureUpload = &CLinuxRendererGLES::UploadYV12Texture;
787 m_textureCreate = &CLinuxRendererGLES::CreateYV12Texture;
788 m_textureDelete = &CLinuxRendererGLES::DeleteYV12Texture;
791 if (m_oldRenderMethod != m_renderMethod)
793 CLog::Log(LOGDEBUG, "CLinuxRendererGLES: Reorder drawpoints due to method change from %i to %i", m_oldRenderMethod, m_renderMethod);
795 m_oldRenderMethod = m_renderMethod;
799 void CLinuxRendererGLES::UnInit()
801 CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources");
802 CSingleLock lock(g_graphicsContext);
804 if (m_rgbBuffer != NULL)
806 delete [] m_rgbBuffer;
812 for (int i = 0; i < NUM_BUFFERS; ++i)
813 (this->*m_textureDelete)(i);
815 if (m_dllSwScale && m_sw_context)
817 m_dllSwScale->sws_freeContext(m_sw_context);
821 // cleanup framebuffer object if it was in use
823 m_bValidated = false;
824 m_bImageReady = false;
825 m_bConfigured = false;
826 m_RenderUpdateCallBackFn = NULL;
827 m_RenderUpdateCallBackCtx = NULL;
828 m_RenderFeaturesCallBackFn = NULL;
829 m_RenderFeaturesCallBackCtx = NULL;
832 inline void CLinuxRendererGLES::ReorderDrawPoints()
835 CBaseRenderer::ReorderDrawPoints();//call base impl. for rotating the points
837 //corevideo and EGL are flipped in y
838 if(m_renderMethod & RENDER_CVREF)
841 tmp = m_rotatedDestCoords[0];
842 m_rotatedDestCoords[0] = m_rotatedDestCoords[3];
843 m_rotatedDestCoords[3] = tmp;
844 tmp = m_rotatedDestCoords[1];
845 m_rotatedDestCoords[1] = m_rotatedDestCoords[2];
846 m_rotatedDestCoords[2] = tmp;
850 void CLinuxRendererGLES::ReleaseBuffer(int idx)
852 #ifdef HAVE_VIDEOTOOLBOXDECODER
853 YUVBUFFER &buf = m_buffers[idx];
856 CVBufferRelease(buf.cvBufferRef);
857 buf.cvBufferRef = NULL;
859 #if defined(TARGET_ANDROID)
860 YUVBUFFER &buf = m_buffers[idx];
862 SAFE_RELEASE(buf.mediacodec);
866 void CLinuxRendererGLES::Render(DWORD flags, int index)
868 // If rendered directly by the hardware
869 if (m_renderMethod & RENDER_BYPASS)
872 // obtain current field, if interlaced
873 if( flags & RENDER_FLAG_TOP)
874 m_currentField = FIELD_TOP;
876 else if (flags & RENDER_FLAG_BOT)
877 m_currentField = FIELD_BOT;
880 m_currentField = FIELD_FULL;
882 (this->*m_textureUpload)(index);
884 if (m_renderMethod & RENDER_GLSL)
887 switch(m_renderQuality)
891 RenderSinglePass(index, m_currentField);
896 RenderMultiPass(index, m_currentField);
901 RenderSoftware(index, m_currentField);
906 else if (m_renderMethod & RENDER_OMXEGL)
908 RenderOpenMax(index, m_currentField);
911 else if (m_renderMethod & RENDER_EGLIMG)
913 RenderEglImage(index, m_currentField);
916 else if (m_renderMethod & RENDER_CVREF)
918 RenderCoreVideoRef(index, m_currentField);
921 else if (m_renderMethod & RENDER_MEDIACODEC)
923 RenderSurfaceTexture(index, m_currentField);
927 RenderSoftware(index, m_currentField);
932 void CLinuxRendererGLES::RenderSinglePass(int index, int field)
934 YV12Image &im = m_buffers[index].image;
935 YUVFIELDS &fields = m_buffers[index].fields;
936 YUVPLANES &planes = fields[field];
944 glDisable(GL_DEPTH_TEST);
947 glActiveTexture(GL_TEXTURE0);
948 glEnable(m_textureTarget);
949 glBindTexture(m_textureTarget, planes[0].id);
952 glActiveTexture(GL_TEXTURE1);
953 glEnable(m_textureTarget);
954 glBindTexture(m_textureTarget, planes[1].id);
957 glActiveTexture(GL_TEXTURE2);
958 glEnable(m_textureTarget);
959 glBindTexture(m_textureTarget, planes[2].id);
961 glActiveTexture(GL_TEXTURE0);
964 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
965 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
966 m_pYUVShader->SetWidth(im.width);
967 m_pYUVShader->SetHeight(im.height);
968 if (field == FIELD_TOP)
969 m_pYUVShader->SetField(1);
970 else if(field == FIELD_BOT)
971 m_pYUVShader->SetField(0);
973 m_pYUVShader->SetMatrices(g_matrices.GetMatrix(MM_PROJECTION), g_matrices.GetMatrix(MM_MODELVIEW));
974 m_pYUVShader->Enable();
976 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
977 GLfloat m_vert[4][3];
978 GLfloat m_tex[3][4][2];
980 GLint vertLoc = m_pYUVShader->GetVertexLoc();
981 GLint Yloc = m_pYUVShader->GetYcoordLoc();
982 GLint Uloc = m_pYUVShader->GetUcoordLoc();
983 GLint Vloc = m_pYUVShader->GetVcoordLoc();
985 glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert);
986 glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]);
987 glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, m_tex[1]);
988 glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, m_tex[2]);
990 glEnableVertexAttribArray(vertLoc);
991 glEnableVertexAttribArray(Yloc);
992 glEnableVertexAttribArray(Uloc);
993 glEnableVertexAttribArray(Vloc);
995 // Setup vertex position values
996 for(int i = 0; i < 4; i++)
998 m_vert[i][0] = m_rotatedDestCoords[i].x;
999 m_vert[i][1] = m_rotatedDestCoords[i].y;
1000 m_vert[i][2] = 0.0f;// set z to 0
1003 // Setup texture coordinates
1004 for (int i=0; i<3; i++)
1006 m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1;
1007 m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1;
1008 m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2;
1009 m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2;
1012 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1016 m_pYUVShader->Disable();
1019 glDisableVertexAttribArray(vertLoc);
1020 glDisableVertexAttribArray(Yloc);
1021 glDisableVertexAttribArray(Uloc);
1022 glDisableVertexAttribArray(Vloc);
1024 glActiveTexture(GL_TEXTURE1);
1025 glDisable(m_textureTarget);
1027 glActiveTexture(GL_TEXTURE2);
1028 glDisable(m_textureTarget);
1030 glActiveTexture(GL_TEXTURE0);
1031 glDisable(m_textureTarget);
1033 g_matrices.MatrixMode(MM_MODELVIEW);
1038 void CLinuxRendererGLES::RenderMultiPass(int index, int field)
1040 // TODO: Multipass rendering does not currently work! FIX!
1041 CLog::Log(LOGERROR, "GLES: MULTIPASS rendering was called! But it doesnt work!!!");
1044 YV12Image &im = m_buffers[index].image;
1045 YUVPLANES &planes = m_buffers[index].fields[field];
1047 if (m_reloadShaders)
1049 m_reloadShaders = 0;
1050 LoadShaders(m_currentField);
1053 glDisable(GL_DEPTH_TEST);
1056 glEnable(m_textureTarget);
1057 glActiveTexture(GL_TEXTURE0);
1058 glBindTexture(m_textureTarget, planes[0].id);
1062 glActiveTexture(GL_TEXTURE1);
1063 glEnable(m_textureTarget);
1064 glBindTexture(m_textureTarget, planes[1].id);
1068 glActiveTexture(GL_TEXTURE2);
1069 glEnable(m_textureTarget);
1070 glBindTexture(m_textureTarget, planes[2].id);
1073 glActiveTexture(GL_TEXTURE0);
1076 // make sure the yuv shader is loaded and ready to go
1077 if (!m_pYUVShader || (!m_pYUVShader->OK()))
1079 CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render");
1083 m_fbo.BeginRender();
1086 m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f);
1087 m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f);
1088 m_pYUVShader->SetWidth(im.width);
1089 m_pYUVShader->SetHeight(im.height);
1090 if (field == FIELD_TOP)
1091 m_pYUVShader->SetField(1);
1092 else if(field == FIELD_BOT)
1093 m_pYUVShader->SetField(0);
1097 // glPushAttrib(GL_VIEWPORT_BIT);
1098 // glPushAttrib(GL_SCISSOR_BIT);
1099 g_matrices.MatrixMode(MM_MODELVIEW);
1100 g_matrices.PushMatrix();
1101 g_matrices.LoadIdentity();
1104 g_matrices.MatrixMode(MM_PROJECTION);
1105 g_matrices.PushMatrix();
1106 g_matrices.LoadIdentity();
1108 g_matrices.Ortho2D(0, m_sourceWidth, 0, m_sourceHeight);
1109 glViewport(0, 0, m_sourceWidth, m_sourceHeight);
1110 glScissor(0, 0, m_sourceWidth, m_sourceHeight);
1111 g_matrices.MatrixMode(MM_MODELVIEW);
1115 if (!m_pYUVShader->Enable())
1117 CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
1120 // 1st Pass to video frame size
1122 // float imgwidth = planes[0].rect.x2 - planes[0].rect.x1;
1123 // float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
1124 // if (m_textureTarget == GL_TEXTURE_2D)
1126 // imgwidth *= planes[0].texwidth;
1127 // imgheight *= planes[0].texheight;
1130 // glBegin(GL_QUADS);
1132 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1);
1133 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1);
1134 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1);
1135 // glVertex2f(0.0f , 0.0f);
1137 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
1138 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
1139 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
1140 // glVertex2f(imgwidth, 0.0f);
1142 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
1143 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
1144 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
1145 // glVertex2f(imgwidth, imgheight);
1147 // glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
1148 // glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
1149 // glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
1150 // glVertex2f(0.0f , imgheight);
1155 m_pYUVShader->Disable();
1157 g_matrices.MatrixMode(MM_MODELVIEW);
1158 g_matrices.PopMatrix(); // pop modelview
1159 g_matrices.MatrixMode(MM_PROJECTION);
1160 g_matrices.PopMatrix(); // pop projection
1162 // glPopAttrib(); // pop scissor
1163 // glPopAttrib(); // pop viewport
1164 g_matrices.MatrixMode(MM_MODELVIEW);
1169 glActiveTexture(GL_TEXTURE1);
1170 glDisable(m_textureTarget);
1171 glActiveTexture(GL_TEXTURE2);
1172 glDisable(m_textureTarget);
1173 glActiveTexture(GL_TEXTURE0);
1174 glDisable(m_textureTarget);
1176 glEnable(GL_TEXTURE_2D);
1177 glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
1180 // Use regular normalized texture coordinates
1182 // 2nd Pass to screen size with optional video filter
1184 if (m_pVideoFilterShader)
1186 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_NEAREST);
1187 m_pVideoFilterShader->SetSourceTexture(0);
1188 m_pVideoFilterShader->SetWidth(m_sourceWidth);
1189 m_pVideoFilterShader->SetHeight(m_sourceHeight);
1190 m_pVideoFilterShader->Enable();
1193 m_fbo.SetFiltering(GL_TEXTURE_2D, GL_LINEAR);
1198 // imgwidth /= m_sourceWidth;
1199 // imgheight /= m_sourceHeight;
1201 // glBegin(GL_QUADS);
1203 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f);
1204 // glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
1206 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
1207 // glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
1209 // glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
1210 // glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
1212 // glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight);
1213 // glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
1219 if (m_pVideoFilterShader)
1220 m_pVideoFilterShader->Disable();
1224 glDisable(m_textureTarget);
1228 void CLinuxRendererGLES::RenderSoftware(int index, int field)
1230 YUVPLANES &planes = m_buffers[index].fields[field];
1232 glDisable(GL_DEPTH_TEST);
1235 glEnable(m_textureTarget);
1236 glActiveTexture(GL_TEXTURE0);
1237 glBindTexture(m_textureTarget, planes[0].id);
1239 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1241 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1244 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1246 GLint posLoc = g_Windowing.GUIShaderGetPos();
1247 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1248 GLint colLoc = g_Windowing.GUIShaderGetCol();
1250 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1251 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1252 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1254 glEnableVertexAttribArray(posLoc);
1255 glEnableVertexAttribArray(texLoc);
1256 glEnableVertexAttribArray(colLoc);
1258 // Set vertex coordinates
1259 for(int i = 0; i < 4; i++)
1261 ver[i][0] = m_rotatedDestCoords[i].x;
1262 ver[i][1] = m_rotatedDestCoords[i].y;
1263 ver[i][2] = 0.0f;// set z to 0
1267 // Set texture coordinates
1268 tex[0][0] = tex[3][0] = planes[0].rect.x1;
1269 tex[0][1] = tex[1][1] = planes[0].rect.y1;
1270 tex[1][0] = tex[2][0] = planes[0].rect.x2;
1271 tex[2][1] = tex[3][1] = planes[0].rect.y2;
1273 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1275 glDisableVertexAttribArray(posLoc);
1276 glDisableVertexAttribArray(texLoc);
1277 glDisableVertexAttribArray(colLoc);
1279 g_Windowing.DisableGUIShader();
1283 glDisable(m_textureTarget);
1287 void CLinuxRendererGLES::RenderOpenMax(int index, int field)
1289 #if defined(HAVE_LIBOPENMAX)
1290 GLuint textureId = m_buffers[index].openMaxBuffer->texture_id;
1292 glDisable(GL_DEPTH_TEST);
1295 glEnable(m_textureTarget);
1296 glActiveTexture(GL_TEXTURE0);
1297 glBindTexture(m_textureTarget, textureId);
1299 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1301 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1304 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1306 GLint posLoc = g_Windowing.GUIShaderGetPos();
1307 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1308 GLint colLoc = g_Windowing.GUIShaderGetCol();
1310 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1311 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1312 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1314 glEnableVertexAttribArray(posLoc);
1315 glEnableVertexAttribArray(texLoc);
1316 glEnableVertexAttribArray(colLoc);
1318 // Set vertex coordinates
1319 for(int i = 0; i < 4; i++)
1321 ver[i][0] = m_rotatedDestCoords[i].x;
1322 ver[i][1] = m_rotatedDestCoords[i].y;
1323 ver[i][2] = 0.0f;// set z to 0
1327 // Set texture coordinates
1328 tex[0][0] = tex[3][0] = 0;
1329 tex[0][1] = tex[1][1] = 0;
1330 tex[1][0] = tex[2][0] = 1;
1331 tex[2][1] = tex[3][1] = 1;
1333 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1335 glDisableVertexAttribArray(posLoc);
1336 glDisableVertexAttribArray(texLoc);
1337 glDisableVertexAttribArray(colLoc);
1339 g_Windowing.DisableGUIShader();
1343 glDisable(m_textureTarget);
1348 void CLinuxRendererGLES::RenderEglImage(int index, int field)
1350 #if defined(HAS_LIBSTAGEFRIGHT)
1351 #ifdef DEBUG_VERBOSE
1352 unsigned int time = XbmcThreads::SystemClockMillis();
1355 YUVPLANE &plane = m_buffers[index].fields[field][0];
1357 glDisable(GL_DEPTH_TEST);
1359 glActiveTexture(GL_TEXTURE0);
1360 glBindTexture(m_textureTarget, plane.id);
1362 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1364 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1367 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1369 GLint posLoc = g_Windowing.GUIShaderGetPos();
1370 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1371 GLint colLoc = g_Windowing.GUIShaderGetCol();
1373 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1374 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1375 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1377 glEnableVertexAttribArray(posLoc);
1378 glEnableVertexAttribArray(texLoc);
1379 glEnableVertexAttribArray(colLoc);
1381 // Set vertex coordinates
1382 for(int i = 0; i < 4; i++)
1384 ver[i][0] = m_rotatedDestCoords[i].x;
1385 ver[i][1] = m_rotatedDestCoords[i].y;
1386 ver[i][2] = 0.0f;// set z to 0
1390 // Set texture coordinates (is flipped in y)
1391 tex[0][0] = tex[3][0] = 0;
1392 tex[0][1] = tex[1][1] = 1;
1393 tex[1][0] = tex[2][0] = 1;
1394 tex[2][1] = tex[3][1] = 0;
1396 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1398 glDisableVertexAttribArray(posLoc);
1399 glDisableVertexAttribArray(texLoc);
1400 glDisableVertexAttribArray(colLoc);
1402 g_Windowing.DisableGUIShader();
1405 glBindTexture(m_textureTarget, 0);
1408 #ifdef DEBUG_VERBOSE
1409 CLog::Log(LOGDEBUG, "RenderEglImage %d: tm:%d\n", index, XbmcThreads::SystemClockMillis() - time);
1414 void CLinuxRendererGLES::RenderSurfaceTexture(int index, int field)
1416 #if defined(TARGET_ANDROID)
1417 #ifdef DEBUG_VERBOSE
1418 unsigned int time = XbmcThreads::SystemClockMillis();
1421 YUVPLANE &plane = m_buffers[index].fields[0][0];
1423 glDisable(GL_DEPTH_TEST);
1425 glActiveTexture(GL_TEXTURE0);
1426 glBindTexture(GL_TEXTURE_EXTERNAL_OES, plane.id);
1428 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA_OES);
1430 glUniformMatrix4fv(g_Windowing.GUIShaderGetCoord0Matrix(), 1, GL_FALSE, m_textureMatrix);
1432 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1436 GLint posLoc = g_Windowing.GUIShaderGetPos();
1437 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1440 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1441 glVertexAttribPointer(texLoc, 4, GL_FLOAT, 0, 0, tex);
1443 glEnableVertexAttribArray(posLoc);
1444 glEnableVertexAttribArray(texLoc);
1446 // Set vertex coordinates
1447 for(int i = 0; i < 4; i++)
1449 ver[i][0] = m_rotatedDestCoords[i].x;
1450 ver[i][1] = m_rotatedDestCoords[i].y;
1451 ver[i][2] = 0.0f; // set z to 0
1455 // Set texture coordinates (MediaCodec is flipped in y)
1456 tex[0][0] = tex[3][0] = 0.0f;
1457 tex[0][1] = tex[1][1] = 1.0f;
1458 tex[1][0] = tex[2][0] = 1.0f;
1459 tex[2][1] = tex[3][1] = 0.0f;
1461 for(int i = 0; i < 4; i++)
1467 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1469 glDisableVertexAttribArray(posLoc);
1470 glDisableVertexAttribArray(texLoc);
1472 const float identity[16] = {
1473 1.0f, 0.0f, 0.0f, 0.0f,
1474 0.0f, 1.0f, 0.0f, 0.0f,
1475 0.0f, 0.0f, 1.0f, 0.0f,
1476 0.0f, 0.0f, 0.0f, 1.0f
1478 glUniformMatrix4fv(g_Windowing.GUIShaderGetCoord0Matrix(), 1, GL_FALSE, identity);
1480 g_Windowing.DisableGUIShader();
1483 glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
1486 #ifdef DEBUG_VERBOSE
1487 CLog::Log(LOGDEBUG, "RenderMediaCodecImage %d: tm:%d", index, XbmcThreads::SystemClockMillis() - time);
1492 void CLinuxRendererGLES::RenderCoreVideoRef(int index, int field)
1494 #ifdef HAVE_VIDEOTOOLBOXDECODER
1495 YUVPLANE &plane = m_buffers[index].fields[field][0];
1497 glDisable(GL_DEPTH_TEST);
1499 glEnable(m_textureTarget);
1500 glActiveTexture(GL_TEXTURE0);
1501 glBindTexture(m_textureTarget, plane.id);
1503 g_Windowing.EnableGUIShader(SM_TEXTURE_RGBA);
1505 GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip
1508 GLfloat col[3] = {1.0f, 1.0f, 1.0f};
1510 GLint posLoc = g_Windowing.GUIShaderGetPos();
1511 GLint texLoc = g_Windowing.GUIShaderGetCoord0();
1512 GLint colLoc = g_Windowing.GUIShaderGetCol();
1514 glVertexAttribPointer(posLoc, 4, GL_FLOAT, 0, 0, ver);
1515 glVertexAttribPointer(texLoc, 2, GL_FLOAT, 0, 0, tex);
1516 glVertexAttribPointer(colLoc, 3, GL_FLOAT, 0, 0, col);
1518 glEnableVertexAttribArray(posLoc);
1519 glEnableVertexAttribArray(texLoc);
1520 glEnableVertexAttribArray(colLoc);
1522 // Set vertex coordinates
1523 for(int i = 0; i < 4; i++)
1525 ver[i][0] = m_rotatedDestCoords[i].x;
1526 ver[i][1] = m_rotatedDestCoords[i].y;
1527 ver[i][2] = 0.0f;// set z to 0
1531 // Set texture coordinates (corevideo is flipped in y)
1532 tex[0][0] = tex[3][0] = 0;
1533 tex[0][1] = tex[1][1] = 1;
1534 tex[1][0] = tex[2][0] = 1;
1535 tex[2][1] = tex[3][1] = 0;
1537 glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx);
1539 glDisableVertexAttribArray(posLoc);
1540 glDisableVertexAttribArray(texLoc);
1541 glDisableVertexAttribArray(colLoc);
1543 g_Windowing.DisableGUIShader();
1546 glDisable(m_textureTarget);
1551 bool CLinuxRendererGLES::RenderCapture(CRenderCapture* capture)
1556 // If rendered directly by the hardware
1557 if (m_renderMethod & RENDER_BYPASS)
1559 capture->BeginRender();
1560 capture->EndRender();
1564 // save current video rect
1565 CRect saveSize = m_destRect;
1566 saveRotatedCoords();//backup current m_rotatedDestCoords
1568 // new video rect is thumbnail size
1569 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1571 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1572 // clear framebuffer and invert Y axis to get non-inverted image
1573 glDisable(GL_BLEND);
1575 g_matrices.MatrixMode(MM_MODELVIEW);
1576 g_matrices.PushMatrix();
1577 // fixme - we know that cvref & eglimg are already flipped in y direction
1578 // but somehow this also effects the rendercapture here
1579 // therefore we have to skip the flip here or we get upside down
1581 if (m_renderMethod != RENDER_CVREF)
1583 g_matrices.Translatef(0.0f, capture->GetHeight(), 0.0f);
1584 g_matrices.Scalef(1.0f, -1.0f, 1.0f);
1587 capture->BeginRender();
1589 Render(RENDER_FLAG_NOOSD, m_iYV12RenderBuffer);
1591 glReadPixels(0, g_graphicsContext.GetHeight() - capture->GetHeight(), capture->GetWidth(), capture->GetHeight(),
1592 GL_RGBA, GL_UNSIGNED_BYTE, capture->GetRenderBuffer());
1594 // OpenGLES returns in RGBA order but CRenderCapture needs BGRA order
1595 // XOR Swap RGBA -> BGRA
1596 unsigned char* pixels = (unsigned char*)capture->GetRenderBuffer();
1597 for (unsigned int i = 0; i < capture->GetWidth() * capture->GetHeight(); i++, pixels+=4)
1599 std::swap(pixels[0], pixels[2]);
1602 capture->EndRender();
1604 // revert model view matrix
1605 g_matrices.MatrixMode(MM_MODELVIEW);
1606 g_matrices.PopMatrix();
1608 // restore original video rect
1609 m_destRect = saveSize;
1610 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1615 //********************************************************************************************************
1616 // YV12 Texture creation, deletion, copying + clearing
1617 //********************************************************************************************************
1618 void CLinuxRendererGLES::UploadYV12Texture(int source)
1620 YUVBUFFER& buf = m_buffers[source];
1621 YV12Image* im = &buf.image;
1622 YUVFIELDS& fields = buf.fields;
1625 #if defined(HAVE_LIBOPENMAX)
1626 if (!(im->flags&IMAGE_FLAG_READY) || m_buffers[source].openMaxBuffer)
1628 if (!(im->flags&IMAGE_FLAG_READY))
1634 // if we don't have a shader, fallback to SW YUV2RGB for now
1635 if (m_renderMethod & RENDER_SW)
1637 if(m_rgbBufferSize < m_sourceWidth * m_sourceHeight * 4)
1639 delete [] m_rgbBuffer;
1640 m_rgbBufferSize = m_sourceWidth*m_sourceHeight*4;
1641 m_rgbBuffer = new BYTE[m_rgbBufferSize];
1644 #if defined(__ARM_NEON__)
1645 if (g_cpuInfo.GetCPUFeatures() & CPU_FEATURE_NEON)
1647 yuv420_2_rgb8888_neon(m_rgbBuffer, im->plane[0], im->plane[2], im->plane[1],
1648 m_sourceWidth, m_sourceHeight, im->stride[0], im->stride[1], m_sourceWidth * 4);
1653 m_sw_context = m_dllSwScale->sws_getCachedContext(m_sw_context,
1654 im->width, im->height, PIX_FMT_YUV420P,
1655 im->width, im->height, PIX_FMT_RGBA,
1656 SWS_FAST_BILINEAR, NULL, NULL, NULL);
1658 uint8_t *src[] = { im->plane[0], im->plane[1], im->plane[2], 0 };
1659 int srcStride[] = { im->stride[0], im->stride[1], im->stride[2], 0 };
1660 uint8_t *dst[] = { m_rgbBuffer, 0, 0, 0 };
1661 int dstStride[] = { m_sourceWidth*4, 0, 0, 0 };
1662 m_dllSwScale->sws_scale(m_sw_context, src, srcStride, 0, im->height, dst, dstStride);
1667 if (m_currentField == FIELD_FULL)
1668 deinterlacing = false;
1670 deinterlacing = true;
1672 glEnable(m_textureTarget);
1675 if (m_renderMethod & RENDER_SW)
1680 LoadPlane( fields[FIELD_TOP][0] , GL_RGBA, buf.flipindex
1681 , im->width, im->height >> 1
1682 , m_sourceWidth*8, m_rgbBuffer );
1684 LoadPlane( fields[FIELD_BOT][0], GL_RGBA, buf.flipindex
1685 , im->width, im->height >> 1
1686 , m_sourceWidth*8, m_rgbBuffer + m_sourceWidth*4);
1690 LoadPlane( fields[FIELD_FULL][0], GL_RGBA, buf.flipindex
1691 , im->width, im->height
1692 , m_sourceWidth*4, m_rgbBuffer );
1697 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1702 LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
1703 , im->width, im->height >> 1
1704 , im->stride[0]*2, im->plane[0] );
1706 LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
1707 , im->width, im->height >> 1
1708 , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
1713 LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
1714 , im->width, im->height
1715 , im->stride[0], im->plane[0] );
1721 if (!(m_renderMethod & RENDER_SW))
1723 glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1727 // Load Even U & V Fields
1728 LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex
1729 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1730 , im->stride[1]*2, im->plane[1] );
1732 LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
1733 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1734 , im->stride[2]*2, im->plane[2] );
1736 // Load Odd U & V Fields
1737 LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex
1738 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1739 , im->stride[1]*2, im->plane[1] + im->stride[1] );
1741 LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
1742 , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
1743 , im->stride[2]*2, im->plane[2] + im->stride[2] );
1748 LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex
1749 , im->width >> im->cshift_x, im->height >> im->cshift_y
1750 , im->stride[1], im->plane[1] );
1752 LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
1753 , im->width >> im->cshift_x, im->height >> im->cshift_y
1754 , im->stride[2], im->plane[2] );
1757 CalculateTextureSourceRects(source, 3);
1759 glDisable(m_textureTarget);
1762 void CLinuxRendererGLES::DeleteYV12Texture(int index)
1764 YV12Image &im = m_buffers[index].image;
1765 YUVFIELDS &fields = m_buffers[index].fields;
1767 if( fields[FIELD_FULL][0].id == 0 ) return;
1769 /* finish up all textures, and delete them */
1770 g_graphicsContext.BeginPaint(); //FIXME
1771 for(int f = 0;f<MAX_FIELDS;f++)
1773 for(int p = 0;p<MAX_PLANES;p++)
1775 if( fields[f][p].id )
1777 if (glIsTexture(fields[f][p].id))
1778 glDeleteTextures(1, &fields[f][p].id);
1779 fields[f][p].id = 0;
1783 g_graphicsContext.EndPaint();
1785 for(int p = 0;p<MAX_PLANES;p++)
1789 delete[] im.plane[p];
1795 bool CLinuxRendererGLES::CreateYV12Texture(int index)
1797 /* since we also want the field textures, pitch must be texture aligned */
1798 YV12Image &im = m_buffers[index].image;
1799 YUVFIELDS &fields = m_buffers[index].fields;
1801 DeleteYV12Texture(index);
1803 im.height = m_sourceHeight;
1804 im.width = m_sourceWidth;
1808 im.stride[0] = im.width;
1809 im.stride[1] = im.width >> im.cshift_x;
1810 im.stride[2] = im.width >> im.cshift_x;
1812 im.planesize[0] = im.stride[0] * im.height;
1813 im.planesize[1] = im.stride[1] * ( im.height >> im.cshift_y );
1814 im.planesize[2] = im.stride[2] * ( im.height >> im.cshift_y );
1816 for (int i = 0; i < 3; i++)
1817 im.plane[i] = new BYTE[im.planesize[i]];
1819 glEnable(m_textureTarget);
1820 for(int f = 0;f<MAX_FIELDS;f++)
1822 for(int p = 0;p<MAX_PLANES;p++)
1824 if (!glIsTexture(fields[f][p].id))
1826 glGenTextures(1, &fields[f][p].id);
1833 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
1835 int fieldshift = (f==FIELD_FULL) ? 0 : 1;
1836 YUVPLANES &planes = fields[f];
1838 planes[0].texwidth = im.width;
1839 planes[0].texheight = im.height >> fieldshift;
1841 if (m_renderMethod & RENDER_SW)
1843 planes[1].texwidth = 0;
1844 planes[1].texheight = 0;
1845 planes[2].texwidth = 0;
1846 planes[2].texheight = 0;
1850 planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
1851 planes[1].texheight = planes[0].texheight >> im.cshift_y;
1852 planes[2].texwidth = planes[0].texwidth >> im.cshift_x;
1853 planes[2].texheight = planes[0].texheight >> im.cshift_y;
1856 if(m_renderMethod & RENDER_POT)
1858 for(int p = 0; p < 3; p++)
1860 planes[p].texwidth = NP2(planes[p].texwidth);
1861 planes[p].texheight = NP2(planes[p].texheight);
1865 for(int p = 0; p < 3; p++)
1867 YUVPLANE &plane = planes[p];
1868 if (plane.texwidth * plane.texheight == 0)
1871 glBindTexture(m_textureTarget, plane.id);
1872 if (m_renderMethod & RENDER_SW)
1874 if(m_renderMethod & RENDER_POT)
1875 CLog::Log(LOGDEBUG, "GL: Creating RGB POT texture of size %d x %d", plane.texwidth, plane.texheight);
1877 CLog::Log(LOGDEBUG, "GL: Creating RGB NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1879 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
1880 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1884 if(m_renderMethod & RENDER_POT)
1885 CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d", plane.texwidth, plane.texheight);
1887 CLog::Log(LOGDEBUG, "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
1889 glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
1892 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1893 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1894 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1895 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1899 glDisable(m_textureTarget);
1903 //********************************************************************************************************
1904 // CoreVideoRef Texture creation, deletion, copying + clearing
1905 //********************************************************************************************************
1906 void CLinuxRendererGLES::UploadCVRefTexture(int index)
1908 #ifdef HAVE_VIDEOTOOLBOXDECODER
1909 CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
1913 YUVPLANE &plane = m_buffers[index].fields[0][0];
1915 CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1916 #if !TARGET_OS_IPHONE
1917 int rowbytes = CVPixelBufferGetBytesPerRow(cvBufferRef);
1919 int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
1920 int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
1921 unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
1923 glEnable(m_textureTarget);
1926 glBindTexture(m_textureTarget, plane.id);
1927 #if !TARGET_OS_IPHONE
1928 #ifdef GL_UNPACK_ROW_LENGTH
1930 glPixelStorei( GL_UNPACK_ROW_LENGTH, rowbytes);
1932 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
1933 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
1934 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
1938 // Using BGRA extension to pull in video frame data directly
1939 glTexSubImage2D(m_textureTarget, 0, 0, 0, bufferWidth, bufferHeight, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bufferBase);
1941 #if !TARGET_OS_IPHONE
1942 #ifdef GL_UNPACK_ROW_LENGTH
1944 glPixelStorei( GL_UNPACK_ROW_LENGTH, 0);
1947 glBindTexture(m_textureTarget, 0);
1949 glDisable(m_textureTarget);
1952 CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
1953 CVBufferRelease(m_buffers[index].cvBufferRef);
1954 m_buffers[index].cvBufferRef = NULL;
1956 plane.flipindex = m_buffers[index].flipindex;
1960 void CLinuxRendererGLES::DeleteCVRefTexture(int index)
1962 #ifdef HAVE_VIDEOTOOLBOXDECODER
1963 YUVPLANE &plane = m_buffers[index].fields[0][0];
1965 if (m_buffers[index].cvBufferRef)
1966 CVBufferRelease(m_buffers[index].cvBufferRef);
1967 m_buffers[index].cvBufferRef = NULL;
1969 if(plane.id && glIsTexture(plane.id))
1970 glDeleteTextures(1, &plane.id);
1974 bool CLinuxRendererGLES::CreateCVRefTexture(int index)
1976 #ifdef HAVE_VIDEOTOOLBOXDECODER
1977 YV12Image &im = m_buffers[index].image;
1978 YUVFIELDS &fields = m_buffers[index].fields;
1979 YUVPLANE &plane = fields[0][0];
1981 DeleteCVRefTexture(index);
1983 memset(&im , 0, sizeof(im));
1984 memset(&fields, 0, sizeof(fields));
1986 im.height = m_sourceHeight;
1987 im.width = m_sourceWidth;
1989 plane.texwidth = im.width;
1990 plane.texheight = im.height;
1992 if(m_renderMethod & RENDER_POT)
1994 plane.texwidth = NP2(plane.texwidth);
1995 plane.texheight = NP2(plane.texheight);
1997 glEnable(m_textureTarget);
1998 glGenTextures(1, &plane.id);
2001 glBindTexture(m_textureTarget, plane.id);
2002 #if !TARGET_OS_IPHONE
2003 #ifdef GL_UNPACK_ROW_LENGTH
2005 glPixelStorei(GL_UNPACK_ROW_LENGTH, m_sourceWidth);
2007 #ifdef GL_TEXTURE_STORAGE_HINT_APPLE
2008 // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
2009 glTexParameteri(m_textureTarget, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
2010 // Set client storage
2012 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
2015 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2016 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2017 // This is necessary for non-power-of-two textures
2018 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2019 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2020 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
2021 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
2023 #if !TARGET_OS_IPHONE
2024 // turn off client storage so it doesn't get picked up for the next texture
2025 glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_FALSE);
2027 glBindTexture(m_textureTarget, 0);
2028 glDisable(m_textureTarget);
2033 //********************************************************************************************************
2034 // BYPASS creation, deletion, copying + clearing
2035 //********************************************************************************************************
2036 void CLinuxRendererGLES::UploadBYPASSTexture(int index)
2039 void CLinuxRendererGLES::DeleteBYPASSTexture(int index)
2042 bool CLinuxRendererGLES::CreateBYPASSTexture(int index)
2047 //********************************************************************************************************
2048 // EGLIMG creation, deletion, copying + clearing
2049 //********************************************************************************************************
2050 void CLinuxRendererGLES::UploadEGLIMGTexture(int index)
2052 #ifdef HAS_LIBSTAGEFRIGHT
2053 #ifdef DEBUG_VERBOSE
2054 unsigned int time = XbmcThreads::SystemClockMillis();
2057 if(m_buffers[index].eglimg != EGL_NO_IMAGE_KHR)
2059 YUVPLANE &plane = m_buffers[index].fields[0][0];
2061 glActiveTexture(GL_TEXTURE0);
2062 glBindTexture(m_textureTarget, plane.id);
2063 glEGLImageTargetTexture2DOES(m_textureTarget, (EGLImageKHR)m_buffers[index].eglimg);
2064 glBindTexture(m_textureTarget, 0);
2066 plane.flipindex = m_buffers[index].flipindex;
2069 #ifdef DEBUG_VERBOSE
2070 CLog::Log(LOGDEBUG, "UploadEGLIMGTexture %d: img:%p, tm:%d\n", index, m_buffers[index].eglimg, XbmcThreads::SystemClockMillis() - time);
2074 void CLinuxRendererGLES::DeleteEGLIMGTexture(int index)
2076 #ifdef HAS_LIBSTAGEFRIGHT
2077 YUVPLANE &plane = m_buffers[index].fields[0][0];
2079 if(plane.id && glIsTexture(plane.id))
2080 glDeleteTextures(1, &plane.id);
2084 bool CLinuxRendererGLES::CreateEGLIMGTexture(int index)
2086 #ifdef HAS_LIBSTAGEFRIGHT
2087 YV12Image &im = m_buffers[index].image;
2088 YUVFIELDS &fields = m_buffers[index].fields;
2089 YUVPLANE &plane = fields[0][0];
2091 DeleteEGLIMGTexture(index);
2093 memset(&im , 0, sizeof(im));
2094 memset(&fields, 0, sizeof(fields));
2096 im.height = m_sourceHeight;
2097 im.width = m_sourceWidth;
2099 plane.texwidth = im.width;
2100 plane.texheight = im.height;
2102 if(m_renderMethod & RENDER_POT)
2104 plane.texwidth = NP2(plane.texwidth);
2105 plane.texheight = NP2(plane.texheight);
2107 glEnable(m_textureTarget);
2108 glGenTextures(1, &plane.id);
2111 glBindTexture(m_textureTarget, plane.id);
2113 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
2114 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2115 // This is necessary for non-power-of-two textures
2116 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2117 glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2119 glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
2121 glDisable(m_textureTarget);
2126 //********************************************************************************************************
2127 // SurfaceTexture creation, deletion, copying + clearing
2128 //********************************************************************************************************
2129 void CLinuxRendererGLES::UploadSurfaceTexture(int index)
2131 #if defined(TARGET_ANDROID)
2132 #ifdef DEBUG_VERBOSE
2133 unsigned int time = XbmcThreads::SystemClockMillis();
2137 YUVBUFFER &buf = m_buffers[index];
2141 mindex = buf.mediacodec->GetIndex();
2142 buf.fields[0][0].id = buf.mediacodec->GetTextureID();
2143 buf.mediacodec->UpdateTexImage();
2144 buf.mediacodec->GetTransformMatrix(m_textureMatrix);
2145 SAFE_RELEASE(buf.mediacodec);
2148 #ifdef DEBUG_VERBOSE
2149 CLog::Log(LOGDEBUG, "UploadSurfaceTexture %d: img: %d tm:%d", index, mindex, XbmcThreads::SystemClockMillis() - time);
2153 void CLinuxRendererGLES::DeleteSurfaceTexture(int index)
2155 #if defined(TARGET_ANDROID)
2156 SAFE_RELEASE(m_buffers[index].mediacodec);
2159 bool CLinuxRendererGLES::CreateSurfaceTexture(int index)
2164 void CLinuxRendererGLES::SetTextureFilter(GLenum method)
2166 for (int i = 0 ; i<m_NumYV12Buffers ; i++)
2168 YUVFIELDS &fields = m_buffers[i].fields;
2170 for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
2172 glBindTexture(m_textureTarget, fields[f][0].id);
2173 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2174 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2177 if (!(m_renderMethod & RENDER_SW))
2179 glBindTexture(m_textureTarget, fields[f][1].id);
2180 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2181 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2184 glBindTexture(m_textureTarget, fields[f][2].id);
2185 glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, method);
2186 glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, method);
2193 bool CLinuxRendererGLES::Supports(ERENDERFEATURE feature)
2195 // Player controls render, let it dictate available render features
2196 if((m_renderMethod & RENDER_BYPASS))
2198 Features::iterator itr = std::find(m_renderFeatures.begin(),m_renderFeatures.end(), feature);
2199 return itr != m_renderFeatures.end();
2202 if(feature == RENDERFEATURE_BRIGHTNESS)
2205 if(feature == RENDERFEATURE_CONTRAST)
2208 if(feature == RENDERFEATURE_GAMMA)
2211 if(feature == RENDERFEATURE_NOISE)
2214 if(feature == RENDERFEATURE_SHARPNESS)
2217 if (feature == RENDERFEATURE_NONLINSTRETCH)
2220 if (feature == RENDERFEATURE_STRETCH ||
2221 feature == RENDERFEATURE_CROP ||
2222 feature == RENDERFEATURE_ZOOM ||
2223 feature == RENDERFEATURE_VERTICAL_SHIFT ||
2224 feature == RENDERFEATURE_PIXEL_RATIO ||
2225 feature == RENDERFEATURE_POSTPROCESS ||
2226 feature == RENDERFEATURE_ROTATION)
2233 bool CLinuxRendererGLES::SupportsMultiPassRendering()
2238 bool CLinuxRendererGLES::Supports(EDEINTERLACEMODE mode)
2240 // Player controls render, let it dictate available deinterlace modes
2241 if((m_renderMethod & RENDER_BYPASS))
2243 Features::iterator itr = std::find(m_deinterlaceModes.begin(),m_deinterlaceModes.end(), mode);
2244 return itr != m_deinterlaceModes.end();
2247 if (mode == VS_DEINTERLACEMODE_OFF)
2250 if(m_renderMethod & RENDER_OMXEGL)
2253 if(m_renderMethod & RENDER_EGLIMG)
2256 if(m_renderMethod & RENDER_CVREF)
2259 if(mode == VS_DEINTERLACEMODE_AUTO
2260 || mode == VS_DEINTERLACEMODE_FORCE)
2266 bool CLinuxRendererGLES::Supports(EINTERLACEMETHOD method)
2268 // Player controls render, let it dictate available deinterlace methods
2269 if((m_renderMethod & RENDER_BYPASS))
2271 Features::iterator itr = std::find(m_deinterlaceMethods.begin(),m_deinterlaceMethods.end(), method);
2272 return itr != m_deinterlaceMethods.end();
2275 if(m_renderMethod & RENDER_OMXEGL)
2278 if(m_renderMethod & RENDER_EGLIMG)
2281 if(m_renderMethod & RENDER_MEDIACODEC)
2284 if(m_renderMethod & RENDER_CVREF)
2287 if(method == VS_INTERLACEMETHOD_AUTO)
2290 #if defined(__i386__) || defined(__x86_64__)
2291 if(method == VS_INTERLACEMETHOD_DEINTERLACE
2292 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
2293 || method == VS_INTERLACEMETHOD_SW_BLEND)
2295 if(method == VS_INTERLACEMETHOD_SW_BLEND)
2302 bool CLinuxRendererGLES::Supports(ESCALINGMETHOD method)
2304 // Player controls render, let it dictate available scaling methods
2305 if((m_renderMethod & RENDER_BYPASS))
2307 Features::iterator itr = std::find(m_scalingMethods.begin(),m_scalingMethods.end(), method);
2308 return itr != m_scalingMethods.end();
2311 if(method == VS_SCALINGMETHOD_NEAREST
2312 || method == VS_SCALINGMETHOD_LINEAR)
2318 EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod()
2320 // Player controls render, let it pick the auto-deinterlace method
2321 if((m_renderMethod & RENDER_BYPASS))
2323 if (!m_deinterlaceMethods.empty())
2324 return ((EINTERLACEMETHOD)m_deinterlaceMethods[0]);
2326 return VS_INTERLACEMETHOD_NONE;
2329 if(m_renderMethod & RENDER_OMXEGL)
2330 return VS_INTERLACEMETHOD_NONE;
2332 if(m_renderMethod & RENDER_EGLIMG)
2333 return VS_INTERLACEMETHOD_NONE;
2335 if(m_renderMethod & RENDER_CVREF)
2336 return VS_INTERLACEMETHOD_NONE;
2338 #if defined(__i386__) || defined(__x86_64__)
2339 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
2341 return VS_INTERLACEMETHOD_SW_BLEND;
2345 unsigned int CLinuxRendererGLES::GetProcessorSize()
2347 if(m_format == RENDER_FMT_OMXEGL
2348 || m_format == RENDER_FMT_CVBREF
2349 || m_format == RENDER_FMT_EGLIMG
2350 || m_format == RENDER_FMT_MEDIACODEC)
2356 #ifdef HAVE_LIBOPENMAX
2357 void CLinuxRendererGLES::AddProcessor(COpenMax* openMax, DVDVideoPicture *picture, int index)
2359 YUVBUFFER &buf = m_buffers[index];
2360 buf.openMaxBuffer = picture->openMaxBuffer;
2363 #ifdef HAVE_VIDEOTOOLBOXDECODER
2364 void CLinuxRendererGLES::AddProcessor(struct __CVBuffer *cvBufferRef, int index)
2366 YUVBUFFER &buf = m_buffers[index];
2367 if (buf.cvBufferRef)
2368 CVBufferRelease(buf.cvBufferRef);
2369 buf.cvBufferRef = cvBufferRef;
2370 // retain another reference, this way dvdplayer and renderer can issue releases.
2371 CVBufferRetain(buf.cvBufferRef);
2374 #ifdef HAS_LIBSTAGEFRIGHT
2375 void CLinuxRendererGLES::AddProcessor(CStageFrightVideo* stf, EGLImageKHR eglimg, int index)
2377 #ifdef DEBUG_VERBOSE
2378 unsigned int time = XbmcThreads::SystemClockMillis();
2381 YUVBUFFER &buf = m_buffers[index];
2382 if (buf.eglimg != EGL_NO_IMAGE_KHR)
2383 stf->ReleaseBuffer(buf.eglimg);
2384 stf->LockBuffer(eglimg);
2387 buf.eglimg = eglimg;
2389 #ifdef DEBUG_VERBOSE
2390 CLog::Log(LOGDEBUG, "AddProcessor %d: img:%p: tm:%d\n", index, eglimg, XbmcThreads::SystemClockMillis() - time);
2395 #if defined(TARGET_ANDROID)
2396 void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index)
2398 #ifdef DEBUG_VERBOSE
2399 unsigned int time = XbmcThreads::SystemClockMillis();
2403 YUVBUFFER &buf = m_buffers[index];
2406 buf.mediacodec = mediacodec->Retain();
2407 mindex = buf.mediacodec->GetIndex();
2408 // releaseOutputBuffer must be in same thread as
2409 // dequeueOutputBuffer. We are in DVDPlayerVideo
2410 // thread here, so we are safe.
2411 buf.mediacodec->ReleaseOutputBuffer(true);
2414 #ifdef DEBUG_VERBOSE
2415 CLog::Log(LOGDEBUG, "AddProcessor %d: img:%d tm:%d", index, mindex, XbmcThreads::SystemClockMillis() - time);